I'm a coop student and I'm working with Highcharts in MVC 4. My employer would like to be able to click on a column on a Column chart and have it take the user to a new page. Does anyone have any ideas on how to do this?
I'm having a hard time finding examples of Highcharts in MVC, so if someone has some good resources please send them my way.
Thanks to the comment and the resource here I was able to solve my own problem. My view takes in a Highcharts object as the model, and when my Controller passes it the following Highcharts object it works:
new Highcharts("chart")
//define the type of chart
.InitChart(new Chart { DefaultSeriesType = ChartTypes.Column})
//overall Title of the chart
.SetTitle(new Title { Text = chartTitle })
//small label below the main Title
.SetSubtitle(new Subtitle { Text = subTitle })
//load the X values
.SetXAxis(new XAxis { Categories = xAxisData })
//set the Y title
.SetYAxis(new YAxis { Title = new YAxisTitle { Text = yAxisTitle } })
.SetTooltip(new Tooltip
{
Enabled = true,
Formatter = #"function() { return '<b>'+ this.series.name +'</b><br/>'+ this.x +': '+ this.y; }"
})
.SetPlotOptions(new PlotOptions
{
Line = new PlotOptionsLine
{
DataLabels = new PlotOptionsLineDataLabels
{
// this makes the value of the dot appear above it if it is set to true (for Line charts)
Enabled = true
},
// set to true so that when the user hovers their mouse over a column/dot it's value and name will appear
EnableMouseTracking = true
},
/***********
* IMPORTANT PART
************/
Series = new PlotOptionsSeries
{
Point = new PlotOptionsSeriesPoint
{
Events = new PlotOptionsSeriesPointEvents
{
// Here you can put code for different event handlers (like Click and MouseOver) in javaScript.
// The one below makes an alert box pop up with the name of the column and its value when a
// column is clicked
Click = "function () {alert('Category: ' + this.category + ', value: ' + this.y);}"
}
}
}
})
//load the Y values
.SetSeries(yAxisData.ToArray());
Defaulty in the highcharts you should catch click event on serie's point.
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function () {
alert('Category: ' + this.category + ', value: ' + this.y);
}
}
}
}
},
Check that wrappers for asp.net supports that option.
Related
I am trying to implement font-awesome-picker to a website that i am making using vue2/php/mysql, but within standard js scripting, so no imports, .vue etc.
The script i am trying to add is taken from here: https://github.com/laistomazz/font-awesome-picker
The problem that i am facing is that i have 3 columns that have a title and an icon picker next it, that will allow the user to select 1 icon for each title. It is kinda working well...but if the same icon is used in 2 different columns then any time the user clicks again any of the 2 icons both instances of the picker will fire up, thus showing 2 popups. I need to somehow make them unique.
I've tried using
:key="list.id"
or
v-for="icon in icons" :icon:icon :key="icon"
but nothing worked. Somehow i have to separate all the instances (i think) so they are unique.
This is the template code:
Vue.component('font-awesome-picker', {
template: ' <div><div class="iconPicker__header"><input type="text" class="form-control" :placeholder="searchPlaceholder" #keyup="filterIcons($event)" #blur="resetNew" #keydown.esc="resetNew"></div><div class="iconPicker__body"><div class="iconPicker__icons"><i :class="\'fa \'+icon"></i></div></div></div>',
name: 'fontAwesomePicker',
props: ['seachbox','parentdata'],
data () {
return {
selected: '',
icons,
listobj: {
type: Object
}
};
},
computed: {
searchPlaceholder () {
return this.seachbox || 'search box';
},
},
methods: {
resetNew () {
vm.addNewTo = null;
},
getIcon (icon) {
this.selected = icon;
this.getContent(this.selected);
},
getContent (icon) {
const iconContent = window
.getComputedStyle(document.querySelector(`.fa.${icon}`), ':before')
.getPropertyValue('content');
this.convert(iconContent);
},
convert (value) {
const newValue = value
.charCodeAt(1)
.toString(10)
.replace(/\D/g, '');
let hexValue = Number(newValue).toString(16);
while (hexValue.length < 4) {
hexValue = `0${hexValue}`;
}
this.selecticon(hexValue.toUpperCase());
},
selecticon (value) {
this.listobj = this.$props.parentdata;
const result = {
className: this.selected,
cssValue: value,
listobj: this.listobj
};
this.$emit('selecticon', result);
},
filterIcons (event) {
const search = event.target.value.trim();
let filter = [];
if (search.length > 3) {
filter = icons.filter((item) => {
const regex = new RegExp(search, 'gi');
return item.match(regex);
});
}else{
this.icons = icons;
}
if (filter.length > 0) {
this.icons = filter;
}
}
},
});
I've setup a fiddle with the problem here:
https://jsfiddle.net/3yxk1ahb/1/
Just pick the same icon in both cases, and then click any of the icons again. You'll see that the popups opens for both columns.
How can i separate the pickers ?
problem is in your #click and v-show
you should use list.id instead of list.icon (i.e #click="addNewTo = list.id")
working fiddle https://jsfiddle.net/q513mhwt/
i try to change the navbar properties on a jqgrid in a callback function without succes.
The grid is display afeter user is chosing a period. Depend on either the period is open or close user can or cannot edit, add, delete rows. So the navbar need to change properties dynamically.
My code look like that:
$('#mygrid').jqGrid({
// some properties of my grid that works fine
pager : '#gridpager'
});
$("#mygrid").bind("jqGridLoadComplete",function(){
$.ajax({
url: 'checkifperiodopen.php',
data: {
$("#period").val()
},
success: function(data){
if(period==='open'){
jQuery("#mygrid").jqGrid('navGrid','#gridpager',{add:false,edit:false,del:true,search:true,refresh:true});
}
if(period==='close'){
jQuery("#mygrid").jqGrid('navGrid','#gridpager',{add:true,edit:true,del:true,search:true,refresh:true});
}
}
});
});
$('#validChossenPeriod').click(function () {
ajax call to get data on choosen period
success:function(data){
$("#mygrid").jqGrid('clearGridData');
$("#mygrid").jqGrid('setGridParam', { datatype: 'local'});
$("#mygrid").jqGrid('setGridParam', { data: data});
$("#mygrid").trigger('reloadGrid');
}
});
I finally found the answer by show or hide the div that include the navgrid button:
grid = $("#mygrid");
gid = $.jgrid.jqID(grid[0].id);
var $tdadd = $('#add_' + gid);
var $tdedit = $('#edit_' + gid);
var $tddel = $('#del_' + gid);
$("#mygrid").jqGrid('navGrid','#gridpager',{add:true,edit:true,del:true,search:true,refresh:true});
condition if false =
$tdadd.hide();
$tdedit.hide();
$tddel.hide();
if true =
$tdadd.show();
$tdedit.show();
$tddel.show();
Why so complex? There is a other clear way to do this
var view_buttons = true;
if(condition_to_hide) {
view_buttons = false;
}
$("#mygrid").jqGrid('navGrid','#gridpager', { add:view_buttons, edit:view_buttons, del:view_buttons, search:true, refresh:true});
I'm using videojs. For some reason the duration of videos is displaying as 0, even when fully loaded.
At line 2487 of the video.js file I've made sure this section...
ControlBar.prototype.options_ = {
children: ['playToggle', 'volumeMenuButton', 'currentTimeDisplay', 'timeDivider', 'durationDisplay', 'progressControl', 'liveDisplay', 'remainingTimeDisplay', 'customControlSpacer', 'playbackRateMenuButton', 'chaptersButton', 'descriptionsButton', 'subtitlesButton', 'captionsButton', 'audioTrackButton', 'fullscreenToggle']
};
...includes the 'durationDisplay' property, so does anyone know why the duration is displaying as 0?
The videos are mp4 and are loaded inside an AngularJS directive:
app.directive('engVideo',['$timeout', '$http', function($timeout, $http) {
return {
restrict: 'A',
priority: 100,
replace: true,
templateUrl: 'components/video.html',
link: function(scope, element, attrs) {
....
function VideoJSPlayerInit(window, videojs) {
var player = videojs(scope.component.video.id, {
html5: {
nativeTextTracks: false
}
});
player.pause();
}
From a suggestion in the comments, I've also tried listening for the 'loadedmetadata' event, when the videojs element is created, like this:
function VideoJSPlayerInit(window, videojs) {
var player = videojs(scope.component.video.id, {
html5: {
nativeTextTracks: false
}
}, function() {
this.on('loadedmetadata', function(){
console.log("video metadata loaded");
});
}
);
But nothing gets output to console - so I'm guessing there's no metadata loaded(?) I have also changed it to listen for the 'loadeddata' event and that DOES gets consoled.
Could this be a video encoding issue? I've been looking for how to export from Premiere with the duration metadata included, but as far as I can tell, it's there.
Any clues, much appreciated.
OK, I've finally figured it out: It was not to do with metadata; The version of video.js we're using for some reason was hardcoding the duration value as '0:00'. If it's useful to anyone else, here's what I added (to the video.js file from line 5241) to get the duration to display correctly:
DurationDisplay.prototype.createEl = function createEl() {
var el = _Component.prototype.createEl.call(this, 'div', {
className: 'vjs-duration vjs-time-control vjs-control'
});
// following three lines are new...
var intSeconds = parseInt(this.player_.duration());
var intMinutes = parseInt(intSeconds / 60);
intSeconds = intSeconds - (60 * intMinutes);
this.contentEl_ = Dom.createEl('div', {
className: 'vjs-duration-display',
// label the duration time for screen reader users
//innerHTML: '<span class="vjs-control-text">' + this.localize('Duration Time') + '</span> 0:00' // - old line
innerHTML: '<span class="vjs-control-text">' + this.localize('Duration Time') + '</span>' + intMinutes + ':' + intSeconds
}, {
// tell screen readers not to automatically read the time as it changes
'aria-live': 'off'
});
el.appendChild(this.contentEl_);
return el;
};
I created a View extend Ext.grid.Panel and also attach a tbar to it, in the toolbar I got 2 buttons [Add] and [Remove] in this question I am focus on the [Remove] command only.
As usual I want to get hold to current selected record in the grid which I want to delete.
so in the controller:
init: function() {
this.control({
'extendgridlist button[action=remove]': {
click: this.removeCurrentRow;
}
});
}
removeCurrentRow: function(t){
// how do i get current selected record
}
removeCurrentRow: function(t){
var grid = t.up('gridpanel');
var arraySelected =grid.getSelectionModel().getSelection();
//assuming you have a single select, you have the record at index 0;
var record = arraySelected[0]
}
The answer by 'nscrob' should work just fine, I just wanted to point out an alternate method. Every Ext component can have an 'id' field. So, if you gave your grid a config option like the following when it was created:
id:'my_grid_id'
Then, from anywhere including inside your removeCurrentRow function, you could do the following:
var grid = Ext.getCmp('my_grid_id');
var rows = grid.getSelectionModel().getSelection();
if(!rows.length)
{ //in case this fires with no selection
alert("No Rows Selected!");
return;
}
var row = rows[0];
As I said, similar to other answers, but just another way of accessing the grid.
In case grid is to selType = "cellModel" use code below:
var grid = Ext.getCmp('id-of-grid');
var recid = grid.getSelectionModel().getCurrentPosition();
if(recid && recid.row){
var r = grid.getStore().getAt(recid.row)
alert(r.data.anyofgridfieldid)
}
more details: http://as400samplecode.blogspot.com/2012/01/extjs-grid-selected-row-cell.html
...
xtype: 'button',
text: 'Edit',
handler: function() {
onEdit(this.up('theGrid')); // alias: 'widget.theGrid' in definition
}
...
function onEdit(theGrid) {
if (theGrid.getSelectionModel().hasSelection()) {
var rows = theGrid.getSelectionModel().getSelection();
var row = rows[0];
console.log('Count Rows Selected : ' + rows.length);
console.log('The Row : ' + row); // columns: 'id', 'name', 'age'
console.log('Student Id: ' + row.get('id'));
console.log('Student Name: ' + row.get('name'));
console.log('Student Age: ' + row.get('age'));
}
else {
console.log('No Row Selected.');
}
}
I am trying to create a button widget for dojox.grid.
My problems are:
1) The button is only shown when I double click the grid.
2) I can't figure out how to set attributes through declarative markup. It seems that the markupFactory function is responsible for it but it doesn't set the widget's label.
The following code demonstrates what I've got so far:
dojo.require("dojox.grid.DataGrid");
dojo.require("dojo.data.ItemFileWriteStore");
dojo.require("dijit.form.Button");
dojo.require("dojox.grid.cells.dijit");
dojo.require("dojo.parser");
dojo.declare("dojox.grid.cells.Button", dojox.grid.cells._Widget, {
widgetClass: dijit.form.Button,
alwaysEditing: true,
constructor: function(inCell)
{
this.inherited(arguments);
this.widget = new dijit.form.Button;
},
setValue: function(inRowIndex, inValue){
if (this.widget) {
this.widget.attr('value', inValue);
}
else {
this.inherited(arguments);
}
}
});
dojox.grid.cells.Button.markupFactory = function(node, cell)
{
dojox.grid.cells._Widget.markupFactory(node, cell);
}
For 1) The button is only shown when I double click the grid.
Set singleClickEdit: true in the Grid parameters
this.grid = new dojox.grid.DataGrid({
singleClickEdit: true,
structure: view1,
}, tmp);