jquery.ui.widget.js 5.9 KB

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