-
-
Save cmcnulty/7036509 to your computer and use it in GitHub Desktop.
( function( $ ) { | |
"use strict"; | |
$.fn.fireOnDisable = function( settings ) { | |
// Only perform this DOM change if we have to watch changes with propertychange | |
// Also only perform if getOwnPropertyDescriptor exists - IE>=8 | |
// I suppose I could test for "propertychange fires, but not when form element is disabled" - but it would be overkill | |
if( !( 'onpropertychange' in document.createElement( 'input' ) ) || Object.getOwnPropertyDescriptor === undefined ) { | |
return this; | |
} | |
// IE9-10 use HTMLElement proto, IE8 uses Element proto | |
var someProto = window.HTMLElement === undefined ? window.Element.prototype : window.HTMLElement.prototype, | |
someTrigger = function(){}, | |
origDisabled = Object.getOwnPropertyDescriptor( someProto, 'disabled' ); | |
if( document.createEvent ) { | |
someTrigger = function( newVal ){ | |
var event = document.createEvent('MutationEvent'); | |
/* | |
Instantiate the event as close to native as possible: | |
event.initMutationEvent(eventType, canBubble, cancelable, relatedNodeArg, prevValueArg, newValueArg, attrNameArg, attrChangeArg); | |
*/ | |
event.initMutationEvent( 'DOMAttrModified', true, false, this.getAttributeNode('disabled'), '', '', 'disabled', 1 ); | |
this.dispatchEvent( event ); | |
}; | |
} else if( document.fireEvent ) { | |
someTrigger = function(){ | |
this.fireEvent( 'onpropertychange' ); | |
}; | |
} | |
return this.each( function() { | |
// call prototype's set, and then trigger the change. | |
Object.defineProperty( this, 'disabled', { | |
set: function( isDisabled ) { | |
// We store preDisabled here, so that when we inquire as to the result after throwing the event, it will be accurate | |
// We can't throw the event after the native send, because it won't be be sent. | |
// We must do a native fire/dispatch, because native listeners don't catch jquery trigger 'propertychange' events | |
$.data( this, 'preDisabled', isDisabled ); | |
if ( isDisabled ) { | |
// Trigger with dispatchEvent | |
someTrigger.call( this, isDisabled ); | |
} | |
return origDisabled.set.call( this, isDisabled ); | |
}, | |
get: function() { | |
var isDisabled = $.data( this, 'preDisabled' ); | |
if( isDisabled === undefined ) { | |
isDisabled = origDisabled.get.call( this ); | |
} | |
return isDisabled; | |
} | |
}); | |
}); | |
}; | |
})( jQuery ); |
Never mind, I removed the if ( isDisabled )
, and it worked for me.
Huh. Not sure what you're seeing @meilechh. the isDisabled test is to prevent the event from being triggered twice - since propertychange should be triggered natively when we're enabling the element. I guess this is why I should have written some unit tests.
Updated to work with the lastest select2 plugin which uses a native listener, rather than a jQuery listener. This forces me to employ a native trigger, which means that the trigger event has to occur before the disabled property is set - which means that I have to save/retrieve the state using .data rather than using the native state. Which is all to say that it now works.
Should note that disabling a field with .setAttribute('disabled') does not trigger DOMAttrModified, which means that this won't work in in IE8-10.
What licence have you released this under? I can't find one.
Great work!, however i have one problem, I cannot enable it back with $('#id').prop('disabled', false);