Following code example provided by Telerik I am trying to preserve Kendo Grid state. Everything seems to be working but whenever I use date column filter and reload page the date in filter is decreased by one day... I pick 5th Oct., refresh and BAM! filter says 4th Oct. :) Any clues?
$(document).ready(function () {
var grid = $("#ProjectsGrid").data("kendoGrid");
var state = JSON.parse($.cookie("projectsState"));
if (state) {
if (state.filter) {
parseFilterDates(state.filter, grid.dataSource.options.schema.model.fields);
}
grid.dataSource.query(state);
}
else {
grid.dataSource.read();
}
});
function dataBound(e) {
var grid = this;
var dataSource = this.dataSource;
var state = kendo.stringify({
page: dataSource.page(),
pageSize: dataSource.pageSize(),
sort: dataSource.sort(),
group: dataSource.group(),
filter: dataSource.filter()
});
$.cookie("projectsState", state);
if ($.cookie('empRows')) {
$.each(JSON.parse($.cookie('empRows')), function() {
var item = dataSource.get(this);
var row = grid.tbody.find('[data-uid=' + item.uid + ']');
row.addClass('k-state-selected');
})
}
}
function parseFilterDates(filter, fields) {
if (filter.filters) {
for (var i = 0; i < filter.filters.length; i++) {
parseFilterDates(filter.filters[i], fields);
}
}
else {
if (fields[filter.field].type == "date") {
filter.value = kendo.parseDate(filter.value);
}
}
}
Related
I am not getting the concepts of how pagination works in load more requested data from json api. Even i am getting the data of first page but for remaining pages not getting. If I am using the two api for paging and fetching data but still not getting. Any one help me clear this concepts please..
main-view-model.js
const httpModule = require("tns-core-modules/http");
var observableModule = require("tns-core-modules/data/observable");
function RegisterViewModel() {
var viewModel = observableModule.fromObject({
_sourceDataItems: [],
initDataItems: function () {
//This url for the pagination
var url1 = "https://example.org/api.php?action=query&gcmtitle=Category:xyz&pilimit=max&prop=pageimages&pithumbsize=200&generator=categorymembers&format=json&gcmcontinue=";
httpModule.getJSON(url1).then((r) => {
id = r.continue.gcmcontinue
gcm.push(id)
console.log(gcm)
var pageid = [];
for (var id in r.query.pages) {
pageid.push(id);
}
for (var i = 0; i < pageid.length; i++) {
if (r.query.pages[pageid[i]].thumbnail == null) {
let abc = {
ttt: r.query.pages[pageid[i]].title,
path1: "~/images/xyz.png"
}
this._sourceDataItems.push(abc)
}
else {
let aaa = {
ttt: r.query.pages[pageid[i]].title,
path1: r.query.pages[pageid[i]].thumbnail.source
}
this._sourceDataItems.push(aaa)
}
}
}, (e) => {
});
var gcm = [];
//This url for the fetching the data on scroll
for (var i = 0; i < gcm.length; i++) {
var url2 = "https://example.org/api.php?action=query&gcmtitle=Category:xyz&pilimit=max&prop=pageimages&pithumbsize=200&generator=categorymembers&format=json&gcmcontinue=" + gcm[i];
httpModule.getJSON(url2).then((r) => {
id= r.continue.gcmcontinue)
gcm.push(id)
console.log(r.continue.gcmcontinue)
var pageid = [];
for (var id in r.query.pages) {
pageid.push(id);
}
for (var i = 0; i < pageid.length; i++) {
//placeholder Image
if (r.query.pages[pageid[i]].thumbnail == null) {
let abc = {
ttt: r.query.pages[pageid[i]].title,
path1: "~/images/xyz.png"
}
this._sourceDataItems.push(abc)
}
else {
let aaa = {
ttt: r.query.pages[pageid[i]].title,
path1: r.query.pages[pageid[i]].thumbnail.source
}
this._sourceDataItems.push(aaa)
}
}
}, (e) => {
});
}
},
_DataItems: [],
addMoreItemsFromSource: function (chunkSize) {
let newItems = this._sourceDataItems.splice(0, chunkSize);
this._DataItems = this._DataItems.concat(newItems);
},
onLoadMoreItemsRequested: function (args) {
console.log("---load item called----");
const that = new WeakRef(this);
const listView = args.object;
if (this._sourceDataItems.length > 0) {
setTimeout(function () {
that.get().addMoreItemsFromSource(5);
listView.notifyLoadOnDemandFinished();
}, 100);
args.returnValue = true;
} else {
args.returnValue = false;
}
},
});
return viewModel;
}
exports.RegisterViewModel = RegisterViewModel;
Even loading of the data is working fine for page one. While passing the gcm continue id it wont take that please help me to clear this concept
I am required to stop the execution of the JavaScript function as soon as any of the table cells contains a zero. I tried my best, but nothing seems to work. I can not understand why is it not working.
function ZeroCheck(IDTable) {
var myData = [];
$('#' + IDTable).find("tr:gt(0)").each(function(i, row) {
var oRow = [];
$(row).find("td").each(function(j, cell) {
if ($(cell).text() == '0') {
alert('Please correct input. There should not be a 0 in any cell');
return false;
}
oRow.push(parseFloat($(cell).text()));
});
myData.push(oRow);
});
};
Please try with this:
function ZeroCheck(IDTable) {
let isZeroDetectted = false;
let myData = [];
$('#' + IDTable).find("tr:gt(0)").each(function(i, row) {
let oRow = [];
$(row).find("td").each(function(j, cell) {
if ($(cell).text() == '0') {
alert('Please correct input. There should not be a 0 in any cell');
isZeroDetectted = true;
return false;
}
oRow.push(parseFloat($(cell).text()));
});
if(isZeroDetectted){
return false;
}
myData.push(oRow);
});};
Corrected and Used version of mplungjan suggested piece of code. I find this code better than my one in my question. It is self-explanatory, fairly easy and gives more control over rows and columns.
function calculateAHP(IDTable){
var myData = [];
var rows = document.getElementById(IDTable).rows;
for (var i = 1; i<rows.length;i++) {
var oRow = [];
for ( var j=1; j<rows[i].cells.length; j++) {
var val = rows[i].cells[j].innerText;
if (parseFloat(val) == 0) {
alert('Please correct input. There should not be a 0 in any cell');
return false;
}
oRow.push(parseFloat(val));
}
myData.push(oRow);
}
};
I have a table where I can drag and drop elements, and I want to save the table and then display the table with all the values saved on that indexes only as was saved from db.
I am able to get index of columns and rows. but i am facing challenge in identifying the approach for how to set the values at particular index as was saved.
Table structure is like I get the inputs for the number of input,outputcolumns and rows from user. So I create the table according to the input.. that's why i have taken three separate arrays for input_column, output_column and rows. also need to add some validations so taken separate drop method for drop on input and output header.
This is my controller.js
angular.module('myApp', []).controller('myCtrl', function($scope) {
$scope.buttons = [1,2,3,4,5,6,7,8,9];
$scope.tableSelection = {};
$scope.tableInputColSelection={};
$scope.tableOutputColSelection={};
$scope.output_columns=[1];
$scope.input_columns=[1];
$scope.data = [];
$scope.rows = [1, 2, 3];
$scope.removeSelectedItems = function(){
// $scope.rows = $scope.rows.filter(function(item, index){
// return !($scope.tableSelection[index] !== undefined && $scope.tableSelection[index]);
if(Object.keys($scope.tableSelection).length>0){
for (var i = $scope.rows.length - 1; i >= 0; i--) {
if ($scope.tableSelection[i]) {
//delete row from data
if($scope.rows.length>1){
$scope.rows.splice(i, 1);
}
delete $scope.tableSelection[i];
}
}
}
if(Object.keys($scope.tableInputColSelection).length>0){
for (var i = $scope.input_columns.length - 1; i >= 0; i--) {
if ($scope.tableInputColSelection[i]) {
//delete row from data
if($scope.input_columns.length>1){
$scope.input_columns.splice(i, 1);
}
delete $scope.tableInputColSelection[i];
}
}
}
if(Object.keys($scope.tableOutputColSelection).length>0){
for (var i = $scope.output_columns.length - 1; i >= 0; i--) {
if ($scope.tableOutputColSelection[i]) {
//delete row from data
if($scope.output_columns.length>1){
$scope.output_columns.splice(i, 1);
}
delete $scope.tableOutputColSelection[i];
}
}
}
}
$scope.addNewRow = function() {
//set row selected if is all checked
$scope.rows.push({
id: $scope.rows.length,
name: 'Name ' + $scope.rows.length
});
};
$scope.addInput= function () {
for(var i=0;i<1;i++){
$scope.input_columns.push({
id:$scope.input_columns.length,
name: 'Name'+$scope.input_columns.length
});
}
},
$scope.addOutput= function () {
for(var i=0;i<1;i++){
$scope.output_columns.push({
id:$scope.output_columns.length,
name:'Name'+$scope.output_columns.length
});
}
}
$scope.handleDragEnd = function(e) {
//debugger
this.style.opacity = '1.0';
};
$scope.handleDragOver = function(e) {
e.preventDefault(); // Necessary. Allows us to drop.
e.dataTransfer.dropEffect = 'move'; // See the section on the DataTransfer object.
return false;
};
$scope.handleHeaderDrop = function(e,item,index) {
debugger
var path = undefined;
item.dropped=true;
var data = e.dataTransfer.getData("text");
e.target.innerHTML = data;
e.preventDefault();
e.stopPropagation();
e.target.id=path;
};
$scope.handleHeaderDropOutput = function(e,item,index) {
debugger
var path = undefined;
item.dropped=true;
var data = e.dataTransfer.getData("text");
e.target.innerHTML = data;
e.target.id=path;
e.preventDefault();
e.stopPropagation();
};
$scope.drag= function (ev) {
ev.dataTransfer.setData("text", ev.path[0].innerText);
$scope.rhsContentProvider = new TreeContentProviderForXMI($scope.currentDictionaryModel.rhsDataDictionary);
};
$scope.allowDrop= function (ev) {
if(ev!=false)
ev.preventDefault();
};
$scope.drop= function (ev,item,indx) {
debugger
ev.preventDefault();
ev.stopPropagation();
var path = undefined;//CCGBASE-2218 changes
var data = ev.dataTransfer.getData("text");
};
});
I have added the plunker for full code. though I am not able to set the values of button which I have dropped on table cell.
Here i want that what approach i should follow to get all the values which i have dropped on each cell for setting the table again with the same values when fetching data from db.
Plunker-
http://plnkr.co/edit/MB2icqN9csG7RmJVMhyL?p=preview
I built out a custom pagination script to display data for my app. It works wonderfully. However, I am having a slight problem when it comes to trying to figure out how to grab a subset of the same paginated subscription.
Meteor.startup(function(){
Session.setDefault('page', 1);
Session.setDefault('recordCount', 0);
Session.setDefault('recordsPerPage', 10);
Session.setDefault('currentIndustry', null);
Session.setDefault('currentMapArea', null);
Session.setDefault('gmapLoaded', false);
});
Deps.autorun(function () {
Meteor.call('getJobsCount', Session.get('currentIndustry'), Session.get('currentMapArea'), function (err, count) {
Session.set('recordCount', count);
});
Meteor.subscribe('pagedRecords', Session.get('page'), Session.get('recordsPerPage'), Session.get('currentIndustry'), Session.get('currentMapArea'));
});
Template.gmap.rendered = function() {
if(!Session.get('gmapLoaded'))
gmaps.initialize();
}
var templateName = "jobs";
function plotCities(jobs) {
var addresses = _.chain(jobs)
.countBy('address')
.pairs()
.sortBy(function(j) {return -j[1];})
.map(function(j) {return j[0];})
.slice(0, 99)
.value();
gmaps.clearMap();
$.each(_.uniq(addresses), function(k, v){
var addr = v.split(', ');
Meteor.call('getCity', addr[0].toUpperCase(), addr[1], function(error, city){
if(city) {
var opts = {};
opts.lng = city.loc[1];
opts.lat = city.loc[0];
opts.population = city.pop;
opts._id = city._id;
gmaps.addMarker(opts);
}
});
});
}
Template[templateName].helpers({
selected: function(){
return Session.get('recordsPerPage');
}
});
Template[templateName].pages = function() {
var numPages = Math.ceil(Session.get('recordCount') / Session.get('recordsPerPage'));
var currentPage = Session.get('page');
var totalPages = Session.get('recordCount');
var prevPage = Number(currentPage) - 1;
var nextPage = Number(currentPage) + 1;
var html = '<div class="pagination-cont"><ul class="pagination">';
if (numPages !== 1) {
if (currentPage > 1) {
html += '<li>«</li>';
}
for (var i = currentPage; (i <= numPages) && (i - currentPage < 4); i++) {
if (i < 1) continue;
if (i !== currentPage)
html += '<li>' + i + '</li>';
else
html += '<li class="active">' + i + '</li>';
}
if (currentPage < numPages) {
html += '<li>»</li>';
}
}
html += '</ul></div>';
return html;
}
Template[templateName].jobs = function() {
var options = {};
var cursor;
if(!Session.get('currentMapArea')) {
cursor = Jobs.find({}, {limit: 500});
plotCities(cursor.fetch());
}
return Jobs.find({}, { limit: Session.get('recordsPerPage') });
}
Template[templateName].rendered = function(){
var select = $('#perPage');
var option = select.attr('_val');
$('option[value="' + option + '"]').attr("selected", "selected");
select.selectpicker({
style: 'btn-info col-md-4',
menuStyle: 'dropdown-inverse'
});
}
Template[templateName].events({
'click div.select-block ul.dropdown-menu li': function(e){
var selectedIndex = $(e.currentTarget).attr("rel");
var val = $('select#perPage option:eq(' + selectedIndex + ')').attr('value');
var oldVal = Session.get('recordsPerPage');
if(val != oldVal)
Session.set('recordsPerPage', Number(val));
},
'click .pageNum': function(e){
e.preventDefault();
var num = $(e.currentTarget).data('page');
Session.set('page', Number(num));
}
});
Currently, by default, only 10 records per page show up (unless the user selects from a drop-down a different amount). I have a plotCities function that I am using to try to plot the top 100 cities from the subset that is returned, however, I can't grab the top 100 because only 10 at a time show up.
Is there anyway to do what I am describing?
Ok, so the jobsPerCity and jobs are two totally different things, so I would use a separate on-fly-collection for the first one. Nothing will be stored in the database but the client will "think" that there is actually a jobsPerCity collection, which you can use to plot your map. The way you can achieve this is to define another named collection:
// only on the client !!!
var jobsPerCity = new Meteor.Collection("jobsPerCity");
On the server you will need to define a custom publish method:
Meteor.publish('jobsPerCity', function (options) {
var self = this;
var cities = new Meteor.Collection(null);
var jobToCity = {};
handle1 = Jobs.find({/* whatever condition you want */}).observeChanges({
added: function (id, fields) {
jobToCity[id] = fields.address.split(',')[0].toUpper();
cities.upsert({ _id: jobToCity[id] }, { $inc: { jobsCount: 1 } });
},
removed: function (id) {
cities.upsert({ _id: jobToCity[id] }, { $inc: { jobsCount: -1 } });
delete jobToCity[id];
},
changed: function (id, fields) {
// left as an exercise ;)
},
});
handle2 = cities.find({}, {sort: {jobsCount: -1}, limit: 100}).observeChanges({
added: function (id, fields) {
self.added('jobsPerCity', id, fields);
},
changed: function (id, fields) {
self.changed('jobsPerCity', id, fields);
},
removed: function (id) {
self.removed('jobsPerCity', id);
},
});
self.ready();
self.onStop(function () { handle1.stop(); handle2.stop(); });
});
and your good to go :)
EDIT (simple solution for more static data)
If the data is not going to be updated very often (as #dennismonsewicz suggested in one of his comments), the publish method can be implemented in a much simpler way:
Meteor.publish('jobsPerCity', function (options) {
var self = this, jobsPerCity = {};
Jobs.find({/* whatever condition you want */}).forEach(function (job) {
var city = job.address.split(',')[0].toUpper();
jobsPerCity[city] = jobsPerCity[city] !== undefined ? jobsPerCity[city] + 1 : 1;
});
_.each(jobsPerCity, function (jobsCount, city) {
self.added('jobsPerCity', city, { jobsCount: jobsCount });
});
self.ready();
});
I am making a custom datetime filter, because the datetime filter of Ext is not very nice. I have a datetime field: a datefield and timefield in a fieldcontainer that has value... it works fine.
I extend the Ext.ux.grid.filter.Filter and build my filter like the date filter.
fieldCfg = Ext.apply(me.fieldOpts, {
xtype: 'datetimefield',
overflowX: 'visible',
format: me.format,
});
fields = {};
for (i = 0, len = me.menuItems.length; i < len; i++) {
item = me.menuItems[i];
if (item !== '-') {
cfg = {
itemId: 'range-' + item,
text: me[item + 'Text'],
menu: Ext.create('Ext.menu.Menu', {
plain: true,
items: [
Ext.apply(fieldCfg, {
itemId: item,
margin: '2 10 2 2',
overflowX: 'visible'
})
],
}),
listeners: {
scope: me,
checkchange: me.onCheckChange,
render: function (t){
var dtf = t.menu.items.items[0];
var df = dtf.getDateField();
var tf = dtf.getTimeField();
df.on("select", me.selectDateEvent, me)
tf.on("select", me.selectDateEvent, me)
},
}
};
item = me.fields[item] = Ext.create('Ext.menu.CheckItem', cfg);
}
me.menu.add(item);
}
me.values = {};
Here is the function to make value of filter:
selectDateEvent: function (t) {
if(t.ownerCt.getValue() !== undefined){
var date = Ext.Date.format(t.ownerCt.getValue(), format);
this.values[t.ownerCt.itemId] = date;
this.fireEvent('update', this);
this.onMenuSelect(t.ownerCt, date);
}
},
Here's the code of the other handlers:
onCheckChange: function(item, checked) {
var me = this,
picker = item.menu.items.items[0],
itemId = picker.itemId,
values = me.values;
if (checked) {
values[itemId] = picker.getValue();
} else {
delete values[itemId]
}
me.setActive(me.isActivatable());
me.fireEvent('update', me);
}
onMenuSelect: function(picker, date) {
var fields = this.fields,
field = this.fields[picker.itemId];
field.setChecked(true);
if (field == fields.on) {
fields.before.setChecked(false, true);
fields.after.setChecked(false, true);
} else {
fields.on.setChecked(false, true);
if (field == fields.after && this.getFieldValue('before') < date) {
fields.before.setChecked(false, true);
} else if (field == fields.before && this.getFieldValue('after') > date) {
fields.after.setChecked(false, true);
}
}
this.fireEvent('update', this);
picker.up('menu').hide();
}
But it doesn't filter the data of grid. How can I make it to work? What did I wrong?
If your store is filtered on the client side, you need to implement the validateRecord method.