jquery.ui.widget.js (6011B)
1 /*! 2 * jQuery UI Widget 1.8 3 * 4 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) 5 * Dual licensed under the MIT (MIT-LICENSE.txt) 6 * and GPL (GPL-LICENSE.txt) licenses. 7 * 8 * http://docs.jquery.com/UI/Widget 9 */ 10 (function( $ ) { 11 12 var _remove = $.fn.remove; 13 14 $.fn.remove = function( selector, keepData ) { 15 return this.each(function() { 16 if ( !keepData ) { 17 if ( !selector || $.filter( selector, [ this ] ).length ) { 18 $( "*", this ).add( this ).each(function() { 19 $( this ).triggerHandler( "remove" ); 20 }); 21 } 22 } 23 return _remove.call( $(this), selector, keepData ); 24 }); 25 }; 26 27 $.widget = function( name, base, prototype ) { 28 var namespace = name.split( "." )[ 0 ], 29 fullName; 30 name = name.split( "." )[ 1 ]; 31 fullName = namespace + "-" + name; 32 33 if ( !prototype ) { 34 prototype = base; 35 base = $.Widget; 36 } 37 38 // create selector for plugin 39 $.expr[ ":" ][ fullName ] = function( elem ) { 40 return !!$.data( elem, name ); 41 }; 42 43 $[ namespace ] = $[ namespace ] || {}; 44 $[ namespace ][ name ] = function( options, element ) { 45 // allow instantiation without initializing for simple inheritance 46 if ( arguments.length ) { 47 this._createWidget( options, element ); 48 } 49 }; 50 51 var basePrototype = new base(); 52 // we need to make the options hash a property directly on the new instance 53 // otherwise we'll modify the options hash on the prototype that we're 54 // inheriting from 55 // $.each( basePrototype, function( key, val ) { 56 // if ( $.isPlainObject(val) ) { 57 // basePrototype[ key ] = $.extend( {}, val ); 58 // } 59 // }); 60 basePrototype.options = $.extend( {}, basePrototype.options ); 61 $[ namespace ][ name ].prototype = $.extend( true, basePrototype, { 62 namespace: namespace, 63 widgetName: name, 64 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, 65 widgetBaseClass: fullName 66 }, prototype ); 67 68 $.widget.bridge( name, $[ namespace ][ name ] ); 69 }; 70 71 $.widget.bridge = function( name, object ) { 72 $.fn[ name ] = function( options ) { 73 var isMethodCall = typeof options === "string", 74 args = Array.prototype.slice.call( arguments, 1 ), 75 returnValue = this; 76 77 // allow multiple hashes to be passed on init 78 options = !isMethodCall && args.length ? 79 $.extend.apply( null, [ true, options ].concat(args) ) : 80 options; 81 82 // prevent calls to internal methods 83 if ( isMethodCall && options.substring( 0, 1 ) === "_" ) { 84 return returnValue; 85 } 86 87 if ( isMethodCall ) { 88 this.each(function() { 89 var instance = $.data( this, name ), 90 methodValue = instance && $.isFunction( instance[options] ) ? 91 instance[ options ].apply( instance, args ) : 92 instance; 93 if ( methodValue !== instance && methodValue !== undefined ) { 94 returnValue = methodValue; 95 return false; 96 } 97 }); 98 } else { 99 this.each(function() { 100 var instance = $.data( this, name ); 101 if ( instance ) { 102 if ( options ) { 103 instance.option( options ); 104 } 105 instance._init(); 106 } else { 107 $.data( this, name, new object( options, this ) ); 108 } 109 }); 110 } 111 112 return returnValue; 113 }; 114 }; 115 116 $.Widget = function( options, element ) { 117 // allow instantiation without initializing for simple inheritance 118 if ( arguments.length ) { 119 this._createWidget( options, element ); 120 } 121 }; 122 123 $.Widget.prototype = { 124 widgetName: "widget", 125 widgetEventPrefix: "", 126 options: { 127 disabled: false 128 }, 129 _createWidget: function( options, element ) { 130 // $.widget.bridge stores the plugin instance, but we do it anyway 131 // so that it's stored even before the _create function runs 132 this.element = $( element ).data( this.widgetName, this ); 133 this.options = $.extend( true, {}, 134 this.options, 135 $.metadata && $.metadata.get( element )[ this.widgetName ], 136 options ); 137 138 var self = this; 139 this.element.bind( "remove." + this.widgetName, function() { 140 self.destroy(); 141 }); 142 143 this._create(); 144 this._init(); 145 }, 146 _create: function() {}, 147 _init: function() {}, 148 149 destroy: function() { 150 this.element 151 .unbind( "." + this.widgetName ) 152 .removeData( this.widgetName ); 153 this.widget() 154 .unbind( "." + this.widgetName ) 155 .removeAttr( "aria-disabled" ) 156 .removeClass( 157 this.widgetBaseClass + "-disabled " + 158 this.namespace + "-state-disabled" ); 159 }, 160 161 widget: function() { 162 return this.element; 163 }, 164 165 option: function( key, value ) { 166 var options = key, 167 self = this; 168 169 if ( arguments.length === 0 ) { 170 // don't return a reference to the internal hash 171 return $.extend( {}, self.options ); 172 } 173 174 if (typeof key === "string" ) { 175 if ( value === undefined ) { 176 return this.options[ key ]; 177 } 178 options = {}; 179 options[ key ] = value; 180 } 181 182 $.each( options, function( key, value ) { 183 self._setOption( key, value ); 184 }); 185 186 return self; 187 }, 188 _setOption: function( key, value ) { 189 this.options[ key ] = value; 190 191 if ( key === "disabled" ) { 192 this.widget() 193 [ value ? "addClass" : "removeClass"]( 194 this.widgetBaseClass + "-disabled" + " " + 195 this.namespace + "-state-disabled" ) 196 .attr( "aria-disabled", value ); 197 } 198 199 return this; 200 }, 201 202 enable: function() { 203 return this._setOption( "disabled", false ); 204 }, 205 disable: function() { 206 return this._setOption( "disabled", true ); 207 }, 208 209 _trigger: function( type, event, data ) { 210 var callback = this.options[ type ]; 211 212 event = $.Event( event ); 213 event.type = ( type === this.widgetEventPrefix ? 214 type : 215 this.widgetEventPrefix + type ).toLowerCase(); 216 data = data || {}; 217 218 // copy original event properties over to the new event 219 // this would happen if we could call $.event.fix instead of $.Event 220 // but we don't have a way to force an event to be fixed multiple times 221 if ( event.originalEvent ) { 222 for ( var i = $.event.props.length, prop; i; ) { 223 prop = $.event.props[ --i ]; 224 event[ prop ] = event.originalEvent[ prop ]; 225 } 226 } 227 228 this.element.trigger( event, data ); 229 230 return !( $.isFunction(callback) && 231 callback.call( this.element[0], event, data ) === false || 232 event.isDefaultPrevented() ); 233 } 234 }; 235 236 })( jQuery );