I have a click event that triggers other click events that adds an element to the DOM.
EDIT: But when I click it a second time two elements get added and third time two elements get added. When I check the jQuery queue it confirms that I have added an event to the queue that fires every time.
What I try to accomplish is to add a click event to two dropdownlists by clicking another element.
$(".step-1 a").on("click", function(e){
e.preventDefault();
var userValue = $(this).attr('id');
$(".template-image").removeClass("selected");
$(this).children(":first").addClass("selected");
$("#page_template option ").each(function(){
var t = $(this);
var cValue = t.attr("value");
if(t.attr("selected") === "selected"){
t.removeAttr("selected");
}
if(t.attr("value") === userValue ){
t.prop("selected", "selected");
$('#page_template').trigger('change');
var template = t.attr("value");
switch (template)
{
case "default":
$(".step-2").slideDown("fast");
$(".step-2").addClass("show");
break;
default:
$(".step-2").removeClass("show");
$(".step-2").slideUp("fast");
break;
}
}
});
});
$('.step-2 img').on("click", function(e){
e.preventDefault();
var userinput = $(this).attr('id');
$('.flexible-footer .acf-fc-add').each(function(){
var text = $(this).text();
if(text === "Add columns"){
$(this).trigger('click');
$('.flexible-footer .acf-fc-popup ul li a').each(function(){
var column = $(this).attr('data-layout');
if (column === userinput) {
$(this).trigger('click');
$(this).finish();
console.log($(this).queue());
}
});
}
});
It sounds like you're assigning click events multiple times on the same elements. A simple solution to this problem is to use the jQuery function off() to remove the old click-event before adding a new one. Or make sure you're only adding the click event to new element that doesn't already have them. You can do it like this:
$('img.or-whatever').off('click').on('click', function(ev){...});
Or maybe use namespaces for increased readability:
$('img.or-whatever').off('click.custom-namespace').on('click.custom-namespace', function(ev){...});
It might not be the correct answer to your question, but it might be a solution.
Edit:
If you just want to clear the event queue, you could try clearQueue().
Related
This is my logic, here I am trying to disable the save changes button and prevent click event on it if the user enters a duplicate value and enable it again if the user changes the values but after enabling it the update / save event does not occur am I doing something wrong? This is my code
function OnChange(data) {
//data.preventDefault();
$(".k-grid-save-changes")
.attr("role", "button")
.removeClass("k-state-disabled")
//.addClass("k-grid-save-changes")
.click(function () {
return true;
});
//console.log("data", data.items["0"].ProviderTypeName);
var name = data.items["0"].ProviderTypeName;
var Id = data.items["0"].Id;
var grid = $("#grid").data("kendoGrid");
//console.log("Grid ", grid);
grid.tbody.find('>tr').each(
function () {
$(this).css('background', 'white');
var dataItem = grid.dataItem(this);
//console.log(dataItem.ProviderTypeName)
if (dataItem.ProviderTypeName == name && dataItem.Id != Id) {
$(this).css('background', 'red');
$(".k-grid-save-changes")
//.removeClass("k-grid-save-changes")
.addClass("k-state-disabled")
//.removeAttr("role")
.click(function () {
return false;
});
}
});
}
This is where is call the on change event
.Events(events => events.RequestStart("OnRequestStart").Change("OnChange").RequestEnd("OnRequestEnd").Error("onError"))
If I remove the "return false;" it is working as expected but this allows duplicated values to be saved. So I have used this.
If I understand correctly in your code you do exactly what you mention as a problem. At every change you disable the save functionality with the return false. You don't enable it again at any point.
If you add an event handler to the button then you have to undo it at a later point. Since though I don't believe that the validation should occur at the change event but at the button click I would suggest to use the grid Save event where you could iterate dataSource.data() of your grid (much better) do your check and if anything happens return false.
One other way to go since you probably want the css effect with the background is to keep your code and discard the click event. Just set a flag that you could use in the save event. Something like this:
if(// your control){
$(this).css('background', 'red');
duplicatedValue = true;
}else{
.removeClass("k-grid-save-changes");
duplicatedValue = false;
}
And in the save event
function onSave(){
if(duplicatedValue){
return false;
}
}
I am using appendTo to move list items between two list, upon a button click. The button resides in each li element. Each li has two buttons, of which only one is visible at a time, depending on the list the li currently resides.
Here is the function:
// 'this' is the first list
// Click Handler for remove and add buttons
$(this.selector + ', ' + settings.target + ' li button').click(function(e) {
var button = $(e.target);
var listItem = button.parent('li');
listItem.children("button").toggleClass("hidden");
if (button.hasClass("assign")) {
// Add Element to assignment list
listItem.appendTo(settings.target);
}
else
if (button.hasClass("remove")) {
// Remove Element from assignment list
listItem.appendTo(source);
}
})
As long as the list item reside in the original li, the click events in the buttons are triggered. However, once it is moved to the other list using listItem.apendTo. The click item no longer fires. Why is this the case? I cant find anything about this in the docs.
Sometimes jQuery won't be able to find something if it isn't present in the DOM when your script first loads. If it is a dynamically created element, try replacing your click event handlers with 'on'
Rather than:
$(".aClass").click(function(){
// Code here
})
Try:
$("body").on("click", ".aClass", function(){
Code here
})
http://api.jquery.com/on/
You should use on event.
$(".aClass").on("click", function(){
//Your custom code
})
on event is usful for Dynamically generated data + static data already in HTML.
As recommended by user 'apsdehal', a deleate was what i needed:
// Click Handler for remove and add buttons
$(source.selector + ', ' + settings.target ).delegate("li button", "click", function(e) {
var button = $(e.target);
var listItem = button.parent('li');
listItem.children("button").toggleClass("hidden");
if (button.hasClass("assign")) {
// Add Element to assignment list
listItem.appendTo(settings.target);
}
else
if (button.hasClass("remove")) {
// Remove Element from assignment list
listItem.appendTo(source);
}
});
I know this is a similar question to my previous one however its slightly different.
I have this script adding each 'dropped' element to a list. Now i need it adding into a variable / hidden field so i can pass it to the next page via a form.
When i run it at the moment. It alerts for each one however, it does it not just for every item dropped but if there are 10 items dropped it will run 10 times per item droped rather than once per item dropped.
Any help would be great.
//Record and add dropped items to list
var txt = $("#listbox");
var dtstart = copiedEventObject.start + '\n'
var caltitle = copiedEventObject.title
var txt = $('#listbox');
txt.append("<li class ='listItem'> "+dtstart +"</li>")
var listItems = $('.listItem');
$('#calendarform').submit(function() {
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
return false;
});
// remove the element from the "Draggable Events" list
$(this).remove();
the problem lies in this code
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
you are alerting the text of all the list items for each list item.
use jQuery(this) to access the current item within an each block
listItems.each(function(){ //For each event do this:
alert( $(this).text() );
});
Assuming your code is within a drop event handler, you are also adding a submit handler each time you drop. This means that each time you drop, you queue up another submit event. This is probably not desired. Move this submit(function(){}) block outside your drop handler to prevent it from firing that function more than once.
$('#calendarform').submit(function(e) {
var listItems = $('.listItem');
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
e.preventDefault();//stop normal behavior
return false;
});
and to create elements on the fly you just pass jQuery the html, and append it to your form.
$('<input type="hidden" name="listItem[]"/>').appendTo("#calendarForm").val(listItem.text())
you may have to fiddle with the name element to get it to submit as an array in your server side language, but you're also within an each loop, which provides you with an index, so you can do the following.
$('#calendarform').submit(function(e) {
var form = $(this);
var listItems = $('.listItem');
listItems.each(function(index){ //For each event do this:
var listItem = $(this);
$("<input type='hidden'/>").val(listItem.text()).appendTo(form).attr('name', 'listItem[' + index + ']');
});
e.preventDefault();//stop normal behavior
return false;
});
In my page I have many edit buttons each name starts with "edit" and then some id. I want to know any of my edit buttons is clicked or not.
In details, I have form. In form I have many edit buttons which name starts with "edit" , delete buttons which name starts with "delete" and 1 add button. All are submit buttons. form onsubmit I call JavaScript function in which I want if the button is edit confirm("some text") else submit form.
How can I do that in JavaScript?
I think give all these buttons same id and then getElementById but then how con I change?
This is simple using jQuery:
$(':button').click(function() {
// reference clicked button via: $(this)
var buttonElementId = $(this).attr('id');
});
Try it out:
http://jsfiddle.net/7YEay/
UPDATE based on feedback in comments
This is untested/pseudo code:
$(':submit').click(function(event) {
var buttonName = $(this).attr('name');
if (buttonName.indexOf('edit') >= 0) {
//confirm("some text") logic...
}
event.preventDefault();
});
This documentation may be helpful too: http://api.jquery.com/submit/
function MyOnSubmit(e){
e = e || window.event;
// srcElement for IE, target for w3c
var target = e.target || e.srcElement;
if (target.id.indexOf("edit") > -1){
// an edit button fired the submit event
}
}
although i advice you research further to find a better way to handle edit and delete buttons (like making them links with href=editpage.jsp?id=23)
I'm pretty sure you just answered this yourself...
Each starts with "edit", and ends with a unique ID?
So... $(button).attr("id") would give you that. Store it in a variable? Not sure what you're trying to do..
bind click event on all button:
for (var i = 0; i < buttons.length; i++) {
var button = buttons[i];
if (button.addEventListener) {
button.addEventListener('click', handler, false);
}
else {
button.attachEvent('onclick', handler);
}
}
in your event handler, get the Event object, and then get the target:
function handler(e) {
e = e || window.event;
// srcElement for IE, target for w3c
var target = e.target || e.srcElement;
var id = target.name.substring(4);
/* your code rely on id */
}
I think you might not have phrased your question correctly. If you are using jquery, locating the button is as easy as $('#id'), and if you want to store any information on that button, you can either add an attribute or use jquery.data function.
$('#id').attr("pressed", "true");
Or
$('#id').data('pressed', 'true');
I have a function called handleOnClickRadio(i, j); and lots of radio buttons named as id="something-radio[i][j]". All these radio buttons are in a table called "bigtable".
How could I attach the function handleOnClickRadio() to all these radio buttons? And call it correct with handleOnClickRadio(i,j).
Thanks.
I would not attach the click handler to the buttons at all. You say you have lots of them. Attaching the same event handler to each of them is a waste of memory and could even be a performance problem.
Use event delegation instead:
$('#tableID').delegate('input[type=radio]', 'click', function() {
// code here
});
Then you could extract the i and j via regular expression (you could also consider to change the pattern so that you can use something simpler like split()):
var exp = new RegExp("\\[(.+?)\\]\\[(.+?)\\]", 'g');
var match = exp.exec(this.id);
var i = match[1];
var j = match[2];
You could put this together like so:
$('#tableID').delegate('input[type=radio]', 'click', function() {
var match = this.id.match(/\[(.+?)\]\[(.+?)\]/)
var i = match[1]; // use parseInt(match[1]) if you need an integer
var j = match[2];
handleOnClickRadio(i,j);
});
edit: Made code a bit simpler.
If i and j correspond to column and row indicies, see #Caspar Kleijne's answer for an alternative way to retrieve them.
For accessibility, you should consider binding the handler to the change event. Then changes via the keyboard will be recognized too.
wire up the event like this
$("#bigtable input[type='radio']").bind("click", OnClickRadio);
and use the handler like
var OnClickRadio = function () {
var col = $(this).parent("td").index();
var row = $(this).parent("td").parent("tr").index();
handleOnClickRadio(col, row)
});
You can attach an onClick method to a collection of radio buttons within a table with a simple bit of jQuery. When you say 'table called "bigtable"', I'm assuming that you mean that it has id="bigtable" in the following code.
$(document).ready(function() {
$("#bigtable input:radio").click(function() {
// Your on click code here
});
});
However, I would usually give each of the radio buttons a specific class using class="magicRadioButton" and then your jQuery code becomes a little clearer and doesn't rely on all of those radio buttons being within a table;
$(document).ready(function() {
$(".magicRadioButton").click(function() {
// Your on click code here
});
});
Now, if you need to then plug this information into your current handleOnClickRadio method, you can do so with the following.
$(document).ready(function() {
$("#bigtable input:radio").click(function() {
var button_id = $(this).attr("id");
var re = new RegExp("\\[(.*?)\\]\\[(.*)\\]");
var matches = re.exec(button_id);
var i = matches[1];
var j = matches[2];
handleOnClickRadio(i,j);
});
});
Give them class names in conjunction with $(this) in your click trigger
I suggest using delegate if you have lot of radios: that way, only one Event listener will be attached
see http://api.jquery.com/delegate/
$("#globalContainer").delegate("input", "click", function(){
//Perform a string test / regex to test if the id matches something-radio[i][j]
//With a regex with capturing groups you can retrieve [i] and [j] values at the same time
if ( test($(this).attr("id")) ) {
}
});
Ideally, you'd have a onclick assigned to the big table rather than each and every radio button. Events in JavaScript bubble up so the table (which is the eventual parent of all these radio buttons) will receiving the event.
So in jQuery you would have code like this
$('#bigtable').click(handleOnClickRadio);
The signature of your handleOnClickRadio function would be
function handleOnClickRadio(evt) {
var radio = evt.target;
var id = $(radio).attr('id');
}
evt.target will identify the actual radio button that was clicked/checked and you can access other attributes of the radio as well. such as
$(radio).attr('id)
Will give you the id of the radio button.
<input type="radio" class="many-radio-buttons" ....
jQuery:
$('.many-radio-buttons').click(function() {
//your_code;
});