Last active
July 26, 2019 07:48
-
-
Save cmcnulty/7036509 to your computer and use it in GitHub Desktop.
Allows you to listen for propertychange on setting disabled to true on form elements. Very useful for resolving some select2 issues.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
( 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 ); |
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.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.