-
-
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);