Handling priority with events from extenal libraries in Javascript - javascript

I'm using Remodal Javascript lib to handle with modal windows.
The point is that the library has handlers for custom events, e.g. the following javascript
$(document).on('opening', '.remodal', function (e) {
console.log('opening');
});
will be triggered when a modal window is open by clicking on another DOM element.
<a data-remodal-target="modal-window-id" id="trigger">CLICK ME TO OPEN MODAL</a>
<div class="remodal data-remodal-id="modal-window-id>MODAL CONTENT</div>
Now, If I add in a javascript file also the following call to a click event
$(document).on('click', '#trigger', function (e) {
console.log('trigger clicked');
});
regardless of the position of the previous script (i.e. before or after the other), I see that the opening event is fired before. I know, in Javascript there is not really a guarantee of event execution, apart from some exeptions or when using jQuery (e.g. attaching the listeners in the proper sequence).
Now, how can I manage to execute click before opening? It occurs before, but somehow there should be another click listener attached to that anchor that is executed before.
Any idea?

If what you're really after is a way to force execution of code in opening handler to run after click handler, you can always use setTimeout:
setTimeout("console.log('opening');",100);

Related

Listen for "event removal" in JS / jQuery

I am working with a very large application with a lot of JavaScript. I am trying to determine how I can find the location where a click event is being removed from a specific element.
There is a simple event listener on a specific field added via jQuery (this is an example).
$(document).ready(function() {
$('#id-name').on('click', function(e) {
window.alert('hello');
});
});
If break execution right after this and examine the element in Chrome Inspector, I see the event attached to the element. However, once I continue execution and the page finishes loading, the element no longer has the event. Something is removing it, but I can't find out where this is happening.
Is there a way to listen for "event removal" and trigger code then, so that I can identify where and how this is getting removed? Any other suggestions in locating where the click event is being removed?
Maybe you could override the removeEventListener method and trace it back to see what's calling it.
window.removeEventListener = (type, listener, useCapture)=>console.trace(type, listener, useCapture)

Require multiple event listeners to be active at once to call function (jQuery)

I'm using Woocommerce (Wordpress) and utilizing the custom event listener defined by woocommerce called show_variation to listen for changes in the variation shown (when changed from viewing one variation of a product to another).
Question 1
The problem with this event listener is that it fires on page load, and I need it to only fire on changes (after page load). As I'm not sure whether this could load after the jQuery $(window).on('load', function(){... I'm reluctant to placing my faith entirely on the on(load) event. Also I would prefer it to only be fired .on('click').
Therefore my question is: is it possible to require a double event for the function to be fired? I'm thinking something like beneath (doesn't work though):
$(element).on('click + show_variation', function(){
alert("variation shown");
});
As of now I've "solved" this by doing wrapping the show_variation event listener inside a click event listener, but I'm afraid that this isn't a bulletproof solution:
$(container).on('click', function(){
$(element).on('show_variation', function(){
alert("variation shown");
});
});
However, using te last solution causes the show_variation event listener to bubble (adding multiple event listeners and firing multiple functions).

Simulate clicking a button

If I have an existing click event associated with a button, can I use code to simulate that button being pressed so the code in the click event will run? I'm asking because I want there to be certain times where the user does not have to press the button for code to be executed. I would like to press the button automatically for them in certain instances if that makes any sense.
As simple as this,
$(function() {
$('#button').trigger('click');
});
var button = document.getElementById('yourButtonIdHere');
button.click();
This will fire a click event in the button
You can trigger a click event on an element by calling the .click() function on the element. By passing no value to the function the click event will fire, as opposed to setting up a listener for the click event.
If the button has an id of "form-btn", here's what that would like:
<button id="form-btn">Submit</button>
<script type="text/javascript">
//Setup the click event
$('#form-btn').on('click', function (e) {
alert('clicked!');
});
//Call the click event
$('#form-btn').click();
</script>
This should work fine, although I usually try to use a named function when setting up my event handlers, instead of anonymous functions. By doing so, rather than triggering the event I can call the function directly.
Note that in my experience, older browsers (IE6, IE7) sometimes limit what code-triggered events can do as a safety precaution for the user.
Here's documentation on the .click() function: http://www.w3schools.com/jquery/event_click.asp
Edit 1
I forgot that jQuery also has the .trigger() function, as used in choz's answer. That will also the job quite nicely as an alternative to .click(). What's nice about .trigger() is that it can trigger standard events as well as custom events, and also allow you to pass more data in your event.
Just make a function and run the function from within the button.
Three Choices:
You can call the click event handling function directly when appropriate:
if(timeIsRightForClick){
yourClickHandler();
}
You can simulate a button click by calling the .click() method of the button.
$("#ButtonID").click()
https://api.jquery.com/click/
Same as #2, but using jQuery's trigger() function, which can be used on standard events and custom ones:
$("#ButtonID").trigger("click");
http://api.jquery.com/trigger/
Choices #2 and #3 are usually better because they will cause the event handling function to receive a reference to the click event in case it needs to use that object. Choice #1 doesn't cause an actual click event (just runs the code you tell it to) and so no event object is created or passed to the event handler.

Method for triggering certain click event using .trigger() but suppressing all others

My situation is that I am trying to trigger a single event using the jQuery .trigger() method. However the element I am triggering has multiple click event listeners.
Actually finding what these listeners are and what they trigger from the source code is probably not viable as its included in the sites main JS file and its all minified and pretty much unreadable.
At the moment I know that the element when clicked performs some kind of ajax call and loads more data into the DOM of the page (which is what i want to trigger), however it also displays an overlay (which is what I want to suppress temporarily).
As its just an overlay there are workaround I can make; using a display:none on it straight after click etc. However it would be much more elegant if i could somehow suppress all click events on this element except the desired event.
Any ideas if this is actually possible? And if so how I would go about it?
You need to register your own event at the top of the event chain. And cancel the event chain in your event. Here is a solution with writing a custom jquery extention.
$.fn.bindFirst = function (which, handler) {
var $elm = $(this);
$elm.unbind(which, handler);
$elm.bind(which, handler);
var events = $._data($elm[0]).events;
var registered = events[which];
registered.unshift(registered.pop());
events[which] = registered;
}
$("#elm").bindFirst("click", function(e) {
// edit: seems like preventing event does not work
// But your event triggers first anyway.
e.preventDefault();
e.stopPropagation();
});
Reference:
https://gist.github.com/infostreams/6540654
EDIT:
https://jsfiddle.net/8nb9obc0/2/
I made a jsFiddle and it seems like event preventing does not work in this example. There might be another solution.

jQuery is not catching click on some content loaded

I'm using jQuery 1.7.2 with Zoomy and jmpress plugins. Also I'm using boilerplate+bootstrap downloaded from initializr.com
I'm trying to create a "game" like [Waldo/Wally] when you have to find some character in a photo. Each photo has a different character to find.
I'm using jmpress as a presentation plugin to go from one photo to another every time the character is found. jmpress loads the content trough ajax (and I need that behavior) because I want a pretty fast load of the web.
Problem: The .on("click") event is not being caught on one of the elements that exist inside the content loaded.
As an example, I'll explain my problem with one of this characters (just taking parts of code).
I have in my index.html some divs to load the characters, I'll take the nurse character:
<div id="nurse" class="step container" data-src="women/nurse.html" data-x="7500">
Loading...
</div>
The jmpress load the data-src (women/nurse.html) trough ajax when the user is near to that div (step). It loads great.
This is the code of nurse.html
<script type="text/javascript">
new Image().src = "img/nurse_big.jpg";
</script>
<div class="descripcion">
<p>Bla, bla, bla.</p>
</div>
<div class="imagen">
<img src="img/nurse.jpg" alt="Find the nurse" />
</div>
As you can see, I have two divs loaded inside the #nurse div (that has .step class).
I have this code on my js/script.js file when I try to catch the click event:
$(".step").on("click", function(event){
console.log(event.target);
});
I'm also trying with "body" tag to see what happens
$("body").on("click", function(event){
console.log(event.target);
});
If you check the console while the message is showing (div.descripcion) it catch the event and print. But, after the div.descripcion is removed and the image appears, it dosen't. Like if that div.imagen or even elements inside it dosen't exist. The click event is not catched. I tried to catch mousemove event and It does.
Why is not catching the click? any idea?
You can see a working version: [Removed]
And the not working version: [Removed]
UPDATE: I forgot, if I use .on("click") it dosen't work. But if I use .on("mousemove") for example, it works. That's the weird part. .on() is working, but not for the click event.
UPDATE 2: I have removed the links of the live examples because they where dev versions. I'll publish the link to the final work when is published. Thanks to all of you for taking the time. Specially to #Esailija that gives me the answer.
Once again, you need to use on for content loaded later on:
$("body").on("click", ".step", function(event){
console.log(event.target);
});
Replace body with the closest static element that holds the .step elements.
Static means exist in the DOM when the you execute the line:
$(...).on("click", ".step", function(event){
Example:
$('#ContainerId').on("click", ".step", function(event){
// Do what you want.
});
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
on docs
The zoomy plugin you are using does this:
'click': function () {
return false;
}
Since the element you are clicking when you are on the image, is actually the zoomy elements, those get to handle the events first. They handle it by returning false, which means doinge.stopPropagation() as well as e.preventDefault(). So the event won't even come to .imagen.
There is also unterminated multi-line comment in your code, not sure what that does but it can't be good. Consider just deleting code instead of commenting it out.
Anyway, clearing everything like this:
$.cache = {}; //Can also do $("*").off() I think
And then doing:
$(".step").on("click", ".imagen", function(event){
console.log(event.target);
event.preventDefault();
});
And it works fine. You might wanna edit the plugin to do this instead:
'click': function (e) {
e.preventDefault();
}
Alternatively you could look for a plugin that is developed by someone who knows what the hell they are doing or write it yourself.
In the documentation in http://zoomy.me/Options.html you can allow the plugin to have a clickable area by adding in true to the clickable option.
So when calling zoomy() on a element all you have to do is add a little bit of code inside the zoomy function.
$('.element').zoomy({clickable:true});
and that should fix everything,
The alternative way to catch the function on click event is just like below.
<div onclick="fireClickEvent();" > Just firing the click event!</div>
function fireClickEvent() {
console.log(event.target);
}

Categories