Double click on added select option not working - javascript

I have two selects that both have use a function to add elements to the other select.
Here's what I have:
$("#lecturers option").dblclick(function ()
{
var element = $("#lecturers option:selected");
var value = element.val();
element.remove();
var values = value.split(";")
$("#selected_lecturers").append('<option value="' + value + '">' + values[2] + ', ' + values[1] + '</option>');
});
and vice versa:
http://jsfiddle.net/VJAJB/
It somehow only works once, and the newly added elements don't trigger the function.
Any idea on how to fix this?

The issue is how you bind the dblclick function to the elements. The current selector only returns the option elements you have in your select element at the time of binding. To alter this, you can use delegated events.
$('#lecturers').on('dblclick', 'option', function() {
//Do stuff here
});
This makes sure that any option element you add to the select element will trigger this event when it is double clicked.
Here is an updated fiddle: http://jsfiddle.net/VJAJB/4/
Please note that other users have given you solutions that will work. However, best practice is to limit the number of events bound to the document itself. Whenever possible, you should bind delegated event listeners to the nearest non changing element.

This happens because the handler doesn't get bound to the new elements. You can do it like this, which will bind it to a descendant (in this case body) and specify the selector it will be applied to:
$('body').on('dblclick', '#lecturers option', function ()
{
var element = $("#lecturers option:selected");
var value = element.val();
element.remove();
var values = value.split(";")
$("#selected_lecturers").append('<option value="' + value + '">' + values[2] + ', ' + values[1] + '</option>');
});
$('body').on('dblclick', '#selected_lecturers option', function ()
{
var element = $("#selected_lecturers option:selected");
var value = element.val();
element.remove();
var values = value.split(";")
$("#lecturers").append('<option value="' + value + '">' + values[2] + ', ' + values[1] + '</option>');
});
If both have a parent/descendant element that is present at the time of binding, you can use that instead of 'body' to improve performance.
Fiddle: http://jsfiddle.net/VJAJB/2/

You need to use on method instead. In latest jQuery versions is:
$( document ).on( "dblclick", "#lecturers option", function ()
Updated jsFiddle

Related

jQuery Custom AutoComplete

I am trying to make an autocomplete suggestion for countries listed in my database. I managed to get the list and I am trying to bind click event for entries for each country. Although I believe this is the way to do it, code is always using the last item's value and placing it to the input field.
Suggestions is my autocomplete container and the text field that I want to update is the box.
$('#box').on('input', function (){
var typedLocation = { 'location' : $(this).val() };
var key;
$.post( "/suggestions.php", typedLocation, function( data ) {
$('#Suggestions').html('').show();
for (key in data) {
$('#Suggestions').append('<div id="suggest' + key + '" >' + data[key] + '</div>');
$('#Suggestions').find('#suggest' + key).click(function (){
$('#Suggestions').hide();
$('#box').val(data[key]);
});
}
});
});
Instead of using the variable for setting the value of input field, I have used $(this).html() in the click function.
Adopting it to Joe's example (as it seems more elegant):
var $elem = $('<div>' + data[key] + '</div>');
$elem.click(function () {
$('#Suggestions').hide();
$('#box').val($(this).html());
});
$('#Suggestions').append($elem);

How to auto trigger an onclick function in dynamically added HTML element using jQuery or JavaScript

I am doing an attach files project where I need to auto check a file name when there is only one file to be chosen to attach. It is easy to auto check it as a checkbox, but when it is checked, there is an onclick function called to update the file in the server side.
Since the <input> tag is dynamically added based on the number of required attaching files, .trigger('click') didn't work on it.
$.each(speedLetterArray, function (key, value) {
var idLine = fileId + '_b' + value.reasonCode;
var idContainer = 'sliC_f' + idLine;
var idItem = 'sli_f' + idLine;
output.push('<div style="' + cssDisplay + '" class="sliContainer" id="' + idContainer + '">');
//auto checked if only one item
if (fileCount == speedLetterArray.length) {
value.isSelected = 'true';
}
if (value.isSelected == 'true') {
output.push('<input id="' + idItem + '" onclick="updateSpeedLetterItemLists(this);" type="checkbox" name="' + idItem + '" value="' + value.reasonCode + '" class="testClass" style="margin:0px;" />');
} else {
//some code here
}
}
I used checked=checked to auto check the file, but couldn't trigger the onclick function updateSpeedLetterItemLists(this) to update the files on server side.
which works fine when I manually click it.
I tried $(.sliContainer).find('input:checkbox:first').trigger('click'); after the <input> tag or in $(document).ready, either of them works.
I thought maybe I didn't find the right object since when I use alert($(.sliContainer).find('input:checkbox:first').val()) I get "undefined" value.
You could do
$('yourelemtid').click()
Or since it is dynamically added
$( "yourelemtid" ).live( "click", function() {
});
Since the element is added after the initial javascript initialization it won't see your new elements to add the hooks onto.
jQuery Doc for .live
.live is deprecated, use this:
$(document).on( "click", "#yourelemtid", function() {
...
});

Bind handlers on page load with .each() and adopt them with jQuery .clone(true,true)

To prepare dropdown elements and their behavior i bind click event handlers to show/hide the appropriate shallow divs (e.g. the dropdown menu lists) with jQuery .each().
// Excerpt, this is just for debugging purpose, s. below also
$('.m-dropdown-select__trigger').each(function() {
var triggerElem = $(this);
triggerElem.on('click', function(e) {
if(e) e.stopPropagation();
if(e) e.preventDefault();
if(triggerElem.hasClass('is-open')) {
// debug if we are in the original or cloned object
alert('hide this, ' + triggerElem.closest('dl').attr('id') + ', parent: ' + triggerElem.parents('.m-form-elements--accompanied__item').attr('id'));
triggerElem.removeClass('is-open');
} else {
// debug if we are in the original or cloned object
alert('show this, ' + triggerElem.closest('dl').attr('id') + ', parent: ' + triggerElem.parents('.m-form-elements--accompanied__item').attr('id'));
triggerElem.addClass('is-open');
}
});
});
When i deep copy (with .clone(true, true)) a div which comprises one of those dropdowns, the event handler are not bound to the dropdown within the cloned div but on the original object.
E.g. i have a link somewhere in the page which copies additional accompanies form inputs (and a dropdown for salutation) and insert them after the last item.
// Clone first hardcoded container, adapt some attributes and insert it
var accompaniesCount = 2;
$('.js-add-accompanies').on('click', function(e) {
if(e) e.preventDefault();
var count = accompaniesCount++;
// Grap the first (hardcoded) item and copy it
var cont = $('#accompanied-item-1').clone(true, true);
// change clone attributes
cont.attr('id', 'accompanied-item-' + count );
cont.find('.m-form-elements--accompanied__heading span').text(count);
cont.find('.m-dropdown-select__select')
.attr('id', function(index, attr) {
return attr.replace(1, count);
})
.attr('name', function(index, attr) {
return attr.replace(1, count);
})
cont.find('.m-dropdown-select__definitionlist')
.attr('id', function(index, attr) {
return attr.replace(1, count);
})
cont.find('input').val('');
cont.insertAfter($('[id^=accompanied-item-]:last'));
});
Demo: http://jsfiddle.net/felic/L98jzkko/18/
Info for the fiddle example: Click on "Anrede" twice to get debugged output. Then click on "Add accompanies" and toggle "Anrede" there. Parent is always the first entry (e.g. the original object).
What i am missing here? Thx in advance.
You are dealing with dynamic elements, so the way to register event handlers is to use event delegation
$(document).on('click', '.m-dropdown-select__trigger', function(e) {
var triggerElem = $(this);
if(e) e.stopPropagation();
if(e) e.preventDefault();
if(triggerElem.hasClass('is-open')) {
// debug if we are in the original or cloned object
alert('hide this, ' + triggerElem.closest('dl').attr('id') + ', parent: ' + triggerElem.parents('.m-form-elements--accompanied__item').attr('id'));
triggerElem.removeClass('is-open');
} else {
// debug if we are in the original or cloned object
alert('show this, ' + triggerElem.closest('dl').attr('id') + ', parent: ' + triggerElem.parents('.m-form-elements--accompanied__item').attr('id'));
triggerElem.addClass('is-open');
}
});
Demo: Fiddle

jQuery highlight matched elements with live() or on()

in my jsFiddle example can you see that I made a button where I add some elements and links to delete this elements. In this example it is not about going to delete the elements, but to hover the (remove)link made by clicking the button so it highlights the element with the same "number" attribute.
I have tried to use live(); and on(); for it, but it does not do anything, because the items are made after building the page.
I prefer to use on(); now because jQuery says:
As of jQuery 1.7, the .live() method is deprecated. Use .on() to
attach event handlers. Users of older versions of jQuery should use
.delegate() in preference to .live().
My jQuery code:
function numbers() {
return $('#links span').length;
}
$('#add').on('click', function () {
$('#links').append('<span number="' + (numbers() + 1) + '">Remove element ' + (numbers() + 1) + '</span><br />');
$('#elements').append('<div number="' + numbers() + '" class="element">Element ' + numbers() + '</div>');
});
$('#links span').live('hover', function () {
var number = $(this).attr('number');
if ($('#elements .element').attr('number') == number) {
$(this).addClass('highlight');
}
});
First of all, you should dynamically bind the events, since the elements are added dynamically. Second of all, you should make use of mouseenter and mouseleave events, since you want to toggle the highlighting and need to know when the cursor is leaving the element. And third of all I recommend using data--attributes instead of a custom attribute called number.
function numbers() {
return $("#links span").length;
}
$("#add").on("click", function () {
var number = numbers() + 1;
$("#links").append("<span data-number='" + number + "'>Remove element " + number + "</span><br />");
$("#elements").append("<div data-number='" + number + "' class='element'>Element " + number + "</div>");
});
// Dynamically bind mouseenter and mouseleave events, so they also apply to dynamically added elements
$("body").on("mouseenter", "#links span", function () {
var number = $(this).data("number");
$(".element[data-number='" + number + "']").addClass("highlight");
}).on("mouseleave", "#links span", function () {
var number = $(this).data("number");
$(".element[data-number='" + number + "']").removeClass("highlight");
});
FIDDLE

calling javascript function too many times

I'm just getting into Javascript and I've run into the same problem a number of times with different pieces of code: I have a function that creates a type of element and a function that does something with that type of element. It seems obvious to me that I need to call the "do something" function after the element has been created, but when I do, it ends up running more times than I'd like.
Here's an example of my problem:
function rightClick(){
$(".element").mousedown(function(e){
switch (e.which){case 3: alert( $(this).attr("id") )};
});
};
function doubleClick(){
var counter = 0;
$(document).dblclick(function(e){
counter++;
elementId = "element" + counter;
$("#new_elements").append("<div class='element'" +
"id='" + elementId + "'" +
"style='position:absolute;" +
"top:" + e.pageY + ";" +
"left:" + e.pageX + ";'>" +
elementId+ "</div>");
rightClick();
});
In this example, if I create 4 elements and I right-click on the first one I created, I end up getting 4 alert boxes instead of one. If I right-click on the second element I created, I get three alerts; the third: 2 alerts; the fourth: one alert.
Can anyone explain to me why this is happening, and how to fix it so that I only get one alert each time I right-click on an element?
Binding is the act of associating an event with a DOM element. The .mousedown and similar events only bind on elements that already exist.
Each time you call rightClick() you bind a new event to all current .element elements.
You can bind functions to the same element as much as you'd like, which is why you see the function being called many times.
For dynamic elements should checkout .on or .delegate which work like this:
Example of jQuery.fn.on
$(document.body).on("mousedown", ".element", function(e) {
if (e.which === 3) alert($(this).attr("id"));
});
Example of jQuery.fn.delegate
$(document.body).delegate(".element", "mousedown", function(e) {
if (e.which === 3) alert($(this).attr("id"));
});
Only call this once and you should be pretty much okay. If you're not using jQuery 1.7 or higher you will want to use .delegate() instead of .on.
You do not need to bind the event everytime you insert and element into the DOM. You can use .on to attach event handlers for elements that are dynamically inserted.
$(document).on('mousedown','.element', (function(e){
switch (e.which){
case 3: alert( $(this).attr("id") );
break;
};
});
var counter = 0;
$(document).dblclick(function(e){
counter++;
elementId = "element" + counter;
$("#new_elements").append("<div class='element'" +
"id='" + elementId + "'" +
"style='position:absolute;" +
"top:" + e.pageY + ";" +
"left:" + e.pageX + ";'>" +
elementId+ "</div>");
});
I believe you are adding the same handler several times, meaning that when you click a button you are re-binding the action to the same function.
You've bound your event handler to the class '.element'. This means that every element with the class '.element' on your page will fire that event when the right click occurs.

Categories