Bind function only works on last element - javascript

I am creating an application to store my homeworks, whenever I touch the li of the homework, the information of this homework yould be displayed from a sqlite database. My problem is that when I add each li from javascript, I bind a function so that each time I touch the item it will return its uid. But whenever I add a new hw, the other ones wont return their uid.
Some of my code:
function newFormSuccess(tx, results){
var lista = $("#lHw");
var obj = $(
'<li><a id="' + results.id + '" href="#detalle" data-uid=' + results.id +
' class="ui-btn ui-btn-icon-right ui-icon-carat-r" data-transition="pop" data-direction="reverse">' +
'<h2>' + results.title + '</h2>' +
'<p>' + results.desc + '</p><p>' + results.date + '</p>' +
'<p class="ui-li-aside">Type</p></a>' +
'</li>'
);
obj.find('#' + results.id).bind('click', function (e) {
$.id = $(this).data('uid');
});
lista.append(obj).listview('refresh');
$.mobile.changePage("#home");
}
Any suggestions? Why is this happening?

I fixed the problem by changing the bind to .on, and using it ona a device ready function, I think this is what the Delegate comments where all about.
$("#lHw").on("click", "li a", function(e){
$.id= $(this).data('uid');
});

Related

onclick function in loop, executes without clicking

Im fetching data from a blizzard api(working fine) and i have a jquery $each loop to retrieve the data which i then append in a ul. i want to add a button within every time the loop gives out data to an object. the problem is that when i use onclick='"+myfunction(param)+"' inside the loop, it will execute the function before i have pressed the button the onclick is attached to. when i check the browser it says onclick="undefined". here is the code:
let tid;
function reply_click(clicked_id){
console.log(clicked_id);
}
$('#searchnow').bind('click',
function (){
function kaldapiclass(){
// console.log("card");
var classSelect=$('#thisclass').val();
$.getJSON('https://us.api.blizzard.com/hearthstone/cards?
locale=en_US&access_token=hidden&class='+classSelect, function(data) {
$('#kortliste').empty();
$.each( data.cards, function(i, card) {
$()
$('#kortliste').append("<li id='" + card.id + "'><img src='" + card.image + "'><p>"+
card.name +"</p><button onclick='"+reply_click(card.id)+"'>HERE</button></li>");
});
});
};
clearTimeout(tid);
tid=setTimeout(kaldapiclass, 500);
});
ty for your time
-Morten
The code you entered will actually execute the function. So, instead of:
"<button onclick='"+reply_click(card.id)+"'>HERE</button>"
you should just define the element the way you would place it in dom:
"<button onclick='reply_click("+card.id+")'>HERE</button>"
Only the card.id should be dynamic.
I would also suggest to append html only once, this way:
var toAppend = '';
$.each( data.cards, function(i, card) {
toAppend += "<li id='" + card.id + "'><img src='" + card.image + "'><p>" + card.name + "</p><button onclick='reply_click(" + card.id + ")'>HERE</button></li>";
});
$('#kortliste').html( toAppend );

jQuery getJSON and get value from button

I'm download data from JSON file and display button with value:
function iterateOverPrzepisy(best) {
$('#listaPrzepisow').html('');
$.getJSON('przepisy.json', function(data) {
for (var x in przepisyDost) {
$('#listaPrzepisow').append(" <div data-role=\"collapsible\"><h2>" + przepisyDost[x].nazwa + "</h2>" +
"<ul data-role=\"listview\" data-theme=\"d\" data-divider-theme=\"d\">" +
"<li>" +
"<h3>Składniki: " + przepisyDost[x].skladniki + "</h3>" +
"<p class='ui-li-desc' style='white-space: pre-wrap; text-align: justify;'>" + przepisyDost[x].tresc + "</p>" +
"<button id='ulubioneBtn' value='" + przepisyDost[x].id + "'>Ulubione</button></li>" +
"</ul>" +
"</div>");
j++;
}
})
}
When I click to button #ulubioneBtn I would like to get value from this button. So I add done to getJSON
}).done(function(data){
$('button#ulubioneBtn').click(function (event) {
console.log("Ulubione: ");
event.preventDefault();
var id = $("button#ulubioneBtn").val();
console.log("Value: " + id);
//dodajemy do ulubionych
localStorage.setItem("ulubione"+id, id);
});
});
But it's not working. When I click on button Ulubione I always get in console log value = 0
The problem seems to be that you add multiple buttons with the same id. An id of a html element should be unique.
przepisyDost does not appear to be defined at
for (var x in przepisyDost) {
? Try
for (var x in data.przepisyDost) {
Duplicate id's are appended to document at
"<button id='ulubioneBtn' value='" + przepisyDost[x].id
+ "'>Ulubione</button></li>" +
within for loop. Try substituting class for id when appending html string to document
"<button class='ulubioneBtn' value='" + data.przepisyDost[x].id
+ "'>Ulubione</button></li>" +
You could use event delegation to attach click event to .ulubioneBtn elements, outside of .done()
$("#listaPrzepisow").on("click", ".ulubioneBtn", function() {
// do stuff
})
I have created a dummy JSON and executed the same JS with a single change.
In onclick handler instead of getting button I am using $(event.target).
And it is working fine.
Please find the fiddle https://jsfiddle.net/85sctcn9/
$('button#ulubioneBtn').click(function (event) {
console.log("Ulubione: ");
event.preventDefault();
var id = $(event.target).val();
console.log("Value: " + id);
//dodajemy do ulubionych
localStorage.setItem("ulubione"+id, id);
});
Seems like first object doesn't have any id value.
Please check JSON response returned from server.
Hope this helps you in solving.

Using an event handler on a anchor link added in Javascript

I have an Ajax call that returns an array of movie titles. I'd like to click on a button next to each title and add the title to a "currently watching" list. My "add" link doesn't seem to be accepting the event handler. What can I do to add the specified title to my "currently watching" list
$("#search").click(function(event){ event.preventDefault();
var show = $("#showTitle").val().toLowerCase();
console.log("the show title is " + show);
var url = "https://api.themoviedb.org/3/search/movie?query=" + encodeURIComponent(show)+ "&api_key=9b97ec8f92587c3e9a6a21e280bceba5";
console.log(url);
$.ajax ({
url: url,
dataType: "json",
success: function (data) {
// console.log(data.results);
var htmlStr = '';
$.each(data.results, function(i, results){
htmlStr += '' + 'Add' + ' <h2 class="movie-title">' + results.original_title + '</h2>' + "Average Rating " + results.vote_average + '<br>' + '<p class="showDescription">' + results.overview + '</p>' + '<br />' + '<img src=https://image.tmdb.org/t/p/w185' + results.poster_path + '>';
});
// console.log(htmlStr);
$('#searchresults').html(htmlStr);
}
// updateCount(); - count the classes inside the "currentywatching" function
}); //close .ajax
});
$('.addCurrentlyWatching').on('click', function(e){
e.preventDefault();
var movieTitle = $('.movie-title').text();
// console.log(movieTitle);
$('.currently-watching').append('<li>' + movieTitle + '</li>');
});
<section id = "shelf1">
<h2> Currently Watching </h2>
<ul class="currently-watching"></ul>
<div class="number">
<p> You currently have <span id="count"> 0 </span> shows in this list. </p>
</div>
</section>
The solution:
$(document).on('click','.addCurrentlyWatching', function(e){
e.preventDefault();
var movieTitle = $('.movie-title').text();
// console.log(movieTitle);
$('.currently-watching').append('<li>' + movieTitle + '</li>');
});
If you are interested in a more detailed answer:
Explanation
use
$('body').on('click','.addCurrentlyWatching', function(e){
take a look at Event binding on dynamically created elements?
and in
' + 'Add' + '
if you have Add variable defined use
' + Add + '
if you not
Add
and you can use
var movieTitle = $(this).next('.movie-title').text();
instead of
var movieTitle = $('.movie-title').text();
For older versions of jQuery use $.live & $.delegate
Docs:
http://api.jquery.com/live/
http://api.jquery.com/delegate/

Dynamically add jQuery event

I'm trying to dynamically add buttons, and add a jQuery listening even to them.
However, I'm having troubles with JavaScript's scoping (at least I think that's it is).
This is pretty much my code:
for (var item in group) {
$('div').append("<input type='button' value='" + item + "' id = 'id" + item + "'>");
$('#id' + item).click(function() {
alert("Hello from " + item);
});
}
Now the problem is that no matter which button I click, the alert inside the event callback always uses the last item.
Now I understand why this is happening (well, roughly :P), but how I can fix it?
one way of achieving this correctly is like so
for (var item in group) {
$('div').append("<input type='button' value='" + item + "' id = 'id" + item + "'>");
(function(item){
$('#id' + item).click(function() {
alert("Hello from " + item);
});
})(item);
}
here is a jsfiddle to demonstrate http://jsfiddle.net/reefbarman/bbP64/
You can use jQuery's $.each method to iterate over the group array in the same way, but this will solve the issue for you:
$.each(group,function(i,v){
$('div').append("<input type='button' value='" + v + "' id = 'id" + v + "'>");
console.log($('#id' + v))
$('#id' + v).click(function() {
alert("Hello from " + v);
});
});
http://jsfiddle.net/ebiewener/byV9X/
I would look in to using the jQuery Delegate function.
http://api.jquery.com/delegate/
That will attach an event handler to a container. All the element events in the container will trickle up to the container and if handled will trigger the event handler.
It works for me: http://jsfiddle.net/bgt89/ but i did change your handler to use closures.
var group = ['asdf', 'rere', 'eeeee']
$(document).ready(function() {
for (var item in group) {
$('div').append("<input type='button' value='" + item + "' id = 'id" + item + "'>");
$('#id' + item).click((function(item) {
return function() {
alert("Hello from " + item);
}
})(item));
}
});
Most of answers above are correct, but unnecessarily verbose. "this" is your friend.
for (item in group) {
$('div').append("<input type='button' value='" + item + "' id = 'id" + item + "'>");
$('#id' + item).click(function() {
alert("Hello from " + this.id.slice(2) );
});
}
The easy ways: pass some event data:
for (var item in group) {
$('div').append("<input type='button' value='" + item + "' id = 'id" + item + "'>");
$('#id' + item).click({item: item}, function(event) {
alert("Hello from " + event.item);
});
}
Or use event.target or this:
for (var item in group) {
$('div').append("<input type='button' value='" + item + "' id = 'id" + item + "'>");
$('#id' + item).click(function(event) {
alert("Hello from " + event.target.id); //or this.id
});
}
I think everything is OK in your code except for using the item variable in the alert() statement.
Since the alert runs long after the for loop has finished, the alert will see the last value for item, not the one you want. If you just want to access the currently clicked on items ID, then you can just get that from the this reference rather than passing it in. Try changing your code to this:
for (var item in group) {
$('div').append("<input type='button' value='" + item + "' id = 'id" + item + "'>");
$('#id' + item).click(function() {
alert("Hello from " + this.id.slice(2));
});
}
Works here in this jsFiddle: http://jsfiddle.net/jfriend00/uyK3m/
Harmen,
Why not you jquery's live function.
It allows you to bind a function to an event on a set of objects with the jquery selector just like $('#button').click() does but also allows new elements that are appended in the future to also work with the click event. This would fit your dynamically requirement.
See the example below. I use the live function to bind click event to all elements that are a class 'testButton'. Then to get the value use the attr('value') on the $(this) because this is the element clicked.
var group = ["Test 1", "Test 2", "Test 3"];
for (var item in group) {
$('div').append("<input class='testButton' type='button' value='" +item+ "'>");
}
$('.testButton').live('click', function(e) {
alert('Hello Im From ' + $(this).attr('value'));
});
Jquery Live Function : http://api.jquery.com/live/
Working Example : http://jsfiddle.net/bbP64/12/
Hope that helps.

How to fetch the id of dynamically generated textboxes?

How is it possible to get the id of the dynamically generated textboxes using jquery?. I need to fire the TextChanged event for the corresponging textbox. There is no method reference for the textboxes in the code behind.How can i refer to any method in the codebehind on firing the event. Somebody please help. I dont know jquery much. The entire script im using is as as follows:
<script type="text/javascript">
$(init);
function init()
{
$('#test').droppable(// Div Control
{
drop: handleDropEvent
});
$('a').each(function(idx, item) {
$(item).draggable({ cursor: 'move', helper: 'clone' })
});
}
$(function() {
$("#draggable").draggable(); //Nothing to do with this div
});
function handleDropEvent(event, ui)
{
var draggable = ui.draggable;
document.getElementById('test').innerHTML += addColumn(draggable.attr('text')) + '<br>';
}
function addColumn(column)
{
var iHtml;
// This code will generate a checkbox and a textbox. I need to fire the event of thus generated textboxes.
iHtml = '<div id="dv' + column + '" width="100px;" height="20px;" padding: "0.5em;"> ' + '<span title="ToolTipText">' + '<input type="checkbox" id="cb' + column + '" value="' + column + '" /> <label for="cb' + column + '">' + column + '</label></span><input type="text" runat="server" id="aln' + column + '"> </div>';
return iHtml;
}
</script>
There's two ways: keep the generated element, or generate an ID when you generate your new element.
a) keep the generated element
This requires that you don't use innerHTML, but create the element (with document.createElement, or with jQuery's $), and then you can use the element directly (no need to call it by ID any more). For instance, with jQuery:
var container = $('#container');
var myDiv = $('<div id="myDiv"/>');
var myCheck = $('<input type="checkbox"/>');
myDiv.append(myCheck);
container.append(myDiv);
b) generate the ID
container.innerHTML = '<div id="myDiv"><input type="checkbox" id="myCheck"/></div>';
// and after this you can get them by ID:
var myCheck = $('#myCheck');
I would just add a class to the textbox in your iHtml then use .live() event
replace your iHtml with this
iHtml = '<div id="dv' + column + '" width="100px;" height="20px;" padding: "0.5em;"> ' + '<span title="ToolTipText">' + '<input type="checkbox" id="cb' + column + '" value="' + column + '" /> <label for="cb' + column + '">' + column + '</label></span><input class="myclass" type="text" runat="server" id="aln' + column + '"> </div>';
then add the live event
$('.myclass').live('change', function() {
alert(' Live handler called.');
});
here is a WORKING DEMO

Categories