I am trying to stop propagation of the click event into Google Maps API Autocomplete's dynamically created pac-container divs with no luck. A similar question has already been asked but the answer doesn't work well for me.
google places api autocomplete - adding click event
The solution from that question says that the click event is cancelled by Autocomplete, and to use the mousedown event instead. That technically worked for me but required me to change the event of document from click to mousedown which is a sacrifice I don't want to make.
I've looked into google maps api events and Autocomplete only emits the 'place_changed' event so no help there. My code to stop propagation on the pac-container divs below.
var pacContainers = document.getElementsByClassName("pac-container");
angular.forEach(pacContainers, function(value, key) {
// the click event is cancelled by the Autocomplete instance
angular.element(value).on('click', function($event) {
$event.stopPropagation();
});
});
Since you're using Angular, you can create a directive named pacContainer, and run the code inside your forEach for the element either in the link or controller, and it will bind the click event handler with stopPropagation on any pac-container element as it's created.
A similar problem has been solved before without using intervals or timeouts, and instead using ng-focus to signify the element is ready.
See https://github.com/driftyco/ionic/issues/1798#issuecomment-95943955
The pac-container will be ready by the time it receives focus, and that's when you know you can attach the click handler.
Related
I was reading through MaterializeCSS's js files, in its "cards.js" file, there are these lines:
$(document).on('click.card', '.card', function (e) {
//something
});
I am not unfamiliar with jQuery's .on() function, but I never used custom event as the first parameter. What I don't understand is there seems to be nowhere defining this custom event click.card(if it is a custom event), because I only load this card.js and another velocity.min.js file from the MaterializeCSS package besides jQuery, and I searched velocity.min.js there is nothing related to this event. It seems to me that the custom event is in this pattern:original event.classname, but I tried replacing card with other class name and it didn't work.
I tried to look for more information about how to define a custom event but couldn't find anything useful.
My question is how to find where this custom event is defined.
This is not a custom event, this is a DOM event with a namespace:
click is the DOM event, and card the event namespace.
If you have multiple handlers on the same element, this can help you discern them. You could remove only this listener (and leave all other click listeners):
$(document).off('click.card');
And you can trigger them manually using $('...').trigger:
$('.card').trigger('click.card'); // only triggers this specific click listener, not the others
You can find out more about event namespaces here.
I'm using the leanModal plug-in on a site I'm building. I'm currently working on an administrator page and want to disable the overlay click event handler until the user has successfully authenticated. I can successfully unbind all event handlers using $("#lean_overlay").off("click");, but I'm unable unbind/rebind the specific event handler when it's stored in a variable. I'm using jQuery 1.10.2 and the most up-to-date leanModal.
Here's a snippet of my code:
var overlay_event = $._data($('#lean_overlay')[0], "events");
$('#lean_overlay').off('click', overlay_event);
// insert code to check if user's logged in
$('#lean_overlay').on('click', overlay_event);
Is this the proper way to store a handler in a variable using jQuery 1.8+?
EDIT:
I neglected to mention that I've tried event.preventDefault(); and return false; to stop the event from firing. My logic for checking the user's authentication state is working. What's not working is the disabling of the click event handler for the overlay to force users to use the login modal before accessing the page. I'm unsure if that was clear in my original post. Storing the event handler seemed like the best option...
2nd EDIT:
I figured out how to stop the overlay click event handler from firing using a botched version of namespacing:
$('#lean_overlay').off('click', $(this).leanModal.close_modal);
The removal of the event handler works, but the re-bind doesn't appear to be working. I can't seem to find an easy way of re-binding an event handler function found in a linked plug-in. Ideas?
So, no way I could find to "capture" the event handler referenced by the plug-in. My solution was to make my own overlay and use that for the login screen. Works perfectly because it's MINE! :)
I've been reading about custom events and looked at some examples. Perhaps I am misunderstanding what custom events are and how they are triggered and would appreciate some help.
Example Problem
To trigger an event when the background colour of a div changes from one colour to another.
Situation A) The colour changes as result of user activity detectable from within the script, eg by onclick, onmouseover, onkeypress then I would set up a listener for these events and respond accordingly. This I understand how to do.
Situation B) The colour changes as the result of user activity not detectable from within the script, eg a new theme applied to the page, then am I correct in thinking the following are necessary?
I would need to create a custom event for colour change.
Add a listener for the event to the appropriate DIV
The listener would need to poll the DIV at intervals to check for colour changes
Really its step 3 I am not clear about. If you are not polling the DIV how does the event colour change trigger an event? In other words how does the script know that a colour change has taken place?
Custom events are not like DOM events, they don't fire because some interaction happened in the browser. They happen when the person who writes the code decides for them to happen. You have to explicitly trigger custom event when you need one.
For example, you might have function like
function updateBackground (element, color) {
elmenet.css('background-color', color);
// element has to be an object that has `trigger` function on its prototype
// like jQuery wrapped element, for example
element.trigger('updated-background', color);
}
Then every time this code is executed you'll have 'updated-background' fired in context of this element.
UPD.
Using browser options a user can change font size, background colours
etc, ie apply a new theme. As far as I know there are no native events
within javascript to deal with these so I would need to create a
custom event within my script. What I am trying to ask is how to you
find out when a custom event takes place?
You find out because you create them. You are correct (to my knowledge) that there are no DOM events fired when user changes font-size / default body background etc. You could poll for body and fire custom event when you detect a change, as you said.
In JavaScript, a custom event is simply a message, broadcast to all event listeners, that says, "Attention everyone: event X just happened!" Any listener that cares about that event can then run some function.
However, your custom event still needs to be fired somehow. Custom events aren't fired unless, somewhere in your code, you call .dispatchEvent (or .trigger, in jQuery). Your program must decide when it is time to fire the event. If the browser doesn't natively fire an event that you can use as a cue for your own custom event, then often polling is the only way to know when to fire the event.
The bottom line here is events are just messages. It's up to you and the code you write to decide when to fire them.
Is there a way to temporarily disable an event listener?
In my case, I have a third party library (not jQuery centric) that creates mouseover/mouseout events on an element using addEventListener/attachEvent.
Under certain circumstances another event fires on a different element and I need to disable those event listeners. My solution thus far has been to simply unbind the mouseover/mouseout. This usually works fine because that event generally causes the page to refresh.
However, every now and again an error can occur (think validation error) that results in the page not refreshing, and I need to re-attach the mouseover/mouseout event listeners.
Helpful information
It's probably worth mentioning that because the mouseover/mouseout event listeners are created and attached within a third party library I cannot simply assign the event to a variable and bind/unbind it in that manner (which AFIK is the best way to do this).
Update
I had originally asked
Is there a way in jQuery to get the event listeners already assigned to an object?
I have since found out it is impossible to access events assigned by addEventListener/attachEvent: Access events added with attachEvent() / addEventListener() in JavaScript
jQuery uses data to store events internally, so you can use it to get all of the event handlers for an object:
$("#foo").data("events")
You can then remove a specific handler by using unbind:
$("#foo").unbind('click', $("#foo").data("events").click[42]);
Unfortunately, you can't access them. At best, you can remove event listeners using W3C's removeEventListener (docs) and/or Microsofts detachEvent (docs). Once the listener is removed, however, it's gone for good.
There's one caveat with removeEventListener, in that if the event was registered twice, once indicating to capture, and once indicating not to capture, you must remove it twice; once for each case.
To learn more about capturing and not capturing, see the W3C spec.
If you want to temporarily disable an event handler being run, why not just add escape code to the function?
like so:
$('#button').click(function(){
var clicked_element = $(this);
if(elem.hasClass('event-click-disabled'))
{
// logging code so we know exactly what events are being skipped
console.info(
'The click event on following element was skipped',
clicked_element
);
return;
}
alert('Button clicked');
});
Then if you want to disable an event on a specific element, just call
element.addClass('event-click-disabled');
The event handler is still run, but it will return immediately.
I'm trying to build a Chrome browser extension, that should enhance the way the twitter website behaves in Google Chrome. I want to mark the top tweet that gets moved down when new tweets are loaded, and scroll to it.
I'm able to fetch the top tweet before the click by hooking the mousedown event using .live(). After that, I have to wait until the tweets are loaded, before I scroll down to the previous tweet. I have a hack in place with a setTimeout() now, and that works for me, but I'd like a better solution.
Possible solutions:
Somehow hook an event that fires when elements are loaded to a div
Hook an event that fires when an element gets removed from the DOM
Since you are targeting Google Chrome, you could use the DOM Level 2 Mutation Events, specifically:
DOMNodeInserted
DOMNodeRemoved
You can bind them by using addEventListener:
someElement.addEventListener('DOMNodeInserted', eventHandlerFunction, false);
Or since you're using jQuery's, with the bind method:
$(selector).bind('DOMNodeInserted', function () {
//..
});
Be careful to not modify the affected DOM in those events, because you could get into an infinite event recursion, for example, if you insert an element in the DOMNodeInserted event, it will fire again.