I have an implementation of jqgrid with a method that checks for duplicates cell entries. This method is part of a custom validation method defined in editrules. It appears to work ok, but once I delete rows from the grid, the $grid.jqGrid('getGridParam', '_index'); seems to be getting messed up. I'm doing local deletes I scavenged as follows:
delSettings = {
onclickSubmit: function (options) {
var gridId = $.jgrid.jqID($grid[0].id),
gridP = $grid[0].p,
newPage = gridP.page,
rowids = gridP.multiselect ? gridP.selarrrow : [gridP.selrow],
reloadLastPage = false;
options.processing = true; // - reset the value of processing option which could be modified
$.each(rowids, function () { // - delete selected rows
$grid.delRowData(this);
});
This is the pertinent method, the idea is to check for rows with a duplicate entry, skipping the row being edited (selectedRowId).
function IsIDImagePathUnique(imagePath) {
var status = true,
$grid = $('#list'),
selectedRowId = $grid.jqGrid('getGridParam', 'selrow'),
gridData = $grid.jqGrid('getGridParam', 'data'),
idsToDataIndexes = $grid.jqGrid('getGridParam', '_index');
$.each(idsToDataIndexes, function (id, index) {
if (_editType === 'edit' && id === selectedRowId) // - skip edited row
return true;
if( gridData[index].IDImage === imagePath ) {
status = false;
return false; // - break
}
});
return status;
}
Help or comments appreciated.
UPDATED:
I still need to figure out what my issue was, but I came up with a workaround to avoid using the $grid.jqGrid('getGridParam', '_index'); :
function IsIDImagePathUnique(imagePath) {
var status = true,
$grid = $('#list'),
gridData = $grid.jqGrid('getGridParam', 'data'),
allowed = _editType ? 1 : 0,
counter = 0;
for (var i = 0; i < gridData.length; i++) {
if (gridData[i].IDImage === imagePath && ++counter > allowed) {
status = false;
break;
}
}
return status;
}
Related
I want to validate a row on click of Save. This question is already discussed with the following solution. I see that rows are invalid and the failures array has the invalid entries but cells are not highlighted.
Following is the my code:
function save(){
grid.validate();
}
//Validate only on Save
grid.validate = function() {
var rowFailures = {}
for (r in data) {
if(r == 'getItemMetadata'){continue;}
var failures = validateColumns({item: data[r], row: r})
if(failures.length > 0){
rowFailures[r] = failures;
}
}
if(Object.keys(rowFailures).length > 0){
grid.onValidationError.notify({"rowFailures": rowFailures}, new Slick.EventData())
}
}
//Validation Error invoked
grid.onValidationError.subscribe(function(e, args) {
console.log("Validation error");
if(args.rowFailures){
var rowsIndexValues = Object.keys(args.rowFailures);
for(i in rowsIndexValues) {
var rowFailures = args.rowFailures[rowsIndexValues[i]]
for(j in rowFailures){
var failure = rowFailures[j];
//scroll first failure into view
if(0 == i){grid.scrollRowIntoView(failure.rowIndex)}
grid.flashCell(failure.rowIndex, failure.columnIndex, 500);//Makes no difference!
}
}
}
});
//Changes the background color for the failed cells
data.getItemMetadata = function(row) {
var failures = validateColumns({row: row, item: data[row]})
if(failures.length > 0){
var obj = {};
var metadata = {"columns": obj}
//Its iterating through these failures
for(f in failures){
//Changes the background color of the cell
obj[failures[f].column.id] = {"formatter": function(row, cell, value, m, item){return '<div style="background: #FFCCCC" title="This field is //invalid">'+failures[f].item[failures[f].column.field]+'</div>'}}
}
return metadata;
}
return {}
}
I was able to achieve this using the following code
dataView.getItemMetadata = metadata(dataView.getItemMetadata);
function metadata(old_metadata_provider) {
return function (row) {
var item = this.getItem(row);
var ret = (old_metadata_provider(row) || {});
if (item) {
ret.cssClasses = (ret.cssClasses || '');
var failures = //check for some condition
if(failures.length > 0){
return {
cssClasses: 'validationError'
};
}
}
}
I have a select2 to select multiple options from a dropdown, i also have it selecting multiple options. Is there anyway of populating the input field with values that are selected on page load by changing its value in some way, so when the page is loaded there are options already selected.
part of my code as follows:
$('#fruitSelect').select2({
multiple: true,
placeholder: "Select fruits...",
data: FRUIT_GROUPS,
query: function (options) {
var selectedIds = options.element.select2('val');
var data = jQuery.extend(true, {}, FRUIT_GROUPS);
var selectableGroups = $.map(data, function (group) {
var areAllChildrenSelected = true,
parentMatchTerm = false,
anyChildMatchTerm = false;
if (group.text.toLowerCase().indexOf(options.term.toLowerCase()) >= 0) {
parentMatchTerm = true;
}
var i = group.children.length
while (i--) {
var child = group.children[i];
if (selectedIds.indexOf(child.id) < 0) {
areAllChildrenSelected = false;
};
if (options.term == '' || (child.text.toLowerCase().indexOf(options.term.toLowerCase()) >= 0)) {
anyChildMatchTerm = true;
}
else if (!parentMatchTerm) {
var index = group.children.indexOf(child);
if (index > -1) {
group.children.splice(index, 1);
};
};
};
return (!areAllChildrenSelected && (parentMatchTerm || anyChildMatchTerm)) ? group : null;
});
options.callback({ results: selectableGroups });
}
}).on('select2-selecting', function (e) {
var $select = $(this);
if (e.val == '') {
e.preventDefault();
$select.select2('data', $select.select2('data').concat(e.choice.children));
$select.select2('close');
}
});
JS Fiddle
i have a jsp page and call a JS function which is in some abc.js file from this JSP page.
i have included this js file to jsp page.
JSP JavaScript Code:-
function doFinish(tableId, col, field)
{
var oldselectedCells = "";
var selItemHandle = "";
var selRightItemHandle = "";
var left = -1;
var right = -1;
// Get the table (tBody) section
var tBody = document.getElementById(tableId);
// get field in which selected columns are stored
var selectedCellsFld = document.getElementById(tableId + datatableSelectedCells);
selectedCellsFld.value = oldselectedCells;
for (var r = 0; r < tBody.rows.length; r++)
{
var row = tBody.rows[r];
if (row.cells[col].childNodes[0].checked == true)
{
selectedCellsFld.value = oldselectedCells +
row.cells[col].childNodes[0].id;
selItemHandle = row.cells[col].childNodes[0].value
oldselectedCells = selectedCellsFld.value + datatableOnLoadDivider;
left = selItemHandle.indexOf("=");
right = selItemHandle.length;
selRightItemHandle = selItemHandle.substring(left+1,right);
var index=getColumnIndex(tBody,"Name");
if(index!=null)
{
if(field == 1)
{
window.opener.document.TemplateForm.eds_asbactionscfg_item_handle_child_physpart.value = selRightItemHandle;
window.opener.document.TemplateForm.ChildPhysicalPart.value = row.cells[index].childNodes[0].innerHTML;
}
else if (field == 2)
{
window.opener.document.TemplateForm.eds_asbactionscfg_dev_doc_item_handle_name.value = selRightItemHandle;
window.opener.document.TemplateForm.DeviationObject.value = row.cells[index].childNodes[0].innerHTML;
}
else if (field == 3)
{
window.opener.document.TemplateForm.eds_asbactionscfg_dev_doc_item_handle_name.value = selRightItemHandle;
window.opener.document.TemplateForm.DeviationObject.value = row.cells[index].childNodes[0].innerHTML;
}
}
}
}
window.close();
}
JS Code:-
function getColumnIndex(tBody,columnName)
{
var cells = tBody.parentNode.getElementsByTagName('th');
for (var i=0;i<cells.length; i++)
{
if(cells[i].hasChildNodes())
{
if(cells[i].childNodes[0].innerHTML.replace(/(\r\n|\n|\r)/gm ,"").trim() == columnName)
{
return i;
}
}
}
}
i had debug this code with firebug & calling getColumnIndex(tBody,columnName) function works fine but when it return to caller the var index=getColumnIndex(tBody,"Name"); the index value is "undefine".
suggest some solution.
getColumnIndex(tBody,columnName) function works fine.
as if it matches this if condition
if(cells[i].childNodes[0].innerHTML.replace(/(\r\n|\n|\r)/gm ,"").trim() == columnName)
{
return i;
}
so that it returns something.
but when you replace this
var index=getColumnIndex(tBody,"Name"); so that coulmnName would be "Name" in String.
And it doesn't match with any columnName so that your condition going to be wrong and function doesn't return anything.
var index=getColumnIndex(tBody,"Name"); the index value is "undefine".
suggestion is put some else condition on that and return some error message like this :
if(cells[i].childNodes[0].innerHTML.replace(/(\r\n|\n|\r)/gm ,"").trim() == columnName)
{
return i;
} else{
// put some error message
// return null
}
i had debug this code with firebug & calling getColumnIndex(tBody,columnName) function works fine
From this, I'm assuming that there isn't anything wrong with the implementation of your getColumnIndex function, so your issue with getting an undefined value must have to do with when this function is returning a value.
but when it return to caller the var index=getColumnIndex(tBody,"Name"); the index value is "undefine".
This leads me to assume that your tBody variable is not being set correctly, given that the "function works fine".
I'm assuming there is a case in your code where the conditions of your getColumnIndex function is not met.
function getColumnIndex(tBody,columnName)
{
var cells = tBody.parentNode.getElementsByTagName('th');
for (var i=0;i<cells.length; i++)
{
if(cells[i].hasChildNodes())
{
if(cells[i].childNodes[0].innerHTML.replace(/(\r\n|\n|\r)/gm ,"").trim() == columnName)
{
return i;
}
}
}
// If your code reaches this point, then the prior conditions have not been met
// You can choose to do something else here for return false/undefined etc.
return undefined;
}
I needed some help with datatables. I might be missing something here:-
Below is my HTML
<div id="cfcPhoneDirectory">
<table id="dynamicPhoneDirectory">
<thead>
<tr><th>Phone Book</th><th>Last Name</th><th>First Name</th><th>Number</th></tr>
</thead>
</table>
And the Script
var rawxmlData = "<PhoneBooks><PhoneBook><name>PhoneBook1</name><type>GLOBAL</type><Contacts><Contact><LNAME>Elis</LNAME><FNAME>Jason</FNAME><Number>1234567890</Number></Contact><Contact><LNAME>Randell</LNAME><FNAME>Mark</FNAME><Number>7895896710</Number></Contact><Contact><LNAME>Flower</LNAME><FNAME>Andy</FNAME><Number>8796024589</Number></Contact></Contacts></PhoneBook><PhoneBook><name>PhoneBook2</name><type>TEAM</type><Contacts><Contact><LNAME>Cullinan</LNAME><FNAME>David</FNAME><Number>6027051573</Number></Contact><Contact><LNAME>Webber</LNAME><FNAME>Mark</FNAME><Number>4842051298</Number></Contact><Contact><LNAME>Mitchell</LNAME><FNAME>Randy</FNAME><Number>7012841562</Number></Contact></Contacts></PhoneBook></PhoneBooks>";
var t = $('#dynamicPhoneDirectory').DataTable();
var xmlData = JSON.stringify(xmlToJson(rawxmlData));
($(xmlData)).find("PhoneBook").each(function ()
{
var phoneBookType = $(this).find("type").text()
$(this).find("Contact").each(function () { t.row.add([phoneBookType, $(this).find("LNAME").text(), $(this).find("FNAME").text(), $(this).find("Number").text()]).draw();
});
});
// Changes XML to JSON
function xmlToJson(xml) {
// Create the return object
var obj = {};
if (xml.nodeType == 1) { // element
// do attributes
if (xml.attributes.length > 0) {
obj["#attributes"] = {};
for (var j = 0; j < xml.attributes.length; j++) {
var attribute = xml.attributes.item(j);
obj["#attributes"][attribute.nodeName] = attribute.nodeValue;
}
}
} else if (xml.nodeType == 3) { // text
obj = xml.nodeValue;
}
// do children
if (xml.hasChildNodes()) {
for(var i = 0; i < xml.childNodes.length; i++) {
var item = xml.childNodes.item(i);
var nodeName = item.nodeName;
if (typeof(obj[nodeName]) == "undefined") {
obj[nodeName] = xmlToJson(item);
} else {
if (typeof(obj[nodeName].push) == "undefined") {
var old = obj[nodeName];
obj[nodeName] = [];
obj[nodeName].push(old);
}
obj[nodeName].push(xmlToJson(item));
}
}
}
return obj;
};
I am using Jquery version of 1.4.4 and datatable version of 1.7.5?
Any help would be appreciated.
Thanks,
Hash
I gave up debugging the XML parsing - too cryptic. There is no need for porting the XML to JSON at all. So made this up instead :
var table = $('#dynamicPhoneDirectory').dataTable();
var parser = new DOMParser(),
xmlDoc = parser.parseFromString(rawxmlData,"text/xml"),
phoneBook = xmlDoc.querySelector('PhoneBooks'),
phoneBooks = phoneBook.querySelectorAll('PhoneBook');
for (var i=0;i<phoneBooks.length;i++) {
var firstname, lastname, number, contacts,
phoneBookName = phoneBooks[i].querySelector('name').textContent,
phoneBookContacts = phoneBooks[i].querySelector('Contacts'),
contacts = phoneBookContacts.querySelectorAll('Contact');
for (var c=0;c<contacts.length;c++) {
lastName = contacts[c].querySelector('LNAME').textContent;
firstName = contacts[c].querySelector('FNAME').textContent;
number = contacts[c].querySelector('Number').textContent;
//add the contact to dataTables
table.fnAddData([phoneBookName, lastName, firstName, number]);
}
}
this works with datatables 1.7.5 -> http://jsfiddle.net/nsmqg4n2/
the used jQuery is 1.6.4, the lowest possible in jsFiddle, but that does not really inflict on the above code after all. jQuery dataTables 1.7.5 just need jQuery 1.3.x or better.
To retrieve data (for example when the table is clicked) use the API method fnGetData(), example (jQuery 1.6.4, dataTables 1.7.5) :
$("#dynamicPhoneDirectory").delegate('tbody tr', 'click', function() {
var data = table.fnGetData(this);
alert('Number to dial : '+data[3]);
});
forked fiddle -> http://jsfiddle.net/bu87ke7a/
Upgrading my code to use JQuery 1.9.1 and Datatable1.10.7 resolved the issue.
When i click the search button it always alert me "TypeError: this.Rows is undefined
for (var i = 0, row; row = this.Rows[i], rowText = this.RowsText[i]; i++) { "
Here is my code:
<script language="javascript" type="text/javascript">
//define the table search as an object, which can implement both functions and properties
window.tableSearch = {};
//initialize the search, setup the current object
tableSearch.init = function() {
//define the properties I want on the tableSearch object
this.Rows = document.getElementById('data').getElementsByTagName('TR');
this.RowsLength = tableSearch.Rows.length;
this.RowsText = [];
//loop through the table and add the data to
for (var i = 0; i < tableSearch.RowsLength; i++) {
this.RowsText[i] = (tableSearch.Rows[i].innerText) ? tableSearch.Rows[i].innerText.toUpperCase() : tableSearch.Rows[i].textContent.toUpperCase();
}
}
//onlys shows the relevant rows as determined by the search string
tableSearch.runSearch = function() {
//get the search term
this.Term = document.getElementById('textBoxSearch').value.toUpperCase();
//loop through the rows and hide rows that do not match the search query
for (var i = 0, row; row = this.Rows[i], rowText = this.RowsText[i]; i++) {
row.style.display = ((rowText.indexOf(this.Term) != -1) || this.Term === '') ? '' : 'none';
}
}
//runs the search
tableSearch.search = function(e) {
//checks if the user pressed the enter key, and if they did then run the search
var keycode;
if (window.event) { keycode = window.event.keyCode; }
else if (e) { keycode = e.which; }
else { return false; }
if (keycode == 13) {
tableSearch.runSearch();
}
else { return false; }
}
</script>
The two most probable causes to that problem are:
You never called your init function. Make sure to call it after your HTML has loaded and before using Rows the first time.
There is a Firefox bug where getElementsByTagName('TR'); returns undefined. make sure that that is not your problem.