I can not use the data point click event - jqplot

The second chart value is too small to click.
What should I do?
$("#jqplot3").bind('jqplotDataClick',
function (ev, seriesIndex, pointIndex, data){
var url = "<c:url value='/test/salesDetailPage.do'/>" ;
var target = "openPopup";
var itemType = item[pointIndex];
window.open("", "openPopup", "width=1500, height=800, left=600, scrollbars=yes, resizable=yes");
fn_openPopup(url, target, itemType);
}

Related

DC js charts, crossfilter not filtering on click

*Updated with more relevant code.
*Updated again: removing chart groupings results in this error: "Unable to get property 'classed' of undefined or null reference dc.js (5575,9)". I am using dc 3.0.11.
I have an issue where my dc charts are not filtering each other upon clicking a selection on a chart. It does work if I call a function to explicitly do so, but I would like to avoid that.
This is my general approach:
I do have dc.css included (if that matters)
my crossfilter ndx and dimensions are correct
I am defining my charts WITHOUT .on renderlet (is this the reason?)
var masterData = [];
$(document).ready(function () { //UPDATED CODE START
var siteurl = 'site';
var ItemCount= GetItemCount(siteurl, 'list');
createRestUrl(siteurl,ItemCount,'list');
}); // UPDATED CODE END
function GetItemCount(siteurl, ListName){
var ItemCount='';
$.ajax({
url: siteurl+"/_api/web/lists/GetByTitle('"+ListName+"')/ItemCount",
method: "GET",
async: false,
headers: { "Accept": "application/json; odata=verbose" },
success: function (data) {
ItemCount = data.d.ItemCount;
},
error: function (data) {
console.log(data);
}
});
return ItemCount;
} // GetItemCount END
function createRestUrl(siteurl, ItemCount, ListName) {
var listServiceUrl = siteurl+ "/_api/web/lists/GetByTitle('" + ListName + "')/Items";
//Rest call to process each items of list
$.when(processList(listServiceUrl,ItemCount)).done(function () {
console.log("FINISHED");
console.log("--------");
console.log(masterData);
var ndx = crossfilter(masterData),
clientMgr = ndx.dimension(function(d) { return d.clientMgr}),
otherTeammates = ndx.dimension(function(d) { return d.otherTeammates}),
topic = ndx.dimension(function(d) { return d.topic}),
status = ndx.dimension(function(d) { return d.status}),
team = ndx.dimension(function(d) { return d.team}),
requester = ndx.dimension(function(d) { return d.requester}),
requesterBusiness = ndx.dimension(function(d) { return d.requesterBusiness}),
submitted = ndx.dimension(function(d) { return d.submitted}),
clientMgrGroup = clientMgr.group(),
otherTeammatesGroup = otherTeammates.group(),
topicGroup = topic.group(),
statusGroup = status.group(),
teamGroup = team.group(),
requesterGroup = requester.group(),
requesterBusinessGroup = requesterBusiness.group(),
submittedGroup = submitted.group();
var teamChart = dc.rowChart("#team_chart", "team");
var clientMgrChart = dc.pieChart("#mgr_chart", "mgr");
var statusChart = dc.pieChart("#status_chart", "status");
var requesterChart = dc.rowChart("#requester_chart", "request");
var requesterBusinessChart = dc.pieChart("#requesterBusiness_chart", "requestBusiness");
var timeSelect = dc.lineChart("#time_chart", "time");
var topicChart = dc.pieChart("#topic_chart", "topic");
var teamNum = dc.numberDisplay("#teamNum", "teamNum");
Date.prototype.addDays = function(days) {
var dat = new Date(this.valueOf());
dat.setDate(dat.getDate() + days);
return dat;
}
var thisDay = new Date();
var todayMinSix = thisDay.addDays(-30);
var todayPlusSix = thisDay.addDays(30);
teamChart
.dimension(team)
.group(teamGroup)
.width(800)
.height(200)
.transitionDuration(3000)
.ordering(function(d) { return -d.value })
.elasticX(true)
.x(d3.scaleLinear().domain([0, 100]))
.colors('#58D3F7')
//teamNum
//.valueAccessor(function(d) { return d})
//.formatNumber(d3.format())
//.group(teamGroup)
clientMgrChart
.dimension(clientMgr)
.group(clientMgrGroup)
.width(300)
.height(300)
.transitionDuration(3000)
statusChart
.dimension(status)
.group(statusGroup)
.height(200)
.width(500)
.innerRadius(95)
.transitionDuration(3000)
.colors(d3.scaleOrdinal().domain(["02 - Work-In-Progress", "01 - Pending Initial Review"])
.range(['#58D3F7', '#2E9AFE']))
requesterChart
.dimension(requester)
.group(requesterGroup)
.height(200)
.width(800)
.gap(10)
.transitionDuration(3000)
.ordering(function(d) { return -d.value })
.elasticX(true)
.colors('#F78181')
.x(d3.scaleLinear().domain([0, 100]));
requesterBusinessChart
.dimension(requesterBusiness)
.group(requesterBusinessGroup)
.height(300)
.width(300)
.innerRadius(117)
.transitionDuration(3000)
.colors('#F78181')
topicChart
.dimension(topic)
.group(topicGroup)
.height(200)
.width(500)
.innerRadius(95)
.transitionDuration(3000)
.colors(d3.scaleOrdinal().domain(["New Report / Interface", "General Support", "One-Time Data Set", "Recurring Data Set", "Modify Existing Report / Interface", "Production Issue"])
.range(['#F5A9A9', '#F78181', '#FA5858', '#F6CECE', '#F8E0E0', "#FBEFEF"]))
timeSelect
.width(1700)
.height(150)
.dimension(submitted)
.group(submittedGroup)
.transitionDuration(1000)
.elasticY(true)
.renderArea(true)
.x(d3.scaleTime().domain([todayMinSix, thisDay]))
.xUnits(d3.timeDays)
.mouseZoomable(false)
.xAxis();
teamChart.render();
statusChart.render();
requesterChart.render();
topicChart.render();
});
}
//Step 3: Rest call to process each items of list
function processList(nextUrl,ItemCount) {
var dfd = new $.Deferred();
if (nextUrl == undefined) {
dfd.resolve();
return;
}
getJSONDataFromUrl(nextUrl).done(function (listItems) {
TotalItemCount = TotalItemCount+listItems.d.results.length;
console.log("getJSON called");
var items = listItems.d.results;
var next = listItems.d.__next;
$.when(processList(next,ItemCount)).done(function (){
dfd.resolve();
});
$.each(items, function(index, obj){
items = {};
items.clientMgr = obj.ClientMgr; //Assigned To - might not be the right field
items.otherTeammates = obj.OtherTeammatesEngaged; //Assigned To - might not be the right field
items.topic = obj.Topic;
items.status = obj.Status;
items.team = obj.Team;
items.requester = obj.RequesterLOB;
items.submitted = obj.Submitted;
items.requesterBusiness = obj.RequesterBusinessGroup;
console.log("looping through each");
var convert = new Date(items.submitted);
items.submittedConvert = moment(convert).format('L');
items.submitted = convert;
var assignName = items.clientMgr;
items.clientMgr = assignName;
masterData.push(items);
console.log(items.requesterBusiness);
console.log(items.status);
}); //.each END
}); // getJSONDataFromUrl END
return dfd.promise();
} // processList END
I had this working long ago, but as the project became more complex, something broke along the way.
I'm going to guess that the error refers to the use of .classed() a few lines up from 5575. Here are the lines leading up to 5575:
if (d3.sum(_chart.data(), _chart.cappedValueAccessor)) {
pieData = pie(_chart.data());
_g.classed(_emptyCssClass, false);
} else {
// otherwise we'd be getting NaNs, so override
// note: abuse others for its ignoring the value accessor
pieData = pie([{key: _emptyTitle, value: 1, others: [_emptyTitle]}]);
_g.classed(_emptyCssClass, true);
}
if (_g) {
https://github.com/dc-js/dc.js/blob/3.0.11/dc.js#L5565-L5575
So (except for the line number being a little off) it's a good guess that _g is null.
As I noted in my comment above, this probably indicates that the chart was redrawn before it was rendered. This can happen if you create a chart but don't render it. Rendering initializes things like the scale and parent elements like the <g> that holds the chart.
When you create a chart, you either specify a chart group or the default chart group is selected for you. The chart is registered in that group, and when any chart in the group is filtered, all the charts are redrawn.
In your code above, you render specific charts (4 of them), but there are many more charts which you initialize but don't render (8). In particular, all of the pie charts are rendered except for clientMgrChart. When you later click on a chart, it's likely that chart crashes when it tries to redraw.
It would be nice if dc.js implemented a more helpful error for this case since you currently have to guess "hmm, null, guess something hasn't been set up right" and know that render must happen before redraw.
Note: it's more robust to initialize the charts and then call
dc.renderAll();
instead of rendering each one manually.
Note to others: With dc.js 3.1.2, my individual rowCharts would not animate themselves when clicked. The other charts in the crossfilter did animate.
Very confused, traced all the way through the dc.js call stack and learned a lot.
Ultimately, root cause for the failure was not having dc.css linked in my page's HTML.
Another good 'tell' that you don't have dc.css properly linked is that the rowChart vertical lines do not render.
Screenshots
rowChart With CSS - Clicking any of the bars DOES trigger animation.
rowChart Without CSS - Clicking any of the bars does not trigger animation.

Knockout JS - update viewModel with AJAX Call

there are some similar questions but didn't help me to solve my issue. I can't update my results on page / view after updating my viewModel with AJAX. I am getting valid AJAX response that updates the view if I reload the page, but not when I click btnAdvancedSearch
I have simple HTML:
<div>
<input type="button" id="btnAdvancedSearch" data-bind="click: refresh" />
</div>
<div id="resultslist1" data-bind="template: { name: 'rest-template', foreach: restaurants }">
</div>
And I bind in on document load:
$(document).ready(function () {
ko.applyBindings(new RestaurantsListViewModel());
});
My viewModel is like this, and in it I call refresh that is bound with button
// Overall viewmodel for this screen, along with initial state
function RestaurantsListViewModel() {
var self = this;
self.restaurants = ko.observableArray([]);
var mappedRests = $.map($.parseJSON(sessionStorage.getItem('searchResults')), function (item) { return new Restaurant(item) });
self.restaurants = mappedRests;
self.refresh = function () {
updateRestaurantsList(); //Method executes AJAX and saves result to session.
var mappedRests2 = $.map($.parseJSON(sessionStorage.getItem('searchResults')), function (item) { return new Restaurant(item) });
self.restaurants= mappedRests2;
}
}
What am I missing here?
Thanks
I have tried waiting for AJAX to finish like this:
// Overall viewmodel for this screen, along with initial state
function RestaurantsListViewModel() {
var self = this;
self.restaurants = ko.observableArray([]);
var mappedRests = $.map($.parseJSON(sessionStorage.getItem('searchResults')), function (item) { return new Restaurant(item) });
self.restaurants = mappedRests;
self.refresh = function () {
var latitude = sessionStorage.getItem('latitude');
var longitude = sessionStorage.getItem('longitude');
var query = '{"Accepts_Reservations":"' + $('#chkReservation').is(":checked") + '","Accepts_Cards":' + $('#chkAcceptsCards').is(":checked") + '"}';
var searchResults = getRestaurantsAdvancedSearchAJAX(query, latitude, longitude, 40);
searchResults.success(function (data) {
var information = data.d;
var mappedRests2 = $.map($.parseJSON(information), function (item) { return new Restaurant(item) });
self.restaurants = mappedRests2;
});
};
};
Edit 1
Once you have declared your observable like so:
self.restaurants = ko.observableArray([]);
When you want to update restaurants you cannot do this:
self.restaurants = mappedRests2;
Instead, you need to do this:
self.restaurants(mappedRests2);
updateRestaurantsList(); //Method executes AJAX and saves result to session.
The comment after the above line indicates that this method is making an asynchronous call. Therefore, it is likely that the line after it is executing before sessionStorage has been populated. Maybe consider having updateRestaurantsList return a promise. Then you could update your code to something like this:
updateRestaurantsList().then(function() {
var mappedRests2 = $.map($.parseJSON(sessionStorage.getItem('searchResults')), function (item) { return new Restaurant(item) });
self.restaurants= mappedRests2;
});
This way the call to populate your mappedRests2 variable won't happen until after your updateRestaurantsList method has completed.
Edit 1
Be sure to never assign values to an observable using an equal sign.
// Overall viewmodel for this screen, along with initial state
function RestaurantsListViewModel() {
var self = this;
self.restaurants = ko.observableArray([]);
var mappedRests = $.map($.parseJSON(sessionStorage.getItem('searchResults')), function (item) { return new Restaurant(item) });
self.restaurants(mappedRests);
self.refresh = function () {
var latitude = sessionStorage.getItem('latitude');
var longitude = sessionStorage.getItem('longitude');
var query = '{"Accepts_Reservations":"' + $('#chkReservation').is(":checked") + '","Accepts_Cards":' + $('#chkAcceptsCards').is(":checked") + '"}';
var searchResults = getRestaurantsAdvancedSearchAJAX(query, latitude, longitude, 40);
searchResults.success(function (data) {
var information = data.d;
var mappedRests2 = $.map($.parseJSON(information), function (item) { return new Restaurant(item) });
self.restaurants(mappedRests2);
});
};
};

Kendo Grid always focus on first cell of Top Row

I have checkbox in Kendo grid. Once i click on Checkbox it always focus the top cell in Kendo Grid. Below is code for Kendo grid that I am binding to checkbox value on checkbox click event in Kendo Grid
$("#contactgrid").on('click', '.chkbx', function () {
var checked = $(this).is(':checked');
var grid = $('#contactgrid').data().kendoGrid;
var rowIdx = $("tr", grid.tbody).index(row);
var colIdx = $("td", row).index(this);
// grid.tbody.find("tr").eq(rowIndex).foucs(); This doesn't work
var dataItem = grid.dataItem($(this).closest('tr'));
dataItem.set('IsSelected', checked);
});
I can get the row index and cell Index in click event but I was not able to figure out to focus the specific cell.
Thanks!
When you want to edit Grid with checkbox then I would suggest you to use the approach from this code library. No matter it uses the MVC extensions open Views/Home/Index.cshtml and see how the template is defined and the javascript used after initializing the Grid.
Here it is
Column template:
columns.Template(#<text></text>).ClientTemplate("<input type='checkbox' #= IsAdmin ? checked='checked':'' # class='chkbx' />")
.HeaderTemplate("<input type='checkbox' id='masterCheckBox' onclick='checkAll(this)'/>").Width(200);
<script type="text/javascript">
$(function () {
$('#persons').on('click', '.chkbx', function () {
var checked = $(this).is(':checked');
var grid = $('#persons').data().kendoGrid;
var dataItem = grid.dataItem($(this).closest('tr'));
dataItem.set('IsAdmin', checked);
})
})
function checkAll(ele) {
var state = $(ele).is(':checked');
var grid = $('#persons').data().kendoGrid;
$.each(grid.dataSource.view(), function () {
if (this['IsAdmin'] != state)
this.dirty=true;
this['IsAdmin'] = state;
});
grid.refresh();
}
</script>
I struggled with this. I essential refocused the cell as shown below. There's plenty of room for improvement in the Kendo grid client-side API. Hopefully my helper methods below will help people out.
var $row = getRowForDataItem(this);
var $current = getCurrentCell($row);
var currentCellIndex = $row.find(">td").index($current);
this.set('PriceFromDateTime', resultFromDate);
$row = getRowForDataItem(this);
var grid = getContainingGrid($row);
//select the previously selected cell by it's index(offset) within the td tags
if (currentCellIndex >= 0) {
grid.current($row.find(">td").eq(currentCellIndex));
}
//Kendo grid helpers
function getColumn(grid, columnName) {
return $.grep(grid.columns, function (item) {
return item.field === columnName;
})[0];
}
function getRowForDataItem(dataItem) {
return $("tr[data-uid='" + dataItem.uid + "']");
}
function getCurrentCell($elem) {
return getContainingGrid($elem).current();
}
function getContainingDataItem($elem) {
return getDataItemForRow(getContainingRow($elem));
}
function getContainingCell($elem) {
return $elem.closest("td[role='gridcell']");
}
function getContainingRow($elem) {
return $elem.closest("tr[role='row']");
}
function getContainingGrid($elem) {
return $elem.closest("div[data-role='grid']").data("kendoGrid");
}
function getGridForDataItem(dataItem) {
return getContainingGrid(getRowForDataItem(dataItem));
}
function getDataItemForRow($row, $grid) {
if (!$grid) $grid = getContainingGrid($row);
return $grid.dataItem($row);
}
function getMasterRow($element) {
return $element.closest("tr.k-detail-row").prev();
}
function getChildGridForDataItem(dataItem) {
return getRowForDataItem(dataItem).next().find("div.k-grid").data("kendoGrid");
}
function getMasterRowDataItem($element) {
var $row = getMasterRow($element);
return getDataItemForRow($row);
}

My kendo chart is not updating

I Have kendo chart and tree-view in my application.I want to to change the value axis dynamically on check-box checked event,example When we check the "KM" check-box in treeview then value axis for Km and data will be displaying in chart.
so I tried some code then my chart is not displaying.
My checked event code is
$("#treeview").on("change", function (e) {
var chart = $("#chart").data("kendoChart");
var checkedSeries = [];
$("#treeview").find(":checked").each(function() {
var nodeText = $(this).parent().parent().text();
$.each(valueAxes, function(index, valueAxes) {
if (valueAxes.field == nodeText) {
checkedSeries.push(valueAxes);
}
});
});
chart.options.valueAxes = checkedSeries;
chart.refresh();
});
What's wrong in my code please help me.
Here is my jsbin http://jsbin.com/eyibar/11/edit
First you need to assign the chart to a variable in on-change event event of tree view,without that the tree-view didn't recognize the chart and it's value axis and in your valueAxes code there is no property of field,so by name of the valueAxes you need to check the treeview node and then push the valueAxes.
$("#treview").on("change", function (e) {
var chart = $("#chart").data("kendoChart");
var checkedSeries = [];
if ($("#treeview").find(":checked").length !== 0) {
$("#treeview").find(":checked").each(function () {
var nodeText = $(this).parent().parent().text();
$.each(valueAxes, function (index, valueAxes) {
if (valueAxes.name == nodeText) {
checkedSeries.push(valueAxes);
checkedSeries.visible = true;
}
});
});
createChart(checkedSeries);
}
else {
createChart(checkedSeries);
}
});

Put info from google maps InfoWindow into HTML textbox

I have a map that has lots of markers pulled from a database. Each one displays an InfoWindow with a placename and the lat and lng of the location. I need to have the placename affiliated with a marker added to and HTML textbox on click. I can't seem to find any tutorials on this. Maybe someone can point me in the right direction. I am trying to learn this on my own so apologies if it is sloppily designed. Thanks for your help in advance.
function load() {
var map = new google.maps.Map(document.getElementById("map_canvas"), {
center: new google.maps.LatLng(41.640078, -102.669433),
zoom: 3,
mapTypeId: 'roadmap'
});
var infoWindow = new google.maps.InfoWindow;
downloadUrl("mymap.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var name = markers[i].getAttribute("name");
var address = markers[i].getAttribute("address");
var type = markers[i].getAttribute("type");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var html = "<b>" + name + "</b> <br/>" + point;
var icon = customIcons[type] || {};
var marker = new google.maps.Marker({
map: map,
position: point,
icon: icon.icon,
shadow: icon.shadow
});
bindInfoWindow(marker, map, infoWindow, html);
}
});
}
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
It needs to go into a simple textbox like this:
<input type = "text" id = "address_box" value = ""/>
To display that data in your HTML text box, change your bindInfoWindow function, add code in there to put the data in the text box:
function bindInfoWindow(marker, map, infoWindow, html, name) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
document.getElementById("address_box").value = name;
});
}
And add name in to the call to it:
bindInfoWindow(marker, map, infoWindow, html, name);
Do you mean, when the infoWindow opens, you want to display some information into the textbox?
If so, this code might help you(I hope).
var infoWindow = new google.maps.InfoWindow;
var address_box = document.getElementById("address_box");
google.maps.event.addListener(infoWindow, "domready", function() {
address_box.value = infoWindow.get("Content");
});

Resources