Create hidden field element for each drop - javascript

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;
});

Related

on.click not working after first click on dynamically created table

I dynamically create a table full of links of 'actors', which allows to pull the actors information into a form to delete or update the row. The delete button only pops up when you select an actor.
I'm able to click a row, pull the information into the forms, and delete it on first try. However when I attempt to add a new 'Actor' and then delete it, or just delete an existing 2nd row, the button 'Delete Actor' doesn't work. It's only after the first successful delete does the button no longer work.
var addActor = function() {
// Creates a table of links for each added actor with an id based from # of actors
$("#actorsTable").append("<tr><td><a href='' onclick='deleteActor(this)' class='update' data-idx='" + actors.length + "'>" + newActor.fName + " " + newActor.lName + "</a></td></tr> ");
$(".update").off("click");
$(".update").on("click", selectActor);
};
var deleteActor = function(e) {
$("#deleteActor").on('click', function(event) {
event.preventDefault();
var row = e.parentNode.parentNode;
row.parentNode.removeChild(row);
clearForm(actorForm);
actorState("new");
});
};
I'm new to jQuery/javascript, and I'm pretty sure its due to the change in DOM, but I just don't know what to change to make it work.
Here is an Example of it in action
Try
var deleteActor = function(e) {
$("#deleteActor").unbind();
$("#deleteActor").on('click', function(event) {
event.preventDefault();
var row = e.parentNode.parentNode;
row.parentNode.removeChild(row);
clearForm(actorForm);
actorState("new");
});
};
Here is the link for unbind.
http://api.jquery.com/unbind/
The problem is because you're adding another click handler (in jQuery) within the click handler function run from the onclick attribute. You should use one method or the other, not both. To solve the problem in the simplest way, just remove the jQuery code from the deleteActor() function:
var deleteActor = function(e) {
var row = e.parentNode.parentNode;
row.parentNode.removeChild(row);
clearForm(actorForm);
actorState("new");
};
when you add html dynamically you need to attach the event to the parent static element like so:
$("#actorsTable").on("click","a.update", function() {
$(this).closest("tr").remove();
});

jQuery click event lost after appenTo

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);
}
});

clear click queue from jQuery

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().

function called repeatedly in javascript

I define a tag picker which will generate checkbox inputs based on "group". If I select the tags I want and press done button, it should return a string to set the value of a text input.
Here are the related codes. The problem is it only works well at the first time. For example, for the first time, if I checked 'jquery','javascript' in the tags,
console.log('output is:' + tags);
print out 'output is: jquery,javascript'. Works!
Then I use it again and select 'jquery','javascript','bootstrap',
it will return
output is: jquery,javascript,bootstrap
output is:
One more time for 'jquery','javascript','bootstrap', it returns
output is: jquery,javascript,bootstrap
output is:
output is:
Seems the done button pressed, the function is called repeatedly. Being stuck with it for several hours but can't figure out. Really appreciate for your answer! Thanks
(function(){
$.fn.tagPicker = function(source,options){
var settings = $.extend({
perRow : 3
},options);
$.fn.attachRow = function(row,col){
//codes here
...
}
$.fn.attachPicker = function(){
//codes here
// generate html for checkbox inputs
...
};
var $input = this;
if($('.tag-picker').length == 0){
$input.attachPicker();
$('body').on('click','.tag-picker .close-picker',function(){
$('.tag-picker').remove();
})
$('.tag-picker .close-picker').off();
$('body').on('click','.tag-picker #btn-done', function(){
var tags = getTags();
$('.tag-picker').remove();
console.log('output is:' + tags);
$input.val(tags);
});
}
function getTags(){
var t = [];
$('.tag-picker input').each(function(){
if($(this).is(':checked')) t.push($(this).attr('id'));
})
return t.join(',');
}
}
})(jQuery);
$('body').on('click','input.participant',function(){
$(this).val('');
$(this).tagPicker(group);
})
You are initialising the plugin every time the elements are clicked. You should initialise it once, on DOM ready.
OR if you want to do this anyway; you could use .one() for the event to run only once and remove itself. Use .off() to detach an event, attached with .on().

Jquery creating checkboxs dynamically, and finding checked boxes

I have information that comes out of a database and gets put into a list with a checkbox by each element. This is how it is currently done:
function subjects(){
$.ajax({
url: "lib/search/search.subject.php",
async: "false",
success: function(response){
alert(response);
var responseArray = response.split(',');
for(var x=0;x<responseArray.length;x++){
$("#subjects").append("<br />");
$("#subjects").append(responseArray[x]);
$("#subjects").append("<input type='checkbox' />");
}
}
});
}
it works fine, but I need a way to pick up on if a checkbox is clicked, and if it is clicked then display which one was clicked, or if multiple ones are clicked.
I can't seem to find a way to pick up on the checkboxs at all.
the response variable is "math,science,technology,engineering"
Because you are populating the Checkboxes Dynamically you need to Delegate the event
$("#subjects").on("click", "input[type='checkbox']", function() {
if( $(this).is(":checked") ) {
alert('Checkbox checked')
}
});
To better capture the data it is better if you encase the corresponding data into a span , so that it can be easier to search..
$("#subjects").append('<span>'+responseArray[x] + '</span>');
$("#subjects").on("click", "input[type='checkbox']", function() {
var $this = $(this);
if( $this.is(":checked") ) {
var data = $this.prev('span').html();
alert('Current checkbox is : '+ data )
}
});
It would be best to give your dynamically injected checkboxes a class to target them better, but based on your code try:
$("#subjects").on("click", "input", function() {
if( $(this).is(":checked") ) {
// do something
}
});
Since your input elements are added dynamically, you need to use jQuery's .on() function to bind the click event to them. In your case you need to use .on() to bind to an element that exist in the DOM when the script is loaded. In your case, the element with the ID #subjects.
This note from the docs is mainly for machineghost who downvoted my answer for no apparent reason:
Event handlers are bound only to the currently selected elements; they
must exist on the page at the time your code makes the call to .on().
To ensure the elements are present and can be selected, perform event
binding inside a document ready handler for elements that are in the
HTML markup on the page. If new HTML is being injected into the page,
select the elements and attach event handlers after the new HTML is
placed into the page.
$('#subjects input[type=checkbox]').on('click',function(){
alert($(this).prop('checked'));
});
or the change event: in case someone uses a keyboard
$('#subjects input[type=checkbox]').on('change',function(){
alert($(this).prop('checked'));
});
simple fiddle example:http://jsfiddle.net/Dr8k8/
to get the array example use the index of the inputs
alert($(this).prop('checked') +'is'+ $(this).parent().find('input[type=checkbox]').index(this)+ responseArray[$(this).parent().find('input[type=checkbox]').index(this) ]);
simplified example: http://jsfiddle.net/Dr8k8/1/
EDIT: Just for an example, you could put the results in an array of all checked boxes and do somthing with that:
$('#subjects>input[type=checkbox]').on('change', function() {
var checklist = [];
$(this).parent().find('input[type=checkbox]').each(function() {
$(this).css('background-color', "lime");
var myindex = $(this).parent().find('input[type=checkbox]').index(this);
if ($(this).prop('checked') == true) {
checklist[myindex] = responseArray[myindex];
}
});
$('#currentlyChecked').text(checklist);
});
EDIT2:
I thought about this a bit and you can improve it by using .data() and query that or store it based on an event (my button called out by its id of "whatschecked")
var responseArray = ['math', 'science', 'technology', 'engineering'];// just for an example
var myList = '#subjects>input[type=checkbox]';//to reuse
for (var x = 0; x < responseArray.length; x++) {
// here we insert it all so we do not hit the DOM so many times
var iam = "<br />" + responseArray[x] + "<input type='checkbox' />";
$("#subjects").append(iam);
$(myList).last().data('subject', responseArray[x]);// add the data
}
var checklist = [];// holds most recent list set by change event
$(myList).on('change', function() {
checklist = [];
$(myList).each(function() {
var myindex = $(this).parent().find('input[type=checkbox]').index(this);
if ($(this).prop('checked') == true) {
checklist.push($(this).data('subject'));
alert('This one is checked:' + $(this).data('subject'));
}
});
});
// query the list we stored, but could query the checked list data() as well, see the .each() in the event handler for that example
$("#whatschecked").click(function() {
var numberChecked = checklist.length;
var x = 0;
for (x = 0; x < numberChecked; x++) {
alert("Number " + x + " is " + checklist[x] + " of " + numberChecked);
}
});
live example of last one: http://jsfiddle.net/Dr8k8/5/
The general pattern to do something when a checkbox input is clicked is:
$('input[type=checkbox]').click(function() {
// Do something
})
The general pattern to check whether a checkbox input is checked or not is:
var isItChecked = $('input[type=checkbox]').is(':checked');
In your particular case you'd probably want to do something like:
$('#subjects input[type=checkbox]').click(function() {
to limit the checkboxes involved to the ones inside your #subjects element.

Categories

Resources