Prevent all javascript events from firing - javascript

I am working on a firebug like javascript element selector, but cannot figure out how to stop all JavaScript events from firing when clicked. The firebug lite plugin (https://getfirebug.com/firebuglite) is doing exactly what I want, but cannot figure out what they are doing.
Any help would be appreciated.
Senario:
User selects element inspector
User clicks on element
onClick, mousedown, mouseup should NOT fire
I have tried the following with no luck:
function stopEvents(el){
for(var key in window) {
if (key.indexOf("on") == 0)
el.addEventListener(key.substr(2), stop, false);
}
}
function StopEvent(pE)
{
stopEvents(pE);
if (!pE)
if (window.event)
pE = window.event;
else
return;
if (pE.cancelBubble != null)
pE.cancelBubble = true;
if (pE.stopPropagation)
pE.stopPropagation();
if (pE.preventDefault)
pE.preventDefault();
if (window.event)
pE.returnValue = false;
if (pE.cancel != null)
pE.cancel = true;
}
EDIT:
$('.somediv').on("click", function(e){
//Stop bubbling and propagation
StopEvent(e);
//EDIT: Still not working with this
e.stopImmediatePropagation();
//RUN only my code here
console.log("My code is running still");
return false;
});
If there is another library such as YUI binding events to the same DOM element. It will fire there event after mine. I cannot seem to hijack the event to stop this from happening.
EDIT:
I cannot use disabled because I need to be able to fire my event. If I did the following, I wouldn't be able to fire the above event. I cannot attach a parent event either because the DOM will stop firing all events on the Tree for that node.
$('.somediv').on("mouseover", function(e){
$(this).attr("disabled", "disabled");
});
EDIT:
The events I want to disable are already created before my script runs. These events could be any javascript library such as YUI, Dojo, jQuery, JavaScript etc...

Disabling all events on the page is very easy. Hard part is to restore them when needed.
document.body.innerHTML = document.body.innerHTML;
This will effectively remove all events bound to DOM nodes by replacing the DOM with it's "virgin" copy.
Most of the time user won't even notice the redraw.

You can't "disable" all of them without also intercepting the actual event binding, so you'd have to end up with something like this:
(function(prototypes) {
prototypes.forEach(function(prototype) {
var eventTracker = {};
var oldAEL = prototype.addEventListener;
prototype.addEventListener = function(a,b,c) {
if (!eventTracker[a]) { eventTracker[a] = true; }
return oldAEL.call(this, a, function(evt) {
console.log(a, eventTracker[a]);
if(eventTracker[a] === true) {
b(evt);
}
},c);
};
prototype.toggleEvent = function(name, state) {
eventTracker[name] = state;
};
});
}([Document.prototype, HTMLElement.prototype, ...]));
example: http://jsfiddle.net/BYSdP/1/
the button gets three click listeners, but if the second button is clicked, the event regulator for "click" is set to false, so none of the events will actually trigger the originally supplied code. Note that this also makes debugging a LOT harder, because you're wrapping handlers in anonymous functions.

event.stopImmediatePropagation() keeps the rest of the handlers from being executed and prevents the
event from bubbling up the DOM tree.
Example:
$( "p" ).click(function( event ) {
event.stopImmediatePropagation();
});
$( "p" ).click(function( event ) {
// This function won't be executed
$( this ).css( "background-color", "#f00" );
});
Source: https://api.jquery.com/event.stopimmediatepropagation/

Related

jQuery mouse event blocks default propagation

I have an issue with a full-body-overlay effect when clicking on any link.
The wanted effect is:
when any link of the page is "pushed" (mousedown or touchstart), an image overlay appears on the top of the whole body (hiding the complete content of the page)
when the link is (or should be) "released" (mouseup or touchend), the overlay should disappear and the original clicked link target should happen (the "href" attribute must be followed for instance).
The first part is OK: I added an event handler listening the "mousedown touchstart" events on every links. The second part is more complicated as the overlay does not trigger the "release" action of the link (the overlay is over the content with the link). So I attached a "mousedown touchend" event handler on the whole document, which works, but the default behavior of the clicked link (go to its "href" attribute for instance) is never fired :(
Here is my JS:
$(document).ready(function(){
// the full-page overlay selector
var $overlay = $('.body-overlay');
// a flag to keep a trace of clicked element
var overlay_triggered = false;
// the "mousedown" event handler
function show_overlay(evt)
{
var $target = $(evt.target);
if (overlay_triggered === false) {
$overlay.show();
overlay_triggered = $target;
$(document).on('mouseup touchend', hide_overlay);
}
return true;
}
// the "mouseup" event handler
function hide_overlay(evt)
{
if (overlay_triggered !== false) {
$(document).off('mouseup touchend', hide_overlay);
$overlay.hide();
// !!! - here I try to trigger a classic click but it never works
$(overlay_triggered).click();
overlay_triggered = false;
}
return true;
}
// attachment of the mousedown handler on all links
$(document).on('mousedown touchstart', 'a', show_overlay);
});
I made a JS Fiddle to show it more clearly.
Does someone know about any mistake here ? Is my logic wrong ?
The problem is caused by the way jQuery executes .click(). It is a shortcut for jQuery's trigger('click') method, and this is what the documentation says:
Although .trigger() simulates an event activation, complete with a synthesized event object, it does not perfectly replicate a naturally-occurring event.
The solution is to call the click method on the DOM element itself. It seems though that the MDN documentation announces the same limitations apply to that method:
The HTMLElement.click() method simulates a mouse click on an element.
However, the click() method will not initiate navigation on an <a> element.
...but in trying this with the current versions of Firefox, Chrome and Edge, the DOM click method does launch the <a> navigation (also when href has a http URL).
So, change this:
overlay_triggered = $target;
to:
overlay_triggered = evt.target;
And change this (which was overkill anyway):
$(overlay_triggered).click();
to:
overlay_triggered.click();
See the updated jsfiddle.
I am not exactly sure why this won't work but I got it working by changing $(overlay_triggered).click(); to window.location = $(overlay_triggered).attr("href");
I have slightly modified the JS part of yours, and all is okay now
The thing i did is holding the target's href value in a variable ( I stored the target's href value in 'href' vaiable in the code below ), and after that "window.location = href;" in 'hide_overlay' function does the trick.
<script>
$(document).ready(function(){
// the full-page overlay selector
var $overlay = $('.body-overlay');
// a flag to keep a trace of clicked element
var overlay_triggered = false;
var href = false;
// the "mousedown" event handler
function show_overlay(evt)
{
var $target = $(evt.target);
href = evt.target.href;
if (overlay_triggered === false) {
$overlay.show();
overlay_triggered = $target;
$(document).on('mouseup touchend', hide_overlay);
}
return true;
}
// the "mouseup" event handler
function hide_overlay(evt)
{
if (overlay_triggered !== false) {
$(document).off('mouseup touchend', hide_overlay);
$overlay.hide();
// !!! - here I try to trigger a classic click but it never works
if( href ) {
window.location = href;
}
overlay_triggered = false;
}
return true;
}
// attachment of the mousedown handler on all links
$(document).on('mousedown touchstart', 'a', show_overlay);
});
</script>

How to create an "about To Blur" or "will blur" event in Javascript?

I have some code that runs on a "blur" event on an element.
This code needs to actually use the activeElement, and thus can't actually run from the "blur" event.
I was hoping I could create an event like this. The aim was that the "willblur" event would fire before the "blur" event.
var lastTouchedElement;
$('body').on('click', preBlurHandler);
$('body').on('focusin', postFocusHandler);
$('.inp1').on('willblur', function() {alert('willblur');});
$('.inp1').on('blur', function() {alert('blur');});
function preBlurHandler(ev) {
if (!lastTouchedElement) {
postFocusHandler(ev);
return;
}
var focussingElement = ev.target;
if (lastTouchedElement === focussingElement || $.contains(lastTouchedElement, focussingElement)) {
//focus is staying in the same place, do nothing
return;
}
$(lastTouchedElement).trigger('willblur', [ev, {
target: lastTouchedElement,
focussingElement: focussingElement
}]);
}
function postFocusHandler(ev) {
lastTouchedElement = document.activeElement;
}
The full code is in JSFiddle at https://jsfiddle.net/t0un95jt/3/
But it doesn't work. In fact it's not even close.
Help me StackOverflow; you're my only hope.
The key was to use addEventListener instead of JQuery's on(), and to use "mousedown" instead of "click".
instead of this line:
$('body').on('click', preBlurHandler);
I use this:
window.addEventListener('mousedown', preBlurHandler, true);
The final argument for addEventListener: true, means "do this on the capturing phase". The capturing phase starts at the outermost element and works its way through firing an event on subsequent child elements, before the bubbling phase begins which works its way back up the DOM tree.

Prevent keydown() from being captured by document binding

I'm not exactly sure how to phrase this, so I couldn't search it. Basically, I have a keydown() bind on $(document). I'd like to show() another div, and have all keydown events be rerouted to this div and prevented from firing off in the document handler. Is this even possible, or would I have to put all my main keybindings on another div and work from there?
e.stopPropagation, or
e.preventDefault (depending on the situation)
Where e is the event.
Ex:
function onKeyDown(e) {
doStuff();
e.preventDefault();
}
e.preventDefault() will prevent the default behaviour of an event. What you need is to use
e.stopPropagation(), so that the event does not bubble up the DOM structure.
$(element).keydown(function(e) {
// do the task
// allow the default behaviour also
e.stopPropagation();
//^. BUT stop the even bubbling up right here
});
e.stopProgation(), can be bit confusing to grasp on the first but I created a demo with click event to explain it.
Hope it helps!!
Try:
​$(document).on('keydown', function (evt) {
$('#foo').show().trigger(evt);
});​​​​​
$('#foo').on('keydown', function (evt) {
console.log(evt);
return false; // this is very important. Without it, you'll get an endless loop.
});
​
demo: http://jsfiddle.net/Z7vYK/
The only way I can think of to even have a keydown event run on something other than an input or document, is to manually trigger it. You could have a global variable keep track of whether or not your div is showing, then trigger the event on your div accordingly.
Here's one such solution
HTML
Show div
<div id="hiddendiv"></div>​
Javascript
var showing = false;
function showdiv()
{
showing = true;
$('#hiddendiv').show(200);
}
// Set up events on page ready
$(function() {
$(document).keydown(function(e) {
// If the div is showing, trigger it's keydown
// event and return
if(showing)
{
$('#hiddendiv').data('keydown_event', e).keydown();
return true;
}
alert('Document keydown! Keycode: ' + e.keyCode);
// Otherwise do the normal keydown stuff...
});
// Keydown for the hidden div
$('#hiddendiv').keydown(function() {
e = $(this).data('keydown_event');
alert('Hiddendiv keydown! Keycode: ' + e.keyCode);
// Make sure to stop propagation, or the events
// will loop for ever
e.stopPropagation();
return false;
});
});
​
As you can see, the #hiddendiv keydown event is being triggered by the document keydown event. I've also included a slight hack to get the event object to the hidden div using the jQuery data function.
Here's a demonstration of the code: http://jsfiddle.net/Codemonkey/DZecX/1/

Handling clicks outside an element without jquery

I would like to implement the solution like this
How do I detect a click outside an element?
but I'm using another javascript library with $() function already defined
Any suggestions?
This is easy to accomplish. Would be a shame to load the jQuery library just for one feature.
If the other library you're using handles event binding, you could do the same thing in that library. Since you didn't indicate what that other library is, here's a native solution:
Example: http://jsfiddle.net/patrick_dw/wWkJR/1/
window.onload = function() {
// For clicks inside the element
document.getElementById('myElement').onclick = function(e) {
// Make sure the event doesn't bubble from your element
if (e) { e.stopPropagation(); }
else { window.event.cancelBubble = true; }
// Place the code for this element here
alert('this was a click inside');
};
// For clicks elsewhere on the page
document.onclick = function() {
alert('this was a click outside');
};
};
If the $ conflict is your only hold-up, there are ways around that:
http://docs.jquery.com/Using_jQuery_with_Other_Libraries
I also add here the code that stops event bubbling up. Found on quircksmode.org
function doSomething(e) {
if (!e) var e = window.event
// handle event
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
}

Simple click event delegation not working

I have a div
<div class="myDiv">
somelink
<div class="anotherDiv">somediv</div>
</div>
Now, using event delegation and the concept of bubbling I would like to intercept clicks from any of myDiv, myLink and anotherDiv.
According to best practices this could be done by listening for clicks globally (hence the term 'delegation') on the document itself
$(document).click(function(e) {
var $eventElem = $(e.target);
var bStopDefaultClickAction = false;
if ($eventElem.is('.myDiv'))
{
alert('Never alerts when clicking on myLink or anotherDiv, why????');
bStopDefaultClickAction = true;
}
return bStopDefaultClickAction;
});
See my alert question above. I was under the impression that clicks bubble. And it somewhat does because the document actually receives my click and starts delegating. But the bubbling mechanism for clicks on myLink and anotherDiv doesn't seem to work as the if-statement doesn't kick in.
Or is it like this: clicks only bubble one step, from the clicked src element to the assigned delegation object (in this case the document)? If that's the case, then I need to handle the delegation like this:
$('.myDiv').click(function(e) {
//...as before
});
But this kind of defeates the purpose of delegation as I now must have lots of 'myDiv' handlers and possibly others... it's dead easy to just have one 'document' event delegation object.
Anyone knows how this works?
You should use live event from JQuery (since 1.3), it use event delegation :
http://docs.jquery.com/Events/live
So you code will be :
$(".myDiv").live("click", function(){
alert('Alert when clicking on myLink elements. Event delegation powaa !');
});
With that, you have all the benefices of event delegation (faster, one event listener etc..), without the pain ;-)
The event target will not change. You need to mirror what jquery live does and actually check if $eventElem.closest('. myDiv') provides a match.
Try:
$(document).click(function(e) {
var $eventElem = $(e.target);
var bStopDefaultClickAction = false;
if ( $eventElem.closest('.myDiv').length )
{
alert('Never alerts when clicking on myLink or anotherDiv, why????');
bStopDefaultClickAction = true;
}
return bStopDefaultClickAction;
});
Event.target is always the element that triggered the event, so when you click on 'myLink' or 'anotherDiv' you store a reference to these objects using $(e.target); So what you do in effect is: $('.myLink').is('.myDiv') which returns false, and that's why the alert() is not executed.
If you want to use event delegation this way, you should check wheter event.target is the element or any of its children, using jQuery it could be done like this:
$(e.target).is('.myDiv, .myDiv *')
Seems to work fine to me. Try it here: http://jsbin.com/uwari
Check this out: One click handler in one page
var page = document.getElementById("contentWrapper");
page.addEventListener("click", function (e) {
var target, clickTarget, propagationFlag;
target = e.target || e.srcElement;
while (target !== page) {
clickTarget = target.getAttribute("data-clickTarget");
if (clickTarget) {
clickHandler[clickTarget](e);
propagationFlag = target.getAttribute("data-propagationFlag");
}
if (propagationFlag === "true") {
break;
}
target = target.parentNode;
}
});

Categories

Resources