Moving rows to and from Gridviews using .clone, .cloneNode and .append - javascript

I have two Gridviews, one loaded with data and the other not. When I double click an item from gvDisplayAvailItems, I want the row to go to gvDisplaySelectedItems, and vice-versa. The Grids are also multi-select, with a button allowing all selected items to be moved. gvDisplaySelectedItems differs by 1 additional input column.
AddDisplayParams() is called when the button is pressed.
function AddDisplayParams() {
var rows = $("#gvDisplayAvailItems").find('tr.selected');
rows.each(function (index, element) {
element.classList.remove("selected");
var newRow = element.cloneNode(true);
newRow.appendChild(customIdTb.cloneNode(true));
$("#gvDisplaySelectedItems").append(newRow);
element.remove();
});
}
AddDisplayParam is called on double-click.
function AddDisplayParam(param) {
var newRow = param.clone(true);
newRow.append(customIdTb.cloneNode(true));
$("#gvDisplaySelectedItems").append(newRow);
param.remove();
}
And here is how I trigger the selection and double clicks.
$("#gvDisplaySelectedItems tr").click(function () {
$(this).toggleClass("selected");
});
$("#gvDisplaySelectedItems tr").dblclick(function () {
RemoveDisplayParam($(this));
});
$("#gvDisplayAvailItems tr").click(function () {
$(this).toggleClass("selected");
});
$("#gvDisplayAvailItems tr").dblclick(function () {
AddDisplayParam($(this));
});
When I both double click and mass select rows on gvDisplayAvailItems, the rows are moved to gvDisplaySelectedItems correctly. However, nothing is triggered for the functions of gvDisplaySelectedItems for rows that were added via AddDisplayParams. Those added by AddDisplayParam can be highligted, but when double clicked only append another textbox to the row in gvDisplaySelectedItems.
So it seems that .clone and .cloneNode are doing something very different here despite having basically the same function. Could someone please explain why one partially works, while the other does not? And also, why my functions for the second grid are not triggered upon single and double click?

I'd suggest to try delegated event handlers.
E.g.
$("#gvDisplaySelectedItems").on("click", "tr", function () {
$(this).toggleClass("selected");
});
instead of
$("#gvDisplaySelectedItems tr").click(function () {
$(this).toggleClass("selected");
});
and so on for other event handlers.
More info
Regarding other improvements - you don't have to clone()/append()/remove() to move an element. Just doing append() to a new parent will effectively move it since an element can have only one parent each moment of time.
Example: JSFiddle

Related

jQuery calling on() on dynamically generated it after calling click()

I am trying to develop some code to allow the user show/hide a block level element by clicking a button.
The HTML structure is like below
<div class="chat_container"><a class="crm" href="https://google.com" target="_blank">Chat?</a><button id="close_chat"><</button></div>
I have written a click() function for #close_chat which amongst other things changes the ID of the button to #open_chat. I then use the on() method on #open_chat to modify some classes and ids on various elements. In isolation both these methods work, however when combined they don't work. I have noticed that when I click #close_chat even though the ID changes to #open_chat the original event is still attached to the button. After doing some search I suspected the issue might have been related to events bubbling up, but now I am not so sure, still I added event.stopPopagation() to my click function and I can see it appears to be called correctly. I have also tried using the one() method, this appeared to get closer to the behavior I was expecting at the DOM level but still didn't working
My expected behavior is the click() function is called when the user clicks #close_chat, the event is then unbound allowing the .on() event to be called on #open_chat. Id than of course have to reset the original functionality. My code looks like this
$(document).ready(function () {
var close = "<button id='close_chat'><</div>";
var container = $("<div />");
container.addClass("chat_container");
var crmChat = $("<a />");
crmChat.addClass("crm");
crmChat.attr("href", "https://google.com");
crmChat.attr("target", "_blank");
crmChat.text("Chat?");
console.log(crmChat);
console.log(container);
$(container).insertAfter("#heading");
$(container).prepend(crmChat);
$(close).insertAfter(crmChat);
$("#close_chat").click(function (event) {
$("#close_chat").removeAttr("id").attr("id", "open_chat");
event.stopPropagation();
alert(event.isPropagationStopped());
//return false;
});
$(".chat_container").on("#open_chat", "button", function () {
//$(".crm_chat_container").addClass("animate-open").removeClass("animate-close");
$("#open_chat").html(">").removeAttr("id").attr("id", "reopen");
//event.stopPropagation();
});
});
any help is greatly appreciated
Sam
edit, I have now updated my code to look like so
//onclick function for our close button
$("#close_chat").click(function (event) {
attachClosedChatListner();
});
function attachOpendChatListener() {
$(".chat_container").on("click","#open_chat", function () {
$("#open_chat").removeAttr("id").attr("id", "close_chat");
$("#close_chat").html("<")
$(".crm_chat_container").removeClass("animate-close").addClass("animate-open");
});
//attachClosedChatListner();
}
function attachClosedChatListner() {
$("#close_chat").off('click');
$("#close_chat").removeAttr("id").attr("id", "open_chat");
$("#open_chat").html(">")
$(".chat_container").removeClass("animate-open").addClass("animate-close");
//attachOpendChatListener();
}
What about re-attaching the event?
$("#close_chat").click(function (event) {
$("#close_chat").removeAttr("id").attr("id", "open_chat");
attachOpenChatListener();
event.stopPropagation();
alert(event.isPropagationStopped());
//return false;
});
function attachOpenChatListener() {
$("#close_chat").off('click');
$(".chat_container").on("#open_chat", "button", function () {
//$(".crm_chat_container").addClass("animate-open").removeClass("animate-close");
$("#open_chat").html(">").removeAttr("id").attr("id", "reopen");
//event.stopPropagation();
});
}
I managed to work this out, the click function was causing the problem
//onclick function for our close button
$("#close_chat").click(function (event) {
attachClosedChatListner();
});
I've replaced it with .on and it works now
$(".crm_chat_container").on("click", "#close_chat", function (event) {
$("#close_chat").off('click');
$("#close_chat").removeAttr("id").attr("id", "open_chat");
$("#open_chat").html(">");
$(".crm_chat_container").removeClass("primo-animate-open").addClass("animate- close");
attachCloseChatListener();
event.stopImmediatePropagation();
});
function attachCloseChatListener() {
$(".crm_chat_container").on("click", "#open_chat", function (event) {
$("#open_chat").off('click');
$(".crm_chat_container").removeClass("primo-animate-close").addClass("primo-animate-open");
$("#open_chat").removeAttr("id").attr("id", "close_chat");
$("#close_chat").html("<");
event.stopImmediatePropagation();
});
}
on thing is my click events appears to be firing multiple times, that is after clicking my buttons a few times I see several click events in dev tools.
Anyway, thanks for putting me on the right path

Prevent inner div from triggering outer-div events

I created a basic row click-and-drag selection function. However the issue is click-and-dragging over the columns toggles them on and off. I am looking for some sort of return false or stopPropagation of some sort but I cannot get these to work.
return false does help by preventing text selection, but it does not prevent column selection from affecting row selection.
To demonstrate, http://jsfiddle.net/sjwcztre/, try to select the rows from the right side - no problem. But try to select the rows where column text is present - it goes wonky
var isMouseDown = false;
$('.row').each(function () {
$(this).mousedown(function () {
isMouseDown = true;
rowClickHandler(this);
console.log('mdown');
return false;
})
.mouseover(function () {
if (isMouseDown) rowClickHandler(this);
});
$(document).mouseup(function () {
isMouseDown = false;
});
});
function rowClickHandler(obj) {
$(obj).toggleClass('highlight');
}
Check this, see if it works for you. Basically you need to create events for the children of your rows and handle them differently, adding a hoverChild control variable helped to prevent the hover from the parent activating once again.

click event on a cell and not entire row - with FIDDLE

I am currently using this code for row click event in a bootstrap table
$('#myTable').bootstrapTable().on('click-row.bs.table', function (e, row, $element)
{
//....my operation
}
The problem is this triggers for the entire row and I want to be able to trigger it for a single cell.
Note I am using the arguments, row and $element
Here is the FIDDLE
$element is the entire row, you cannot know what cell have been clicked by this way,
bootstrap table do not have cell click event, so you need manually add click event on last cell and fill your needed vars yourself
$('#table').bootstrapTable({
data: data
}).on('click','td:last-child',function(){
var $t = $(this), $row = $t.parent(), i = $row.index(), row = data[i];
var $firstTd = $row.children().eq(0);
if($firstTd.data("haveTable") !== true){
$firstTd.data("haveTable",true);
$firstTd.append('<table class="newTable"><tr><td>NEW TABLE</td></tr></table>');
} else {
$firstTd.data("haveTable",false);
$firstTd.children("table").remove();
}
});
https://jsfiddle.net/e3nk137y/1663/
try
$('#myTable').bootstrapTable().on('click-row.bs.table td', function (e, row, $element)
{
//....my operation
}
Based on my guess, when you click on that cell, you probably want only the triggers for that particular cell to execute and not for the whole table.
This can be achieved by stopping the propagation of event from the table cell to the table row.
$('#myTable').bootstrapTable().on('click-row.bs.table', function (e, row, $element){
//stop the propagation for target cell
if($(event.target).hasClass('myClass')) e.stopPropagation();
//the code for handler
...
...
}
There are many ways stopPropagation can be utilized to do this thing. This was just one of those.
Since I dont know how your other triggers are set, I can't write code that works with those with assumptions.
Try this:
$('#myTable tr td:last-child').on('click', function() {
if( $('.newTable', $(this)).length ) {
$('.newTable', $(this)).remove();
} else {
$(this).append( '<table class="newTable"><tr><td>NEW TABLE</td></tr></table>' );
}
});

jQuery Traversing Dynamically generated DOM (next(), prev())

I have an HTML table and jQuery handlers to move rows up and down, using .next() and .prev(), but I also want to add new rows and after adding new row and trying to move old rows up or down they move more positions than expected. Here is an example on jsfiddle http://jsfiddle.net/3CQYN/
$(function() {
initControls();
$('.new').click(function() {
$('<tr><td>TEST</td><td>Up Down</td></tr>').appendTo($('table tbody'));
initControls();
});
});
function initControls()
{
$('.down').click(function() {
var parentRow = $(this).closest('tr');
parentRow.insertAfter(parentRow.next());
});
$('.up').click(function() {
var parentRow = $(this).closest('tr');
parentRow.insertBefore(parentRow.prev());
});
}
Try to move rows up and down, then add few new rows and move the OLD rows up and down again and you'll see the problem.
Every time you add a new row, you rebind the handlers, ending up with multiple handlers bound to individual up and down links. Instead, use event delegation (only executed once, on DOM ready):
$(document).on('click', '.down', function() {
// ...
});
$(document).on('click', '.up', function() {
// ...
});
http://jsfiddle.net/Gt4Zq/
Note that if you can find a container to bind to that is closer to the elements than document, that would be preferable.

Moving data using Select-All Checkboxes

Currently I have two tables
I have select-all functions on the top left checkboxes, but clicking on one select-all highlights all checkboxes in BOTH tables, whereas I only want all boxes to be selected in the specific 'check-all' clicked.
Also, when I do select all and click one of the directional buttons < or >, it drags all the rows fine but drags the headers with it as shown here:
My JQuery is quite simple at the moment but I'm obviously missing out on something -
$('#select-all').click(function (event) {
if (this.checked) {
// Iterate each checkbox
$(':checkbox').each(function () {
this.checked = true;
});
}
else
// Iterate each checkbox
$(':checkbox').each(function () {
this.checked = false;
});
});
Where 'select-all' is the id of the select-all checkbox in the 'tarifs de quittancement'.
Any help is appreciated
EDIT
My JQuery for the > button code is as follows :
$("#move-to-1").on("click", function () {
var selected = $("#table2").find("input:checked");
selected.each(function (idx, elem) {
$(elem).closest("tr").detach().appendTo($("#table1 tbody"));
});
});
This works fine to move all from one table to the other, but I don't want the row containing the select-all checkbox/table headers to move with the rest of the row data. How can this be done?
Thanks again.
Further Edit
Now it's all sorted, except for a small bug where selecting one checkbox row (not select-all) and moving it < or > results in ALL rows being moved.
JQuery in use:
$('#move-to-1').on('click', function () {
var selected = $('#table2').find('input:checked');
selected.each(function (idx, elem) {
$(elem).closest('tbody').find('tr').detach().appendTo($("#table1 tbody"));
$('input[type=checkbox]').attr('checked', false);
});
});
$('#select-all').click(function (event) {
$(this).closest('table').find(':checkbox').prop('checked', this.checked);
});
You only need to modify the checkboxes inside the current table. Since you haven't shown your markup it is extremely hard to guess how the proper selector might look or whether you are using tables at all but try like this:
$('#select-all').click(function (event) {
$(this).closest('table').find(':checkbox').prop('checked', this.checked);
});
UPDATE:
To address your second question, assuming you have separated the headers from the body inside those tables using the <thead> and <tbody> sections which is the correct way, you could adapt your selector:
$('#move-to-1').on('click', function () {
var selected = $('#table2 tbody').find('input:checked');
selected.each(function (idx, elem) {
$(elem).closest('tr').detach().appendTo($("#table1 tbody"));
});
});
$('#select-all').click(function (event) {
// mention the table
var table = $('selector_to_your_table');
if (this.checked) {
// Iterate each checkbox
table.find(':checkbox').each(function () {
this.checked = true;
});
}
else
// Iterate each checkbox
table.find(':checkbox').each(function () {
this.checked = false;
});
});
Note
In latest version of jQuery :checkbox is deprecated. See here..
Instead of :checkbox use input[type=checkbox].
Instead of:
$(':checkbox').each(function () {
this.checked = true;
});
Do:
$('some_sort_of_selector :checkbox').attr('checked', true);
You don't need that each() loop - jQuery does it automatically. You need some kind of selector to limit which checkboxes are changed.
I notice you have #select-all - and yet you say you have two select-all checkboxes. You can't do that. ID's must be unique.

Categories