2 different on click events conflict? - javascript

I have one link:
link
And I have two different onclick function set to the two classes like this:
jQuery(".lorem").each(function(){
this.onclick = function() {
// stuff
}
});
and
jQuery(".hello").each(function(){
this.onclick = function() {
// stuff
}
});
This stops the top one to work. Why? And how can I make both functions work while being separated?

You can only assign one function to the onclick property. You should use normal jQuery event binding, it allows multiple handlers:
$(".lorem").click(function() {
// stuff
});
$(".hello").click(function() {
// stuff
});
If you want to do it with native Javascript, you can use addEventListener; as the name suggests, these are additive, they don't replace.
jQuery(".lorem").each(function(){
this.addEventListener("click", function() {
// stuff
})
});
jQuery(".hello").each(function(){
this.addEventListener("click", function() {
// stuff
})
});

When you are using query, why use .onclick on the DOM element (therefore overwriting the previous binding). Instead use jQuery's .on:
$('.lorem').on('click', function(){
// something
});
$('.hello').on('click', function(){
// something else
});

Related

How to set a jquery on() function only if it doesn't already existis?

I'm calling via ajax additional content where I add a jquery on() function for a click event. Each time I renew the content the event is also set again so at the end it get executed several times. How can I avoid this behavior?
How do I test if the click event is already set on the document?
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Click
<script>
// first ajax load
$(document).on('click', '.open-alert', function () {
alert('hello world!');
});
// second ajax load
$(document).on('click', '.open-alert', function () {
alert('hello world!');
});
</script>
I already try to just the jQuery.isFunction(), but I don't anderstand how to apply it in this case.
You can Unbind the click event , if you getting more than one time exectuated.
$(document).unbind('click').on("click", ".open-alert", function () {
//do stuff here
});
Or you can also use it
$(document).off("click", ".open-alert").on("click", ".open-alert", function () {
});
Using
$(document).on('click', '#element_id', function() {
//your code
});
Will check the DOM for matching elements every time you click (usually used for dynamically created elements with ajax)
But using
$('#element_id').on('click', function() {
//your code
});
Will only bind to existing elements.
If you use the 1st example, you only need to call it once, you can even call it before your ajax call since it will recheck for matching elements on each click.
<script>
$(document).on('click', '.open-alert', function () {
alert('hello world!');
});
// first ajax load
// second ajax load
...
</script>
In case you cannot bind the event to the specific DOM element (which might happen if you use Turbolinks for example) you can use a variable to check whether you set the event or not.
Local scope
var clickIsSet = false;
// any ajax load
$(document).on('click', '.open-alert', function () {
if ( clickIsSet ) {
alert('hello world!');
clickIsSet = true;
}
});
Global scope
I don't recommend to make clickIsSet global, but in case you are importing/exporting modules you can do that:
// main.js
window.clickIsSet = false;
// any-other-module.js
$(document).on('click', '.open-alert', function () {
if ( window.clickIsSet ) {
alert('hello world!');
window.clickIsSet = true;
}
});
jQuery check if event exists on element : $._data( $(yourSelector)[0], 'events' )
this return all of element events such : click , blur ,
focus,....
Important Note: $._data when worked that at least an event bind to element.
so now:
1.in your main script or first ajax script bind click event on element
<script>
$(document).on('click', '.open-alert', function () {
alert('hello world!');
});
</script>
2. in secound ajax:
var _data = $._data( $('.open-alert')[0], 'events' );
if(typeof _data != "undefined"){
var eventClick = $._data( $('.open-alert')[0], 'events' ).click
var hasEventClick = eventClick != null && typeof eventClick != "undefined";
if(!hasEventClick){
$(document).on('click', '.open-alert', function () {
alert('hello world!');
});
}
}
I get Confuse about your question but as far as understand your question I have three suggestions:
Use Id element (as #Mokun write the answer)
Use Common Function for call functionality instead use through the click event.(Make Sure of function does not overwrite your content by calling).
Use of flag variable (or global variable for your tracking event) in jquery and identify your function call for particular execution.

Binding 'this' and getting this

$('.btn-delete').on('click', this.confirm.bind(this));
Above, on click it runs:
p.confirm = function(e) {
if(!$(this).hasClass('danger')){
$(this).addClass('danger');
$(this).bind('mouseleave',function(){
$(this).removeClass('danger');
$(this).unbind('mouseleave');
});
}
else{
this.delete();
}
};
I'm having trouble with this. I need this to get the button but I also need this to access another method (this.delete). I've tried bind but it faisl to work.
Any ideas?
Assuming I'm understanding your question correctly, you want to be able to pass the clicked element as this to the p.confirm function. You should be able to do this by using call, or by using p.confirm as the handler:
// using call
$('.btn-delete').on('click', function (e) {
p.confirm.call(this, e);
});
// as handler
$('.btn-delete').on('click', p.confirm);
Assuming that this.delete is actually p.delete, just use call in the handler to pass the clicked element as this to the delete method:
p.confirm = function (e) {
var self = $(this); // cache lookup, "this" is the clicked element
if (!self.hasClass('danger')) {
self.addClass('danger');
self.bind('mouseleave', function () {
self.removeClass('danger');
self.unbind('mouseleave');
});
} else {
p.delete.call(this); // pass clicked element to use as "this" in p.delete
}
};

jQuery - how to delegate a toggle

How can I provide a toggle for a dynamically created element?
My code does not work:
JS
$("body").on('toggle', ".buttonA", function(){
function() {
..do stuff
},
function() {
.. revert stuff
}
});
Try this:
$('body').on('click','.buttonA', function () {
var toggled = $(this).data('toggled');
$(this).data('toggled', !toggled);
if (!toggled) {
//..do stuff
}
else {
//.. revert stuff
}});
If you are using jQuery,you can use .live() methods for binding a dynamically created element.
$('#hello').live("click", function() {
alert( "Goodbye!" ); // jQuery 1.3+
});
I didn't use jQuery for a long time.So I don't know the method is valid or not.But it is very easy to write a new method to resolve this requirement.The more important thing is you bind the element whether or not.

jQuery: Call a function twice

I'm trying to run a function twice. Once when the page loads, and then again on click. Not sure what I'm doing wrong. Here is my code:
$('div').each(function truncate() {
$(this).addClass('closed').children().slice(0,2).show().find('.truncate').show();
});
$('.truncate').click(function() {
if ($(this).parent().hasClass('closed')) {
$(this).parent().removeClass('closed').addClass('open').children().show();
}
else if ($(this).parent().hasClass('open')) {
$(this).parent().removeClass('open').addClass('closed');
$('div').truncate();
$(this).show();
}
});
The problem is on line 13 where I call the truncate(); function a second time. Any idea why it's not working?
Edit jsFiddle here: http://jsfiddle.net/g6PLu/
That's a named function literal.
The name is only visible within the scope of the function.
Therefore, truncate doesn't exist outside of the handler.
Instead, create a normal function and pass it to each():
function truncate() { ...}
$('div').each(truncate);
What's the error message do you get?
You should create function and then call it as per requirement
Define the function
function truncate(){
$('div').each(function(){
});
}
Then call the function
truncate();
Another approach is to establish, then trigger, a custom event :
$('div').on('truncate', function() {
$(this).......;
}).trigger('truncate');
Then, wherever else you need the same action, trigger the event again.
To truncate all divs :
$('div').trigger('truncate');
Similarly you can truncate just one particular div :
$('div#myDiv').trigger('truncate');
The only prerequisite is that the custom event handler has been attached, so ...
$('p').trigger('truncate');
would do nothing because a truncate handler has not been established for p elements.
I know there's already an accepted answer, but I think the best solution would be a plugin http://jsfiddle.net/g6PLu/13/ It seems to be in the spirit of what the OP wants (to be able to call $('div').truncate). And makes for much cleaner code
(function($) {
$.fn.truncate = function() {
this.addClass('closed').children(":not('.truncate')").hide().slice(0,2).show();
};
$.fn.untruncate = function() {
this.removeClass('closed').children().show();
};
})(jQuery);
$('div').truncate();
$('.truncate').click(function() {
var $parent = $(this).parent();
if ($parent.hasClass('closed')) {
$parent.untruncate();
} else {
$parent.truncate();
}
});

Overwriting a Backbone Models Change Event

I think what I want to do is pretty simple I just don't know how to do it. I would like to fire my own event when one of my models attributes changes for the purpose of passing some data to the event handler (whether the change was an increase or decrease in value).
Basically I want my handler to do this in the view
handler: function(increased) {
if(increased) {
alert("the value increased")
}
else {
alert("the value decreased")
}
}
// ...
this.model.on("change:attr", this.handler, this);
Here you go: You basically listen for change:myvar. When a change occurs you use your model's previous() to get the old value. Depending on whether it increased or decreased you fire the appropriate event. You can listen to these events as shown in the initialize().
(function($){
window.MyModel = Backbone.Model.extend({
initialize: function () {
this.on('change:myvar', this.onMyVarChange);
this.on('increased:myvar', function () {
console.log('Increased');
});
this.on('decreased:myvar', function () {
console.log('Decreased');
});
},
onMyVarChange: function () {
if (this.get('myvar') > this.previous('myvar')) {
this.trigger('increased:myvar');
} else {
this.trigger('decreased:myvar');
}
}
});
window.mymodel = new MyModel({myvar: 1});
mymodel.set({myvar: 2});
mymodel.set({myvar: 3});
mymodel.set({myvar: 1});
})(jQuery);​
Running the above will print "Increased", "Increased", "Decreased" to your console.
Just look at previousAttributes()
You can then compare:
If(this.get(attr) > this.previousAttributes()[attr]){
console.log('bigger');
} else {
console.log('smaller');
}
If you use that in your change event handler you're all set. No need for a custom trigger or a ton of code.
EDIT
This is from my Backbone.Validators project and how I obtain the list of all attributes which have changed during the validation step:
var get_changed_attributes = function(previous, current){
var changedAttributes = [];
_(current).each(function(val, key){
if(!_(previous).has(key)){
changedAttributes.push(key);
} else if (!_.isEqual(val, previous[key])){
changedAttributes.push(key);
}
});
return changedAttributes;
};
This requires Underscore 1.3.1 because it's using _.has. If you can't upgrade that's an easy thing to replace though. In your case you'd passing this.previousAttributes() and this.attributes
What if you fire your own custom event after listening to the change event?
handler: function(increased) {
this.model.trigger('my-custom-event', stuff, you, want);
},
myHandler: function(stuff, you, want){
// Do it...
}
// ...
this.model.on("change:attr", this.handler, this);
this.model.on('my-custom-event, this.myHandler, this);

Categories