I am inserting elements into the DOM populated with some data I retrieved from a web service. I attached an inline click event to call a function when invoked. The problem is I am not getting a reference to the element that invoked that function.
Code that appends the new elements:
$.getJSON("/search?" + $(this).serialize(), function (data) {
if (data != null) {
$.each(data, function (index, video) {
resultItem.append("<li ><a onclick='loadNewVideo(e)' href='play?video=" + video.video_id + "'>" + "<img width='185' src='" + video.defaultImg + "'/>" + "<span class='video_left_title'>" + video.song.song_name + "<h6 class='artist_name'>" + video.artist.artist_name + "</h6></span></a>");
});
}
});
Function:
function loadNewVideo (e) {
e.preventDefault();
alert($(this).attr("href"));
}
Instead of using inline event handlers, you could delegate the clicks on all a to resultItem:
// Call this only once, when resultItem is already in the DOM
// (for example, on a document.ready callback)
resultItem.on('click', 'a', loadNewVideo);
// Proceed with your current code (slightly modified):
function loadNewVideo (e) {
e.preventDefault();
alert($(this).attr("href"));
}
$.getJSON ("/search?" + $(this).serialize(),function (data) {
if (data != null) {
$.each (data,function (index,video) {
resultItem.append("<li ><a href='play?video=" + video.video_id +"'>"
+ "<img width='185' src='"+video.defaultImg +"'/>"
+ "<span class='video_left_title'>"+ video.song.song_name
+ "<h6 class='artist_name'>"+video.artist.artist_name
+ "</h6></span></a>");
});
}
});
Inline onclick handlers don't go through jQuery, which is why you don't have access.
You can either leave those there and change the handler:
function loadNewVideo(e) {
e.preventDefault();
alert($(e.target).attr("href"));
}
Or, and more preferably, don't use the inline handlers. Just give the a elements a class of video (or whatever) and install handlers with jQuery:
...
resultItem.append("<li><a class='video' href=...'")
...
// and elsewhere
$(resultItem).on('click', 'a.video', loadNewVideo);
jQuery's event object allowed me to grab what the documentation calls the 'current DOM element within the event bubbling phase'.
var originatingElement = event.currentTarget;
Related
$(document).ready(function(){
$.getJSON("https://api.deckbrew.com/mtg/sets", function(sets) {
$(sets).each(function() {
$('<div id="' + this.name + '" class="set"/>')
.text(this.name)
.appendTo("#collection");
});
});
$.getJSON("https://api.deckbrew.com/mtg/cards", function(cards) {
$(cards).each(function(){
$('<div id="' + this.name + '" class="card"/>')
.text(this.name)
.appendTo("#" + this.editions[0].set);
});
});
});
I was wondering how I might (without using ajax and sticking to the "getJSON" method) make the two calls happen asynchronously. I can't make anything useful happen with the second jQuery object; I believe that's because of the synchronous nature of the calls. How can I make them work in order?
If you want these to happen in order, then you need to specifically serialize them and using the built-in promises that getJSON() returns is a simple way to do that:
$(document).ready(function () {
$.getJSON("https://api.deckbrew.com/mtg/sets").then(function (sets) {
$(sets).each(function () {
$('<div id="' + this.name + '" class="set"/>')
.text(this.name)
.appendTo("#collection");
});
}).then(function () {
$.getJSON("https://api.deckbrew.com/mtg/cards").then(function (cards) {
$(cards).each(function () {
$('<div id="' + this.name + '" class="card"/>')
.text(this.name)
.appendTo("#" + this.editions[0].set);
});
});
});
});
Or, a little faster (end to end time) would be to launch both requests at the same time and then process the results in order. Again using jQuery promises to manage this:
$(document).ready(function(){
$.when(
$.getJSON("https://api.deckbrew.com/mtg/sets"),
$.getJSON("https://api.deckbrew.com/mtg/cards")
).then(function(r1, r2) {
// process sets
var sets = r1[0];
$(sets).each(function() {
$('<div id="' + this.name + '" class="set"/>')
.text(this.name)
.appendTo("#collection");
});
// process cards
var cards = r2[0];
$(cards).each(function(){
$('<div id="' + this.name + '" class="card"/>')
.text(this.name)
.appendTo("#" + this.editions[0].set);
});
});
});
This last scheme uses $.when() to tell us when both ajax calls are done and it also sequences the results for us, regardless of which one actually finished first.
To run the getJSONS's in sequence, run the second in the callback of the first
like so
$(document).ready(function() {
$.getJSON("https://api.deckbrew.com/mtg/sets", function(sets) {
$(sets).each(function() {
$('<div id="' + this.name + '" class="set"/>')
.text(this.name)
.appendTo("#collection");
});
$.getJSON("https://api.deckbrew.com/mtg/cards", function(cards) {
$(cards).each(function() {
$('<div id="' + this.name + '" class="card"/>')
.text(this.name)
.appendTo("#" + this.editions[0].set);
});
});
});
});
personally, I would go with #jfriend00's promise method - I was going to add that to this answer, but he answered in the meantime, so, go with that more flexible method
EDIT
Since you said you were trying to use call both getJSON methods in order, then you can make the second call work after the first by using the DOMNodeInserted event
Well maybe a solution would be to use DOMNodeInserted event since you are appending to #collection
so:
$("#collection").on('DOMNodeInserted',function(){
$.getJSON...
});
According to DOCS
DOMNodeInserted
Fired when a node has been added as a child of another node. This
event is dispatched after the insertion has taken place. The target of
this event is the node being inserted.
I am having some trouble trying to store the url parameters of some dynamic links that I created with an ajax post response. The ajax post is working correctly and the name and subgenre vars are being properly filled from the ajax response. Now what I would like to happen is that a user clicks on one of the generated urls, the parameters inside of the urls, i.e. subgenre="blah", are going to be sent to a database and stored. The problem I am having is that a standard event click function will not work inside or outside of the document ready function.
$(document).ready(function() {
$.each(data, function() {
$('#artist-suggestions').append('<li>' + this.name + this.new + '</li>');
});
});
I then created an onclick function, as below, but I can not use the "this" query because it is outside of the document scope. I had to put the onclick function outside of the document ready function or else it would not work.
function artistGen(){
alert('dfdsf');
};
What am I missing here or what am I doing wrong?
You can pass these in the onclick function when you make each element.
$(document).ready(function() {
$.each(data, function() {
artist = this.name;
$('#artist-suggestions').append('<li>' + this.name + this.new + '</li>');
});
})
;
function artistGen(Blah1, Blah2){
saveData(Blah1, Blah2);
alert('dfdsf');
};
In jQuery for dynamic elements you can use the click event in this way
$('#artist-suggestions li').on('click', 'a', function() {
// do something
});
or you can continue with the way you did, by using a function but just add a parameter to that function
like
function artistGen(Artist){
// do something
};
You need to remove the artistGen() function from the scope of the .load()
$(window).load(function(){
$('#artist-suggestions').append('<li>jim new</li>');
});
function artistGen(){
alert('dfdsf');
}
JSFIDDLE DEMO
That's just how it is a function called in those event attributes have to be defined globally(or defined right there) not in any wrapper function. A better solution would be to attach event handlers.
$(document).ready(function() {
function artistGen(){
alert(this.href);
};
$.each(data, function() {
var $li = $('<li>' + this.name + this.new + '</li>');
$li.find('a').on('click', artistGen);
$('#artist-suggestions').append($li)
});
});
I have a problem with displaying the id of the clicked div on the screen in an alert window. I am pretty confident this is because of the order of the controls and event handlers being added to the page, however after trying different ways I am unable to get this to work. Unfortunately I can't post reproducible code due to the div's being created from an ajax get request.
$(document).ready(function () {
$.getJSON('ClientPortal/GetSkills', function (data) {
var test = 'poo';
$.each(data, function (data) {
$('#flipContainer').append("<div class=flip id='" + this.Value + "' value='" + this.Value + "'>" + this.Text + "<//div>");
})
})
})
$(document).ready(function () {
$(".flip").on('click', function () {
alert($(this).attr("id"));
})
})
Try this :
$(document).ready(function () {
$("#flipContainer").on("click", ".flip", function () {
alert($(this).attr("id"));
})
})
You effectively have to base you click-binding on an element existing when the DOM ready event fires... But with this syntax, you delegate the binding on an existing element but it applies to another element contain in the first one...
See the jQuery documentation for on (for line "selector") : http://api.jquery.com/on/#on-events-selector-data-handlereventObject .
i have the following code that, if the #test button is click, a content will be generated in #currentActivities. There is another #hide button which simple hide the content of #currentActivities. My problem is if the first time i click #test, i can get the content. When i click #hide, the content of #currentActivities can be hidden as expected. However, if i click #test again, the content cannot be generated. I have tried to add $('#currentActivities').empty(); at the beginning, but seems not work. Can anyone help me and point out my problems?
$("#test").click(function() {
$('#currentActivities').empty();
$.ajax({
type: "GET",
dataType: "jsonp",
jsonpCallback: "jsoncallback",
data: {
//some data here
},
url: "http://mydomain.com/check.php?jsoncallback=?",
success: function(data) {
$.each(data, function(index, student) {
$('#currentActivities').append(
'<li><a href="tutor_student_detail.html" data-name="' + data[index].data.NameA + '">' +
'<h4>' + data[index].data.NameA + '</h4>' +
'<p>' + data[index].data.NameA + '</p>' +
'</a></li>');
$("li a").click(function() {
window.localStorage["view"] = $(this).data('name');
window.localStorage["Request"] = "true";
}); //end of li a
});
$('#load2').hide();
$('#filter').show();
$('#currentActivities').listview('refresh');
},
error: function(jqXHR, textStatus) {
alert("Request failed: " + textStatus);
}
});
return false;
});
You need to use delegate event (aka live event). Cause you're working with a dynamically loaded DOM elements.
Something like:
$('body').on('click', '#test', function() {
// all code belong to click handler
});
For more on delegate event binding using .on() see here.
NOTE:
Instead of body user any static-container of all those newly loaded and appended element.
As your question is on jquery mobile so I think for live evnet delegation you can try something like:
$('#test').live('click', function() {
// all codes belong to click hander
});
and another way is :
$(document).delegate('#test', 'click', function() {
// codes
});
I'm wondering how is possible to call a function with parameters inside a method.
I have 2 functions and i'd like to call function deleteCode() when clicked on list element which is created by addCode() function.
I'm sure the solution is really simple, but i just can't see it right now.
Many thanks!
function addCode(code) {
$('#codeList').append('<li class="codeList" onClick="deleteCode(code);">' + code + '</li>');
}
function deleteCode(code) {
$('#'+code).remove();
}
Do it unobtrusive and you're fine.
function addCode(code) {
$('#codeList').append($('<li>', {
'class': 'codeList',
'text': code,
'click': function(e) {
deleteCode(code);
}
}));
}
Ref.: $()
Create the <li> element via code rather than appending raw HTML.
function addCode(code) {
// Create the <li>
var newEl = document.createElement("li");
newEl.className = "codeList";
// Assign the click function via jquery's event helper.
$(newEl).click(function(code) {
// Call your deleteCode function and pass in the given parameter.
deleteCode(code);
});
// Append the new element to the codeList node.
$(#codeList).append(newEl);
}
You can try:
function addCode(code) {
$('#codeList').append('<li class="codeList" onClick="deleteCode(' + code + ');">'+code+'</li>');
}
You can do that like this:
function addCode(code) {
$('<li class="codeList">' + code + '</li>').click(function() {
deleteCode(code);
}).appendTo('#codeList');
}
function deleteCode(code) {
$('#'+code).remove();
}
...or more simply:
function addCode(code) {
$('<li class="codeList">' + code + '</li>').click(function() {
$('#'+code).remove();
}).appendTo('#codeList');
}
When using a library like jQuery (or even when not, frankly), there's virtually never any reason to use the old-style onclick attributes for setting up handlers. In the above, I've replaced it with the click function, which sets up a handler when the user clicks the element.
Note: Lazarus notes that your code is removing an element by id using the code value:
$('#' + code).remove();
...but that the code doesn't produce an element with that ID. I assume you've added that element with some other code elsewhere, and that the goal isn't to remove the li you've added with this code.
If you did want to remove that same li on click, no need for an ID at all:
function addCode(code) {
$('<li class="codeList">' + code + '</li>').click(function() {
$(this).remove(); // <== Changed here
}).appendTo('#codeList');
}