JavaScript window resize event - javascript

How can I hook into a browser window resize event?
There's a jQuery way of listening for resize events but I would prefer not to bring it into my project for just this one requirement.

Best practice is to add to the resize event, rather than replace it:
window.addEventListener('resize', function(event) {
...
}, true);
An alternative is to make a single handler for the DOM event (but can only have one), eg.
window.onresize = function(event) {
...
};
jQuery may do some work to ensure that the resize event gets fired consistently in all browsers, but I'm not sure if any of the browsers differ, but I'd encourage you to test in Firefox, Safari, and IE.

First off, I know the addEventListener method has been mentioned in the comments above, but I didn't see any code. Since it's the preferred approach, here it is:
window.addEventListener('resize', function(event){
// do stuff here
});
Here's a working sample.

Never override the window.onresize function.
Instead, create a function to add an Event Listener to the object or element.
This checks and incase the listeners don't work, then it overrides the object's function as a last resort. This is the preferred method used in libraries such as jQuery.
object: the element or window object
type: resize, scroll (event type)
callback: the function reference
var addEvent = function(object, type, callback) {
if (object == null || typeof(object) == 'undefined') return;
if (object.addEventListener) {
object.addEventListener(type, callback, false);
} else if (object.attachEvent) {
object.attachEvent("on" + type, callback);
} else {
object["on"+type] = callback;
}
};
Then use is like this:
addEvent(window, "resize", function_reference);
or with an anonymous function:
addEvent(window, "resize", function(event) {
console.log('resized');
});

Solution for 2018+:
You should use ResizeObserver. It is a browser-native solution that has a much better performance than to use the resize event. In addition, it not only supports the event on the document but also on arbitrary elements.
var ro = new ResizeObserver( entries => {
for (let entry of entries) {
const cr = entry.contentRect;
console.log('Element:', entry.target);
console.log(`Element size: ${cr.width}px x ${cr.height}px`);
console.log(`Element padding: ${cr.top}px ; ${cr.left}px`);
}
});
// Observe one or multiple elements
ro.observe(someElement);
Currently, Firefox, Chrome, Safari, and Edge support it. For other (and older) browsers you have to use a polyfill.

The resize event should never be used directly as it is fired continuously as we resize.
Use a debounce function to mitigate the excess calls.
window.addEventListener('resize',debounce(handler, delay, immediate),false);
Here's a common debounce floating around the net, though do look for more advanced ones as featuerd in lodash.
const debounce = (func, wait, immediate) => {
var timeout;
return () => {
const context = this, args = arguments;
const later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
This can be used like so...
window.addEventListener('resize', debounce(() => console.log('hello'),
200, false), false);
It will never fire more than once every 200ms.
For mobile orientation changes use:
window.addEventListener('orientationchange', () => console.log('hello'), false);
Here's a small library I put together to take care of this neatly.

I do believe that the correct answer has already been provided by #Alex V, yet the answer does require some modernization as it is over five years old now.
There are two main issues:
Never use object as a parameter name. It is a reservered word. With this being said, #Alex V's provided function will not work in strict mode.
The addEvent function provided by #Alex V does not return the event object if the addEventListener method is used. Another parameter should be added to the addEvent function to allow for this.
NOTE: The new parameter to addEvent has been made optional so that migrating to this new function version will not break any previous calls to this function. All legacy uses will be supported.
Here is the updated addEvent function with these changes:
/*
function: addEvent
#param: obj (Object)(Required)
- The object which you wish
to attach your event to.
#param: type (String)(Required)
- The type of event you
wish to establish.
#param: callback (Function)(Required)
- The method you wish
to be called by your
event listener.
#param: eventReturn (Boolean)(Optional)
- Whether you want the
event object returned
to your callback method.
*/
var addEvent = function(obj, type, callback, eventReturn)
{
if(obj == null || typeof obj === 'undefined')
return;
if(obj.addEventListener)
obj.addEventListener(type, callback, eventReturn ? true : false);
else if(obj.attachEvent)
obj.attachEvent("on" + type, callback);
else
obj["on" + type] = callback;
};
An example call to the new addEvent function:
var watch = function(evt)
{
/*
Older browser versions may return evt.srcElement
Newer browser versions should return evt.currentTarget
*/
var dimensions = {
height: (evt.srcElement || evt.currentTarget).innerHeight,
width: (evt.srcElement || evt.currentTarget).innerWidth
};
};
addEvent(window, 'resize', watch, true);

window.onresize = function() {
// your code
};

The following blog post may be useful to you: Fixing the window resize event in IE
It provides this code:
Sys.Application.add_load(function(sender, args) {
$addHandler(window, 'resize', window_resize);
});
var resizeTimeoutId;
function window_resize(e) {
window.clearTimeout(resizeTimeoutId);
resizeTimeoutId = window.setTimeout('doResizeCode();', 10);
}

The already mentioned solutions above will work if all you want to do is resize the window and window only. However, if you want to have the resize propagated to child elements, you will need to propagate the event yourself. Here's some example code to do it:
window.addEventListener("resize", function () {
var recResizeElement = function (root) {
Array.prototype.forEach.call(root.childNodes, function (el) {
var resizeEvent = document.createEvent("HTMLEvents");
resizeEvent.initEvent("resize", false, true);
var propagate = el.dispatchEvent(resizeEvent);
if (propagate)
recResizeElement(el);
});
};
recResizeElement(document.body);
});
Note that a child element can call
event.preventDefault();
on the event object that is passed in as the first Arg of the resize event. For example:
var child1 = document.getElementById("child1");
child1.addEventListener("resize", function (event) {
...
event.preventDefault();
});

You can use following approach which is ok for small projects
<body onresize="yourHandler(event)">
function yourHandler(e) {
console.log('Resized:', e.target.innerWidth)
}
<body onresize="yourHandler(event)">
Content... (resize browser to see)
</body>

<script language="javascript">
window.onresize = function() {
document.getElementById('ctl00_ContentPlaceHolder1_Accordion1').style.height = '100%';
}
</script>

var EM = new events_managment();
EM.addEvent(window, 'resize', function(win,doc, event_){
console.log('resized');
//EM.removeEvent(win,doc, event_);
});
function events_managment(){
this.events = {};
this.addEvent = function(node, event_, func){
if(node.addEventListener){
if(event_ in this.events){
node.addEventListener(event_, function(){
func(node, event_);
this.events[event_](win_doc, event_);
}, true);
}else{
node.addEventListener(event_, function(){
func(node, event_);
}, true);
}
this.events[event_] = func;
}else if(node.attachEvent){
var ie_event = 'on' + event_;
if(ie_event in this.events){
node.attachEvent(ie_event, function(){
func(node, ie_event);
this.events[ie_event]();
});
}else{
node.attachEvent(ie_event, function(){
func(node, ie_event);
});
}
this.events[ie_event] = func;
}
}
this.removeEvent = function(node, event_){
if(node.removeEventListener){
node.removeEventListener(event_, this.events[event_], true);
this.events[event_] = null;
delete this.events[event_];
}else if(node.detachEvent){
node.detachEvent(event_, this.events[event_]);
this.events[event_] = null;
delete this.events[event_];
}
}
}

Related

How to delete listener with anonymous function? [duplicate]

I have an object that has methods in it. These methods are put into the object inside an anonymous function. It looks like this:
var t = {};
window.document.addEventListener("keydown", function(e) {
t.scroll = function(x, y) {
window.scrollBy(x, y);
};
t.scrollTo = function(x, y) {
window.scrollTo(x, y);
};
});
(there is a lot more code, but this is enough to show the problem)
Now I want to stop the event listener in some cases. Therefore I am trying to do a removeEventListener but I can't figure out how to do this. I have read in other questions that it is not possible to call removeEventListener on anonymous functions, but is this also the case in this situation?
I have a method in t created inside the anonymous function and therefore I thought it was possible. Looks like this:
t.disable = function() {
window.document.removeEventListener("keydown", this, false);
}
Why can't I do this?
Is there any other (good) way to do this?
Bonus info; this only has to work in Safari, hence the missing IE support.
You can name the function passed and use the name in the removeEventListener. as in:
button.addEventListener('click', function eventHandler() {
///this will execute only once
alert('only once!');
this.removeEventListener('click', eventHandler);
});
EDIT:
This will not work if you are working in strict mode ("use strict";)
EDIT 2:
arguments.callee is now deprecated (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/callee)
I believe that is the point of an anonymous function, it lacks a name or a way to reference it.
If I were you I would just create a named function, or put it in a variable so you have a reference to it.
var t = {};
var handler = function(e) {
t.scroll = function(x, y) {
window.scrollBy(x, y);
};
t.scrollTo = function(x, y) {
window.scrollTo(x, y);
};
};
window.document.addEventListener("keydown", handler);
You can then remove it by
window.document.removeEventListener("keydown", handler);
A version of Otto Nascarella's solution that works in strict mode is:
button.addEventListener('click', function handler() {
///this will execute only once
alert('only once!');
this.removeEventListener('click', handler);
});
in modern browsers you can do the following...
button.addEventListener( 'click', () => {
alert( 'only once!' );
}, { once: true } );
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters
window.document.removeEventListener("keydown", getEventListeners(window.document.keydown[0].listener));
May be several anonymous functions, keydown1
Warning: only works in Chrome Dev Tools & cannot be used in code: link
There's a new way to do this that is supported by the latest versions of most popular browsers with the exception of Safari.
Check caniuse for updated support.
Update: Now also supported by Sefari (version 15^).
We can add an option to addEventListner called signal and assign a signal from an AbortController on which you can later call the abort() method.
Here is an example.
We create an AbortController:
const controller = new AbortController();
Then we create the eventListner and pass in the option signal:
document.addEventListener('scroll',()=>{
// do something
},{signal: controller.signal})
And then to remove the eventListner at a later time, we call:
controller.abort()
This is not ideal as it removes all, but might work for your needs:
z = document.querySelector('video');
z.parentNode.replaceChild(z.cloneNode(1), z);
Cloning a node copies all of its attributes and their values, including
intrinsic (in–line) listeners. It does not copy event listeners added using
addEventListener()
Node.cloneNode()
A not so anonymous option
element.funky = function() {
console.log("Click!");
};
element.funky.type = "click";
element.funky.capt = false;
element.addEventListener(element.funky.type, element.funky, element.funky.capt);
// blah blah blah
element.removeEventListener(element.funky.type, element.funky, element.funky.capt);
Since receiving feedback from Andy (quite right, but as with many examples, I wished to show a contextual expansion of the idea), here's a less complicated exposition:
<script id="konami" type="text/javascript" async>
var konami = {
ptrn: "38,38,40,40,37,39,37,39,66,65",
kl: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
};
document.body.addEventListener( "keyup", function knm ( evt ) {
konami.kl = konami.kl.slice( -9 );
konami.kl.push( evt.keyCode );
if ( konami.ptrn === konami.kl.join() ) {
evt.target.removeEventListener( "keyup", knm, false );
/* Although at this point we wish to remove a listener
we could easily have had multiple "keyup" listeners
each triggering different functions, so we MUST
say which function we no longer wish to trigger
rather than which listener we wish to remove.
Normal scoping will apply to where we can mention this function
and thus, where we can remove the listener set to trigger it. */
document.body.classList.add( "konami" );
}
}, false );
document.body.removeChild( document.getElementById( "konami" ) );
</script>
This allows an effectively anonymous function structure, avoids the use of the practically deprecated callee, and allows easy removal.
Incidentally: The removal of the script element immediately after setting the listener is a cute trick for hiding code one would prefer wasn't starkly obvious to prying eyes (would spoil the surprise ;-)
So the method (more simply) is:
element.addEventListener( action, function name () {
doSomething();
element.removeEventListener( action, name, capture );
}, capture );
To give a more up-to-date approach to this:
//one-time fire
element.addEventListener('mousedown', {
handleEvent: function (evt) {
element.removeEventListener(evt.type, this, false);
}
}, false);
JavaScript: addEventListener
method registers the specified listener on the EventTarget(Element|document|Window) it's called on.
EventTarget.addEventListener(event_type, handler_function, Bubbling|Capturing);
Mouse, Keyboard events Example test in WebConsole:
var keyboard = function(e) {
console.log('Key_Down Code : ' + e.keyCode);
};
var mouseSimple = function(e) {
var element = e.srcElement || e.target;
var tagName = element.tagName || element.relatedTarget;
console.log('Mouse Over TagName : ' + tagName);
};
var mouseComplex = function(e) {
console.log('Mouse Click Code : ' + e.button);
}
window.document.addEventListener('keydown', keyboard, false);
window.document.addEventListener('mouseover', mouseSimple, false);
window.document.addEventListener('click', mouseComplex, false);
removeEventListener
method removes the event listener previously registered with EventTarget.addEventListener().
window.document.removeEventListener('keydown', keyboard, false);
window.document.removeEventListener('mouseover', mouseSimple, false);
window.document.removeEventListener('click', mouseComplex, false);
caniuse
I have stumbled across the same problem and this was the best solution I could get:
/*Adding the event listener (the 'mousemove' event, in this specific case)*/
element.onmousemove = function(event) {
/*do your stuff*/
};
/*Removing the event listener*/
element.onmousemove = null;
Please keep in mind I have only tested this for the window element and for the 'mousemove' event, so there could be some problems with this approach.
Possibly not the best solution in terms of what you are asking. I have still not determined an efficient method for removing anonymous function declared inline with the event listener invocation.
I personally use a variable to store the <target> and declare the function outside of the event listener invocation eg:
const target = document.querySelector('<identifier>');
function myFunc(event) {
function code;
}
target.addEventListener('click', myFunc);
Then to remove the listener:
target.removeEventListener('click', myFunc);
Not the top recommendation you will receive but to remove anonymous functions the only solution I have found useful is to remove then replace the HTML element. I am sure there must be a better vanilla JS method but I haven't seen it yet.
I know this is a fairly old thread, but thought I might put in my two cents for those who find it useful.
The script (apologies about the uncreative method names):
window.Listener = {
_Active: [],
remove: function(attached, on, callback, capture){
for(var i = 0; i < this._Active.length; i++){
var current = this._Active[i];
if(current[0] === attached && current[1] === on && current[2] === callback){
attached.removeEventListener(on, callback, (capture || false));
return this._Active.splice(i, 1);
}
}
}, removeAtIndex(i){
if(this._Active[i]){
var remove = this._Active[i];
var attached = remove[0], on = remove[1], callback = remove[2];
attached.removeEventListener(on, callback, false);
return this._Active.splice(i, 1);
}
}, purge: function(){
for(var i = 0; i < this._Active.length; i++){
var current = this._Active[i];
current[0].removeEventListener(current[1], current[2]);
this._Active.splice(i, 1);
}
}, declare: function(attached, on, callback, capture){
attached.addEventListener(on, callback, (capture || false));
if(this._Active.push([attached, on, callback])){
return this._Active.length - 1;
}
}
};
And you can use it like so:
// declare a new onclick listener attached to the document
var clickListener = Listener.declare(document, "click" function(e){
// on click, remove the listener and log the clicked element
console.log(e.target);
Listener.removeAtIndex(clickListener);
});
// completely remove all active listeners
// (at least, ones declared via the Listener object)
Listener.purge();
// works exactly like removeEventListener
Listener.remove(element, on, callback);
I just experienced similiar problem with copy-protection wordpress plugin. The code was:
function disableSelection(target){
if (typeof target.onselectstart!="undefined") //For IE
target.onselectstart=function(){return false}
else if (typeof target.style.MozUserSelect!="undefined") //For Firefox
target.style.MozUserSelect="none"
else //All other route (For Opera)
target.onmousedown=function(){return false}
target.style.cursor = "default"
}
And then it was initiated by loosely put
<script type="text/javascript">disableSelection(document.body)</script>.
I came around this simply by attaching other annonymous function to this event:
document.body.onselectstart = function() { return true; };
Set anonymous listener:
document.getElementById('ID').addEventListener('click', () => { alert('Hi'); });
Remove anonymous listener:
document.getElementById('ID').removeEventListener('click',getEventListeners(document.getElementById('ID')).click[0].listener)
Using the AbortController, neat and clean
Attaching EventListener
const el = document.getElementById('ID')
const controller = new AbortController;
el.addEventListener('click',() => {
console.log("Clicked")
},{signal: controller.signal})
when you want to remove the event listener
controller.abort()
Another alternative workaround to achieve this is adding an empty event handler and preventing event propagation.
Let's assume you need to remove mouseleave event handler from an element which has #specific-div id, that is added with an anonymous function, and you can't use removeEventListener() since you don't have a function name.
You can add another event handler to that element and use event.stopImmediatePropagation(), for being sure this event handler works before existing ones you should pass the third parameter (useCapture) as true.
The final code should look like the below:
document.getElementById("specific-div")
.addEventListener("mouseleave", function(event) {
event.stopImmediatePropagation()
}, true);
This could help for some specific cases that you can't prefer cloneNode() method.
window.document.onkeydown = function(){};

Capture *all* events of a given type, regardless of bubble/target

I'm writing a Chrome extension that needs to be notified of all click and keyup events, regardless of whether stopPropagation/etc was called in consuming code. This means that document.addEventListener is off the table.
I have tried the following:
Attempt 1: Hook into addEventListener
const _addEventListener = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function(eventName, eventHandler) {
console.log('DOM Event', eventName);
_addEventListener.call(this, eventName, eventHandler);
};
Attempt 2: Hook into stopPropagation
const _stopPropagation = Event.prototype.stopPropagation;
Event.prototype.stopPropagation = function() {
console.log('Stop Propagation:', this);
return _mouseEvent.apply(this, arguments);
};
Attempt 3: Hook into even constructors
const _mouseEvent = MouseEvent;
MouseEvent = function() {
console.log('Mouse Event:', this);
return _mouseEvent.apply(this, arguments);
};
const _keyboardEvent = KeyboardEvent;
KeyboardEvent = function() {
console.log('Keyboard Event:', this);
return _keyboardEvent.apply(this, arguments);
};
As a last resort I could add my own click event listener on every DOM element—but that just seems like a ton of overhead for something that seems like it should be doable.
Anyone know of a viable option?
Gah, I don't know how I forgot about useCapture. This works:
document.addEventListener('click', function() {}, true /* <--- this */);

Removing child-function event listeners

In building an extended input field (a complex date picker), I need to use two key event listeners. One is attached to the input field, and launches the interface. This is easy.
The second is attached to document, in order to close the complex overlay. Click on the overlay, and it does nothing. Click outside: the overlay disappears and the input field's value is updated.
It also needs to remove the event listener from the document.
This would all be straightforward… if it weren't based on object structures. I am not calling a stand-alone function. I am calling a child function of the data object associated with the field (which the field then has no way of referencing back to).
__DateField.prototype.activate = function () {
…
var t = this;
window.setTimeout(function () { document.addEventListener("click", function (ev) { t.closeDateSelector(ev) }, false); }, 0);
…
}
(I haven't figured out why that event attachment needs to be nested within the setTimeout, but if I don''t do it that way, it calls itself immediately.)
Anyhow, the problem is then that I cannot successfully call document.removeEventListener() because I it's not the same initial function.
Also, I can't approach it by attaching the function as a stand-alone, because I need the reference to the related __DateField object.
How can I remove that function from document?
I have looked at the various threads that say there is no way to inspect event listeners added via 'addEventListener`, though wonder if they may be out of date, as Firebug can list them…
To remove it, you must have a reference to the function, so the question boils down to: How can I keep a reference to the function?
The simplest answer, since you already have an object handy, is a property on the object, if you can rely on this being correct as of when you do the removal:
__DateField.prototype.activate = function () {
// …
var t = this;
window.setTimeout(function () {
t.listener = function (ev) {
t.closeDateSelector(ev)
};
document.addEventListener("click", listener, false);
}, 0);
// …
};
// To remove
__DateField.prototype.deactivate = function() {
if (this.listener != null) {
document.removeEventListener("click", this.listener, false);
this.listener = null;
}
};
Or if that's a problem for some reason, you could use a variable in a scoping function:
(function() {
var listener = null;
__DateField.prototype.activate = function () {
// …
var t = this;
window.setTimeout(function () {
listener = function (ev) {
t.closeDateSelector(ev)
};
document.addEventListener("click", listener, false);
}, 0);
// …
};
// Later, when removing
function removeIt() {
if (listener != null) {
document.removeEventListener("click", listener, false);
listener = null;
}
}
})();

Custom event document onContentChange

Here jsFiddle to test sample
I'm currently writing a jQuery snippet to handle any html content change in DOM 'triggered' by any jQuery domManip function (extending some functions). Not sure it's the best way to do it, so any advice will be welcome.
This snippet works as expected if bound to document. However, if I try to bind it to a specific element, I'm facing problem which some function as .remove(). Maybe it's due to custom event not using normal propagation behaviour but I'm really not sure.
This is a working sample, I bind contentChange event to document, works cross-browser as I can test it: {Firefox, IE9, Chrome and Safari under Win7}
;
(function ($) {
$.fn.contentChange = function (types, data, fn) {
return this.on('contentChange', types, null, data, fn);
};
var oDomManip = $.fn.domManip,
oHtml = $.fn.html,
oEmpty = $.fn.empty,
oRemove = $.fn.remove,
extendFct = function (oFct, sender, args) {
return oFct.apply(sender, args), $.event.trigger('contentChange');
//=>if testing specific element (#test) use instead following line
//return oFct.apply(sender, args), $(sender).trigger('contentChange');
};
$.fn.domManip = function () {
extendFct(oDomManip, this, arguments)
};
$.fn.html = function () {
extendFct(oHtml, this, arguments)
};
$.fn.empty = function () {
extendFct(oEmpty, this, arguments)
};
$.fn.remove = function () {
extendFct(oRemove, this, arguments)
};
})(jQuery);
I use: $.event.trigger('contentChange') to trigger custom event.
Called like it:
$(document).contentChange(function () {
console.log("onContentChange")
});
However, if I use:
$('#test').contentChange(function () {
console.log("onContentChange")
});
The custom event is not triggered.
So, to trigger a custom event on a specific element, I can triggered it like this:
$(sender).trigger('contentChange');
But now, call to remove() method on self or children doesn't triggered my custom event.
I can understand that event callback function won't be called if I remove the element, but why isn't it called when removing children (while it's working if bound to document!)?
I was expecting this line to make custom event bubbles to '#test':
$('#test').find('div:first').remove();
Is there any way to triggered this custom event bound to a specific element when manipulating this element and/or its children?
You need to trigger the event on the element that was modified.
http://jsfiddle.net/Gw4Lj/2/
return oFct.apply(sender, args), sender.trigger('contentChange');
however, with that change, you will no longer catch the event that was triggered on an element that isn't connected to the DOM because it isn't a descendant of that document, which is ok in my opinion because it isn't associated to that DOM, it's in a DOM Fragment.
I come with slightly modified version wich seems to work fine for the purpose i reach.
Need optimization for the .on() method extend, so please feel free to share your feedbacks.
Inspired from here: https://groups.google.com/forum/?fromgroups=#!topic/jquery-dev/ZaMw2XB6wyM
Thanks to Wil Stuckey
Here jsFiddle
;(function ($) {
var fctsToObserve = {
append: [$.fn.append, 'self'],
prepend: [$.fn.prepend, 'self'],
remove: [$.fn.remove, 'parent'],
before: [$.fn.before, 'parent'],
after: [$.fn.after, 'parent']
}, fctsObserveKeys = '';
$.each(fctsToObserve, function (key, element) {
fctsObserveKeys += "hasChanged." + key + " ";
});
var oOn = $.fn.on;
$.fn.on = function () {
if (arguments[0].indexOf('hasChanged') != -1) arguments[0] += " " + fctsObserveKeys;
return oOn.apply(this, arguments);
};
$.fn.hasChanged = function (types, data, fn) {
return this.on(fctsObserveKeys, types, null, data, fn);
};
$.extend($, {
observeMethods: function (namespace) {
var namespace = namespace ? "." + namespace : "";
var _len = $.fn.length;
delete $.fn.length;
$.each(fctsToObserve, function (key) {
var _pre = this;
$.fn[key] = function () {
var target = _pre[1] === 'self' ? this : this.parent(),
ret = _pre[0].apply(this, arguments);
target.trigger("hasChanged." + key + namespace, arguments);
return ret;
};
});
$.fn.length = _len;
}
});
$.observeMethods()
})(jQuery);

confusion regarding event handling in Javascript

I am new to Javascript. while practicing i encounter a code regarding event handling. Here is the code
//This generic event handler creates an object called eventHandler
var etHandler = {};
if (document.addEventListener) {
//eventHandler object has two methods added to it, add()and remove(),
etHandler.add = function(element, eventType, eventFunction) {
/**
* The add method in each model determines whether the event type is a load event, meaning that
* the function needs to be executed on page load.
*/
if (eventType == "load") {
.......
}
};// end of eventHandler.add = function()
etHandler.remove = function(element, eventType, eventFunction) {
element.detachEvent("on" + eventType, eventFunction);
}; //end of etHandler.remove = function()
}
function sendAlert() {
alert("Hello");
} //end of sendAlert()
function startTimer() {
var timerID = window.setTimeout(sendAlert,3000);
}//end of startTimer()
var mainBody = document.getElementById("mainBody");
etHandler.add(mainBody, "load", function() {
startTimer();
}
);
The questions that i want to ask are this. We create an empty object.var etHandler = {};. It's fine. Then we are checking condition if (document.addEventListener) {}. we didn't add any event listener to the document, but this condition is true. Why this condition is returning true?
Then we write etHandler.add = function(element, eventType, eventFunction) {}. Why we are writing etHandler.add? etHandler object has no property, when we created it. It's a null object. If we create etHandler like this
var etHandler = {
add: function() {
},
remove: function(){
}
};
Then we can write etHandler.add. The same question is for etHandler.remove also.
Thanks
The call if (document.addEventListener) is checking whether the browser supports this method. It is checking to see whether it exists on the document object. This is called feature detection and is frequently used to detect differences between browsers.
The call etHandler.add = function(element, eventType, eventFunction) defines the add method and creates it simultaneously. It is basically the same as in your example.

Categories

Resources