This is how i populate the table
I'm having some trouble with the datatables plugin for jquery. The table is populated dynamically, I have 3 columns with text and a fourth column which consists of a delete and an edit button. For the edit button I have a modal, and if I confirm the changes, it does indeed change the specific line in the table.
However, if I click on several edit buttons and cancel, when I actually want to change one it changes all the previously canceled lines.
Here is the relevant code:
$("#example").on("click", ".edit-button", function() {
$("#edit-modal").modal("show");
saveChanges(this);
});
function saveChanges(k) {
$("#edit-confirm").click(function() {
$(".itm-loader-modal").show();
setTimeout(function() {editJob(k);},1000);
});
}
function editJob(currentButton) {
$(".itm-loader-modal").fadeOut("slow");
var editedName = $("#job-name").val();
var editedDescription = $("#job-description").val();
var editedCompany = $("#job-company").val();
var data = {
"name":editedName,
"description": editedDescription,
"company": editedCompany
};
var currentLine = $(currentButton).parent().parent().children();
currentLine.eq(0).text(data.name);
currentLine.eq(1).text(data.description);
currentLine.eq(2).text(data.company);
$("#edit-modal").modal("hide");
}
Hard to say for sure, but one think that looks wrong is that each time saveChanges is called, you register new event listener on #edit-confirm button.
Once that #edit-confirm is clicked, it will execute all the registered event handlers – one for each .edit-button click.
Instead, you probably want to have a single #edit-confirm click handler and find a way to pass the info about the line that's currently being edited to it.
Cheers.
so when you call saveChanges it assign event handler to "#edit-confirm", all those event handlers are executed at once,
to avoid it you should attach event handler to it via delegation or i think this quick fix should work
$(this).find('#edit-confirm').click(function() {
/...
})
Related
I have a table with some records in it and each of that records can be edited. I have a sidebar with edit form in it with the same inputs and the same submit button. When I try to execute the function on that button which will send an AJAX request, it executes as many times as many sidebars I opened before, when I need to update only that record which was actually edited.
That's the code:
// On Edit
$('.action-edit').on("click",function(e){
e.stopPropagation();
$(".add-new-data").addClass("show");
$(".overlay-bg").addClass("show");
const row = $(this).closest('td').parent('tr').first();
const agendaID = row.data('agenda_id');
const form = document.querySelector('#update_form');
const url = $(form).data('action_url').replace('.ID.', agendaID);
getAgendaInfo(agendaID);
$('.add-data-btn').on('click', function (e){
e.preventDefault();
console.log(agendaID); // displays IDs of all records where sidebar was opened.
const ajaxData = grabFormData();
editAgenda(url, row, ajaxData);
})
});
I think the issue is that you are adding new click event listener each time you show a new editor but you don't remove the previous event listener.
Try doing $('.add-data-btn').off() before the $('.add-data-btn').on('click'....
The problem you have is that your click handler is created whenever that .on() function is evaluated. The issue is that you execute that multiple times. Instead of that, you will need to perform a few steps for an elegant solution:
#1
Find a tag which exists before you populate your action-edit elements. In the worst case that would be body and I suggest that you need to start experimenting with
$(function() {
$('body').on("click", '.action-edit',function(e){
e.stopPropagation();
$(".add-new-data").addClass("show");
$(".overlay-bg").addClass("show");
const row = $(this).closest('td').parent('tr').first();
const agendaID = row.data('agenda_id');
const form = document.querySelector('#update_form');
const url = $(form).data('action_url').replace('.ID.', agendaID);
getAgendaInfo(agendaID);
$('.add-data-btn').on('click', function (e){
e.preventDefault();
console.log(agendaID); // displays IDs of all records where sidebar was opened.
const ajaxData = grabFormData();
editAgenda(url, row, ajaxData);
})
});
});
Note that this needs to run exactly once and will automatically create click handlers for you.
#2
Find the closest tag to your grid which already exists at the time the page is loaded and change the selector accordingly.
#3
Test, test, test
We have a tabulator column definition , where one of them is a button created by a formatter
{title:"input", field:"blank", width:30, frozen:true, responsive:0,formatter:customFormatter2}
Into formatter we create a button
var customFormatter2 = function (cell, formatterParams) {
var $button=$('<button>').text('Hola')
$button.click(function(){
$(cell.getElement()).trigger('contextmenu')
})
return $button.get(0);
}
Also we have a rowContextmenu created into tabulator.
I want call to menu that tabulator shows when we do right click in any row.
I tried call a trigger from cell,from row... and I dont know if the event is accessible ,or I dont know do it.
Thanks
I don't user jQuery often, but I believe the only thing missing is preventing the propagation of the click event after the contextmenu event, which hides the menu. Something like this should work, but I also had to add pageX and pageY to my custom event, so that Tabulator could calculate where to display the menu. I am not sure how I would do this in jQuery.
$button.click(function(event){
event.stopImmediatePropagation();
$(cell.getElement()).trigger('contextmenu');
});
Or without jQuery and definitely works,
function customFormatter(cell, formatterParams){
const button = document.createElement('button');
button.textContent = "Hola";
button.addEventListener('click', (event) => {
event.stopImmediatePropagation();
const myEvent = new Event('contextmenu');
myEvent.pageX = event.pageX;
myEvent.pageY = event.pageY;
cell.getRow().getElement().dispatchEvent(myEvent);
})
return button;
}
Here is a full example without jQuery.
https://jsfiddle.net/nrayburn/guxkw394/101/
Be careful with this. Because we are creating a custom event, it doesn't contain all of the normal properties that a real event would. If Tabulator starts relying on different event properties, it would break this code. (Maybe you could copy the original event from the click and pass those properties into the custom event. Not really sure how to do that.)
I am using dojo dgrid for table representation. I have handled a row click event with grid.on('.dgrid-content .dgrid-row:click', function(){ // Open a Dialog}). But the problem I am facing here is: while user is trying to select any text on the row with a hope to copy, the event eventually ends up opening the dialog.
As per my knowledge, HTML5 has the support of ondrag event, but that is not working in my case. What are the other ways to separate these two events and handle accordingly?
Thanks in advance.
You can distinguish select from click in following way inside of your click handler:
clickHandler: function () {
var collapsed = window.getSelection().isCollapsed;
if (collapsed) {
console.log("Clicked");
//Open dialog
} else {
console.log("Selected");
//Do something else
}
}
You should add set allowTextSelection to true inside your grid. This allows the user select text inside the rows.
Make sure you read the documentation on the topic.
I've found a script that converts json file into quiz using jquery.
I am playing with it's code for almost a day now and I can't come with what I wanted to have.
Functions quiz().init(); and quiz().bindSubmit(); are called when page loaded.
What I want is the START button must be clicked first to load the Quiz.
$("#start").click(function(){
currentQuestion = 0;
questionCount = 0;
answerArray = [];
infoMode = false;
gotData = false;
inMemoryData = [];
quiz().init();
quiz().bindSubmit();
});
HTML:
<button type="button" id="start">Start</button>
<div id="quiz-content"></div>
It works at first click of START button also in the next clicks, it successfully reset the quiz and goes back to #1.
But the problem is after the first click of Start Button, the quiz won't work normally when submitting the quiz. The quiz began to stucked in #1.
For better understanding, JSfiddle here.
Edited:
Basically when the user click start button more than once,the quiz gets started from the beginning ,but didn't get to the next question(Gets stuck on the 1st question itself)
When you call bindSubmit function, inside it you are attaching to the submit event of the #quizForm. So when you press Start button twice, there two event handlers attached to the same event and that is because it is not behaving as it should be. So inside the bindSubmit function you need always disconnect all submit handlers ($(document).off('submit');), like this:
var bindSubmit = function () {
$(document).off('submit');
$(document).on('submit', '#quizForm', function (event) {
event.preventDefault();
next(this);
quiz().init();
});
};
Here is your original fiddle with mentioned update
https://jsfiddle.net/t4p8x02b/35/
There are couple of things i observed in your code, which needs to be rectified for better management of code:
There is no need to expose init() outside your quiz library, for first time initialization, you can call init() before your return from the library(end of quiz() module code).
Also exposing init() makes your quiz() module vulnerable since it can be modified by any external program which could spoil your entire quiz() logic.
Inside bindSubmit(), you dont need to re-initialize your quiz instance to call init(), rather just call init()(refer below code snippet), your event handler will call it without any error [This is the magic of Closure].
bindSubmit():
$(document).on('submit', '#quizForm', function (event) {
event.preventDefault();
next(this);
init();
});
In jqGrid, Is there a "built-in" way to know what mouse button was clicked, before row selection?
Currently we have jqGrid with some actions bind on "onSelectRow" event of jqGrid. The problem is that when user right click on that row, onSelectRow event raised to and action performed. What I need, is to ignore "onSelectRow" when user right click on a row.
EDIT: I know there exists onRightClickRow event, but it raised after onSelectRow and action already performed.
I found that I can know what button clicked by "type" of event object. When it's click, the type is "click" when it's right click, the type is "contextmenu"....Does exists the additional way, or I must check type to know what button is clicked?
Thanks
It's good question! The reason of such behavior is the following. jqGrid register an event handler for the event contextmenu on the whole grid <table> element with the following code (see here)
.bind('contextmenu', function(e) {
td = e.target;
ptr = $(td,ts.rows).closest("tr.jqgrow");
if($(ptr).length === 0 ){return;}
if(!ts.p.multiselect) { $(ts).jqGrid("setSelection",ptr[0].id,true,e); }
ri = ptr[0].rowIndex;
ci = $.jgrid.getCellIndex(td);
$(ts).triggerHandler("jqGridRightClickRow", [$(ptr).attr("id"),ri,ci,e]);
if ($.isFunction(this.p.onRightClickRow)) {
ts.p.onRightClickRow.call(ts,$(ptr).attr("id"),ri,ci, e);
}
});
How one can see from the code it calls setSelection method and calls onRightClickRow callback and trigger jqGridRightClickRow event. So if you don't need the selection of rows and if you don't use onRightClickRow and jqGridRightClickRow you can just unbind the event handler:
$("#list").unbind("contextmenu");
If you do want use onRightClickRow callback or if you don't sure whether you need to use jqGridRightClickRow somewhere you can "subclass" the event handler. The implementation is depend a little from the version of jQuery which you use. Starting with jQuery 1.8 one should use a little another call to get the current events registered on the DOM element. The corresponding code could be about the following:
//$grid.unbind('contextmenu');
var getEvents = $._data($grid[0], "events"); // $grid.data("events") in jQuery ver<1.8
if (getEvents && getEvents.contextmenu && getEvents.contextmenu.length === 1) {
var orgContextmenu = getEvents.contextmenu[0].handler;
$grid.unbind('contextmenu', orgContextmenu);
$grid.bind('contextmenu', function(e) {
var oldmultiselect = this.p.multiselect, result;
this.p.multiselect = true; // set multiselect to prevent selection
result = orgContextmenu.call(this, e);
this.p.multiselect = oldmultiselect; // restore multiselect
return result;
});
}
The demo demonstrate the above code live.
Events are listed here: http://www.trirand.com/jqgridwiki/doku.php?id=wiki:events
There is an onRightClickRow event.
Also, using the plain jquery event object and which will tell you. http://api.jquery.com/event.which/
You must use 3rd parameter to onRowSelected and which or the type like you mentioned.