Get the Id of an jqGrid row where a checkbox is clicked - javascript

I am using jqGrid and I added a column of checkboxes to the grid but I want to alert which checkbox is checked .. here is my code
dataGrid.prototype = {
display: function () {
var self = this;
var html = [];
var check = 0;
html.push("<table id='" + this.id + "" + "'class='table'>\n</table>");
html.push("<div id='pagger_" + this.id + "'></div>");
$('body').append(html.join(""));
$("#" + this.id).jqGrid({
url: "index.jsp",
styleUI: 'Bootstrap',
datatype: "local",
data: this.data,
colModel: this.getColModels(this.data[0]),
onSelectRow: this.editRow,
viewrecords: true,
width: 1300,
height: 250,
rowNum: 50,
pager: "#pagger_" + this.id,
loadComplete: function () {
var iCol = self.getColumnIndexByName('Enable');
var rows = $("#" + this.id).jqGrid('getGridParam', 'data');
var i;
var c = rows.length;
for (i = 0; i < c; i += 1) {
$(rows[i].cells[iCol]).click(
function (e) {
var id = $(e.target).closest('tr')[0].id, isChecked = $(e.target).is(':checked');
alert("checked:" + isChecked);
// you can also get the
// values of the row
// data
alert('clicked on the checkbox in the row with id=' + id + '\nNow the checkbox is ' + (isChecked ? 'checked' : 'not checked'));
});
}
}
});
},
getColNames: function (data) {
var keys = [];
for (var key in data) {
if (data.hasOwnProperty(key)) {
keys.push(key);
}
}
return keys;
},
getColModels: function (data) {
var colNames = this.getColNames(data);
var colModelsArray = [];
var str2;
for (var i = 0; i < colNames.length; i++) {
var str1;
str1 = {
name: colNames[i],
index: colNames[i],
align: 'center',
editable: true,
edittype: "text",
};
colModelsArray.push(str1);
}
str2 = {
name: 'Enable',
index: 'Enable',
formatter: 'checkbox',
editable: true,
edittype: 'checkbox',
width: 60,
align: 'center',
formatoptions: {
disabled: false
},
editoptions: {
value: '1:0'
},
};
colModelsArray.push(str2);
return colModelsArray;
},
getColumnIndexByName: function (columnName) {
var cm = $("#" + this.id).jqGrid('getGridParam', 'colModel'), i, l;
for (i = 0, l = cm.length; i < l; i += 1) {
if (cm[i].name === columnName) {
return i;
}
}
return -1;
},
};
hint ..
the data is json object
whenever i print rows[i] it gives me [object object]
Whats wrong here?

You can trust delegation instead of adding a handler to every checkbox. Let's assume you put an ID to the container, like #containerDataGrid:
$("#containerDataGrid").on("click", "input[type=checkbox]", function(e){
var $this = $(this); //this is the checkbox
//this is more reliable than e.target,
// because it DOES point to the input not some child it could have
var $row = $this.closest("tr"); //in case the rows are tr. If not, change by the class or parameter identifying a row
var id = $row.attr("id"); //here's the ID you want! :D
console.log("The checkbox in the row: ",$row, " which has id= ", id, " is " $this.is(":checked")?"checked":"not checked");
});
If you only wanted to get some particular checkbox, you can make the "input[type=checkbox]"selector more specific, adding a class for instance:
"input[type=checkbox].the-checkbox-I-want"
or making sure it's the child of a wrapper:
".wrapper-of-my-beloved-checkbox > input[type=checkbox]"

Related

On typeahead selected event function is calling many times when it should one only

I have below function using typeahead.js and it binds on the input field.
The problem is I am trying to pass custom function when user will select value from dropdown.
So for the first time it send right values ( one time ) only. For the next selection it sends the same value twice. When selecting new from dropdown then it randomly send 4 times.
On selection from dropdown it should pass variables only once.
$(document).on('mouseenter', '.js-ma-product-autocomplete', function (e) {
var current_handler = $(this).attr('id');
$('#' + current_handler).typeahead("destroy");
var current_selected_id = $(this).siblings('.js-ma-linked-product-id').attr('id');
var current_selected_type = $(this).siblings('.js-ma-linked-product-type').val();
var current_selected_container = $(this).siblings('.js-ma-linked-product-container').val();
var current_selected_btn = $(this).siblings('.js-ma-linked-product-add-btn').val();
var initialize_master_agent_products_typeahead;
initialize_master_agent_products_typeahead = function () {
var master_agent_products_typeahead;
master_agent_products_typeahead = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace("name"),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: "/productions/mas_products_autocomplete?query=%QUERY",
replace: function (url, uriEncodedQuery) {
return url.replace("%QUERY", uriEncodedQuery) + '&product_type=' + encodeURIComponent(current_selected_type)
},
filter: function (list) {
if (list.length == 0) {
$('#' + current_selected_id).val('');
}
return list;
}
}
});
master_agent_products_typeahead.initialize();
$('#' + current_handler).typeahead(null, {
displayKey: "name",
source: master_agent_products_typeahead.ttAdapter(),
templates: {empty: "<div> No matching products found </div>"}
});
$('#' + current_handler).one('typeahead:selected', function (event, datum, name) {
var count = 1;
$('#' + current_selected_id).val(datum.id);
show_options(current_selected_type);
create_fields(current_selected_id, current_selected_type, current_selected_container, current_selected_btn, datum.id, datum.name, count++); // from this part its calling more than once.
});
};
initialize_master_agent_products_typeahead();
});
function create_fields(c_p_id, c_p_type, c_p_container, c_p_btn, l_p_id, l_p_name, count){
// var minNumber = 300;
// var maxNumber = 400;
// var randomNumber = randomNumberFromRange(minNumber, maxNumber);
// debugger;
console.log(c_p_id);
console.log(c_p_type);
console.log(c_p_container);
console.log(c_p_btn);
console.log(l_p_id);
console.log(l_p_name);
console.log(count);
console.log('*****************');
//here it sends values multiple times
}
See below I typed once only and it shows as:
After going back and forth with different options I came to the point that I am initializing typeahead again on each mouseenter.
So, a fix would be to call it only once per field not all the time. And using one on it will make it work like a charm.
Here is final working code:
$('.js-ma-product-autocomplete').one('mouseenter', function (e) {
var current_handler = $(this).attr('id');
console.log(current_handler);
$('#' + current_handler).typeahead("destroy");
var c_p_id = $(this).siblings('.js-ma-product-id').val();
// var c_lp_id = $(this).siblings('.js-ma-linked-product-id').attr('id');
var c_p_type = $(this).siblings('.js-ma-linked-product-type').val();
var c_container = $(this).siblings('.js-ma-linked-product-container').val();
var c_btn = $(this).siblings('.js-ma-linked-product-add-btn').val();
var initialize_master_agent_products_typeahead;
initialize_master_agent_products_typeahead = function () {
var master_agent_products_typeahead;
master_agent_products_typeahead = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace("name"),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: "/productions/mas_products_autocomplete?query=%QUERY",
replace: function (url, uriEncodedQuery) {
return url.replace("%QUERY", uriEncodedQuery) + '&product_type=' + encodeURIComponent(c_p_type)
},
filter: function (list) {
if (list.length == 0) {
//$('#' + c_lp_id).val('');
}
return list;
}
}
});
master_agent_products_typeahead.initialize();
$('#' + current_handler).typeahead(null, {
displayKey: "name",
source: master_agent_products_typeahead.ttAdapter(),
templates: {empty: "<div> No matching products found </div>"}
});
$('#' + current_handler).on('typeahead:selected', function (event, datum, name) {
// $('#' + c_lp_id).val(datum.id);
show_options(c_p_type);
create_fields(c_p_id, c_p_type, c_container, c_btn, datum.id, datum.name);
});
};
initialize_master_agent_products_typeahead();
});
function show_options(type) {
if (type == 'compatible') {
$('#subsidize_rent_lease_options').removeClass('hide');
}
}
function create_fields(c_p_id, c_p_type, c_p_container, c_btn, c_lp_id, c_lp_name){
var randomNumber = randomNumberFromRange(300, 400);
console.log(c_p_id);
console.log(c_p_type);
console.log(c_p_container);
console.log(c_btn);
console.log(c_lp_id);
console.log(c_lp_name);
$("#" + c_btn).removeAttr('disabled', false);
var item_container = $('<div/>', {'class': "div_" + randomNumber});
$('<input>').attr({
type: 'hidden',
name: "product[linked_products_attributes]["+randomNumber+"][product_id]",
value: c_p_id
}).appendTo(item_container);
$('<input>').attr({
type: 'hidden',
name: "product[linked_products_attributes]["+randomNumber+"][linked_product_id]",
value: c_lp_id
}).appendTo(item_container);
$('<input>').attr({
type: 'hidden',
name: "product[linked_products_attributes]["+randomNumber+"][link_type]",
value: c_p_type
}).appendTo(item_container);
$('<input>').attr({
type: 'hidden',
name: "product[linked_products_attributes]["+randomNumber+"][name]",
value: c_lp_name
}).appendTo(item_container);
$("#" + c_p_container).append(item_container);
}
function randomNumberFromRange(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}

How to remain a checkbox "checked" in dataTables after move rows up and down

I have a dataTable that each row in it has a checkbox and up or down buttons to move rows. But if I check a checkbox and then move the row, checkbox change to unchecked state.
How can I prevent this event and hold the checkbox checked?
{ name: 'name',
data: 'name',
title: 'Name',
searchable: true,
sortable: false,
render: function (data, type, full, meta) {
if (type === 'display') {
var $span = $('<span></span>');
$('<input type="checkbox">').appendTo($span);
return $span.html();
}
return data;
}
},
here is my code : jsFiddle
You can save the states in variable and after drawing table can check and update the state of checkboxes
Fiddle https://jsfiddle.net/jdvusytn/1/
function moveRow(row, direction) {
var index = table.row(row).index();
var order = -1;
if (direction === 'down') {
order = 1;
}
var data1 = table.row(index).data();
data1.order += order;
var data1Checked = $(table.row(index).node()).find('input[type=checkbox]').prop('checked');
var data2 = table.row(index + order).data();
data2.order += -order;
var data2Checked = $(table.row(index + order).node()).find('input[type=checkbox]').prop('checked');
table.row(index).data(data2);
table.row(index + order).data(data1);
table.page(0).draw(false);
$(table.row(index + order).node()).find('input[type=checkbox]').prop('checked', data1Checked);
$(table.row(index).node()).find('input[type=checkbox]').prop('checked', data2Checked)
}

Calling ASMX webservice from JQuery Autocomplete

I'm currently trying to get the response from an asmx service and use it in an autocomplete textbox
Here the code i'm currently using:
$(function () {
$("#<%=txtParentCat.ClientID %>").autocomplete({
selectFirst: true,
source: Magelia.WebStore.Admin.Scripts.Services.AutoCompleteServices.GetCategoriesFull,
extraParams: { contains: $('#<%=txtParentCat.ClientID %>').val(), storeId: '<%=this.Page.UnitOfWorkContext.StoreId.ToString() %>' },
minLength: 0,
delay: 0,
autoFocus: true,
dataType: 'json',
parse: function (data) {
var rows = new Array();
for (var i = 0; i < data.length; i++) {
rows[i] = { data: data[i], value: data[i], result: data[i] };
}
return rows;
},
formatItem: function (row) {
return row;
},
autofill: true,
highlight: false,
multiple: true,
multipleSeparator: ";"
,
response: function (event1, ui) {
var input = $('#<%=txtParentCat.ClientID %>');
input.on('keydown', function (event) {
var key = event.keyCode || event.charCode;
if (key == 8 || key == 46)
select = false;
else
select = true;
});
if (select == true && ui.content.length > 0) {
var $userVal = this.value;
var $newVal = ui.content[0].value;
if ($userVal != "") {
var n = $newVal.toLowerCase().indexOf($userVal.toLowerCase());
if (n == 0)
n = n + $userVal.length;
if (n != -1) {
$("#<%=txtParentCat.ClientID %>").val($newVal);
setSelectionRange($("#<%=txtParentCat.ClientID %>").get(0), n, $newVal.length);
}
}
}
}
});
});
I keep getting a 500 internal error which i think must be because i'm sending the parameters needed to call the webservice the wrong way.
Here the parameters required to call the service:
Magelia.WebStore.Admin.Scripts.Services.AutoCompleteServices.GetCategoriesFull(contains,storeId,onSuccess,onFailed,userContext)
Any help is much appreciated. Thank you in advance :)

Filter DOM elements via JavaScript

I have elements that get created like this:
function appendCalendarEventToList(className, event) {
var eventObject = {
title: event.title,
id: event.id,
type: event.type,
color: event.color,
description: event.description,
canReoccur: event.canReoccur,
reoccurVal: event.reoccurVal,
estHours: event.estHours,
project: event.project
};
var div = document.createElement("div");
div.className = 'external-event';
div.style.background = event.color;
div.innerHTML = event.title;
// store the Event Object in the DOM element so we can get to it later
$(div).data('eventObject', eventObject);
$(div).draggable({
helper: function () {
$copy = $(this).clone();
$copy.data('eventObject', eventObject);
$copy.css({ "list-style": "none", "width": $(this).outerWidth() }); return $copy;
},
appendTo: 'body',
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0 // original position after the drag
});
$(className).append(div);
$(div).qtip({
content: event.title,
position:
{
target: 'mouse'
},
// show: { event: 'click' },
hide: { event: 'mousedown mouseleave' },
style: {
classes: 'custSideTip',
width: 200,
padding: 5,
color: 'black',
textAlign: 'left',
border: {
width: 1,
radius: 3
}
}
});
return div;
}
Every event has a project attribute as you see.
However there are projects and tasks (and cases that can be ignored):
function refetchUnscheduled() {
$.ajax({
type: "POST",
url: "CalendarServices.aspx/GetUnscheduled",
data: '',
async:false,
success: function (data) {
var projects = '.project-container';
var tasks = '.task-container';
var cases = '.case-container';
$(projects).html('');
$(tasks).html('');
$(cases).html('');
var numProjects = 0;
var numTasks = 0;
var numCases = 0;
$.each(data, function () {
var className = '';
var url = '';
var typeName = '';
var crm = this.crm;
switch(this.type)
{
case 'p':
className = projects;
url = 'ProjectViewFrame.aspx?id=' + this.id;
typeName = 'Project';
numProjects++;
break;
case 't':
className = tasks;
url = 'TaskViewFrame.aspx?id=' + this.id;
typeName = 'Task';
numTasks++;
break;
case 'c':
className = cases;
url = 'CaseViewFrame.aspx?id=' + this.id;
typeName = 'Case';
numCases++;
break;
default:
}
var curDiv = appendCalendarEventToList(className, this);
var curEvent = this;
$(curDiv).bind('contextmenu', function (e) {
$('#contextMenuContainer').html('');
var btn1 = createLink('Edit ' + typeName, 'context-elem-name');
$('#contextMenuContainer').append(btn1);
$(btn1).on('click', function () {
if (crm == '')
showCalendarModal('Edit ' + typeName, url);
else
showCRM(crm);
})
prepContextMenu(e);
return false;
});
});
changeUnscheduledHeaders();
}
,
error: function () {
}
});
}
Here is what I need that I am unsure how to do:
I need an OR based filter:
Given the following:
function filter(criteria,projects-div,tasks-div)
{
var words = criteria.split(' ');
}
I need to first, hide all projects whos
obj.data('eventObject').title contains one or more words.
Then, once these are filtered:
I need to first show all tasks whos project is visible,
So:
obj.data('eventObject').project is == to one of the visible project's project property.
Then, I need to also show any tasks that have any of the words.
All comparing must be case insensitive too.
So say my criteria is 'hello world'
I show all projects with hello or world in the title.
I show all tasks whos project attribute is visible after the first step
I show all tasks whos title has hello or world
Thanks
I'm on mobile, but at first glance, what about [].filter.call (NodeList, filterFn)?

JQuery AutoComplete Append to Open List

I tested the JQuery autocomplete UI widget and noticed that the autocomplete has extremely poor performance in IE when dealing with large amount of data. My client uses internet explorer 7.
I found a solution to mitigate the performance issue. Instead of returning all the matches of the autocomplete search I only return the first 40 matches. Code below
source: function (request, response) {
var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term), "i");
var select_el = select.get(0); // get dom element
var rep = new Array(); // response array
var maxRepSize = 40; // maximum response size
// simple loop for the options
var looper = 0;
for (var i = 0; i < select_el.length; i++) {
var text = select_el.options[i].text;
if (!request || request == '') {
// add element to result array
rep[looper++] = {
label: text,
value: text,
option: select_el.options[i]
};
}
else if ( select_el.options[i].value && matcher.test(text) ) {
// add element to result array
rep[looper++] = {
label: text,
value: text,
option: select_el.options[i]
};
}
if ( rep.length > maxRepSize ) {
needMoreItems = true;
break;
}
}
// send response
response( rep );
},
The client asked me to append a "More Results" item to the autocomplete list. If there were more than 40 items that matched the search the "More Results" item would appear of at the bottom of the list. If a user clicked on the "More Results" item, the autocomplete drop down would expand to include the next 40 matches. I experimented with the jQuery autocomplete and I was able to populate the auto suggest list with the next 40 items but when the user clicked on one of the dynamically added items, I could not bind the click event to the Select Event of the autocomplete UI widget. Code below:
open: function( event, ui ) {
if (needMoreItems) {
needMoreItems = false;
$('<li class="ui-menu-item" role="menuitem" id="yoADDMORE" ><a class="ui-corner-all" tabindex="-1">... more available<br/><br/></a></li>')
.bind({
click: function(e) {
var appendHtml = '';
var select_el = select.get(0);
var maxRepSize = 40; // maximum response size
// simple loop for the options
var looper = 0;
for (var i = 41; i < select_el.length; i++) {
appendHtml += '<li class="ui-menu-item" role="menuitem"><a class="ui-corner-all" tabindex="-1">' + select_el.options[i].text + '</a></li>';
if ( looper ++ > maxRepSize ) {
needMoreItems = true;
break;
}
}
if (needMoreItems)
appendHtml += '<li class="ui-menu-item" role="menuitem" id="yoADDMORE" ><a class="ui-corner-all" tabindex="-1">... more available<br/><br/></a></li>';
$('#yoADDMORE').remove();
$('ul.ui-autocomplete').html($('ul.ui-autocomplete').html() + appendHtml);
$('ul.ui-autocomplete > li')
.bind({
mouseenter: function(e) {
// Hover event handler
$("> a",this).attr('class','ui-corner-all ui-state-hover');
},
mouseleave: function(e) {
// Hover event handler
$("> a",this).attr('class','ui-corner-all');
}
});
},
mouseenter: function(e) {
// Hover event handler
$("> a",this).attr('class','ui-corner-all ui-state-hover');
},
mouseleave: function(e) {
// Hover event handler
$("> a",this).attr('class','ui-corner-all');
}
})
.appendTo('ul.ui-autocomplete');
}
},
Links to jsFiddle
http://jsfiddle.net/eyecode/sX4Ba/
Any help would be appreciated.
Thanks in Advance
In order to list the top 20 options with a "More .." at the bottom of the first 20 items. Once a user presses "More .." link. All the items will be displayed in the drop down.
(function ($) {
$.widget("ui.typeaheadtextbox", {
_create: function () {
var self = this,
select = this.element.hide(),
theWidth = select.width(),
selected = select.children(":selected"),
value = selected.val() ? selected.text() : "";
var _searchItem = '';
var _more = false;
var _lastIndex = 0;
var _maxSize = 20;
var _rep = null;
var input = this.input = $("<input id='" + select[0].id + "_jq' style=\"width: " + theWidth + "px\">")
.insertAfter(select)
.val(value)
.autocomplete({
delay: 10,
minLength: 0,
source: function (request, response) {
var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term), "i");
var j = 0;
_rep = response;
_searchItem = request.term;
var select_el = select.get(0); // get dom element
var rep = new Array(); // response array
for (var i = 0; i < select_el.length; i++) {
var text = select_el.options[i].text;
if (select_el.options[i].value && (!request.term || matcher.test(text))) {
j++;
if (j > _maxSize) {
_more = true;
_lastIndex = i;
break;
}
// add element to result array
rep[(j - 1)] = {
label: text.replace(new RegExp("^(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(_searchItem) + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>"), value: text, option: select_el.options[i]
};
}
}
return response(rep);
},
autoFocus:true,
open: function(event, ui) {
if (_more) {
_more = false;
$('<li class="ui-menu-item_more" role="menuitem" id="' + select.get(0).id + '_ADDMORE_' + _lastIndex + '" ><a class="ui-corner-all" tabindex="-1"><img width="16" src="Content/themes/base/images/icon-search-small.png"/> <strong>View All</strong></a></li>')
.bind({
click: function(e) {
var response = _rep;
var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(_searchItem), "i");
var select_el = select.get(0); // get dom element
var rep = new Array(); // response array
var j = 0;
for (var i = 0; i < select_el.length; i++) {
var text = select_el.options[i].text;
if (select_el.options[i].value && (!_searchItem || matcher.test(text))) {
// add element to result array
rep[j++] = {
label: text.replace(new RegExp("^(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(_searchItem) + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>"), value: text, option: select_el.options[i]
};
}
}
$(this).remove();
return _rep(rep);
},
mouseenter: function(e) { $("> a",this).attr('class','ui-corner-all ui-state-hover'); },
mouseleave: function(e) { $("> a",this).attr('class','ui-corner-all');}
})
.appendTo('ul.ui-autocomplete');
_lastIndex = 0;
return true;
}
},
select: function (event, ui) {
ui.item.option.selected = true;
self._trigger("selected", event, {
item: ui.item.option
});
},
change: function (event, ui) {
if (!ui.item) {
var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex($(this).val()) + "$", "i"),
valid = false;
select.children("option").each(function () {
if ($(this).text().match(matcher)) {
this.selected = valid = true;
return false;
}
});
if (!valid) {
// remove invalid value, as it didn't match anything
$(this).val("");
select.val("");
input.data("autocomplete").term = "";
return false;
}
}
}
})
.addClass("ui-widget ui-widget-content ui-corner-all");
input.data("autocomplete")._renderMenu = function( ul, items ) {
var self = this; var htm = ''; var beginHtm = '<li><a>'; var endHtm = '</a></li>';
for(var i=0;i<items.length;i++) {
htm += beginHtm + items[i].label + endHtm;
}
ul[0].innerHTML = htm;
var liTags = ul[0].getElementsByTagName('li');
for(var i=0;i<liTags.length;i++) {
$(liTags[i]).data("item.autocomplete", items[i]);
}
return true;
};
},
destroy: function () {
this.input.remove();
this.element.show();
$.Widget.prototype.destroy.call(this);
},
clear: function () {
this.element.val("");
this.input.val("");
}
});
})(jQuery);

Categories