How to select all in primefaces dataTable with liveScroll - primefaces

I'm using primefaces v5.3 dataTable with liveScroll="true" and selectionMode="multiple".
Header checkbox selects only visible rows and when i scroll down new rows appear non selected.
I want header checkbox to select all rows: visible and invisible.
Selection of only visible rows is meaningless and useless.
Is it possible to fix?
I tried to add all table data to selection by processing "toggleSelect, rowSelectCheckbox and rowUnselectCheckbox" events. It works on backend, but in UI rows are unselected anyway.

Use this script to replace the original updateData function of primefaces
PrimeFaces.widget.DataTable.prototype.updateData = (function() {
var cached_function = PrimeFaces.widget.DataTable.prototype.updateData;
return function() {
var reselectAll = (this.selection != undefined && (this.selection[0] === '#all' || this.selection.length === this.getTbody()[0].getElementsByTagName('tr').length);
var result = cached_function.apply(this, arguments);
if (reselectAll) {
this.selectAllRows();
}
return result;
};
})();
that will automatically select the new loaded rows on the table(only the ones that are visible on the client side)

Related

How to dynamically change images using Metaio

I have just start learning Metaio. I am working on a simple development test project.
I have so far made the tracking sheet, put image and two arrows (buttons) which means next image and previous image.
For testing I made one of the buttons to display the image and the other for hiding the image. All this works fine so far.
My question is when I added extra images how can I shift the images dynamically back and forward using my next and previous buttons?
My testing code:
button2.onTouchStarted = function () {
image1.hide();
};
button1.onTouchStarted = function () {
image1.display();
};
It can be done different ways, I suggest you to use arel.Scene.getObject and put your image names inside array and each time you click next or previous you count the array key up or down.
I assume you are using Metaio Creator editor.
You have to added codes 3 different places:
Previous (left arrow button)
button1.onTouchStarted = function () {
if (currentImageIndex == firstImageIndex) {
return;
}
arel.Scene.getObject(imageArray[currentImageIndex]).hide();
currentImageIndex--;
arel.Scene.getObject(imageArray[currentImageIndex]).display();
globalsVar['currentImageIndex'] = currentImageIndex;
};
Next (right arrow button)
button2.onTouchStarted = function () {
if (currentImageIndex == lastImageIndex) {
return;
}
arel.Scene.getObject(imageArray[currentImageIndex]).hide();
currentImageIndex++;
arel.Scene.getObject(imageArray[currentImageIndex]).display();
globalsVar['currentImageIndex'] = currentImageIndex;
};
On your Global Script
var imageArray = ["image1", "image2"]; // and so on extra image names
var firstImageIndex = 0;
var lastImageIndex = imageArray.length - 1;
var currentImageIndex = firstImageIndex;
globalsVar = {};
arel.Scene.getObject(imageArray[currentImageIndex]).display();

Flex selectedItem sort order

I have a code as following
var selectedWindows = new ShowSelectedFilesFolderWindow;
selectedWindows.setParentData(MainFileGrid.selectedItems);
The problem is that when I retrieved the list from the dialog, the list(hierarchical data) was sorted according to the way the selection was made in the main window. For example, if I selected bottom-up,it displayed folder first, if I selected up-to-bottom, it displayed file first.
How can I keep the default folder first display ?
I got it solved as the following
public function setParentData(obj:Object):void{
var tempArr:Array = obj as Array;
if(tempArr[0].Type == "file"){
this.parentData = tempArr.reverse();
}else{
this.parentData = tempArr;
}
}

Kendo hierarchy grid -- get count of child rows on selecting master row

I think this is probably pretty simple, but I need pointing in the right direction.
I've got a master/child grid and I'd simply like to be able to get a count of child rows when selecting (or various other actions, e.g. save or edit ) the master row.
Thanks
I created a fiddle and played around a bit. It's not always working, e.g. when you haven't got the details grid yet or when opening a detail row for the first time, but it should give you an idea on how get the cound of a hierarchical grid.
Fiddle: http://jsfiddle.net/9BGpr/
Open console to get output.
Main code is here:
selectable: 'row',
change: function (e) {
var kendoGrid = this;
setTimeout(function () {
console.log("e", e)
var $selectedRow = kendoGrid.select();
if ($selectedRow.length != 1) {
console.log("Please select a single row!");
return false;
}
if ($selectedRow.hasClass('k-master-row')) {
var $detailRow = $selectedRow.next().filter('.k-detail-row');
if ($detailRow.length === 0) {
console.log("Could not find detail row!");
return false;
}
var $detailGrid = $detailRow.find('.k-grid');
if ($detailGrid.length === 0) {
console.log("Could not find grid in detail row!");
return false;
}
var kendoGridDetails = $detailGrid.getKendoGrid();
console.log("Total of records in detail grid: " + kendoGridDetails.dataSource.total());
}
});

JSON object does not update correctly

First of all, I'm not sure if my title describes the problem correctly... I did search but didn't find anything that helped me out...
The project I'm working on has an #orderList. All orders have a delete option. After an order gets deleted the list is updated.
Sounds simple... I ran into a problem though.
/**
* Data returned at the end of selecting some options
*/
$.post(myUrl, $('#myForm').serialize(), function(data) {
// I build the orderlist
// The data returned is a JSON object holding session data (including orders)
buildOrderList(data);
...
// Do some other work
});
/*
* function to build the html list
*/
function buildOrderList(data) {
// Empty list
$('#orderList').empty();
// The click handler for the delete button is in here because it needs the data object
$(document).on('click', '[id^=delete_]', function() {
// Get the orderId from the delete button
var orderId = $(this).attr('id').split('_');
orderId = orderId['1'];
// I call the delete function
deleteOrder(orderId, data);
});
var html = '';
// Loop the data object
$.each(data, function(key,val){
...
// Put html code needed in var html
...
});
$('#orderList').append(html);
}
/*
* function to delete an order
*/
function deleteOrder(orderId, data) {
// Because of it depends on other 'products' in the list if the user can
// simply delete it, I use a jQuery dialog to give him some options.
// These options I send to a php script so it knows what should be deleted.
// This fires when a user clicks on the 'delete' button from a dialog.
// The dialog uses data to show options but does not change the value of data.
switch(data.type) {
case 'A':
delMsg += '<p>Some message for case A</p>';
delMsg += '<select>with some options for case A</select>';
$('#wizard_dialog').append(delMsg);
$('#wizard_dialog').dialog('option', 'buttons', [
{ text: "Delete", click: function() {
$.post(myUrl, $('#myDeleteOptions').serialize(), function(newData) {
// Now the returned data is the updated session data
// So I build the orderList again...
buildOrderList(newData);
...
// Do some other work
});
$( this ).dialog( "close" );
$(this).html(''); }},
{ text: "Cancel", click: function() { $( this ).dialog("close"); $(this).html(''); }}
] );
break;
case 'B':
// Do the same thing but different text and <select> elements
break;
}
}
The orderList updates correctly, however if I try to delete another order, the jQuery dialog gives me the option for the current (correct product) AND the option for the product that previously owned the id of the current. (Hope I didn't loose anyone in my attempt to explain the problem)
The main question is how to 'refresh' the data send to buildOrderList.
Since I call the function in a new $.post with fresh data object returned it should work, shouldn't it?
/**
* Enable the JQuery dialog
* (#wizard_dialog)
* this is the init (note that I only open the dialog in deleteOrder() and set text and buttons according to the data send to deleteOrder() )
*/
$('#wizard_dialog').dialog({
autoOpen: false,
resizable: false,
modal: true,
dialogClass: "no-close",
open: function() {
$('.ui-dialog-buttonpane').find('button:contains("Annuleren")').addClass('cancelButtonClass');
$('.ui-dialog-buttonpane').find('button:contains("Verwijderen")').addClass('deleteButtonClass');
$('.ui-dialog :button').blur(); // Because it is dangerous to put focus on 'OK' button
$('.ui-widget-overlay').css('position', 'fixed'); // Fixing overlay (else in wrong position?)
if ($(document).height() > $(window).height()) {
var scrollTop = ($('html').scrollTop()) ? $('html').scrollTop() : $('body').scrollTop(); // Works for Chrome, Firefox, IE...
$('html').addClass('noscroll').css('top',-scrollTop); // Prevent scroll without hiding the bar (thus preventing page to shift)
}
},
close: function() {
$('.ui-widget-overlay').css('position', 'absolute'); // Brake overlay again
var scrollTop = parseInt($('html').css('top'));
$('html').removeClass('noscroll'); // Allow scrolling again
$('html,body').scrollTop(-scrollTop);
$('#wizard_dialog').html('');
}
});
EDIT:
Because the problem could be in the dialog I added some code.
In the first code block I changed deleteOrder();
ANSWER
The solution was rather simple. I forgot to turn the click handler off before I added the new one. This returned the previous event and the new event.
$(document).off('click', '[id^=delete_]').on('click', '[id^=delete_]', function() {
// Get the orderId from the delete button
var orderId = $(this).attr('id').split('_');
orderId = orderId['1'];
// I call the delete function
deleteOrder(orderId, data);
});

Safe getElementById or try to determine if ID exists in GUI

Method UiInstance.getElementById(ID) always returns GenericWidget object, even if ID does not exist.
Is there some way how to find out that returned object does not exist in my app, or check whether UI contains object with given ID?
Solution for UI created with GUI builder:
function getSafeElement(app, txtID) {
var elem = app.getElementById(txtID);
var bExists = elem != null && Object.keys(elem).length < 100;
return bExists ? elem : null;
}
It returns null if ID does not exist. I didn't test all widgets for keys length boundary, so be careful and test it with your GUI.
EDIT: This solution works only within doGet() function. It does not work in server handlers, so in this case use it in combination with #corey-g answer.
This will only work in the same execution that you created the widget in, and not in a subsequent event handler where you retrieve the widget, because in that case everything is a GenericWidget whether or not it exists.
You can see for yourself that the solution fails:
function doGet() {
var app = UiApp.createApplication();
app.add(app.createButton().setId("control").addClickHandler(
app.createServerHandler("clicked")));
app.add(app.createLabel(exists(app)));
return app;
}
function clicked() {
var app = UiApp.getActiveApplication();
app.add(app.createLabel(exists(app)));
return app;
}
function exists(app) {
var control = app.getElementById("control");
return control != null && Object.keys(control).length < 100;
}
The app will first print 'true', but on the click handler it will print 'false' for the same widget.
This is by design; a GenericWidget is a "pointer" of sorts to a widget in the browser. We don't keep track of what widgets you have created, to reduce data transfer and latency between the browser and your script (otherwise we'd have to send up a long list of what widgets exist on every event handler). You are supposed to keep track of what you've created and only "ask" for widgets that you already know exist (and that you already know the "real" type of).
If you really want to keep track of what widgets exist, you have two main options. The first is to log entries into ScriptDb as you create widgets, and then look them up afterwards. Something like this:
function doGet() {
var app = UiApp.createApplication();
var db = ScriptDb.getMyDb();
// You'd need to clear out old entries here... ignoring that for now
app.add(app.createButton().setId('foo')
.addClickHandler(app.createServerHandler("clicked")));
db.save({id: 'foo', type: 'button'});
app.add(app.createButton().setId('bar'));
db.save({id: 'bar', type: 'button'});
return app
}
Then in a handler you can look up what's there:
function clicked() {
var db = ScriptDb.getMyDb();
var widgets = db.query({}); // all widgets
var button = db.query({type: 'button'}); // all buttons
var foo = db.query({id: 'foo'}); // widget with id foo
}
Alternatively, you can do this purely in UiApp by making use of tags
function doGet() {
var app = UiApp.createApplication();
var root = app.createFlowPanel(); // need a root panel
// tag just needs to exist; value is irrelevant.
var button1 = app.createButton().setId('button1').setTag("");
var button2 = app.createButton().setId('button2').setTag("");
// Add root as a callback element to any server handler
// that needs to know if widgets exist
button1.addClickHandler(app.createServerHandler("clicked")
.addCallbackElement(root));
root.add(button1).add(button2);
app.add(root);
return app;
}
function clicked(e) {
throw "\n" +
"button1 " + (e.parameter["button1_tag"] === "") + "\n" +
"button2 " + (e.parameter["button2_tag"] === "") + "\n" +
"button3 " + (e.parameter["button3_tag"] === "");
}
This will throw:
button1 true
button2 true
button3 false
because buttons 1 and 2 exist but 3 doesn't. You can get fancier by storing the type in the tag, but this suffices to check for widget existence. It works because all children of the root get added as callback elements, and the tags for all callback elements are sent up with the handler. Note that this is as expensive as it sounds and for an app with a huge amount of widgets could potentially impact performance, although it's probably ok in many cases especially if you only add the root as a callback element to handlers that actually need to verify the existence of arbitrary widgets.
My initial solution is wrong, because it returns false exist controls.
A solution, based on Corey's answer, is to add the setTag("") method and here is ready to use code. It is suitable for event handlers only, because uses tags.
function doGet() {
var app = UiApp.createApplication();
var btn01 = app.createButton("control01").setId("control01").setTag("");
var btn02 = app.createButton("control02").setId("control02").setTag("");
var handler = app.createServerHandler("clicked");
handler.addCallbackElement(btn01);
handler.addCallbackElement(btn02);
btn01.addClickHandler(handler);
btn02.addClickHandler(handler);
app.add(btn01);
app.add(btn02);
return app;
}
function clicked(e) {
var app = UiApp.getActiveApplication();
app.add(app.createLabel("control01 - " + controlExists(e, "control01")));
app.add(app.createLabel("control02 - " + controlExists(e, "control02")));
app.add(app.createLabel("fake - " + controlExists(e, "fake")));
return app;
}
function controlExists(e, controlName) {
return e.parameter[controlName + "_tag"] != null;
}