addEventListener to all but one element - javascript

I'm trying to wean myself off jQuery (my heart is in the right place, no?), and I'm having trouble getting to what would be the equivalent of the :not() selector.
I have document.body.addEventListener("mousewheel", scrollTriggered), which I want to fire on scroll of anything but a specific div (in the fiddle, #something). I've tried integrating event.target, to no avail.
Any help greatly appreciated.
See JSFiddle

You can check whether the event originated from within the element you want to avoid. To do that, you have to traverse up the DOM tree from target and compare each Node's id attribute, or use Node.contains (check the compatibility section first though):
var ignore = document.getElementById('something');
function scrollTriggered(event) {
var target = event.target;
if (target === ignore || ignore.contains(target)) {
return;
}
// do other stuff
}
DEMO
That said, Markasoftware's answer is even better, since it prevents the event in the first place.

The easiest way is probably to set an addEventListener with the third argument to false that does the action, and then have another addEventListener on the element you want to exclude, with a third argument true, which will cancel the event from propagating to the other event listener. The third argument is a little complicated, but the important part is that if it's set to true, that listener will fire before any false handlers. As #FelixKling said, you actually don't need it to be true here, but it's good practice to do it whenever you need a handler to fire before another one, because sometimes it IS needed. Here's a jsfiddle example: http://jsfiddle.net/markasoftware/sBg3a/2/
document.body.addEventListener("mousewheel", scrollTriggered,false);
function scrollTriggered() {
console.log('hi');
}
document.getElementById('something').addEventListener('mousewheel',function(e) {
e.stopPropagation();
}, true);
Although #FelixKling's answer works, I personally think this is more elegant and generally use things like this instead of the other way. I just like how you can have the main event listener just have the listener code, and all the stuff that cancels the event from propagating can be completely separate, making it more unobstrusive

You can check the target element inside your event handler and if that target element has id something return false;
something like this:
function scrollTriggered (event) {
if (event.target.id === "something") {
// don't do anything
return;
} else {
// do something
}
}

You will can use next example code with EcmaScript 6:
function scrollTriggered(event) {
var target = event.target;
if (target.outerHTML.includes('something')) {
return;
}
// do other stuff
}
We extract string from html element and try found in it something. This will work if you located inside necessary element which need ignore.

Related

is jquery .one() computing checks every event?

And therefore adding a bit of computing load?
For those of you unfamiliar with the .one() jquery function it basically triggers an event just once. Such as if you wanted to add a div on the first time a page is scrolled.
To bring background to the matter, I came across this question:
How to alert when scroll page only first time using javascript?
I have been in projects where I had to add hundreds or thousands of events, so for me it’s always very important to optimize computing power, plus, I am a curious person so I just need to know.
One of the answers where the guy uses vanilla javascript is basically an endless loop where you switch a boolean on the first instance and basically have to continually enter the function to see if it has been already triggered.
var xxx;
$(window).scroll(function () {
if(!xxx)
{
xxx = true;
var div = $("#myDiv");
alert(div.height());
}
});
My idea is that jquery being already heavy on the page it probably just performs this same action under the hood, but I would like to be completely certain as for my future implementations.
No. jQuery's .one works similarly to, for example:
calling addEventListener, and then, in the callback, calling removeEventListener
calling addEventListener with { once: true } in the options object
in jQuery, like calling .on, and then, in the callback, calling .off
Once the listener runs once, it's de-attached; no further logic takes place when the event occurs in the future, because the listener is no longer connected at all.
So .one is very light on computing resources, even if you add lots and lots of .ones.
You can see the source code of one here:
if (one === 1) {
origFn = fn;
fn = function (event) {
// Can use an empty set, since event contains the info
jQuery().off(event); // <-------------------------------------------------
return origFn.apply(this, arguments);
};
// Use same guid so caller can remove using origFn
fn.guid = origFn.guid || (origFn.guid = jQuery.guid++);
}
return elem.each(function () {
jQuery.event.add(this, types, fn, data, selector);
});
where jQuery() returns a jQuery collection containing elements matching the current selector. When one is called, the callback is wrapped in another that calls .off as soon as the function is executed.
The sample code in the answer you linked to is quite inefficient, and should not be used, especially for scroll events, which fire very frequently.

Event 'e' in Javascript Function's Parameter [duplicate]

I am new to JavaScript/jQuery and I've been learning how to make functions. A lot of functions have cropped up with (e) in brackets. Let me show you what I mean:
$(this).click(function(e) {
// does something
});
It always appears that the function doesn't even use the value of (e), so why is it there so often?
e is the short var reference for event object which will be passed to event handlers.
The event object essentially has lot of interesting methods and properties that can be used in the event handlers.
In the example you have posted is a click handler which is a MouseEvent
$(<element selector>).click(function(e) {
// does something
alert(e.type); //will return you click
}
DEMO - Mouse Events DEMO uses e.which and e.type
Some useful references:
http://api.jquery.com/category/events/
http://www.quirksmode.org/js/events_properties.html
http://www.javascriptkit.com/jsref/event.shtml
http://www.quirksmode.org/dom/events/index.html
http://www.w3.org/TR/DOM-Level-3-Events/#event-types-list
DISCLAIMER: This is a very late response to this particular post but as I've been reading through various responses to this question, it struck me that most of the answers use terminology that can only be understood by experienced coders. This answer is an attempt to address the original question with a novice audience in mind.
Intro
The little '(e)' thing is actually part of broader scope of something in Javascript called an event handling function. Every event handling function receives an event object. For the purpose of this discussion, think of an object as a "thing" that holds a bunch of properties (variables) and methods (functions), much like objects in other languages. The handle, the 'e' inside the little (e) thing, is like a variable that allows you to interact with the object (and I use the term variable VERY loosely).
Consider the following jQuery examples:
$("#someLink").on("click", function(e){ // My preferred method
e.preventDefault();
});
$("#someLink").click(function(e){ // Some use this method too
e.preventDefault();
});
Explanation
"#someLink" is your element selector (which HTML tag will trigger this).
"click" is an event (when the selected element is clicked).
"function(e)" is the event handling function (on event, object is created).
"e" is the object handler (object is made accessible).
"preventDefault()" is a method (function) provided by the object.
What's happening?
When a user clicks on the element with the id "#someLink" (probably an anchor tag), call an anonymous function, "function(e)", and assign the resulting object to a handler, "e". Now take that handler and call one of its methods, "e.preventDefault()", which should prevent the browser from performing the default action for that element.
Note: The handle can pretty much be named anything you want (i.e. 'function(billybob)'). The 'e' stands for 'event', which seems to be pretty standard for this type of function.
Although 'e.preventDefault()' is probably the most common use of the event handler, the object itself contains many properties and methods that can be accessed via the event handler.
Some really good information on this topic can be found at jQuery's learning site, http://learn.jquery.com. Pay special attention to the Using jQuery Core and Events sections.
e doesn't have any special meaning. It's just a convention to use e as function parameter name when the parameter is event.
It can be
$(this).click(function(loremipsumdolorsitamet) {
// does something
}
as well.
In that example, e is just a parameter for that function, but it's the event object that gets passed in through it.
The e argument is short for the event object. For example, you might want to create code for anchors that cancels the default action. To do this you would write something like:
$('a').click(function(e) {
e.preventDefault();
}
This means when an <a> tag is clicked, prevent the default action of the click event.
While you may see it often, it's not something you have to use within the function even though you have specified it as an argument.
In jQuery e short for event, the current event object. It's usually passed as a parameter for the event function to be fired.
Demo: jQuery Events
In the demo I used e
$("img").on("click dblclick mouseover mouseout",function(e){
$("h1").html("Event: " + e.type);
});
I may as well have used event
$("img").on("click dblclick mouseover mouseout",function(event){
$("h1").html("Event: " + event.type);
});
Same thing!
Programmers are lazy we use a lot of shorthand, partly it decreases our work, partly is helps with readability. Understanding that will help you understand the mentality of writing code.
Today I just wrote a post about "Why do we use the letters like “e” in e.preventDefault()?" and I think my answer will make some sense...
At first,let us see the syntax of addEventListener
Normally it will be:
target.addEventListener(type, listener[, useCapture]);
And the definition of the parameters of addEventlistener are:
type :A string representing the event type to listen out for.
listener :The object which receives a notification (an object that implements the Event interface) when an event of the specified type
occurs. This must be an object implementing the EventListener
interface, or a JavaScript function.
(From MDN)
But I think there is one thing should be remarked:
When you use Javascript function as the listener, the object that implements the Event interface(object event) will be automatically assigned to the "first parameter" of the function.So,if you use function(e) ,the object will be assigned to "e" because "e" is the only parameter of the function(definitly the first one !),then you can use e.preventDefault to prevent something....
let us try the example as below:
<p>Please click on the checkbox control.</p>
<form>
<label for="id-checkbox">Checkbox</label>
<input type="checkbox" id="id-checkbox"/>
</div>
</form>
<script>
document.querySelector("#id-checkbox").addEventListener("click", function(e,v){
//var e=3;
var v=5;
var t=e+v;
console.log(t);
e.preventDefault();
}, false);
</script>
the result will be : [object MouseEvent]5 and you will prevent the click event.
but if you remove the comment sign like :
<script>
document.querySelector("#id-checkbox").addEventListener("click", function(e,v){
var e=3;
var v=5;
var t=e+v;
console.log(t);
e.preventDefault();
}, false);
</script>
you will get : 8 and an error:"Uncaught TypeError: e.preventDefault is not a function
at HTMLInputElement. (VM409:69)".
Certainly,the click event will not be prevented this time.Because the "e" was defined again in the function.
However,if you change the code to:
<script>
document.querySelector("#id-checkbox").addEventListener("click", function(e,v){
var e=3;
var v=5;
var t=e+v;
console.log(t);
event.preventDefault();
}, false);
</script>
every thing will work propertly again...you will get 8 and the click event be prevented...
Therefore, "e" is just a parameter of your function and you need an "e" in you function() to receive the "event object" then perform e.preventDefault(). This is also the reason why you can change the "e" to any words that is not reserved by js.
It's a reference to the current event object
this will be my first stackoverflow help but I am confident that my answer will help anyone reading this.
Basically, e is just an object containing information about the EVENT which has just occured.
if it is 'click', then the object will contain about the click,
if it is 'submit', then the object will contain about the submit,
and they are typically found in addEventListener.
clickMe.addEventListener('click', e => {
console.log(e)
}
meaning, whenever I 'click' the button, it will console.log the INFOMRATION about the event that happened which is I did is to 'click' it, this will print information about the click event.
e is very useful because you can access and use the event to your very own project such as printing the location of x value... like
clickMe.addEventListener('click', e => {
console.log(e.clientX)
}
then it will print the location where you 'click' that event.. mine it returns 32
if you prefer video, please watch this
https://www.youtube.com/watch?v=_BVkOvpyRI0
video is not mine
upvoting me will truly help me since I am a student and looking for opportunity to help here. Love lots!
$(this).click(function(e) {
// does something
});
In reference to the above code
$(this) is the element which as some variable.
click is the event that needs to be performed.
the parameter e is automatically passed from js to your function which holds the value of $(this) value and can be used further in your code to do some operation.

Passing object HTMLInputElement as a parameter to function

I am trying to pass a DOM element to a function without any luck. FireBug reports the following issue:
SyntaxError: missing ] after element list
LlenarDetalleReserva([object HTMLInputElement]); return false;
The selector needs to add a few attributes dynamically as it's being created.
I've tried the following:
$('#mySelector').attr({'onkeydown' : 'intOrFloat(event,this.value);', 'onchange' : 'LlenarDetalleReserva('+ $.trim($('#cant_r_'+ vectorid[2])[0]) +'); return false;'});
What am I missing here? What is producing this error?
Thanks in advance.
Please, don't do that. Use on() to bind an event to the element. Never set it as an attribute directly.
$('#mySelector')
.on('keydown', function(event)
{
intOrFloat(event, this.value);
})
.on('change', function(event)
{
if (vectorid && vectorid[2] != undefined)
{
var element = $('#cant_r_'+ vectorid[2]);
if (element.length > 0)
{
LlenarDetalleReserva(element);
}
}
return false;
});
The code above(full of ifs) is made to avoid exceptions at run-time. That is what I would do in your case. Further, I don't really know what you're trying to get in that $.trim() function, but it seems that you want to get the element and pass it as a string. In the code above its being passed by reference, instead.
UPDATE:
In order to answer OP's question of why I shouldn't set an attribute directly I didn't tell you you can't add an attribute directly but an event handler as attribute.I can't tell what happens in the backgrounds of the engine, so in fact, it works adding as attribute. But isn't a best practice and it's part of Unobtrusive approach.

JS function when keyboard key is pressed?

Is there a way to run a JavaScript function when a key is pressed and released?
For example, how would I run a function example() when the T key is pressed? I've seen examples of these before, but they were long and messy, and I couldn't get them to work. Would something like this just go in a <script> in the <head>?
Part 1: Where to put the scriptblock?
To capture over the entire page, like as a page-help-function (maybe you want to capture F1?) then you would put your script block in the <head> tag, inside a script. But if you want to capture a DOM element, then you have to execute the code after the DOM element occurs (because the script is interpreted as it's found, if the DOM element doesn't exist yet, the selector engine can't find it. If this doesn't make sense say something, and an article shall be found).
But here's something for you to consider: Good javascript programmer mentors today recommend all javascript be loaded at the end of the page. The only things you might want to load at the head of the document are libraries like jQuery, because those are widely cached, especially if you're using a CDN version of jQuery, as that generally tends to not impact load times.
So that answers the question of "where do I put the codeblock, in the <head>?": No. At the end.
Now, as to how to actually capture the keystroke, let's do it in three parts:
Part 2: Capturing all keyboard events on the window:
<html>
<head>
<title>blah blah</title>
<meta "woot, yay StackOverflow!">
</head>
<body>
<h1>all the headers</h1>
<div>all the divs</div>
<footer>All the ... ... footers?</footer>
<script>
/* the last example replaces this one */
function keyListener(event){
//whatever we want to do goes in this block
event = event || window.event; //capture the event, and ensure we have an event
var key = event.key || event.which || event.keyCode; //find the key that was pressed
//MDN is better at this: https://developer.mozilla.org/en-US/docs/DOM/event.which
if(key===84){ //this is for 'T'
doThing();
}
}
/* the last example replace this one */
var el = window; //we identify the element we want to target a listener on
//remember IE can't capture on the window before IE9 on keypress.
var eventName = 'keypress'; //know which one you want, this page helps you figure that out: http://www.quirksmode.org/dom/events/keys.html
//and here's another good reference page: http://unixpapa.com/js/key.html
//because you are looking to capture for things that produce a character
//you want the keypress event.
//we are looking to bind for IE or non-IE,
//so we have to test if .addEventListener is supported,
//and if not, assume we are on IE.
//If neither exists, you're screwed, but we didn't cover that in the else case.
if (el.addEventListener) {
el.addEventListener('click', keyListener, false);
} else if (el.attachEvent) {
el.attachEvent('on'+eventName, keyListener);
}
//and at this point you're done with registering the function, happy monitoring
</script>
</body>
</html>
Part 3: Capturing all keyboard events on a specific element
This line: var el = window; //we identify the element we want to target a listener on might also be var el = document.getElementByTagName('input'); or some other document selector. The example still works the same that way.
Part 4: An 'elegant' solution
var KeypressFunctions = [];
KeypressFunctions['T'.charCodeAt(0)] = function _keypressT() {
//do something specific for T
}
KeypressFunctions['t'.charCodeAt(0)] = function _keypresst() {
//do something specific for t
}
//you get the idea here
function keyListener(event){
//whatever we want to do goes in this block
event = event || window.event; //capture the event, and ensure we have an event
var key = event.key || event.which || event.keyCode; //find the key that was pressed
//MDN is better at this: https://developer.mozilla.org/en-US/docs/DOM/event.which
KeypressFunctions[key].call(); //if there's a defined function, run it, otherwise don't
//I also used .call() so you could supply some parameters if you wanted, or bind it to a specific element, but that's up to you.
}
What does all this do?
The KeypressFunctions is an array, that we can populate with various values but have them be somewhat human readable. Each index into the array is done as 'T'.charCodeAt(0) which gives the character code (event.which || event.keyCode look familiar?) for the index position into the array that we're adding a function for. So in this case our array only has two defined index-values, 84 (T) and 116 (t). We could've written that as KeypressFunctions[84] = function ... but that's less human-readable, at the expense of the human-readable is longer. Always write code for yourself first, the machine is often smarter than you give it credit for. Don't try and beat it with logic, but don't code excessive if-else blocks when you can be slightly elegant.
gah! I forgot to explain something else!
The reason for the _keypressT and _keypresst is so that when this gets called as an anonymous function, or as part of a callstack (it will, one day) then you can identify the function. This is a really handy practice to get into the habit of, making sure that all potentially anonymous functions still get "named" even though they have a proper name elsewhere. Once again, good javascript mentors suggest things that help folks ;-).
gah! I forgot to explain something else!
Notice you could just as easily do:
function doThing() //some pre-defined function before our code
var KeypressFunctions = [];
KeypressFunctions['T'.charCodeAt(0)] = doThing
KeypressFunctions['t'.charCodeAt(0)] = doThing
and then for either T or t, the doThing function is run. Notice that we just passed the name of the function and we didn't try to run the function by doThing() (this is a HUGE difference and a big hint if you're going to do this sort of thing)
I can't believe I forgot this one!
Part 5: jQuery:
Because the emphasis today is on jQuery, here's a block you can put anywhere in your app after the jQuery library has loaded (head, body, footer, whatever):
<script>
function doTheThingsOnKeypress(event){
//do things here! We've covered this before, but this time it's simplified
KeypressFunctions[event.which].call();
}
$(document).on('keypress','selector',doTheThingsOnKeypress);
// you could even pass arbitrary data to the keypress handler, if you wanted:
$(document).on('keypress','selector',{/* arbitrary object here! */},doTheThingsOnKeypress);
//this object is accessible through the event as data: event.data
</script>
If you're going to use the KeypressFunctions as from before, ensure they are actually defined before this.
Use the onkeydown event and the keyCode property (where T code is 84):
document.onkeydown = function(e){
e = e || window.event;
var key = e.which || e.keyCode;
if(key===84){
example();
}
}
I just suggest you to use addEventListener/attachEvent methods instead of the onkeydown property
EDIT:
As T.J. Crowder requested, here's the addEventListener/attachEvent usage, with a compatibility check:
var addEvent = document.addEventListener ? function(target,type,action){
if(target){
target.addEventListener(type,action,false);
}
} : function(target,type,action){
if(target){
target.attachEvent('on' + type,action,false);
}
}
addEvent(document,'keydown',function(e){
e = e || window.event;
var key = e.which || e.keyCode;
if(key===84){
example();
}
});
And for a list of the key codes, check this page
Bind a keyup/down/press event handler to the document object.
Check which key was pressed (by looking at key or keyCode on the event object
Call the function if it matches the key want you want
It doesn't matter where the script runs, the document object is (effectively) always available.

Reset element to "default" event

In Javascript, how can you set the event handler of a DOM element to default behavior?
For example, suppose I set the onkeypress event of an input element:
elem.onkeypress = function() { alert("Key pressed!"); }
Later, how can I remove this event? Is it okay to simply set the onkeypress property to null? I tried that and it works, but I don't know if it is the proper way to do this.
I'm pretty sure that the events will be undefined rather than null, so you'd be better off setting back to that.
It's probably overkill, but to be more robust, you're arguably better off keeping a reference to whatever used to be registered to the onkeypress event & reassign that (just in case some other script is trying to use it too). So:
var oldKeyPress = elem.onkeypress;
elem.onkeypress = function() { alert("Key pressed!"); }
//... later ...
elem.onkeypress = oldKeyPress;

Categories