Skip to content

Commit

Permalink
1) Ditch caching in isEventSupported, to make example (and mechanis…
Browse files Browse the repository at this point in the history
…m of this inference) easier to understand.

2) Change `isEventSupported` to use generic element (DIV), when supplied object doesn't implement `Node` interface (and so has no `setAttribute`).
Something like `isEventSupported('hashchange', window)` now internally tries `<DIV>.setAttribute('hashchange', '')`, since `window` is one of `setAttribute`-less objects.
This change fixes some of the false positives from previous verion.

3) Add few more HTML5, as well as proprietary "pageshow" and "pagehide" events to test page.
  • Loading branch information
kangax committed Dec 18, 2009
1 parent 224714a commit 6320eda
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 12 deletions.
61 changes: 53 additions & 8 deletions isEventSupported.js
Expand Up @@ -19,6 +19,45 @@
*/
var isEventSupported = (function(){

var TAGNAMES = {
'select':'input','change':'input',
'submit':'form','reset':'form',
'error':'img','load':'img','abort':'img'
}

function isEventSupported(eventName, element) {

element = element || document.createElement(TAGNAMES[eventName] || 'div');
eventName = 'on' + eventName;

// When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
var isSupported = (eventName in element);

if (!isSupported) {
// if it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
if (!element.setAttribute) {
element = document.createElement('div');
}
if (element.setAttribute && element.removeAttribute) {
element.setAttribute(eventName, '');
isSupported = typeof element[eventName] == 'function';

// if property was created, "remove it" (by setting value to `undefined`)
if (typeof element[eventName] != 'undefined') {
element[eventName] = void 0;
}
element.removeAttribute(eventName);
}
}

This comment has been minimized.

Copy link
@ibolmo

ibolmo Dec 18, 2009

Is style the reason why the method was not inlined?

element = null;
return isSupported;
}
return isEventSupported;
})();

This comment has been minimized.

Copy link
@ibolmo

ibolmo Dec 18, 2009

What about wrapping this file in an anonymous function and sharing the TAGNAMES between the two methods?


var isEventSupportedWithCache = (function(){

var TAGNAMES = {
'select':'input','change':'input',
'submit':'form','reset':'form',
Expand All @@ -40,15 +79,21 @@ var isEventSupported = (function(){
// When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
var isSupported = (eventName in element);

if (!isSupported && element.setAttribute && element.removeAttribute) {
element.setAttribute(eventName, 'return;');
isSupported = typeof element[eventName] == 'function';

// if property was created, "remove it" (by setting value to `undefined`)
if (typeof element[eventName] != 'undefined') {
element[eventName] = void 0;
if (!isSupported) {
// if it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
if (!element.setAttribute) {
element = document.createElement('div');
}
if (element.setAttribute && element.removeAttribute) {
element.setAttribute(eventName, '');
isSupported = typeof element[eventName] == 'function';

// if property was created, "remove it" (by setting value to `undefined`)
if (typeof element[eventName] != 'undefined') {
element[eventName] = void 0;
}
element.removeAttribute(eventName);
}
element.removeAttribute(eventName);
}

element = null;
Expand Down
21 changes: 17 additions & 4 deletions test.js
Expand Up @@ -27,13 +27,13 @@ w('keyup');
document.write('<h2>HTML events</h2>');

w('load');
w('unload', typeof window.onunload != 'undefined' ? window : void 0 );
w('unload', window);
w('abort');
w('error');

document.write('<h2>View events</h2>');

w('resize');
w('resize', window);
w('scroll');

document.write('<h2>Form events:</h2>');
Expand Down Expand Up @@ -89,7 +89,7 @@ w('stop', document);
w('readystatechange');
w('beforeprint', document.body);
w('afterprint', document.body);
w('beforeunload', typeof window.onbeforeunload != 'undefined' ? window : void 0 );
w('beforeunload', window);

document.write('<h2>Unexistent (most likely) events:</h2>');

Expand Down Expand Up @@ -118,4 +118,17 @@ document.write('<h2>HTML5 events</h2>');
w('hashchange', document.body);
w('online', document.body);
w('offline', document.body);
w('message', typeof window.onmessage != 'undefined' ? window : void 0 );
w('message', window);
w('undo', document.body);
w('redo', document.body);
w('storage', window);
w('popstate', window);

w('canplay', document.createElement('video'));
w('seeking', document.createElement('video'));
w('seekend', document.createElement('video'));

document.write('<h2>Proprietary</h2>');

w('pageshow', window);
w('pagehide', window);

3 comments on commit 6320eda

@ibolmo
Copy link

@ibolmo ibolmo commented on 6320eda Dec 18, 2009

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not in this commit, but should the declared function inside of isEventSupportedWithCache should be named isEventSupportedWithCache. It's currently isEventSupported.

@ibolmo
Copy link

@ibolmo ibolmo commented on 6320eda Dec 18, 2009

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've consolidated both methods into one. Since the second only returns the cache iff the cache is populated. Which means that the isEventSupported is called. Moreover, the setting of the cache is only done if the lookup failed.

Was there a reason you wanted to split the cache vs non-cache?

http://gist.github.com/259644

@kangax
Copy link
Owner Author

@kangax kangax commented on 6320eda Dec 18, 2009

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ibolmo
I actually wanted to delete cached version altogether, but copied and renamed it to another method for now. I want to keep this particular method as an example of this technique, without spicing it up with memoization or any other optimizations.

isEventSupportedWithCache is not used anywhere on a test page, but might still be useful for demonstration purposes.

Feel free to fork it and tweak as desired ;)

Please sign in to comment.