Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

1) Ditch caching in `isEventSupported`, to make example (and mechanis…

…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...
commit 6320eda339b9e38a4d634b1e4ff738c828a4ccb8 1 parent 224714a
@kangax authored
Showing with 70 additions and 12 deletions.
  1. +53 −8 isEventSupported.js
  2. +17 −4 test.js
View
61 isEventSupported.js
@@ -23,6 +23,45 @@ var isEventSupported = (function(){
'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);
+ }
+ }
+
+ element = null;
+ return isSupported;
+ }
+ return isEventSupported;
@ibolmo
ibolmo added a note

Is style the reason why the method was not inlined?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+})();
+
+var isEventSupportedWithCache = (function(){
+
+ var TAGNAMES = {
@ibolmo
ibolmo added a note

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ 'select':'input','change':'input',
+ 'submit':'form','reset':'form',
+ 'error':'img','load':'img','abort':'img'
},
cache = { };
@@ -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;
View
21 test.js
@@ -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>');
@@ -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>');
@@ -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

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

@ibolmo

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
Owner

@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.
Something went wrong with that request. Please try again.