jquery ui 的全部组件都是基于一个简单,可重用的widget。

这个widget是jquery ui的核心部分,有用它能实现一致的API。创建有状态的插件,而无需关心插件的内部转换。

$.widget( name, base, prototype )

widget一共同拥有2或3个參数。base为可选。

这里之所以把base放在第二个參数里,主要是由于这样写代码更直观一些。(由于后面的prototype 是个代码很长的大对象)。

name:第一个參数是一个包括一个命名空间和组件名称的字符串,通过”.”来切割。

命名空间必须有。它指向widget prototype存储的全局jQuery对象。

假设命名空间没有,widget factory将会为你生成。

widget name是插件函数和原型的真实名称,

比方: jQuery.widget( “demo.multi”, {…} ) 将会生成 jQuery.demo , jQuery.demo.multi , and jQuery.demo.multi.prototype .

base:第二个參数(可选)是 widget prototype继承于什么对象。

比如jQuery UI有一个“mouse”的插件,它能够作为其它的插件提供的基础。

为了实现这个全部的基于mouse的插件比方draggable,

droppable能够这么做: jQuery.widget( "ui.draggable",
$.ui.mouse, {...} );


假设没有这个參数。widget默认继承自“base widget” jQuery.Widget(注意jQuery.widget 和 jQuery.Widget不同) 。

prototype:最后一个參数是一个对象文字。它会转化为全部widget实例的prototype。widget factory会生成属性链,连接到她继承的widget的prototype。一直到最主要的 jQuery.Widget。

一旦你调用jQuery.widget。它会在jQuery
prototype ( jQuery.fn )
上生成一个新的可用方法相应于widget的名字。比方我们这个样例jQuery.fn.multi。

.fn方法是包括Dom元素的jquery对象和你生成的 widget prototyp实例的接口。为每个jQuery对象生成一个新的widget的实例。

  1. /*!
  2. * jQuery UI Widget @VERSION
  3. * http://jqueryui.com
  4. *
  5. * Copyright 2014 jQuery Foundation and other contributors
  6. * Released under the MIT license.
  7. * http://jquery.org/license
  8. *
  9. * http://api.jqueryui.com/jQuery.widget/
  10. */
  11.  
  12. //这里判定是否支持amd or cmd 模式
  13. (function(factory) {
  14. if (typeof define === "function" && define.amd) {
  15.  
  16. // AMD. Register as an anonymous module.
  17. define(["jquery"], factory);
  18. } else {
  19.  
  20. // Browser globals
  21. factory(jQuery);
  22. }
  23. }(function($) {
  24.  
  25. var widget_uuid = 0,
  26. //插件的实例化数量
  27. widget_slice = Array.prototype.slice; //数组的slice方法,这里的作用是将參赛arguments 转为真正的数组
  28.  
  29. //清除插件的数据及缓存
  30. $.cleanData = (function(orig) {
  31. return function(elems) {
  32. for (var i = 0, elem;
  33. (elem = elems[i]) != null; i++) {
  34. try {
  35. // 重写cleanData方法,调用后触发每一个元素的remove事件
  36. $(elem).triggerHandler("remove");
  37. // http://bugs.jquery.com/ticket/8235
  38. } catch (e) {}
  39. }
  40. orig(elems);
  41. };
  42. })($.cleanData);
  43.  
  44. /**
  45. * widget工厂方法。用于创建插件
  46. * @param name 包括命名空间的插件名称。格式 xx.xxx
  47. * @param base 须要继承的ui组件
  48. * @param prototype 插件的实际代码
  49. * @returns {Function}
  50. */
  51. $.widget = function(name, base, prototype) {
  52. var fullName, //插件全称
  53. existingConstructor, //原有的构造函数
  54. constructor, //当前构造函数
  55. basePrototype, //父类的Prototype
  56. // proxiedPrototype allows the provided prototype to remain unmodified
  57. // so that it can be used as a mixin for multiple widgets (#8876)
  58. proxiedPrototype = {},
  59. //可调用父类方法_spuer的prototype对象,扩展于prototype
  60. namespace = name.split(".")[0];
  61.  
  62. name = name.split(".")[1];
  63. fullName = namespace + "-" + name;
  64. //假设仅仅有2个參数 base默觉得Widget类,组件默认会继承base类的全部方法
  65. if (!prototype) {
  66. prototype = base;
  67. base = $.Widget;
  68. }
  69.  
  70. // console.log(base, $.Widget)
  71.  
  72. // create selector for plugin
  73. //创建一个自己定义的伪类选择器
  74. //如 $(':ui-menu') 则表示选择定义了ui-menu插件的元素
  75. $.expr[":"][fullName.toLowerCase()] = function(elem) {
  76. return !!$.data(elem, fullName);
  77. };
  78.  
  79. // 判定命名空间对象是否存在,没有的话 则创建一个空对象
  80. $[namespace] = $[namespace] || {};
  81. //这里存一份旧版的插件,假设这个插件已经被使用或者定义了
  82. existingConstructor = $[namespace][name];
  83. //这个是插件实例化的主要部分
  84. //constructor存储了插件的实例,同一时候也创建了基于命名空间的对象
  85. //如$.ui.menu
  86. constructor = $[namespace][name] = function(options, element) {
  87. // allow instantiation without "new" keyword
  88. //同意直接调用命名空间上的方法来创建组件
  89. //比方:$.ui.menu({},'#id') 这样的方式创建的话,默认没有new 实例化。
  90.  
  91. 由于_createWidgetprototype上的方法,须要new关键字来实例化
  92. //通过 调用 $.ui.menu 来实例化插件
  93. if (!this._createWidget) {
  94. console.info(this)
  95. return new constructor(options, element);
  96. }
  97.  
  98. // allow instantiation without initializing for simple inheritance
  99. // must use "new" keyword (the code above always passes args)
  100. //假设存在參数,则说明是正常调用插件
  101. //_createWidget是创建插件的核心方法
  102. if (arguments.length) {
  103. this._createWidget(options, element);
  104. }
  105. };
  106. // extend with the existing constructor to carry over any static properties
  107. //合并对象。将旧插件实例,及版本、prototype合并到constructor
  108. $.extend(constructor, existingConstructor, {
  109.  
  110. version: prototype.version,
  111. // copy the object used to create the prototype in case we need to
  112. // redefine the widget later
  113. //创建一个新的插件对象
  114. //将插件实例暴露给外部,可用户改动及覆盖
  115. _proto: $.extend({}, prototype),
  116. // track widgets that inherit from this widget in case this widget is
  117. // redefined after a widget inherits from it
  118. _childConstructors: []
  119. });
  120.  
  121. //实例化父类 获取父类的 prototype
  122. basePrototype = new base();
  123. // we need to make the options hash a property directly on the new instance
  124. // otherwise we'll modify the options hash on the prototype that we're
  125. // inheriting from
  126. //这里深复制一份options
  127. basePrototype.options = $.widget.extend({}, basePrototype.options);
  128. //在传入的ui原型中有方法调用this._super 和this.__superApply会调用到base上(最基类上)的方法
  129. $.each(prototype, function(prop, value) {
  130. //假设val不是function 则直接给对象赋值字符串
  131. if (!$.isFunction(value)) {
  132. proxiedPrototype[prop] = value;
  133. return;
  134. }
  135. //假设val是function
  136. proxiedPrototype[prop] = (function() {
  137. //两种调用父类函数的方法
  138. var _super = function() {
  139. //将当期实例调用父类的方法
  140. return base.prototype[prop].apply(this, arguments);
  141. },
  142. _superApply = function(args) {
  143. return base.prototype[prop].apply(this, args);
  144. };
  145. return function() {
  146. var __super = this._super,
  147. __superApply = this._superApply,
  148. returnValue;
  149. // console.log(prop, value,this,this._super,'===')
  150. // debugger;
  151. //在这里调用父类的函数
  152. this._super = _super;
  153. this._superApply = _superApply;
  154.  
  155. returnValue = value.apply(this, arguments);
  156.  
  157. this._super = __super;
  158. this._superApply = __superApply;
  159. // console.log(this,value,returnValue,prop,'===')
  160. return returnValue;
  161. };
  162. })();
  163. });
  164. // console.info(proxiedPrototype)
  165. // debugger;
  166. //这里是实例化获取的内容
  167. constructor.prototype = $.widget.extend(basePrototype, {
  168. // TODO: remove support for widgetEventPrefix
  169. // always use the name + a colon as the prefix, e.g., draggable:start
  170. // don't prefix for widgets that aren't DOM-based
  171. widgetEventPrefix: existingConstructor ?
  172.  
  173. (basePrototype.widgetEventPrefix || name) : name
  174. }, proxiedPrototype, {
  175. //又一次把constructor指向 constructor 变量
  176. constructor: constructor,
  177. namespace: namespace,
  178. widgetName: name,
  179. widgetFullName: fullName
  180. });
  181.  
  182. // If this widget is being redefined then we need to find all widgets that
  183. // are inheriting from it and redefine all of them so that they inherit from
  184. // the new version of this widget. We're essentially trying to replace one
  185. // level in the prototype chain.
  186. //这里判定插件是否被使用了。一般来说,都不会被使用的。
  187.  
  188. //由于插件的开发人员都是我们自己,呵呵
  189. if (existingConstructor) {
  190. $.each(existingConstructor._childConstructors, function(i, child) {
  191. var childPrototype = child.prototype;
  192.  
  193. // redefine the child widget using the same prototype that was
  194. // originally used, but inherit from the new version of the base
  195. $.widget(childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto);
  196. });
  197. // remove the list of existing child constructors from the old constructor
  198. // so the old child constructors can be garbage collected
  199. delete existingConstructor._childConstructors;
  200. } else {
  201. //父类加入当前插件的实例 主要用于作用域链查找 不至于断层
  202. base._childConstructors.push(constructor);
  203. }
  204.  
  205. //将此方法挂在jQuery对象上
  206. $.widget.bridge(name, constructor);
  207.  
  208. return constructor;
  209. };
  210.  
  211. //扩展jq的extend方法,实际上相似$.extend(true,..) 深复制
  212. $.widget.extend = function(target) {
  213. var input = widget_slice.call(arguments, 1),
  214. inputIndex = 0,
  215. inputLength = input.length,
  216. key, value;
  217. for (; inputIndex < inputLength; inputIndex++) {
  218. for (key in input[inputIndex]) {
  219. value = input[inputIndex][key];
  220. if (input[inputIndex].hasOwnProperty(key) && value !== undefined) {
  221. // Clone objects
  222. if ($.isPlainObject(value)) {
  223. target[key] = $.isPlainObject(target[key]) ? $.widget.extend({}, target[key], value) :
  224. // Don't extend strings, arrays, etc. with objects
  225. $.widget.extend({}, value);
  226. // Copy everything else by reference
  227. } else {
  228. target[key] = value;
  229. }
  230. }
  231. }
  232. }
  233. return target;
  234. };
  235.  
  236. //bridge 是设计模式的一种,这里将对象转为插件调用
  237. $.widget.bridge = function(name, object) {
  238. var fullName = object.prototype.widgetFullName || name;
  239. //这里就是插件了
  240. //这部分的实现主要做了几个工作,也是制作一个优雅的插件的主要代码
  241. //1、初次实例化时将插件对象缓存在dom上,兴许则可直接调用,避免在同样元素下widget的多实例化。
  242.  
  243. 简单的说,就是一个单例方法。
  244. //2、合并用户提供的默认设置选项options
  245. //3、能够通过调用插件时传递字符串来调用插件内的方法。
  246.  
  247. 如:$('#id').menu('hide') 实际就是实例插件并调用hide()方法。
  248.  
  249. //4、同一时候限制外部调用“_”下划线的私有方法
  250. $.fn[name] = function(options) {
  251. var isMethodCall = typeof options === "string",
  252. args = widget_slice.call(arguments, 1),
  253. returnValue = this;
  254.  
  255. // allow multiple hashes to be passed on init.
  256. //能够简单觉得是$.extend(true,options,args[0],...),args能够是一个參数或是数组
  257. options = !isMethodCall && args.length ? $.widget.extend.apply(null, [options].concat(args)) : options;
  258. //这里对字符串和对象分别作处理
  259. if (isMethodCall) {
  260. this.each(function() {
  261. var methodValue, instance = $.data(this, fullName);
  262. //假设传递的是instance则将this返回。
  263. if (options === "instance") {
  264. returnValue = instance;
  265. return false;
  266. }
  267. if (!instance) {
  268. return $.error("cannot call methods on " + name + " prior to initialization; " + "attempted to call method '" + options + "'");
  269. }
  270. //这里对私有方法的调用做了限制,直接调用会抛出异常事件
  271. if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
  272. return $.error("no such method '" + options + "' for " + name + " widget instance");
  273. }
  274. //这里是假设传递的是字符串,则调用字符串方法,并传递相应的參数.
  275. //比方插件有个方法hide(a,b); 有2个參数:a。b
  276. //则调用时$('#id').menu('hide',1,2);//1和2 分别就是參数a和b了。
  277. methodValue = instance[options].apply(instance, args);
  278. if (methodValue !== instance && methodValue !== undefined) {
  279. returnValue = methodValue && methodValue.jquery ?
  280.  
  281. returnValue.pushStack(methodValue.get()) : methodValue;
  282. return false;
  283. }
  284. });
  285. } else {
  286. this.each(function() {
  287. var instance = $.data(this, fullName);
  288.  
  289. if (instance) {
  290. instance.option(options || {});
  291. //这里每次都调用init方法
  292. if (instance._init) {
  293. instance._init();
  294. }
  295. } else {
  296. //缓存插件实例
  297. $.data(this, fullName, new object(options, this));
  298. }
  299. });
  300. }
  301.  
  302. return returnValue;
  303. };
  304. };
  305.  
  306. //这里是真正的widget基类
  307. $.Widget = function( /* options, element */ ) {};
  308. $.Widget._childConstructors = [];
  309.  
  310. $.Widget.prototype = {
  311. widgetName: "widget",
  312. //用来决定事件的名称和插件提供的callbacks的关联。
  313. // 比方dialog有一个close的callback,当close的callback被运行的时候,一个dialogclose的事件被触发。
  314. // 事件的名称和事件的prefix+callback的名称。widgetEventPrefix 默认就是控件的名称。可是假设事件须要不同的名称也能够被重写。
  315. // 比方一个用户開始拖拽一个元素,我们不想使用draggablestart作为事件的名称,我们想使用dragstart,所以我们能够重写事件的prefix。
  316. // 假设callback的名称和事件的prefix同样,事件的名称将不会是prefix。
  317.  
  318. // 它阻止像dragdrag一样的事件名称。
  319.  
  320. widgetEventPrefix: "",
  321. defaultElement: "<div>",
  322. //属性会在创建模块时被覆盖
  323. options: {
  324. disabled: false,
  325.  
  326. // callbacks
  327. create: null
  328. },
  329. _createWidget: function(options, element) {
  330. element = $(element || this.defaultElement || this)[0];
  331. this.element = $(element);
  332. this.uuid = widget_uuid++;
  333. this.eventNamespace = "." + this.widgetName + this.uuid;
  334. this.options = $.widget.extend({}, this.options, this._getCreateOptions(), options);
  335.  
  336. this.bindings = $();
  337. this.hoverable = $();
  338. this.focusable = $();
  339.  
  340. if (element !== this) {
  341. // debugger
  342. $.data(element, this.widgetFullName, this);
  343. this._on(true, this.element, {
  344. remove: function(event) {
  345. if (event.target === element) {
  346. this.destroy();
  347. }
  348. }
  349. });
  350. this.document = $(element.style ?
  351. // element within the document
  352. element.ownerDocument :
  353. // element is window or document
  354. element.document || element);
  355. this.window = $(this.document[0].defaultView || this.document[0].parentWindow);
  356. }
  357.  
  358. this._create();
  359. //创建插件时,有个create的回调
  360. this._trigger("create", null, this._getCreateEventData());
  361. this._init();
  362. },
  363. _getCreateOptions: $.noop,
  364. _getCreateEventData: $.noop,
  365. _create: $.noop,
  366. _init: $.noop,
  367. //销毁模块:去除绑定事件、去除数据、去除样式、属性
  368. destroy: function() {
  369. this._destroy();
  370. // we can probably remove the unbind calls in 2.0
  371. // all event bindings should go through this._on()
  372. this.element.unbind(this.eventNamespace).removeData(this.widgetFullName)
  373. // support: jquery <1.6.3
  374. // http://bugs.jquery.com/ticket/9413
  375. .removeData($.camelCase(this.widgetFullName));
  376. this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(
  377. this.widgetFullName + "-disabled " + "ui-state-disabled");
  378.  
  379. // clean up events and states
  380. this.bindings.unbind(this.eventNamespace);
  381. this.hoverable.removeClass("ui-state-hover");
  382. this.focusable.removeClass("ui-state-focus");
  383. },
  384. _destroy: $.noop,
  385.  
  386. widget: function() {
  387. return this.element;
  388. },
  389. //设置选项函数
  390. option: function(key, value) {
  391. var options = key,
  392. parts, curOption, i;
  393.  
  394. if (arguments.length === 0) {
  395. // don't return a reference to the internal hash
  396. //返回一个新的对象。不是内部数据的引用
  397. return $.widget.extend({}, this.options);
  398. }
  399.  
  400. if (typeof key === "string") {
  401. // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
  402. options = {};
  403. parts = key.split(".");
  404. key = parts.shift();
  405. if (parts.length) {
  406. curOption = options[key] = $.widget.extend({}, this.options[key]);
  407. for (i = 0; i < parts.length - 1; i++) {
  408. curOption[parts[i]] = curOption[parts[i]] || {};
  409. curOption = curOption[parts[i]];
  410. }
  411. key = parts.pop();
  412. if (arguments.length === 1) {
  413. return curOption[key] === undefined ? null : curOption[key];
  414. }
  415. curOption[key] = value;
  416. } else {
  417. if (arguments.length === 1) {
  418. return this.options[key] === undefined ? null : this.options[key];
  419. }
  420. options[key] = value;
  421. }
  422. }
  423.  
  424. this._setOptions(options);
  425.  
  426. return this;
  427. },
  428. _setOptions: function(options) {
  429. var key;
  430.  
  431. for (key in options) {
  432. this._setOption(key, options[key]);
  433. }
  434.  
  435. return this;
  436. },
  437. _setOption: function(key, value) {
  438. this.options[key] = value;
  439.  
  440. if (key === "disabled") {
  441. this.widget().toggleClass(this.widgetFullName + "-disabled", !! value);
  442.  
  443. // If the widget is becoming disabled, then nothing is interactive
  444. if (value) {
  445. this.hoverable.removeClass("ui-state-hover");
  446. this.focusable.removeClass("ui-state-focus");
  447. }
  448. }
  449.  
  450. return this;
  451. },
  452.  
  453. enable: function() {
  454. return this._setOptions({
  455. disabled: false
  456. });
  457. },
  458. disable: function() {
  459. return this._setOptions({
  460. disabled: true
  461. });
  462. },
  463.  
  464. _on: function(suppressDisabledCheck, element, handlers) {
  465. var delegateElement, instance = this;
  466.  
  467. // no suppressDisabledCheck flag, shuffle arguments
  468. if (typeof suppressDisabledCheck !== "boolean") {
  469. handlers = element;
  470. element = suppressDisabledCheck;
  471. suppressDisabledCheck = false;
  472. }
  473.  
  474. // no element argument, shuffle and use this.element
  475. if (!handlers) {
  476. handlers = element;
  477. element = this.element;
  478. delegateElement = this.widget();
  479. } else {
  480. // accept selectors, DOM elements
  481. element = delegateElement = $(element);
  482. this.bindings = this.bindings.add(element);
  483. }
  484.  
  485. $.each(handlers, function(event, handler) {
  486. function handlerProxy() {
  487. // allow widgets to customize the disabled handling
  488. // - disabled as an array instead of boolean
  489. // - disabled class as method for disabling individual parts
  490. if (!suppressDisabledCheck && (instance.options.disabled === true || $(this).hasClass("ui-state-disabled"))) {
  491. return;
  492. }
  493. return (typeof handler === "string" ? instance[handler] : handler).apply(instance, arguments);
  494. }
  495.  
  496. // copy the guid so direct unbinding works
  497. if (typeof handler !== "string") {
  498. handlerProxy.guid = handler.guid = handler.guid || handlerProxy.guid || $.guid++;
  499. }
  500.  
  501. var match = event.match(/^([\w:-]*)\s*(.*)$/),
  502. eventName = match[1] + instance.eventNamespace,
  503. selector = match[2];
  504. if (selector) {
  505. delegateElement.delegate(selector, eventName, handlerProxy);
  506. } else {
  507. element.bind(eventName, handlerProxy);
  508. }
  509. });
  510. },
  511.  
  512. _off: function(element, eventName) {
  513. eventName = (eventName || "").split(" ").join(this.eventNamespace + " ") + this.eventNamespace;
  514. element.unbind(eventName).undelegate(eventName);
  515. },
  516.  
  517. _delay: function(handler, delay) {
  518. function handlerProxy() {
  519. return (typeof handler === "string" ? instance[handler] : handler).apply(instance, arguments);
  520. }
  521. var instance = this;
  522. return setTimeout(handlerProxy, delay || 0);
  523. },
  524.  
  525. _hoverable: function(element) {
  526. this.hoverable = this.hoverable.add(element);
  527. this._on(element, {
  528. mouseenter: function(event) {
  529. $(event.currentTarget).addClass("ui-state-hover");
  530. },
  531. mouseleave: function(event) {
  532. $(event.currentTarget).removeClass("ui-state-hover");
  533. }
  534. });
  535. },
  536.  
  537. _focusable: function(element) {
  538. this.focusable = this.focusable.add(element);
  539. this._on(element, {
  540. focusin: function(event) {
  541. $(event.currentTarget).addClass("ui-state-focus");
  542. },
  543. focusout: function(event) {
  544. $(event.currentTarget).removeClass("ui-state-focus");
  545. }
  546. });
  547. },
  548.  
  549. _trigger: function(type, event, data) {
  550. var prop, orig, callback = this.options[type];
  551.  
  552. data = data || {};
  553. event = $.Event(event);
  554. event.type = (type === this.widgetEventPrefix ? type : this.widgetEventPrefix + type).toLowerCase();
  555. // the original event may come from any element
  556. // so we need to reset the target on the new event
  557. event.target = this.element[0];
  558.  
  559. // copy original event properties over to the new event
  560. orig = event.originalEvent;
  561. if (orig) {
  562. for (prop in orig) {
  563. if (!(prop in event)) {
  564. event[prop] = orig[prop];
  565. }
  566. }
  567. }
  568.  
  569. this.element.trigger(event, data);
  570. return !($.isFunction(callback) && callback.apply(this.element[0], [event].concat(data)) === false || event.isDefaultPrevented());
  571. }
  572. };
  573.  
  574. $.each({
  575. show: "fadeIn",
  576. hide: "fadeOut"
  577. }, function(method, defaultEffect) {
  578. $.Widget.prototype["_" + method] = function(element, options, callback) {
  579. if (typeof options === "string") {
  580. options = {
  581. effect: options
  582. };
  583. }
  584. var hasOptions, effectName = !options ? method : options === true || typeof options === "number" ?
  585.  
  586. defaultEffect : options.effect || defaultEffect;
  587. options = options || {};
  588. if (typeof options === "number") {
  589. options = {
  590. duration: options
  591. };
  592. }
  593. hasOptions = !$.isEmptyObject(options);
  594. options.complete = callback;
  595. if (options.delay) {
  596. element.delay(options.delay);
  597. }
  598. if (hasOptions && $.effects && $.effects.effect[effectName]) {
  599. element[method](options);
  600. } else if (effectName !== method && element[effectName]) {
  601. element[effectName](options.duration, options.easing, callback);
  602. } else {
  603. element.queue(function(next) {
  604. $(this)[method]();
  605. if (callback) {
  606. callback.call(element[0]);
  607. }
  608. next();
  609. });
  610. }
  611. };
  612. });
  613.  
  614. return $.widget;
  615.  
  616. }));

jquery ui widget 源代码分析的更多相关文章

  1. Jquery ui widget开发

    Jquery ui 提供了一些基本的widget,但是他提供了很好的机制来创建widget.在jquery css framework中包含了基本的css样式(视觉和感觉诸如颜色,字体大小,图标等), ...

  2. 使用 jQuery UI Widget Factory 编写有状态的插件(Stateful Plugins)

    使用 jQuery UI Widget Factory 编写有状态的插件(Stateful Plugins) Note 这一章节的内容是基于 Scott Gonzalez 一篇博客 Building ...

  3. JQuery UI Widget Factory官方Demo

    <!doctype html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  4. jQuery UI Widget(1.8.1)工作原理--转载

    先看下代码的相关注释: /*! * jQuery UI Widget 1.8.1 * * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/abo ...

  5. jQuery UI Widget 原理

    先看下代码的相关注释: /*! * jQuery UI Widget 1.8.1 * * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/abo ...

  6. jquery的widget源代码剖析

    dialog_obj(别名): Widget_obj(别名): 调用widget方法 $.widget("ui.dialog",dialog_obj); // jquery.ui. ...

  7. 通过扩展jQuery UI Widget Factory实现手动调整Accordion高度

    □ 实现Accordion高度一致 <head> <meta name="viewport" content="width=device-width&q ...

  8. jQuery UI Widget(1.8.1)工作原理

    /*! * jQuery UI Widget 1.8.1 * * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) * Dual l ...

  9. jQuery UI Widget Factory

    https://learn.jquery.com/jquery-ui/widget-factory/ The jQuery UI Widget Factory is an extensible bas ...

随机推荐

  1. android hook 框架 libinject2 简介、编译、运行

    Android so注入-libinject2 简介.编译.运行 Android so注入-libinject2  如何实现so注入 Android so注入-Libinject 如何实现so注入 A ...

  2. hdu 3790(SPFA)

    最短路径问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  3. Delphi 7 在程序中直接执行SQL脚本文件

    Delphi 7 在程序中直接执行SQL脚本文件 在处理MSDE一些操作中.需要执行一些SQL脚本.有的是从SQLServer 2000中生成的SQL为后缀的脚本.在MSDE中没有企业管理器,操作都是 ...

  4. AC日记——数颜色 bzoj 2120

    2120 思路: 带修改的莫队: 对于离线排序询问的算法,如何修改呢? 每个询问添加一个修改标记: 表示当前询问在第几个修改之后: 然后把修改标记作为第三关键字来排序: 每次更新端点,先更新时间: 块 ...

  5. 在MSSQL中将数字转换成中文

    具体代码如下: CREATE FUNCTION [dbo].[fn_NumberToChinese] (@number INT) ) AS BEGIN ); ); ); SET @res = ''; ...

  6. Peak

    A sequence of \(n\) integers \(a_1, a_2, \dots, a_n\) is called a peak, if and only if there exists ...

  7. Python的并发并行[3] -> 进程[1] -> 多进程的基本使用

    多进程的基本使用 1 subprocess 常用函数示例 首先定义一个子进程调用的程序,用于打印一个输出语句,并获取命令行参数 import sys print('Called_Function.py ...

  8. POJ 2441 Arrange the Bulls(状压DP)

    [题目链接] http://poj.org/problem?id=2441 [题目大意] 每个人有过个喜欢的篮球场地,但是一个场地只能给一个人, 问所有人都有自己喜欢的场地的方案数. [题解] 状态S ...

  9. Struts2笔记--文件下载

    Struts2提供了stream结果类型,该结果类型是专门用于支持文件下载功能的.配置stream类型的结果需要指定以下4个属性. contentType:指定被下载文件的文件类型 inputName ...

  10. 第七章 android-UI组件

    一.本章目录 二.用户界面概述 1,用户界面简介 (1)系统和用户之间进行信息交换的媒介 2,设计手机用户界面应解决的问题 (1)需要界面设计和逻辑代码完全分离(布局和逻辑代码分开放) (2)根据不同 ...