Execute jquery function by id when id is changed by jquery - javascript

It's possible to change an id of html balise with this function :
$("#test").attr('id', 'test2');
My exemple code is :
$("#test").click(function() {
$("#test").attr('id', 'test2');
alert('test');
return false;
});
$("#test2").click(function() {
$("#test2").attr('id', 'test');
alert('test2');
return false;
});
The first function work normally but when the id is changed the second function is not run ...
Can you help me please ?
Thanks,

You need to use event delegation:
$("body").on('click','#test2',function() {
$("#test2").attr('id', 'test');
alert('test2');
return false;
});

The event handler is bound to the element itself, not it's attributes like id or class. So even if you change an attribute which you used to bind the event, the handler will remain with the element.
So in my opinion it's better to re-use the existing handler by condition checking. for example,
$("#test").click(function () {
if (this.id == "test") {
alert('test');
this.id = 'test2';
} else {
alert('test2');
this.id = 'test';
}
return false;
});
No need to bind extra handler to another element. This should be:
faster (No delay of bubbling)
memory efficient (Less number of handlers)
when talking about complex DOM structure with hundreds of elements.

Related

Adding an on event to an e.currentTarget?

A variety of elements on my page have the content editable tag.
When they are clicked I do this:
$('[contenteditable]').on('click', this.edit);
p.edit = function(e) {
console.log(e.currentTarget);
e.currentTarget.on('keydown', function() {
alert("keydown...");
});
};
I get the current target ok, but when I try to add keydown to it, I get the err:
Uncaught TypeError: undefined is not a function
It's a native DOM element, you'll have to wrap it in jQuery
$(e.currentTarget).on('keydown', function() {
alert("keydown...");
});
e.currentTarget should equal this inside the event handler, which is more commonly used ?
It's a little hard to tell how this works, but I think I would do something like
$('[contenteditable]').on({
click : function() {
$(this).data('clicked', true);
},
keydown: function() {
if ($(this).data('clicked'))
alert("keydown...");
}
});
Demo
First issue is you are trying to use jQuery methods on a DOM element. Second issue is I do not think you want to bind what is clicked on, but the content editable element itself.
It also seems weird to be adding the event on click instead of a global listener. But this is the basic idea
$(this) //current content editable element
.off("keydown.cust") //remove any events that may have been added before
.on('keydown.cust', function(e) { //add new event listener [namespaced]
console.log("keydown"); //log it was pressed
});
Edited: I had a fail in code. It works fine now.
Getting your code, I improved to this one:
$(function(){
$('[contenteditable]').on('click', function(){
p.edit($(this));
});
});
var p = {
edit: function($e) {
console.log($e);
$e.on('keydown', function() {
console.log($(this));
alert("keydown...");
});
}
}
You can check it at jsFiddle
You need to wrap the e.currentTarget(which is a native DOM element) in jQuery since "on" event is a jQuery event:
$(e.currentTarget).on('keydown', function() {
alert("keydown...");
});
EDIT:
$('[contenteditable]').on('click', p.edit);
p.edit = function(e) {
$(e.currentTarget).on('keydown', function() {
alert("keydown...");
});
};
You're defining p.edit AFTER $('[contenteditable]').on('click', p.edit); resulting in an error since p.edit doesn't exist when declaring the on.
In case you don't know, you are defining p.edit as a function expression, meaning that you have to define it BEFORE calling it.

click event not working when changing id or class

I'm starting with jquery, and have an issue here:
http://jsfiddle.net/8guzD/
$('#test.off').click(function(){
$(this).removeClass('off').addClass('on');
});
$('#test.on').click(function(){
$(this).removeClass('on').addClass('off');
alert('ok');
});
the first part of the code goes well, the class is apply, but when I attach an event in this element with its new class it won't work.
Can someone explain me what is the problem exactly?
I tried with javascript,
http://jsfiddle.net/R5NRz/
var element = document.getElementById('test');
element.addEventListener('click', function() {
this.id ='test2';
alert("ok");
}, false);
var element2 = document.getElementById('test2');
element2.addEventListener('click', function() {
alert("ok2");
}, false);
and it didn't really help me, having the same issue
try
$(document).on("click",'#test.on',function(){
$(this).removeClass('off').addClass('on');
alert('ok');
});
$(document).on("click",'#test.off',function(){
$(this).removeClass('off').addClass('on');
alert('ok passs');
});
Demo
In your jQuery example you are binding to DOM elements that exist at that time. That is why you see the first fire but not the second. It is not a match for your '#test.on' selector when the code is run. What you want to do instead is use delegation:
$('#test').on('click',function() {
var ele = $(this);
if (ele.hasClass('on')) {
ele.removeClass('on').addClass('off');
} else {
ele.removeClass('off').addClass('on');
}
});
This assumes that you are doing more than just toggling classes. If you want simply toggle classes then an easier solution is to pick one as the default and use the other as a flag. For example, .on is on but without .on it's off. Then you can just use toggle:
$('#test').on('click', function() {
$(this).toggleClass('on');
});
$("#test.on")
Doesn't bind to anything. Try this:
$('#test').click(function() {
if($(this)).hasClass('off') $(this).removeClass('off').addClass('on');
else $(this).removeClass('on').addClass('off');
});
You might consider using an 'active' class instead and just toggling that, instead of have two separate on/off classes. Then you can write:
$("#test").click(function() {
$(this).toggleClass('active');
});

jQuery unbind click event function and re-attach depending on situation

The code below I use to create a sliding menu. I need to know how to unbind the function attached to the click event and re-attach it some other time. (using jQuery 1.7.2)
$(document).ready(function(){
$('.section').hide();
$('.header').click(function(){
if($(this).next('.section').is(':visible'))
{
$('.section:visible').slideUp()
$('.arrows:visible').attr("src","right.gif")
}
else
{
$('.section').slideUp();
$(this).next('.section').slideToggle();
$(this).find('.arrows').attr("src","down.gif")
});
});
The code below is what I have so far
$('#printVers').click(function(){
if($('#formVersion').val() != "Print")
{
$('.header').unbind('click');
}
else
{
//else re-attach functionality?
}
});
Thanks
Simply make a named function. You can go low tech here and back to basics to unbind and reattach specific events.
function doStuff()
{
if($(this).,next('.section').is(':visible'))
...
}
$('.header').on('click', doStuff);
$('.header').off('click', doStuff);
Instead of unbind and re-bind, I suggest you to add a simple class to .header and check for the class in the click handler. See below,
$('#printVers').click(function(){
if($('#formVersion').val() != "Print")
{
$('.header').addClass('dontClick');
} else {
$('.header').removeClass('dontClick');
}
});
And in your .header click handler,
$('.header').click(function(){
if ($(this).hasClass('dontClick')) {
return false;
}
//rest of your code
If you insist on having a unbind and bind, then you can move the handler to a function and unbind/bind the function any number of time..
You can try something like this.
$('#printVers').click(function(){
if($('#formVersion').val() != "Print")
{
$('.header').addClass('clickDisabled');
}
else
{
$('.header').removeClass('clickDisabled');
}
});
And then in the click handler check for this class.
$(document).ready(function(){
$('.section').hide();
$('.header').click(function(){
if(!$(this).hasClass('clickDisabled')){
...
...
}
});
});
Why not make that top section a function, and then call it in your else statement?
You could try setting a variable as a flag. var canClick = ($('#formVersion').val() != 'Print'); Then in the click handler for your .header elements check to see if canClick is true before executing your code.
If you still want to remove the handler you can assign the events object to a variable. var eventObj = #('.header').data('events'); That will give you an object with all the handlers assigned to that object. To reassign the click event it would be like $('.header').bind('click', eventObj.click[0]);
After trying so hard with bind, unbind, on, off, click, attr, removeAttr, prop I made it work.
So, I have the following scenario: In my html i have NOT attached any inline onclick handlers.
Then in my Javascript i used the following to add an inline onclick handler:
$(element).attr('onclick','myFunction()');
To remove this at a later point from Javascript I used the following:
$(element).prop('onclick',null);
This is the way it worked for me to bind and unbind click events dinamically in Javascript. Remember NOT to insert any inline onclick handler in your elements.
You could put all the code under the .click in a separated function
function headerClick(){
if($(this).next('.section').is(':visible'))
{
$('.section:visible').slideUp()
$('.arrows:visible').attr("src","right.gif")
}
else
{
$('.section').slideUp();
$(this).next('.section').slideToggle();
$(this).find('.arrows').attr("src","down.gif")
}
}
and then bind it like this:
$(document).ready(function(){
$('.section').hide();
$('.header').click(headerClick);
});
$('#printVers').click(function(){
if($('#formVersion').val() != "Print")
{
$('.header').unbind('click');
}
else
{
$('.header').click(headerClick);
}
});

On() and off() - Jquery

Trying to understand Jquery's On() and off() a little better. Not understanding why this is not working. I want to activate and inactivate id TurnON and TurnOff Js.
Javascript
$(document).ready(function(){
$(document).on("click.turnon","#TurnOn",function() {
$(document).off('click.turnon');
alert("Turn Off is now turned off");
});
$(document).on("click.turnoff","#TurnOff",function() {
$(document).on('click.turnon');
alert("Turn Off is now turned back on");
});
});
HTML
<div id="TurnOn">Turn Off</div>
<div id="TurnOff">Turn On</div>
If you want an event handler to only fire once then take a look at .one(): http://api.jquery.com/one
As of jQuery 1.7 it does event delegation.
$(function(){
$(document).one("click.turnon","#TurnOn",function() {
alert("Turn Off is now turned off");
});
$(document).one("click.turnoff","#TurnOff",function() {
alert("Turn Off is now turned back on");
});
});
Here is a demo using .one(): http://jsfiddle.net/9qxfT/1/
Also, your code was just about right but you have a couple typos here:
$(document).on("click.turnoff","#TurnOff",function() {
$(document).on('click.turnon');
alert("Turn Off is now turned back on");
});
$(document).on('click.turnon'); should be: $(document).off('click.turnoff');
Here is a demo of these small changes: http://jsfiddle.net/9qxfT/
Update
You can save the state with a variable:
$(function(){
//declare a variable to save whether or not the `#TurnOn` element is 'on' (true) or 'off' (false)
var isOn = true;
$(document).on("click.turnon","#TurnOn",function() {
//check to see if the flag is set to true, which means the `#TurnOn` element is 'on' already
if (isOn) {
alert("#TurnOn is already turned on");
//otherwise set the `#TurnOn` element to 'on'
} else {
alert("#TurnOn is now turned back on");
isOn = true;
}
});
//set the `#TurnOn` element to `off` when the `#TurnOff` element is clicked
$(document).on("click.turnoff","#TurnOff",function() {
isOn = false;
alert("#TurnOn is now turned off");
});
});​
Here is a demo: http://jsfiddle.net/9qxfT/4/
Your logic is right, but may I suggest better implementation?
Please read this page as well: http://api.jquery.com/off/
Here is what I suggest:
// first put a .click event with a separate "ID" to enable another div "ID".
$('#ButtonForTurnOn').click(function () {
//while body is .on(), the ID, when clicked applies whatever effects
$("body").on("click", "#TurnOn", onlight).find("#TurnOn").addClass("clickable").text("ON switch on");
});
// enable OFF switch
$('#ButtonForTurnOff').click(function () {
$("body").on("click", "#TurnOff", offlight).find("#TurnOff").addClass("clickable").text("OFF switch on");
});
Now, for you to have an effective .off function, YOU MUST have the
"selector string match the one passed to .on() when the event handler
was attached."
For example:
If your $("body").on() is this,
$("body").on("click", "#TurnOff", function({
// stuff here
});
Your $("body").off() should be this,
$("body").off("click", "#TurnOff", function({
// stuff here
});
Try out this jsfiddle
Hope this helps explain things!
Just think of it as disabling something, until its turned back on.

How can I attach event to a tag which is in string form?

I'm creating html on runtime like this:
var myVar = "<div id='abc'>some clickable text</div>"
Now, I want to attach some event, say onclick, to this div. How can I do that on next line? I'll add this to DOM later.
PS: I've to accomplish this without using JQuery.
Instead of building your div as a string, you'll want to use document.createElement('div'). This way you will have a real dom object, and can get and set it's propeties, including onClick
Will this help? Since you dynamically generate it, you know the control id of the DIV.
document.getElementbyId('abc').onClick = foo;
function foo()
{
alert("All your impl to go here");
}
Try building the div as a DOM element first.
var myVar = document.createElement("div"),
parentDiv = document.getElementById("parent_div");
parentDiv.appendChild(myVar);
myVar.innerHTML = "some clickable text";
if(myVar.addEventListener){
myVar.addEventListener("click", clickFn, false);
}
else if(myVar.attachEvent){
myVar.attachEvent("onclick", clickFn);
}
else{
myVar.onclick = clickFn;
}
The addEventListener method is standard, but not every browser plays nice with the standard.
EDIT: As mentioned, an element must be added to the DOM first.
Or you can use this technique: attach event to the document.body. Then if the event target is not the needed div than just do nothing. It is the same techinque jquery uses for its live function:
// crossbrowser event attachment function
function listen(evnt, elem, func) {
if (elem.addEventListener) {
elem.addEventListener(evnt, func, false);
}
else if (elem.attachEvent) {
var r = elem.attachEvent("on" + evnt, func);
return r;
}
else window.alert('I\'m sorry Dave, I\'m afraid I can\'t do that.');
}
// this is an analog of the jquery.live
var assignLiveEvent = function(id, evnt, callback) {
var handler = function(e) {
e = e || window.event;
e.target = e.target || e.srcElement;
if (e.target.id == id) {
//your code here
callback(e);
}
};
listen(evnt, document.body, handler);
};
var myVar = "<div id='abc'>some clickable text</div>";
assignLiveEvent("abc", "click", function(e) {
//your code here
});
// now you can add your div to DOM even after event handler assignation
Here is demo.
Brian Glaz is totally right but, if for some reason, you really need to do it this way, you have two options:
you can only add events to something that is already in the DOM, using pure javascript, so you would have to include it in the html like:
document.body.innerHTML += myVar;
and then, attach the event with
document.getElementById('abc').addEventListener('click', function(e){
//your code
}, 1);
With jQuery, you could use .live() to attach events to elements that are not yet present in the DOM:
$('#abc').live('click', function(e){
//your code here
});
so you could add the div later...

Categories

Resources