I have a simple mouseover event that I am trying to work on elements that are loaded with ajax. For example I have a div that when you mouseover hide/show another div. When I load these divs through ajax they no longer work. For example :
<div class="block">
<div class="something">MOUSEOVER</div>
<div class="else" style="display: none" >HI</div>
</div>
$(document).ready(function(){
//using on hoping to catch the mouse events
$('.block').on('mouseenter',function(){
$(this).children('.else').fadeIn('fast');
});
$('.block').on('mouseleave',function(){
$(this).children('.else').fadeOut('fast');
});
});
This works fine straight up like this :
But when I load those elements from another page :
$j('#trigger').load( url + " .block");
The mouse events are no longer recognized. I thought this is what live, on, delegate were for. Can someone help me figure this out please.
One possibility is to change your code like:
var myFunc = function() {
$('.block').on('mouseenter',function(){
$(this).children('.else').fadeIn('fast');
});
$('.block').on('mouseleave',function(){
$(this).children('.else').fadeOut('fast');
});
}
$('#trigger').load(url + " .block", function() {
myFunc();
});
to make this functions like mouseenter or mouseleave in the loaded content possible.
The other possibility is $.live();. Like:
$('.block').live('mouseenter', function() {
//here your code
});
This is exactly what methods like on and delegate can be used for, but they have to be used correctly.
As events bubble from the element on which they originated up through the DOM you need to capture the event on an ancestor element that already existed:
$(".someAncestor").on("mouseenter", ".something", function() {
//Executed when .something triggers the mouseenter event
});
It looks like you are loading the entire .block element via AJAX, so you will need to bind the event somewhere higher up the DOM tree (probably the element inside which you append .block).
You can put the trigger event to load on AJAX success.
Related
I've looked all over the internet with everyone giving the same answer
$(document).on('click', '#targetID', function() {
// do stuff
});
instead of
$('#targetID').click(function() {
// do stuff
});
This is nice and it works fine, if you have a click event. But within that on click function, the part where it says do stuff, how can I now target an appended element? For instance say I append 2 divs back to back.
<div id="mainDiv"></div>
<script>
socket.on('event', function (data) {
$('#mainDiv').append ('<div class="1st" id="'+data.id+'">one</div>
<div class="2nd" id="'+data.id+'">second</div>');
});
$(document).on('click', '.1st', function() {
//and right here i would like to`enter something like
$('.2nd').css('background-color','yellow');
}
</scirpt>
This however seems not to work because to my knowledge, this element hasn't been added to the DOM. So what should I do? Should i use angular.js for this?
PS I've also tried adding the entire appended content into a variable first before appending that variable. and then using variable.find to find the element within to no avail. The variable only has context within that function, but is null in the on click function. Thanks in advance for any information that broadens my understanding of this.
The delegation of 'on' is correct. Once the div element exists in the dom, clicking should work. My only concern is you have named your classname beginning with a number. Maybe name it with an alpha character followed by a number.
The difference between the 2 is the concept of event binding vs event delegation.
$('#targetID').click(function() { is event binding which works on elements as long as they exist in the markup when the page or document loads.
$(document).on('click', '#targetID', function() { is event delegation which means the event would listen to the document for the click event on the element with ID targetID if it exists in the DOM when the page loads or if it is dynamically added.
So In your case, its event delegation since you are dynamically adding the elements. But in order to make it work, you need to register the listener on the document ready event for the document to listen to the event on the element #targetID
<script>
$(document).ready(function() // Add this
{
socket.on('event', function (data) {
$('#mainDiv').append ('<div class="1st" id="'+data.id+'">one</div><div class="2nd" id="'+data.id+'">second</div>');
});
$(document).on('click', '.1st', function() {
//and right here i would like to`enter something like
$('.2nd').css('background-color','yellow');
});
});
</script>
Here's an example : https://jsfiddle.net/nobcp0L7/1/
I have a problem.
I'm looking for document-wide click events, but large chunks of my site is loaded through a div with an innerHTML object.
<div id="contentHolder">
<script>
document.getElementById("contentHolder").innerHTML='<object type="text/html" id="content" data="article.html"></object>';
</script>
</div>
A listener like this:
$(document).on("click", function (event){
alert("Click");
});
Only registers clicks on elements outside of the ContentHolder.
I realise that the loaded content probably has its own document.
Do any of you know of a way I can refer to this content inside the Object? :)
I read up on jQuery delegation, but it didn't seem to offer a solution to my problem.
I set up a semi-working example on Codepen. It doesn't seem to allow loading external pages, understandably so - but the problem persists even without any actual loading. The example works locally.
Edit
I solved the problem myself. Instead of using an HTML Object for a container, you can use jQuery append and the listeners will remain active not only from the sub-document's events but also the parent's.
$.get('document.html', function(result) {
$('#container').append(result);
});`
You can try this:
$('#contentHolder').on('click', '.class-to-be-named', function() {
// do your click stuff
});
It will bind the click event on #contentHolder and whenever you click within #contentHolder it will lookup if element #contentHolder was clicked, when is it calls the callback.
I solved the problem myself. Instead of using an HTML Object for a container, you can use jQuery append and the listeners will remain active not only from the sub-document's events but also the parent's.
$.get('document.html', function(result) {
$('#container').append(result);
});
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 javasript function that should change the value of an element appended after document is ready.
What I mean is: If the javascript appends a div like: <div class="new-div"></div>, I cannot intercept actions on that DIV.
This code does not work:
$(document).ready(function() {
$('.new-div').on('click', function(){
alert('clicked');
});
});
But this code, using delegate, works fine:
$(document).ready(function() {
$(document).on('click', '.author-profile-articles-table', function(){
alert('clicked');
});
});
However, when the scroll event is needed, the following code does not work:
$(document).ready(function() {
$(document).on('scroll', '.author-profile-articles-table', function(){
alert('scrolled');
});
});
According to t.niese, scroll events do not propagate through DOM, so one can't use it with delegate to make this work.
Script tags along with the html do work but I don't feel it is an elegant/smart way.
The question is, if a scroll intercepter does not work with DOM, is that a way to put the event interceptors from a separate javascript file or the html script tag is the only option?
Cheers,
I made it work using the bind tag:
When I finished performing a given action, a trigger an event using:
$.trigger('eventName');
Than I build the event listener using bind:
$(document).bind('eventName', function(){
// Do your stuff here.
}
It works smoothly =)
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.!
});