Skip to content

Instantly share code, notes, and snippets.

@NekR
Created June 10, 2013 13:02
Show Gist options
  • Save NekR/5748541 to your computer and use it in GitHub Desktop.
Save NekR/5748541 to your computer and use it in GitHub Desktop.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script>
(function() {
var disabled = (function() {
var button = document.createElement('button'),
fieldset,
handlesEvents,
handlesEventsWrapped,
e;
var TEST_EVENT_NAME = 'test';
var eventHandler = function() {
handlesEvents = true;
},
wrappedEventHandler = function() {
handlesEventsWrapped = true;
};
button.disabled = true;
document.documentElement.appendChild(button);
button.addEventListener(TEST_EVENT_NAME, eventHandler, false);
e = document.createEvent('CustomEvent');
e.initCustomEvent(TEST_EVENT_NAME, false, false, 1);
button.dispatchEvent(e);
button.removeEventListener(TEST_EVENT_NAME, eventHandler, false);
if (!handlesEvents) {
fieldset = document.createElement('fieldset');
fieldset.disabled = true;
fieldset.appendChild(button);
document.documentElement.appendChild(fieldset);
button.disabled = false;
button.addEventListener(TEST_EVENT_NAME, wrappedEventHandler, false);
e = document.createEvent('CustomEvent');
e.initCustomEvent(TEST_EVENT_NAME, false, false, 1);
button.dispatchEvent(e);
button.removeEventListener(TEST_EVENT_NAME, wrappedEventHandler, false);
document.documentElement.removeChild(fieldset);
} else {
document.documentElement.removeChild(button);
handlesEventsWrapped = true;
}
return {
handlesEvents: handlesEvents,
handlesEventsWrapped: handlesEventsWrapped
};
}());
if (disabled.handlesEvents) return;
var getNative = function() {
var result;
['EventTarget', 'Node', 'Element'].some(function(interface) {
var desc;
interface = window[interface];
if (interface && (desc = Object.getOwnPropertyDescriptor(
interface.prototype, 'dispatchEvent'))) {
result = {
interface: interface,
desc: desc
};
return true;
}
});
return result;
};
var native = getNative(),
nativeDispatch = native.desc,
blockedEvents = {
click: 1
};
var dispatchEvent = function(event, handler, capture) {
var node = this,
disabledDesc,
disabledChanged,
disabledChangedVal = true,
disabledFix,
result;
if (!node.disabled || blockedEvents.hasOwnProperty(event)) {
return nativeDispatch.value.apply(this, arguments);
}
disabledDesc = Object.getOwnPropertyDescriptor(
// Firefox
Object.getPrototypeOf(node),
'disabled'
// IE
) || Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'disabled');
if (disabledDesc && disabledDesc.set && disabledDesc.get &&
!Object.getOwnPropertyDescriptor(node, 'disabled')) {
disabledFix = true;
node.disabled = false;
console.log('used fix');
Object.defineProperty(node, 'disabled', {
enumerable: disabledDesc.enumerable,
configurable: disabledDesc.configurable,
set: function(val) {
disabledChanged = true;
disabledChangedVal = !!val;
},
get: function() {
return disabledChangedVal;
}
});
}
result = nativeDispatch.value.apply(this, arguments);
if (disabledFix) {
delete node.disabled;
node.disabled = disabledChanged ? disabledChangedVal : true;
}
return result;
};
Object.defineProperty(native.interface.prototype, 'dispatchEvent', {
value: dispatchEvent,
writable: nativeDispatch.writable,
configurable: nativeDispatch.configurable,
enumerable: nativeDispatch.enumerable
});
if (disabled.handlesEventsWrapped) return;
// Here should be fix for elements wrapped with some others disabled elements
// <fieldset disabled>
// <button disabled></button>
// </fieldset>
}());
</script>
</head>
<body>
<form>
<button id="test" disabled>test</button>
</form>
<script>
var button = document.querySelector('#test');
button.addEventListener('test', function() {
console.log('test', this.disabled);
this.disabled = true;
var e = document.createEvent('CustomEvent');
e.initCustomEvent('test2', false, false ,1);
button.dispatchEvent(e);
});
button.addEventListener('test2', function() {
console.log('test2', this.disabled);
this.disabled = true;
var e = document.createEvent('CustomEvent');
e.initCustomEvent('test3', false, false ,1);
button.dispatchEvent(e);
});
button.addEventListener('test3', function() {
console.log('test3', this.disabled);
this.disabled = false;
});
var e = document.createEvent('CustomEvent');
e.initCustomEvent('test', false, false ,1);
button.dispatchEvent(e);
console.log('final disabled', button.disabled);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment