I'm working on a jQuery plugin. To separate my logic I do something like this:
$element.on({
mouseenter: function(){
//do something special
}, mouseleave: function(){
//do something else special
}
});
//more stuffs
and then above this I do that again but with other function body
$element.on({
mouseenter: function(){
//do something not special
}, mouseleave: function(){
//do something else not special
}
});
How does jQuery deal with this ? Will 2nd declaration of mouse events function override the first one ? Sometimes I see both things works but sometimes not.
Will 2nd declaration of mouse events function override the first one ?
No.
How does jQuery deal with this ?
It executes your event handlers in the order in which they were attached. From the documentation (about 40% down the page):
Event handlers bound to an element are called in the same order that they were bound.
So for instance, if you have:
var div = $("#someDiv");
div.on("click", function() { console.log("one"); });
div.on("click", function() { console.log("two"); });
div.on("click", function() { console.log("three"); });
...then clicking the div will give you
one
two
three
...in the console.
Note that it doesn't matter how you found the element to attach the handlers. Let's say you have only one div on the page, it has the id "someDiv", and it's the first child of body (just to make the selectors easy). If you have:
$("#someDiv").on("click", function() { console.log("one"); });
$(document.body).children().first().on("click", function() { console.log("two"); });
$("div").on("click", function() { console.log("three"); });
and you click the div, you'll get
one
two
three
...in the console.
Related
I am trying to combine a function which will display alert (ofcourse I have a lot of code In this function but for this case It will be alert) after:
Click on element with class .number
Change select[name=receive]
I have this code but it doesn't work:
$(document).on(("click",".number"),("change","select[name=receive]"),function(){
alert('test');
})
Try this
function doMyWork() {
console.lot( 'TEST' );
}
$('.number').on('click', doMyWork);
$('select[name=receive]').on('change', doMyWork);
Or, if your elements are inserted after DOM ready:
You do not have to use this form if the target elements exist at DOM ready
function doMyWork() {
console.lot( 'TEST' );
}
$(document).on('click', '.number', doMyWork)
.on('change', 'select[name=receive]', doMyWork);
Try this
$(document).on("click change","select[name=receive], .number", function(){
alert('test');
});
Or
var fn = function () {
alert('test');
}
$(document).on("click", ".number", fn);
$(document).on("change", "select[name=receive]", fn);
You cannot separate events and selectors in a single .on() call. You have two options here. You can use them together....
$(document).on("click change", ".number, select[name=receive]"),function(){
alert('test');
});
...however this means that .number will listen to both click and change, possible resulting in the function running 2 times.
You need to move the function outside and reuse it for every handler
var al = function(){
alert('test');
};
$('.number').on('click', al);
$('select[name=receive]').on('change', al);
$(document).on("click change",".number, select[name=receive]", function(){
alert('test');
})
I am not sure where you learned that syntax, but that is not how on() works.
Use a named function and share it.
(function(){
var shared = function(){
console.log(this);
}
$(document)
.on("click",".number", shared)
.on("change","select[name=receive]", shared);
}());
I have few namespaces and I want to reinitialize function inside namespaces on document change in order to be reinitialized every time when the document is modified (*modified = adding/removing new sections on existing dom ).
I have tried this but not working so far:
;namespaceName= {
namespaceFunction1: function() {
$( selector ).on('click', function() {
//my first function run here
})
},
// ************second function in namespace***************/
namespaceFunction2: function() {
$(secondSelector).on('click', function() {
//my second function run here
})
}
}
$(document).on('change', namespaceName.namespaceFunction1() );
$(document).on('change', namespaceName.namespaceFunction2() );
Pls help, ty.
Try this...
$(document).on("DOMSubtreeModified", function () {
namespaceName.namespaceFunction1();
namespaceName.namespaceFunction2();
});
It fires your 2 functions on the DOMSubtreeModified event, which is basically what you were looking for - when the DOM changes.
sounds like you need to listen for the DOMSubtreeModified event like this:
$('body').bind('DOMSubtreeModified', function(){
//your code here
});
There are some similar questions, but they all seem like regarding native jQuery callback functions.
So I have this code which (live) creates a div containting some form elements.
Values of these elements should be retrieved inside a callback function when (before) the div is removed.
function popup(callback) {
// ...
// before removing the div
callback.call();
// remove div
}
Unexpectedly, the callback function is being fired multiple times (increasingly) after the first time popup is executed.
I have simplified the code, and here is the fiddle.
I hope this is what you need.
function popup(callback) {
$("body").append('<div><span id="test">test</span> close</div>');
$(document).on("click", "#close", function() {
callback.call();
//
//callback = function() {};
$(document).off("click", "#close");
$("div").remove();
});
};
$(document).on("click", "#open", function() {
popup(function() {
alert('$("#test").length = ' + $("#test").length);
});
});
Basically, you need to remove event handler by invoking off() method.
Try dynamically generating the elements instead of using a string. This will allow you to bind events easier.
function popup(callback)
{ var $elem = $("<div></div>");
$elem.append($("<span></span>").html("test"));
$elem.append(" ");
$elem.append($("<a></a>").html("close").attr("href", "#"));
$("body").append($elem);
$elem.find("a").click(function() {
callback.call();
$elem.remove();
});
};
$(document).on("click", "#open", function() {
popup(function() {
alert('$("#test").length = ' + $("#test").length);
});
});
Example: http://jsfiddle.net/4se7M/2/
I don't know the exact scenario, but why do you want to bind and unbind the event each time you show the popup?
You can bind only once, like this, can't you?
$(document).on("click", "#close", function() {
alert('$("#test").length = ' + $("#test").length);
$("div").remove();
});
function popup() {
$("body").append('<div><span id="test">test</span> close</div>');
};
$(document).on("click", "#open", function() {
popup();
});
Have the following code:
$("#blogs").mouseover(
function () {
$(this).addClass("hover");
$("#home").removeClass("hover");
$("#homepages").removeClass("hover");
$("#apps").removeClass("hover");
$("#facebook").removeClass("hover");
$("#kontakt").removeClass("hover");
$("#content").hide().load("blogs.html", function(){
$("#content").show("slide");
});
});
Works all fine, but now I would like the load() / show() function only be called if #content does not already contain blogs.html.
In other words: I would like to check if blogs.html is already loaded and if yes, simply do nothing and only if not there yet I would load and show it.
Have tried some things with hasClass() and some if-formulas but struggle to get this check.
Tried stuff like this:
$("#content section").hasClass("check_blog").hide().load("blogs.html", function(){
$("#content").show("slide");
Basically I just need to know how I can check if blogs.html is already the contents of #content.
Thanks a lot for any help. Regards, Andi
Add an ID to some element in blogs.html, say blogsloaded, then you can check for it with:
if (!$("#blogsloaded").length)
$("#content").hide().load("blogs.html" ...
Another method would be to store in a variable if you already loaded it:
if (!this.blogsloaded)
{
this.blogsloaded=true;
$("#content").hide().load("blogs.html" ...
}
I would split up your mouseover events into two namespaced events. One which will only run once.
// This event will only run once
$("#blogs").on("mouseover.runonce", function () {
$("#content").load("blogs.html");
});
// because this event will unbind the previous one
$("#blogs").on("mouseover.alwaysrun", function () {
$(this).off("mouseover.runonce");
$(this).addClass("hover");
$("#home").removeClass("hover");
$("#homepages").removeClass("hover");
$("#apps").removeClass("hover");
$("#facebook").removeClass("hover");
$("#kontakt").removeClass("hover");
$("#content").hide();
});
Update a data attribute on #content that contains the url or id of the currently loaded content. Also, you should handle the case where the user hovers over a different section before the previous is done loading.
var request; // use this same var for all, don't re-declare it
$("#blogs").mouseover(function () {
// exit event if the blog is the current content in #content
if ( $("#content").data("current") == "blog") return;
$("#content").data("current","blog");
$(this).addClass("hover");
$("#home").removeClass("hover");
$("#homepages").removeClass("hover");
$("#apps").removeClass("hover");
$("#facebook").removeClass("hover");
$("#kontakt").removeClass("hover");
// if a previous request is still pending, abort it
if ($.isFunction(request.abort) && request.state() == "pending") request.abort();
// request content
request = $.get("blogs.html");
$("#content").hide();
// when content is done loading, update #content element
request.done(function(result){
$("#content").html(result);
});
});
I strongly suggest against using hover for loading content with ajax.
Also, in it's current form, this code is not very re-usable, you'll have to have one for each link. I suggest instead using classes and having only one event binding handling all of the links.
You can do it like this using .has() to detect descendants of content
$("#blogs").mouseover(
function () {
$(this).addClass("hover");
$("#home,#homepages,#apps,#facebook,#kontakt").removeClass("hover");
var $c = $("#content");
if($c.has('.check_blog')){ // if content contains an element with that class
$("#content").hide().load("blogs.html", function(){
$("#content").show("slide");
}
});
});
You could do something like this:
$("#blogs").mouseover(
function () {
$(this).addClass("hover");
$("#home").removeClass("hover");
$("#homepages").removeClass("hover");
$("#apps").removeClass("hover");
$("#facebook").removeClass("hover");
$("#kontakt").removeClass("hover");
if($('#content').html() == '') {
$("#content").hide().load("blogs.html", function(){
$("#content").show("slide");
});
}
});
I have a block of code like so:
function doSomething() {
someVar.on("event_name", function() {
$('#elementId').click(function(e) {
doSomething();
});
});
}
// and on document ready
$(function () {
$('#anotherElemId').click(function () {
doSomething();
});
});
The problem that I'm encountering is that when I call doSomething() from anotherElemId click event(that is binded on document ready) it works as expected, but calling it recursively from elementId click doesn't work.
Any ideas? Thinking is something trivial that I'm missing.
Is someVar an actual jQuery reference to a dom element? (e.g. $('#someitem'))
The second problem is you cant put a .click event inside a function that you would like to instantiate later on. If you are trying to only allow #elementId to have a click event AFTER some previous event, try testing if a tester variable is true:
var activated = false;
$(function () {
$('#anotherElemId').click(function () {
activated = true;
});
$('#secondElemId').on("event_name", function() {
if (activated) {
// code that happens only after #anotherElemId was clicked.
}
});
});