Refreshing jqGrid doesn't save current page position with infinite scroll enabled - javascript

Example from http://www.trirand.net/demo/javascript/jqgrid/loading_data/scrollbar/index.html
Versions of Guriddo jqGrid JS: 4.7.0 and 4.7.1
(function ($) {
'use strict';
$(function () {
$('#jqGrid').jqGrid({
url: 'http://trirand.com/blog/phpjqgrid/examples/jsonp/getjsonp.php?callback=?&qwery=longorders',
mtype: 'GET',
datatype: 'json',
page: 1,
colNames: ['Order ID', 'Customer ID', 'Order Date', 'Freight', 'Ship Name'],
colModel: [{
name: 'OrderID',
key: true,
width: 75
}, {
name: 'CustomerID',
width: 150
}, {
name: 'OrderDate',
width: 150
}, {
name: 'Freight',
width: 150
}, {
name: 'ShipName',
width: 150
}],
width: 750,
height: 250,
rowNum: 20,
scroll: 1, // set the scroll property to 1 to enable paging with scrollbar - virtual loading of records
emptyrecords: 'Scroll to bottom to retrieve new page', // the message will be displayed at the bottom
pager: '#jqGridPager'
});
});
})(jQuery);
When I call 2 times:
$('#jqGrid').trigger('reloadGrid', {
page: 3
});
first time request: the page param is 3 as expected.
second time request: the page param is 1 !?
The same problems I see at refresh button with refreshstate: 'current', It doesn't work at all.

First of all I can confirm the bug. It exits in more old versions of jqGrid too (for example in jqGrid 4.6). The reason is in the following lines (see the lines of the source code)
if (ts.grid.prevRowHeight && ts.p.scroll) {
delete ts.p.lastpage;
ts.grid.populateVisible();
} else {
ts.grid.populate();
}
jqGrid have undefined value of ts.grid.prevRowHeight on the first reload of the grid and the set ts.grid.prevRowHeight to 22 (22px is the height of row). So the next (the second) reload of the grid will use populateVisible instead of populate. The function populateVisible uses current scrolling position (scrollTop of bDiv) only and it ignores page parameter of the grid.
Thus I can suggest you multiple solution of the problem: If you have to use specific old version of jqGrid (like if you have to use jqGrid 4.7) then you can use the following code as workaround:
$('#jqGrid')[0].grid.prevRowHeight = undefined; // workaround!!
$('#jqGrid').trigger('reloadGrid', {
page: 3
});
Alternatively you can fix the code of jquery.jqgrid.src.js for example to the following
if (ts.grid.prevRowHeight && ts.p.scroll && opts.page === undefined) {
delete ts.p.lastpage;
ts.grid.populateVisible();
} else {
ts.grid.populate();
}
One more option which I can suggest you: you can load the current version of free jqGrid from github. It's my fork of jqGrid which is based on jqGrid 4.7 and which contains many enhancements (see wiki and the readme). I posted just now the corresponding fix.

Related

Custom parameters for bootstrap-table server side pagination

I have a service created with spring boot, for which I am trying to display its data using the bootstrap-table library.
My service allows pagination with the query parameters ?page=x&size=y, where page starts at 0.
The response for the query returns something that looks like this:
{
"_embedded": {
"catalogueOrders": [ .... ]
},
"page": {
"size": 20,
"totalElements": 11,
"totalPages": 1,
"number": 0
}
}
Where _embedded.catalogueOrders contains all the data, and page contains the totals.
I tried configuring my table as following:
$('#orderTable').bootstrapTable({
url: "http://localhost:8088/catalogueOrders?orderStatus=" + orderState,
columns: [
{
field: 'orderId',
title: 'Order ID'
},
{
field: 'priority',
title: 'Priority'
}
],
pagination: true,
sidePagination: 'server',
totalField: 'page.totalElements',
pageSize: 5,
pageList: [5, 10, 25],
responseHandler: function(res) {
console.log(res)
return res["_embedded"]["catalogueOrders"]
}
})
This is able to retrieve and display the data, however it returns all the results, clearly due to it not knowing how to apply the pagination. Total elements doesn't seem to be retrieved either, as the table displays Showing 1 to 5 of undefined rows. Also, if I replace the responseHandler with dataField: '_embedded.catalogueOrders', it's no longer displaying the data.
How do I configure the query parameters needed for pagination?
And am I doing anything wrong when I try and configure dataField and totalField?
Figured it out:
Not sure what was wrong with the dataField and totalField, but it seems to not work with nested fields. To resolve this, I formatted the response into a new object inside responseHandler:
dataField: 'data',
totalField: 'total',
responseHandler: function(res) {
return {
data: res["_embedded"]["catalogueOrders"],
total: res["page"]["totalElements"]
}
}
As for the query parameters, by default, bootstrap-table provides the parameters limit and offset. To customize that and convert to size and page like in my case, the queryParams function can be provided:
queryParams: function(p) {
return {
page: Math.floor(p.offset / p.limit),
size: p.limit
}
}
one, yes, it doesn’t work with nested fields. if you want to use nested fields, try on sass code (get the compiler, just search up on web, there’s plenty of posts on the web).
two, i’m not exactly sure what you’re talking about, but you can set up a css variable
:root{
/*assign variables*/
—-color-1: red;
—-color-2: blue;
}
/*apply variables
p {
color: var(-—color-1):
}
you can find loads of info on this on the web.

Passing API Key via Confluence HTML for Standard Reports

I have been able to get the Java API code to work for Iteration TreeGrid and Iteration Burndown / Release Burnup charts. We have been trying to get this to work on Confluence and there are issues trying to pass just iframes and IT has issues with some of the bypass options. We have been able to get some semblance of this to work via the script below. In fact the Iteration TreeGrid works successfully everytime but most times the Standard Reports just present the Rally login screen. This is not consistent and sometimes this works for me in Chrome, but not in Firefox/IE etc. We have attache the API to the path of the confluence page if entered via link as well as what's in the script. Is there another method for key to passed for Standard Report to be able to generate?
Thanks!
Mark
enter code here {html}
<script type="text/javascript">
var field = 'apiKey';
var url = window.location.href;
if(
(url.indexOf('?' + field + '=') != -1) ||
(url.indexOf('&' + field + '=') != -1)
){
//alert("**** 001");
} else {
var myURL = document.location;
if(window.location.href.indexOf('?') > 0){
document.location = myURL + "&apiKey=_1OS4fhAQBi101VTZ4PytkQXb9jYEt0qYx79WXJacc";
} else {
document.location = myURL + "?apiKey=_1OS4fhAQBi101VTZ4PytkQXb9jYEt0qYx79WXJacc";
}
}
</script>
<div id="div-iterationburndown"></div>
<script type="text/javascript">
Rally.onReady(function() {
Ext.create("Ext.Container", {
context: {},
items: [{
xtype: "rallystandardreport",
width: 750,
height: 500,
reportConfig: {
report: "IterationBurndown",
iteration: "April",
subchart: "hide",
title: "Iteration Burndown"
},
project: "https://rally1.rallydev.com/slm/webservice/v2.0/project/51186094804",
projectScopeUp: !1,
projectScopeDown: !0
}],
renderTo: Ext.get("div-iterationburndown")
});
Rally.launchApp('CustomApp', {
name: "iterationburndown",
parentRepos: ""
});
});
</script>
<div id="div-releaseburnup"></div>
<script type="text/javascript">
Rally.onReady(function() {
Ext.create("Ext.Container", {
context: {},
items: [{
xtype: "rallystandardreport",
width: 750,
height: 500,
reportConfig: {
report: "ReleaseBurnup",
subchart: "hide",
title: "Release Burnup"
},
project: "https://rally1.rallydev.com/slm/webservice/v2.0/project/51186094804",
projectScopeUp: !1,
projectScopeDown: !0
}],
renderTo: Ext.get("div-releaseburnup")
});
Rally.launchApp('CustomApp', {
name: "releaseburnup",
parentRepos: ""
});
});
</script>
<div id="div-RallyGrid" style="border-width:5px 5px 5px 5px;width:300px;height:150px;"></div>
<script type="text/javascript">
Rally.onReady(function() {
Ext.create("Rally.data.wsapi.TreeStoreBuilder").build({
models: ["userstory"],
autoLoad: !0,
context: {
workspace: "https://rally1.rallydev.com/slm/webservice/v2.0/workspace/50876644101",
project: "https://rally1.rallydev.com/slm/webservice/v2.0/project/50891172431"
},
enableHierarchy: !0,
filters: [{
property: "Iteration.Name",
operator: "=",
value: "April"
}, {
property: "Project.Name",
operator: "=",
value: "Harrier"
}]
}).then({
success: function(store) {
Ext.create("Ext.Container", {
width: 1e3,
height: 1e3,
border: 5,
items: [{
xtype: "rallytreegrid",
columnCfgs: ["DisplayColor", "Name", "ScheduleState", "Blocked", "TaskEstimateTotal", "TaskRemainingTotal", "Owner", "Notes"],
store: store
}],
renderTo: Ext.get("div-RallyGrid")
})
}
});
Rally.launchApp('CustomApp', {
name: "RallyGrid",
parentRepos: ""
});
});
</script>
{html}
StandardReport component in AppSDK2 is a wrapper over the first generation analytics service that predates ApiKey. This is the same analytics service that brings you reports on Reports>Reports page. Those reports were also available via StandardReport component in AppSDK1.
ApiKey is not supported in the first generation charts.
AppSDK2 supports ApiKey as described in Embedding Apps guide. AppSDK2 apps can be authenticated with ApiKey. But if an AppSDK2 app is using a StandardReport component, the analytics service behind the report will prompt you to login - it does not work with ApiKey. In your scenario it unfortunately defeats the purpose of embedding the report within other web content to be viewed by stakeholders who may not necessarily have Rally credentials.
I suspect that if it seems that it works occasionally, it is probably because you are already logged in to Rally in another tab of the same browser window. If you open a new window in the incognito mode you will be prompted to login.
Good news! The StandardReport component in AppSDK 2.1 and the backing A1 Analytics service now fully support Api Keys so you should be able to do this fairly easily.
Some useful links:
StandardReport component: https://help.rallydev.com/apps/2.1/doc/#!/api/Rally.ui.report.StandardReport
Embedding Apps externally:
https://help.rallydev.com/apps/2.1/doc/#!/guide/embedding_apps

Automatically create header from JSON file, Bootstrap-table

I'm working with this bootstrap library and actually everything works fine. The question is, Can bootstrap-table generate header automatically in depend of JSON file? I've tried to find any information about that, but unlucky. Now my header is generated from script like from this example:
function initTable() {
$table.bootstrapTable({
height: getHeight(),
columns: [{
field: 'field1',
title: 'title1',
sortable: true
}, {
field: 'field2',
title: 'title2',
sortable: true
}, {
field: 'field3',
title: 'title3',
sortable: true
}, {
field: 'Actions',
title: 'Item Operate',
align: 'center',
events: operateEvents,
formatter: operateFormatter
}
],
formatNoMatches: function () {
return "This table is empty...";
}
});
Does anyone how to generate header automatically?
Populating from a flat json file is definetly possible but harder than from a seperate (slimmer and preped) data request, because title and other attributes 'might' have to be guessed at.
Ill show basic approach, then tell you how to make it work if stuck with a flat file that you CAN or CANT affect the format of (important point, see notes at end).
Make a seperate ajax requests that populates var colArray = [], or passes direct inside done callback.
For example, in callback (.done(),.success(), ect) also calls to the function that contains the js init code for the table.
You might make it look something like this:
function initTable(cols) {
cols.push({
field: 'Actions',
title: 'Item Operate',
align: 'center',
events: operateEvents,
formatter: operateFormatter
});
$("#table").bootstrapTable({
height: getHeight(),
columns: cols,
formatNoMatches: function () {
return "This table is empty...";
}
});
}
$(document).ready(function(){
$.ajax({
method: "POST",
url: "data/getColumns",
// data: { context: "getColumns" }
datatype: "json"
})
.done(function( data ) {
console.log( "getCols data: ", data );
// Prep column data, depending on what detail you sent back
$.each(data,function(ind,val){
data.sortable = true;
});
initTable(data);
});
});
Now, if you are in fact stuck with a flat file, point the ajax towards that then realise the question is whether you can edit the contents.
If yes, then add a columns array into it with whatever base data (title, fieldname, ect) that you need to help build your columns array. Then use responseHandler if needed to strip that columns array if it causes issues when loading into table.
http://bootstrap-table.wenzhixin.net.cn/documentation/#table-options
http://issues.wenzhixin.net.cn/bootstrap-table/ (click 'see source').
If no, you cant edit contents, and only have the fieldname, then look at using that in the .done() handler with whatever string operation (str_replace(), ect) that you need to make it look the way you want.

Kendo UI custom grid popup editor window only opens once

I would like to use a custom window as popup editor of a Kendo UI Grid. Its content will be complex with search fields and a grid to display search results. To do that, I don't want to use the Kendo template mechanism but a real popup window.
While doing tests with custom editor I faced an issue. Even with a very basic and simple scenario (just the create command), I'm only able to open the editor once. The second time I get an error, the editor doesn't show up anymore and the grid becomes empty.
Here is my HTML code :
<div id="main-content">
<div id="custom-window">
</div>
<table id="my-table-grid">
</table>
</div>
The JavaScript part :
function openCustomWindow(e) {
e.preventDefault();
myWindow.center().open();
}
function editorWindowClosed(e) {
myGrid.cancelRow();
}
var myWindow = $("#custom-window").kendoWindow({
modal: true,
resizable: false,
title: "Test",
visible: false,
close: editorWindowClosed
}).data("kendoWindow");
var dummyDataSource = new kendo.data.DataSource(
{
schema : {
model : {
id: "id",
fields: {
postion: { type: "number"},
name: { type: "string"},
}
}
}
});
dummyDataSource.add({postion: 1, name: "gswin"});
var myGrid = $("#my-table-grid").kendoGrid({
dataSource: dummyDataSource,
toolbar: [ {
name: "create",
text: "Create"
} ],
editable: {
mode: "popup",
window: {
animation: false,
open: openCustomWindow,
}
},
columns: [
{
field: "postion",
title: "Postion"
},
{
field: "name",
title: "Name"
}
]
}).data("kendoGrid");
The error message in the JavaScript console :
Uncaught TypeError: Cannot read property 'uid' of
undefinedut.ui.DataBoundWidget.extend.cancelRow #
kendo.all.min.js:29ut.ui.DataBoundWidget.extend.addRow #
kendo.all.min.js:29(anonymous function) #
kendo.all.min.js:29jQuery.event.dispatch #
jquery-2.1.3.js:4430jQuery.event.add.elemData.handle #
jquery-2.1.3.js:4116
And finally a jsfiddle link to show what I'm doing. (The popup is empty because I just want to fix the open / close mechanism before going any further)
I don't understand why I get this error, I expected to be able to open / close the popup as many time as I wanted. The default editor popup is working fine.
One of my colleague found the solution (thanks to him).
Actually this piece of code
editable: {
mode: "popup",
window: {
animation: false,
open: openCustomWindow,
}
}
is designed to configure the default popup...
The right way to use a custom popup is the following :
editable :true,
edit: openCustomWindow,
With this approach it's also better to use
function editorWindowClosed(e) {
myGrid.cancelChanges();
}
Instead of
function editorWindowClosed(e) {
myGrid.cancelRow();
}
Working jsfiddle link
Actually the approach in my previous answer solved my issue but is causing another issue. The grid becomes editable but in the default mode (which is "inline").
Doing this
editable: "popup",
edit: openCustomWindow
has fixed this other issue but is now displaying 2 popups.
I finally succeeded to hide the default popup and only show my custom popup but it ended with the orginal issue described in initial question...
Considering all those informations I arrived to the conclusion that working with a custom popup window is definitely not an option. I'll start working with teamplates instead.
Another solution would have been to use a template to override the toolbar with a custom "Add" button and use a custom command for edition. But at this point I consider that too "tricky".
To prevent Kendo UI custom grid popup editor window, define the editable property:
editable:
{
mode: "popup",
window: {
animation: false,
open: updateRowEventHandler
}
} // skip edit property
Then paste preventDefault() at the beginning of the handler:
function updateRowEventHandler(e) {
e.preventDefault(); //

Smart file component(html5smartfile) not working

I have been working on developing a custom extjs console to enable author drop an asset using html5smartfile component. But somehow, the html5smartfile component is not working the way it should. The Area where an author can drop an asset is not displaying. The same is working fine if I am creating a CQ5 dialog. But in my case where i have created a window it's not working.
I have declared my smartfile component like this:
var assetLinkDropField = {
xtype: 'html5smartfile',
fieldLabel: 'Asset Link',
ddAccept: 'video/.*',
ddGroups: 'media',
fileReferenceParameter: './linkUrl',
name: './linkUrl',
allowUpload: false,
allowFileNameEditing: false,
allowFileReference: true,
transferFileName: false
};
But this is rendering like this:
After a lot of work, I found out that the CQ5 dialog updates the view for the component but in case of my window, I have to update it myself. Thus, with a slight manipulation, i just succeeded in displaying the drag area by tweaking the declaration like this:
var assetLinkDropField = {
xtype: 'html5smartfile',
fieldLabel: 'Asset Link',
ddAccept: 'video/.*',
ddGroups: 'media',
fileReferenceParameter: './linkUrl',
name: './linkUrl',
allowUpload: false,
allowFileNameEditing: false,
allowFileReference: true,
transferFileName: false,
listeners: {
afterlayout: function () {
this.updateView();
}
}
}
So now the panel looks like:
But still the Drag and Drop is not working. My Window declaration is like this:
win = new CQ.Ext.Window({
height : 750,
width : 700,
layout : 'anchor',
// animateTarget : btn.el,
closeAction : 'close', // Prevent destruction on Close
id : 'manageLinkWindow',
title : '<b>Multi Link Widget Dialog</b>',
frame : true,
draggable : false,
modal : false, //Mask entire page
constrain : true,
buttonAlign : 'center',
items : [assetLinkDropField]
});
}
I think you should not use
ddAccept: 'video/.*',
This allows only videos from the content finder to be dragged and dropped. It should be "image/".
Verify your other extjs properties / configs for html5smartfile if the above doesn't resolves your problem.

Categories

Resources