Some code of mine uses jquery to create elements <a> with a function given for click behavior:
$(alternatives).each(function (idx, elt) {
var element = $('<span class="label label-success">');
var link = $('<a class="prop' + idx + '" title="' + elt + '">' + elt + '</a>');
link.click(switchLabel);
element.append(link);
list.append(element);
});
The idea here is to catch the click event on the <a class="prop1-0" title="myTitle">my link</a> to change the text in a <span id="corr1-0">my old text</span>. The link between both element is made by the class suffix, f.i. 1-0.
I have several pairs <a>/<span>, I checked every id.
Some links work, but some do not: no error in console, nothing to trace with firebug...
The function binded is :
function switchLabel(e) {
$('#corr'+ e.target.className.substr(4)).text($(e.target).attr('title'));
}
Do you have some tips to help me track this unwanted behavior?
May I make a mistake in the implementation?
Regards
Your variables don't match, you are using index and not idx etc. and there are easier ways to create elements and event handlers ?
$.each(alternatives, function (idx, elt) {
var element = $('<span />', {'class' : 'label label-success',
id : 'corr'+idx
}
),
link = $('<a />' {id : 'prop' + idx,
title : elt,
text : elt
}
);
link.on('click', function() {
$('#' + this.id.replace('prop','corr')).text(this.title);
});
list.append( element.append(link) );
});
Related
So I have multiple delete buttons on a table and each button has there own unique id. I am trying to get this value via javascript but I can't get it to work at all.
Here is a section js that is working properly and loads the correct html (this is ran for each movie):
function createRow(movie) {
movie.NewDate = new Date(movie.ReleaseDate);
return '<tr><td><img class="movieImage" src="' +
movie.ImageLink +
'" alt="' +
movie.Title +
' Image" style="width:50px;height:75px">' +
'<td>' +
movie.Title +
'</td><td>' +
movie.NewDate.toLocaleDateString("en-US") +
'</td><td><button type="button" class="removeButton" value="' + movie.DVDID + '">Delete</button></td></tr>';
}
And here is the js where I am trying to retrieve the id:
$(document)
.ready(function () {
var deleteButtons = $(".removeButton");
deleteButtons.each(function (index) {
var currentButton = $(this);
var buttonValue = currentButton.val();
currentButton.click(function () {
alert(buttonValue);
});
});
});
I found the last snippet via Click one of multiple buttons, put value in text input
Right now just getting a proper alert would be sufficient.
Have you tried this approach:
$("#tableId").on("click", ".removeButton", function(){ alert($(this).attr("value")); })
This "on" binds all the ".removeButton" elements with the given function when click is triggered.
Your javascript should look like this:
$(document).ready(function () {
var deleteButtons = $(".removeButton");
deleteButtons.on('click', function() {
alert($(this).attr('value'));
});
});
Also, since you adding these buttons dynamicly with javascript, you may need to rebind button click events after you add new row. Also binding should be done after loading button html to DOM.
Since you are creating buttons dynamically, you won't be able to reach them properly because when the javascript was initiated they didn't exist in the DOM. So in order for you to be able to find the buttons, you'll have to look at the document scope and then find which button (class) you click on, like so:
$(document).on('click', '.removeButton', function(){
console.log($(this).val())
})
See fiddle for complete example
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() {
...
});
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
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
I want to make automate color parent changer in my js.
here is my html :
<div id="parent">
<div id="target" >
traget
</div>
</div>
And here is my js :
function ColorBox(target_id, btn) {
this.parent = $("#" + target_id).parent();
this.color = $(this.parent).append('<div class="color" >ops</div>');
$(this.color).append('<button class="change" value="' + btn + '">' + btn + '</button>');
this.ChangeColor = function (elm_id) {
$(this.parent).css('background', $(elm_id).val());
return true;
}
// here my problem start
$("#" + $(this.parent).attr('id') + " .change").bind('click', function () {
// how I can do it in here.
ColorBox.ChangeColor($(this));
});
}
$(document).ready(function () {
ColorBox('target', 'red');
});
I add some element to target parent and I want when clicked on change class the ColorBox.ChangeColor execute and but in bind method I can't use this.ChangeColor.
Now how I can do it ?
Try keeping the function's scope separate by assigning this to a variable (e.g. self). This will avoid any issues with accessing function variables and functions inside different scopes.
Here's a working demo: http://jsfiddle.net/37zq5/10/
Here you can see the code changes I made:
function ColorBox(target_id, btn) {
var self = this;
self.parent = $("#" + target_id).parent();
self.color = self.parent.append('<div class="color" >ops</div>');
self.color.append('<button class="change" value="' + btn + '">' + btn + '</button>');
$("#" + self.parent[0].id + " .change").on('click', function () {
self.parent.css('background', this.value);
});
};
$(document).ready(function () {
new ColorBox('target', 'red');
new ColorBox('target2','lime');
});
Personally I would probably do it this way. It's a bit of a different approach; you don't need this, you don't need new, and it's less code:
function ColorBox(target_id, btn) {
var $parent = $("#" + target_id).parent();
var $color = $('<div class="color">ops</div>').appendTo($parent);
var $button = $('<button class="change" value="' + btn + '">' +
btn + '</button>').appendTo($color);
$button.on( 'click', function (event) {
$parent.css('background', $button.val());
});
}
$(document).ready(function () {
ColorBox('target', 'red');
});
Whether you take this approach or do something more like #Joe's answer, there is one thing you should definitely change to work like I have it in this code. Your parent and color variables are both already jQuery objects; there is no need to wrap them in additional $() calls when you use them. So change the names of these variables to include the $ prefix as a reminder that they are jQuery objects, and then just use them directly where you need them instead of the extra $() wrapper.
If you use self as in #Joe's answer, then it would be code like:
self.$parent = $("#" + target_id).parent();
self.$color = self.$parent.append(...);
The $ prefix on these names isn't necessary, but it's a common convention to indicate a variable or property that is a jQuery object. It helps keep straight whether you need to use another $() around it.
Also, be aware that your parent and color variables are the same element. It looks like you're expecting color to be the <color> element, but it isn't. I changed the code so it is the <color> element.