Make a Scroll Event Occur Once [duplicate] - javascript

I have a link that will load via ajax some content.
My problem is, I don't want to remove the text "Load comments", I just want to not allow more clicks in this class.
Load comments
Jquery
var Progressajax = false;
$(function() {
$(".showcomments").click(function(){
if(Progressajax) return;
Progressajax = true;
var element = $(this);
var id = element.attr("id");
Progressajax = false;
alert("ok");
$(data).hide().prependTo('.varload'+id).fadeIn(1000);
//$(element).remove();
$(element).removeAttr("href");
$(element).removeClass('showcomments');
});
});
I just want to see OK the first time. How can I remove this class?
$(element).removeClass('showcomments');
This is not working...
http://jsfiddle.net/qsn1tuk1/

Use jQuery's one() function
$(".showcomments").one("click", function() {
http://www.w3schools.com/jquery/event_one.asp
The one() method attaches one or more event handlers for the selected elements, and specifies a function to run when the event occurs.
When using the one() method, the event handler function is only run ONCE for each element.

When you bind an event handler, you bind to the element, not to the class. Removing a class from an element doesn't change which event handlers are bound to the element.
You could use off() to remove the event handler:
$(this).off('click');
http://jsfiddle.net/om6ggvyu/

Related

Rebind JavaScript events and addEventListener fires twice

I have a class method which defines the event listeners. Let us use the following code snippet for simplicity.
function bindEvents() {
document.querySelector('button').addEventListener('click', (e) => {
console.log('clicked!');
});
}
// Initial event binding
bindEvents();
// Rebind events at some point for dynamically created elements
bindEvents();
<button type="button">Click</button>
Everything works fine when using bindEvents() only once, however for example calling it again in ajax callback results in listener executed twice. So this means after second bindEvents(), clicking the button will console.log() twice and so on. Is there a way I can get around this behavior?
I know I can bind the events "dynamically" on the document and check with e.target, but there is a situation where I need mouseenter/mouseleave events and I don't think it's a good idea to always have those eventListeners on the document.
I've read somewhere the following, but it seems false...
The .addEventListener method ensures that the same function reference
won't be bound more than once to the same element/event/captures
combination.
Also I have played with the options parameter from here https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener, but without success.
Excuse me if this was answered somewhere, but I failed to find answer in SO and the search engines.
UPDATE: Is there a way to overwrite existing eventListeners or old ones should be removed with removeEventListener like kcp suggested below? Is there more elegant solution to this problem at all?
The .addEventListener method ensures that the same function reference won't be bound more than once to the same element/event/captures combination.
In your case, each time you execute bindEvents() a completely new handler is passed to the click event listener since you define new function (no matter it looks the same, it is different object). To use the same handler each time you must define it outside bindEvents and pass it by name (by reference). This works as expexted:
function clickHandler(e){
alert('clicked!');
}
function bindEvents() {
document.querySelector('button').addEventListener('click', clickHandler);
}
// Initial event binding
bindEvents();
// Rebind events at some point for dynamically created elements
bindEvents();
<button>click</button>
However with jQuery I use the following approach which allows me to specify that only elements in a specific container (context or ctx) will be bound:
$.fn.bindEvents = function bindEvents(ctx){
ctx = ctx || this;
$('button', ctx).on('click', function(event){
alert(1);
});
};
$('body').bindEvents();
$('div').bindEvents();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Click</button>
<div><button>in div </button></div>
In the example above bindEvents is executed twice but the first button is bound only once since it's not in a div. While if you click on the second button it alerts twice because satisfies both contexts.
addEventListener does not overwrite existing event listeners, it simply adds a new one as the method name implies. Existing listeners must be removed using the removeEventListener method.
function onClick($event) {
console.log('clicked!');
}
function bindEvents() {
/** Remove event listener first **/
document.querySelector('button').removeEventListener('click', onClick);
document.querySelector('button').addEventListener('click', onClick);
}
removeEventListener docs
Apart from removeEventListener, You can also use Event delegation. Using this mechanism event is handler by attaching event listener to parent element.
var elem = document.querySelector('div');
elem.addEventListener('click', function(e) {
e = e || event
var target = e.target;
if (target.nodeName != 'BUTTON')
return;
console.log('clicked ' + target.textContent);
});
//Simulate addition of dynamic elements
setTimeout(function() {
var newButton = document.createElement('button');
newButton.innerHTML = 'Click 2';
elem.appendChild(newButton)
}, 2000)
<div>
<button type="button">Click</button>
</div>

Event fires for all items not just the current item

I am trying to attach my plugin to a input field, and it works somewhat. So, I am attaching an on() with onchange to the input field, and when it fires, it fires for each input, and not just the one that changed. What is causing this? Is it because I am using $(document).on()? I added it that way because items are dynamically added to the page.
(function($){
$.fn.itemsave = function(config){
return this.each(function(){
var item = $(this);
var opt = {
// The options
};
var e = $.extend(opt, config);
$(document).on("change", item, function(){
request(false, e);
});
});
})(jQuery);
How it is called:
$(".simplesave").itemsave(null);
You're passing a jQuery object as the second parameter of .on(). That's not an error, but the library will interpret that as being an object to be made available to the event handler as event.data. It also means that there is no event handling delegation going on. Thus, you're establishing a "change" event handler that will fire when ever any "change" event bubbles up to the document level.
You probably should just be attaching the handler directly to your element:
item.on("change", function() {
request(false, e);
});
I believe this line is causing an error as item should be a selector not an element:
$(document).on("change", item, function(){
The solution would be to put an even handler on the item
$(item).on("change", function(){
request(false, e);
})

How to add onclick to Div with a specific class name?

I have a few generated div's on my page listing events on a calender, they all have the same class "fc-event-inner". I would like to add a onclick to these div's but am struggling to get this right.
This is what iv tried, no onclick is added and no errors on page.
$(document).ready(function () {
$('.fc-event-inner').each(
function (element) {
Event.observe("click", element, EventClick);
}
);
function EventClick() {
alert("You clicked an event")
}
});
This is an example of a generated event div:
<div class="fc-event-inner">
<span class="fc-event-title">Requested<br>by Santa</span>
</div>
Use the delegate version of on
$(document).on("click", ".fc-event-inner", function(){
/// do your stuff here
});
This catches the click at the document level then applies the class filter to see if the item clicked is relevant.
Example JSFiddle: http://jsfiddle.net/BkRJ2/
In answer to comment:
You can access the clicked element via this inside the event function. e.g.
$(document).on("click", ".fc-event-inner", function(){
var id = this.id; // Get the DOM element id (if it has one)
var $this = $(this); // Convert DOM element into a jQuery object to do cool stuff
$this.css({'background-color': 'red'}); // e.g. Turn clicked element red
});
*Note: You should never have to run an Each in order to catch events on multiple items that have a common class.
You do not need each() to bind event to elements with specific class, just selector is enough. Use jQuery on() with event delegation it will bind event to those which are generted after the binding code.
$(document).on("click", ".fc-event-inner", function(){
alert("click");
});
Delegated events
Delegated events have the advantage that they can process events from
descendant elements that are added to the document at a later time. By
picking an element that is guaranteed to be present at the time the
delegated event handler is attached, you can use delegated events to
avoid the need to frequently attach and remove event handlers, jQuery doc.
<div class="fc-event-inner">
<span class="fc-event-title">Requested<br />by Santa</span>
</div>
Your JS:
<script>
$(document).ready(function () {
$('.fc-event-inner').on("click", EventClick);
function EventClick() {
alert("You clicked an event")
}
});
</script>
http://jsfiddle.net/UBhk9/
Some explanation:
Because you are using a class(it may be used multiple times, in contrast to an id) it will work for all the elements with this class name. The .on method will attach the event handler(in this example "click") to the selector(the class .fc-event-inner). If you want to remove events bounds you've to use the .off() method and if you only want to attach the event once you can use the .one() method.

Does jQuery overwrite event listeners?

I've got a bunch divs which each contain a remove link attached with the click event below:
var observeRemoveRoom = function
$('.remove_room').click(function(){
$(this).parent().removeClass('active');
});
}
Clicking it removes the 'active' class of the parent (the div). I call this observeRemoveRoom function on window load which works fine.
The thing is, I have another function which adds more of the same divs. Since the a.remove_room links contained within the new divs weren't around on window.load I need to call observeRemoveRoom.
Am I somehow duplicating the event handlers? Does jQuery overwrite them? If so should I unbind the handlers?
Each time you call observeRemoveRoom jQuery will add a new unique event handler function for a click event.
So yes, you need to .unbind() either all currently bound handlers by just calling .unbind() without arguments, or be specific and pass in a function reference.
You can try a live query to keep them updated: http://docs.jquery.com/Plugins/livequery
Yes, you will be duplicating the event-handlers if you call observeRemoveRoom again, but it might not be noticeable since you are only calling the removeClass method which does nothing if the class is not found, which would be the case after the first listener is triggered.
Instead you can un-bind and re-bind the click event each time, like:
var observeRemoveRoom = function(){
var remove_class = function(){
$(this).parent().removeClass('active');
};
$('.remove_room').off('click', remove_class).on('click', remove_class);
}
But that said, it is recommended that you do this outside this function`, rather than binding and unbinding the event every time, like:
$(document).ready(function(){
var remove_class = function(){
$(this).parent().removeClass('active');
};
// If the element exists at dom ready, you can bind the event directly
$('.remove_room').on("click", remove_class);
// If the element is added in dynamically, you can [delegate][1] the event
$('body').on("click", '.remove_room', remove_class);
// Note: Although I've delegated the event to the body tag in this case
// I recommend that you use the closest available parent instead
});
http://api.jquery.com/on/#direct-and-delegated-events : [1]

Hot to get DOM or jQuery element by mouse?

How to get DOM or jQuery element by mouse click?
For example I have the next code:
$("*").mouseup(
function()
{
var clickedElement = ???????????????
}
);
So, how to init 'clickedElement' variable?
Thank you.
Inside an event handler, this refers to the DOM element the event was raised on.
$("*").mouseup(function() {
var clickedElement = this;
});
To get a jQuery element, just pass this to jQuery.
But: It would be much much much better to use event delegation, instead of binding an event handler to every element. You can get the origin of the event with event.target:
$(document).mouseup(function(event) {
var clickedElement = event.target;
});
And a further note: This will not necessarily give you the clicked element, but the element over which the mouse button was released, which can be different from the element the button was pressed. You might want to bind to the click event.
I also suggest to read a jQuery tutorial where these basics are covered.
If you don't want to attach an event to every DOM element (which I wouldn't recommend)...
$(document).mouseup(function(event) {
var clickedElement = event.target;
});
jsFiddle.
Here, any element's event will bubble up all the way to document, where it will be handled, and the originating element that started the event will be in event.target.
Use this. i.e.:
$("*").mouseup( function() {
var clickedElement = this; //HTML DOM Element
var $clickedElement = $(this); //jQuery Wrapped HTML DOM Element
} );

Categories

Resources