HTML
Inside <div id='foo-bar-baz'>
I have a series of image links with unique ids as below
<a href=''><img id='12341234' class='foo-bar-thumbnail-image' src='/path/to/image.jpg'></a>
<a href=''><img id='56785678' class='foo-bar-thumbnail-image' src='/path/to/image.jpg'></a>
Javascript / JQuery
The above div is created by a $.get() to a webservice which returns a chunk of HTML in variable response. On success, the $.get() calls the below function:
var thumbnailsDiv = function (response)
{
var json = $.parseJSON(response);
$('#foo-bar-baz').html(json.html);
alert("Setting click functions on thumbnails");
$('.foo-bar-thumbnail-image').unbind().click(function () {
alert("I am thumbnail " + $(this).id);
}, false);
};
As you can see above, I'm trying to bind a click function to each of the image links. However this is not working (with or without the unbind()).
After the above code has run, if I inspect the image links in the Dev Tools, I can see that there are two click event attached already to the thumbnails. Neither of these is my function above. The paths for both of them are from other applications libraries embedded on the page: one is labelled 'jQuery' and the other is labelled 'Bubbling' and 'DOM2'. I'm guessing that it is these attached events that mean I can't add my event above, but I don't know enough about jQuery or javascript to know if this is true (I am a server-side developer normally, I don't know front-end stuff at all.)
Any suggestions as to how I get an on-click event working for these elements would be much appreciated, so that I can replace the demo code above with the code I need to run.
You should be using $(document).on('click','.foo-bar-thumbnail-image',function() ... instead of $.click(function()... since the event handler is on elements that were rendered on the page via JS. That's a "delegated" event handler - you can read more about that here https://learn.jquery.com/events/event-delegation/
You just need to bind the click event to the parent element which already exists on the page.
$('#foo-bar-baz').on('click', '.foo-bar-thumbnail-image', function(){
// what you want to happen when click
// occurs on elements that match '.foo-bar-thumbnail-image'
// within '#foo-bar-baz'
alert("I am thumbnail " + $(this).id);
});
Related
I have a list of divs, that have individual onclick functions.
The functions lead to http links that open in new windows. I can not rewrite the onclick functions before generating the site because it is a third party rss feed that is being generated based on a rss file. Now i walt to keep the individual links but do something else with them.
The chronology would be the following:
User clicks the element that has a prewritten onclick function.
The onclick functions is blocked from opening in a new page.
The link inside the onclick function is saved for further use.
A HTML5 audio element gets the link as a source.
I have so far tried to overwrite the onclick function. Yet I lose the http link in the process.
<div class="fw-feed-item-url"
onclick="window.open('http://www.example.com/podcasts/podcast_eposode3.mp3'
, '_blank')">
$(".fw-feed-item-url").click(function(){
var audioSrcNew = eval($('.fw-feed-item-url').attr('onclick'));
audioElement.src = audioSrcNew;
console.log(audioSrcNew);
$('.fw-feed-item-url').this.attr('onclick','alert("done"); return
false;');
});
In JavaScript, callbacks and event handlers should be executed in the order they were bound, and there is no way to alter that order. The code in the onclick attribute will be bound directly after creation of the element, and will thus be the first to be executed.
The only way to prevent this is to remove the attribute, either in the source or client-side by using jQuery's .removeAttr. So override the onclick event on page load like the following sample code.
<script>
$(document).ready(function() {
var $elements = $(".fw-feed-item-url");
// Iterate over elements
$elements.each(function () {
var $elm = $(this);
// Reference to onclick attribute value for future use
var onClick = $elm.attr("onclick");
console.log(onClick);
// Remove onclick attr and bind your own click event
$elm.removeAttr("onclick").click(function () {
//Own code comes here
alert("Whoa!!!! click worked!!");
})
});
});
Referenced from
How to decide execution sequence for Javascript and Jquery function
Dear Stack Overflow community,
I have been trying to develop a table creator that creates two tables dynamically when a button is clicked. This has worked... Well it hasn't at least for now.
Right now I am generating a <p> element with class heading and a <div> element with class content. When p is clicked, content is slideToogled.
I have tried using on() with jQuery or attaching any function to the element but it doesn't seem to work. Also .hide() doesn't work on content which is extremely annoying. Can anyone give me some advice as to how to approach this please?
On seems to work for content I hard written with HTML, but it doesn't on AJAX generated code appended to the div.
Here are the related snippets of code:
Ajax:
function submition() {
$.ajax({
type: 'GET',
url: 'phpQueries.php?q=getQueryBuilder&schools=' + mySchools.toString()+ '&depts=' + myDeps.toString() + '&lvls=' + myLevs.toString() + '&srcs='+mySrc.toString() + '&codes='+myCodes.toString(),
success: function (data) {
$("#dump_here").append(data);
}
});
jquery:
$(".heading").on("click", function() {
alert("Hello World");
$(this).next(".content").slideToggle(500);
});
PHP:
echo '<p class="heading">See/Hide Comments</p> ';
echo '<div class="content">I am I am I am.... Superman!</div>';
Kind Regards,
Gempio
This because (if I understand correctly) you create a <p> tag with the class heading after you assign the click event handler.
What you want to do is delegate your events to a container that contains your <p> tag. So, let's assume this is your structure:
<div id="dump_here"></div>
You then do this in your JavaScript:
$("#dump_here").on("click", ".heading", function () {
....
This way you assign an event handler to the parent container which already exists, and the event will bubble up once you click on your paragraph. Now you can dynamically add new elements to your HTML within that container and your event handlers will still work.
Why is that? Because you can't assign event handlers to elements that don't exist.
When you do this:
$(".something").click(...)
You don't tell Javascript to do something whenever you click any element with the something class on the page, you assign an event handler to every single already-existing something on the page. If you create a new element, even if it is the same class, you still need to assign an event handler to it.
A quote from the jQuery documentation:
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()
Also David Walsh wrote a nice article explaining Event Delegation.
Hope this helps.
Change this:
$(".heading").on("click", function() {
alert("Hello World");
$(this).next(".content").slideToggle(500);
});
to:
$(document).on("click", ".heading", function() {
alert("Hello World");
$(this).next(".content").slideToggle(500);
});
Alternatively you can put the definition of $(".heading").on("click", ...) into your AJAX success callback, but if you have multiple .heading elements you'll run into multiple event bindings for elements that were there before the AJAX runs, say if it runs twice and appends 2 tables. The reason your method didn't work is the element has to exist before the event is bound. The 1st option I proposed works because the document is where the event is bound, and the last option works because it's in the callback of the AJAX that creates the element, so the element exists at the time it was bound.
So let's say, that this is your HTML:
<div id="dump_here">
<!-- contents here are dynamic - these don't exist when the page first loads -->
<p class="heading">See/Hide Comments</p>
<div class="content">I am I am I am.... Superman!</div>
<!-- end of dynamic content -->
</div>
Now on doc ready you attach your handler:
$(function() {
// $(".heading").click(//...this won't work, heading doesn't exist on load
$("#dump_here").on("click",".heading",function() {
// this will work - the handler is attached to an element that exists on load
// and will respond to event that bubble up from elements with the class 'heading'
});
submition(); // async function that populates your dynamic parts.
});
Be sure to read the docs on .on()
The important part to understand is this:
$(".heading")
This returns a collection of jQuery objects that represent DOM elements that have the class of heading. If there are no matching elements in the DOM when you execute that line, you will have an empty collection. But jQuery won't complain about this and will still let you chain to that empty collection:
$(".heading").on("click", function() { //...
What this says is attach an event handler to all the matching dom elements in my collection that will execute this function when the click event is triggered. But if your collection is empty, it won't do anything.
I have a page where the contents displayed from database using jquery and ajax. There are lot of processes in the page like Adding new content and image, Editing, Deletion etc and all are using ajax. But now some of event functions like click , mouseenter are not working in the content which where displayed from the database.
for example: This is how i display images in the page
for(var i=0;i<images.length;i++)
{
$("#content").append("<img src='"+images[i]+"' class='img' width='300' height='200' />");
}
Images are displayed properly. but when trying to do somthing on click event in images like this, its not working
$("#content .img").on('click',function()
{
//here comes my process, but its not working
}
Please help me to solve this problem.
Try:
$("#content").on("click", ".img", function() {
});
The problem is that $("#content img") creates a jQuery collection of elements that exist at the time it is run. When you start dynamically adding new elements, they don't have the event listener applied to them automatically.
What $("#content").on("click", ".img") does is provide for event delegation. So what's really happening is an event listener that is applied to $("#content") but only fired when that event comes from a descendant with a matching selector (.img in this case).
More info at http://api.jquery.com/on/.
Try like this
$(document).on('click', '#content .img',function()
{
...
});
This problem will always arise when you are trying to add some dynamic content. So,to resolve this always keep in mind some point.
All use some static element to reference the dynamic you are trying to apply event on.
Example : in your case try using
$("#content").on('click', 'img', function(){
//try using this way make your code works fine.!
});
I have a simple link:
Test Link
I want to get an alert whenever this link is pressed, so I add:
<script>
$('#test').click(function() { alert('clicked!'); } );
</script>
and it works fine, but when i move this code to a remote javascript file, it doesn't work..
any idea why?
I've also tried this code:
$(document).ready(function() {
$('#test').click(function() { alert('clicked!'); });
});
Your second example, using the ready function, should be working. Your first example should also work provided you include the script below the element with the ID "test" (the element has to already exist when your script runs, since you're not waiting for DOM ready). In both cases, your script must be included below (after) the jQuery script.
Example when you don't use ready
Example when you do use ready
I'd check that your external file is actually getting loaded (look for 404 errors in the browser console).
Update: From your comment below, the problem is that the "test" element doesn't exist when you're trying to hook up the handler. click only sets up the handler on the element if it already exists. If you're creating the element later, you have three options (two of which are really the same):
Use the code you already have, but run it after you've created the element (e.g., in the success callback of the ajax call you're making).
Use live, which basically hooks the click event document-wide and then checks to see if the element you tell it ("#test", in this case) was clicked.
Use delegate on the appropriate container (the element within which you're adding "test"). delegate is a more targeted version of live.
live and delegate are both examples of a technique called event delegation, which jQuery makes easy for you by providing those methods.
See the links for further information and examples, but for example, suppose you're going to be adding the "test" element to an element with the ID "target". You'd use delegate like this:
$("#target").delegate("#test", "click", function() {
alert("Clicked");
});
That hooks the click event on "target", but acts a lot like you've just magically hooked it on "test" as soon as "test" was added. Within your handler, this refers to the "test" element just as with click.
Heres my link:
http://tinyurl.com/6j727e
If you click on the link in test.php, it opens in a modal box which is using the jquery 'facebox' script.
I'm trying to act upon a click event in this box, and if you view source of test.php you'll see where I'm trying to loacte the link within the modal box.
$('#facebox .hero-link').click(alert('click!'));
However, it doesn't detect a click and oddly enough the click event runs when the page loads.
The close button DOES however have a click event built in that closes the box, and I suspect my home-grown click event is being prevented somehow, but I can't figure it out.
Can anyone help? Typically its the very last part of a project and its holding me up, as is always the way ;)
First, the reason you're getting the alert on document load is because the #click method takes a function as an argument. Instead, you passed it the return value of alert, which immediately shows the alert dialog and returns null.
The reason the event binding isn't working is because at the time of document load, #facebox .hero-link does not yet exist. I think you have two options that will help you fix this.
Option 1) Bind the click event only after the facebox is revealed. Something like:
$(document).bind('reveal.facebox', function() {
$('#facebox .hero-link').click(function() { alert('click!'); });
});
Option 2) Look into using the jQuery Live Query Plugin
Live Query utilizes the power of jQuery selectors by binding events or firing callbacks for matched elements auto-magically, even after the page has been loaded and the DOM updated.
jQuery Live Query will automatically bind the click event when it recognizes that Facebox modified the DOM. You should then only need to write this:
$('#facebox .hero-link').click(function() { alert('click!'); });
Alternatively use event delegation
This basically hooks events to containers rather than every element and queries the event.target in the container event.
It has multiple benefits in that you reduce the code noise (no need to rebind) it also is easier on browser memory (less events bound in the dom)
Quick example here
jQuery plugin for easy event delegation
P.S event delegation is pencilled to be in the next release (1.3) coming very soon.