Timing_JQuery

try to take over the world!

当前为 2020-06-01 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/404470/811202/Timing_JQuery.js

  1. // ==UserScript==
  2. // @name Timing_JQuery
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description try to take over the world!
  6. // @author You
  7. // @match http://*/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. /**
  12. * code from http://creativecouple.github.io/jquery-timing/jquery-timing.js
  13. * timing.jquery.js
  14. *
  15. * JavaScript functions for waiting / repeating / stopping jQuery actions.
  16. *
  17. * This code is published under the MIT License (MIT).
  18. * http://www.opensource.org/licenses/mit-license.php
  19. *
  20. * For examples, reference, and other information see
  21. * http://creativecouple.github.com/jquery-timing/
  22. *
  23. * @author CreativeCouple
  24. * @author Peter Liske
  25. * @copyright (c) 2011 by CreativeCouple
  26. * @see http://creativecouple.github.com/jquery-timing/
  27. */
  28.  
  29. (function(jQuery, window){
  30. /**
  31. * object to store statically invoked threads
  32. */
  33. var THREAD_GROUPS = {},
  34. /**
  35. * unique timing identifier for different purposes
  36. */
  37. tuid = 1,
  38.  
  39. /**
  40. * remember original core function $.each()
  41. */
  42. originalEach = jQuery.fn.each,
  43.  
  44. /**
  45. * remember original core function $.on() (or $.bind())
  46. */
  47. originalOn = jQuery.fn.on || jQuery.fn.bind,
  48. /**
  49. * remember original core function $.off() (or $.unbind())
  50. */
  51. originalOff = jQuery.fn.off || jQuery.fn.unbind,
  52. /**
  53. * .until() and .all() have special meanings
  54. */
  55. loopEndMethods = {};
  56. function sameOrNextJQuery(before, after) {
  57. after = jQuery(after);
  58. after.prevObject = before;
  59. var i = before.length;
  60. if (i !== after.length) {
  61. return after;
  62. }
  63. while (i--) {
  64. if (before[i] !== after[i]) {
  65. return after;
  66. }
  67. }
  68. return before;
  69. }
  70. function loopCounts(loops) {
  71. var ret = [], i = loops.length;
  72. while (i--) {
  73. ret[i] = loops[i]._count;
  74. }
  75. return ret;
  76. }
  77. /**
  78. * Initialize a new timed invocation chain.
  79. *
  80. * @author CreativeCouple
  81. * @author Peter Liske
  82. *
  83. * @param context initial context
  84. * @param methodStack linked list of methods that has been or will be filled by someone else
  85. * @param ongoingLoops optional arguments for callback parameters
  86. * @param onStepCallback function to call on each step
  87. * @returns the timed invocation chain method
  88. */
  89. function createTimedInvocationChain(context, methodStack, ongoingLoops, onStepCallback) {
  90. ongoingLoops = ongoingLoops || [];
  91. var executionState = {
  92. _context: context,
  93. _method: methodStack
  94. },
  95. preventRecursion = false,
  96. method, otherExecutionState, deferred;
  97. function hookupToProxy(state, mockup){
  98. state._canContinue = false;
  99. function fire(){
  100. state._next = sameOrNextJQuery(state._context, state._next);
  101. state._canContinue = true;
  102. timedInvocationChain();
  103. }
  104. return typeof mockup.promise == "function" ? mockup.promise().then(fire) : mockup.then(fire, true);
  105. }
  106. /**
  107. * Invoke all the methods currently in the timed invocation chain.
  108. *
  109. * @author CreativeCouple
  110. * @author Peter Liske
  111. */
  112. function timedInvocationChain(deferredReturnValue) {
  113. while (!preventRecursion) try {
  114. // keep recursive calls away
  115. preventRecursion = !preventRecursion;
  116. // save current context state
  117. if (typeof onStepCallback == "function") {
  118. onStepCallback(jQuery.makeArray(executionState._next || executionState._context));
  119. }
  120. // leave the chain when waiting for a trigger
  121. if (executionState._canContinue == false) {
  122. break;
  123. }
  124. // check end of chain
  125. if (!executionState._method._name) {
  126. if (deferred && (!ongoingLoops.length || ongoingLoops[0]._allowPromise)) {
  127. // resolve any waiting promise
  128. if (executionState._context && typeof executionState._context.promise == "function") {
  129. executionState._context.promise().then(deferred.resolve);
  130. } else {
  131. deferred.resolveWith(executionState._context);
  132. }
  133. deferred = null;
  134. }
  135. if (!ongoingLoops.length) {
  136. /*
  137. * We've reached the end of our TIC
  138. * and there is nothing left to wait for.
  139. * So we can safely return the original jQuery object
  140. * hence enabling instant invocation.
  141. */
  142. return executionState._context;
  143. }
  144. /*
  145. * Now we have ongoing loops but reached the chain's end.
  146. */
  147. otherExecutionState = ongoingLoops[0]._openEndAction && ongoingLoops[0]._openEndAction(timedInvocationChain, executionState, ongoingLoops);
  148. if (!otherExecutionState) {
  149. // if innermost loop can't help us, just leave the chain
  150. break;
  151. }
  152. executionState = otherExecutionState;
  153. continue;
  154. }
  155. // check if user tries to use a non-existing function call
  156. method = executionState._context && executionState._context[executionState._method._name] || loopEndMethods[executionState._method._name];
  157. if (!method) {
  158. throw 'no such method "'+executionState._method._name+'" on object ('+executionState._context+')';
  159. }
  160. // check whether we came here triggered or not
  161. if (method.timing && !executionState._canContinue) {
  162. // prevent automatic re-trigger in case of loops
  163. executionState._canContinue = false;
  164. // handle timing method
  165. executionState = method.timing(timedInvocationChain, executionState, ongoingLoops, onStepCallback) || executionState;
  166. } else {
  167. if (!method.timing && !executionState._canContinue) {
  168. // prevent automatic re-trigger in case of loops
  169. executionState._next = executionState._context[executionState._method._name].apply(executionState._context, executionState._method._arguments);
  170. if (ongoingLoops.length && executionState._next && executionState._next instanceof PredictingProxy) {
  171. hookupToProxy(executionState, executionState._next);
  172. continue;
  173. }
  174. }
  175. // go to next step
  176. otherExecutionState = {
  177. _context: executionState._next,
  178. _method: executionState._method._next
  179. };
  180. // prevent automatic re-trigger in case of loops
  181. executionState._canContinue = false;
  182. // invoke callback method with given arguments
  183. if (typeof executionState._callback == "function") {
  184. executionState._callback.apply(executionState._context, loopCounts(ongoingLoops));
  185. }
  186. executionState = otherExecutionState;
  187. }
  188. } catch(e) {
  189. /*
  190. * We had a runtime exception.
  191. * In plain JavaScript live the chain would break now.
  192. * So we do, too.
  193. */
  194. preventRecursion = !preventRecursion;
  195. throw e;
  196. } finally {
  197. preventRecursion = !preventRecursion;
  198. }
  199. return deferredReturnValue;
  200. };
  201. if (jQuery.Deferred) {
  202. // add .promise() method to tic
  203. timedInvocationChain.promise = function(type, target){
  204. var ret = (deferred = deferred || jQuery.Deferred()).promise(target);
  205. timedInvocationChain();
  206. return ret;
  207. };
  208. }
  209. return timedInvocationChain;
  210. }
  211. /**
  212. * Create a placeholder object to collect chained method calls.
  213. *
  214. * @author CreativeCouple
  215. * @author Peter Liske
  216. *
  217. * @param context initial context
  218. * @param methodStack a linked list that this placeholder will fill with call parameters
  219. * @return the placeholder object
  220. */
  221. function PredictingProxy(context, methodStack, onStepCallback) {
  222. this['.methods'] = methodStack;
  223. this['.callback'] = onStepCallback;
  224. this.length = 0;
  225. Array.prototype.push.apply(this, jQuery.makeArray(this._ = context._ = context));
  226. for (var key in context) {
  227. if (!(key in PredictingProxy.prototype) && typeof context[key] == "function") {
  228. this[key] = extendMockupPrototype(key);
  229. }
  230. }
  231. }
  232. // enabling jQuery.when(tic);
  233. if (jQuery.Deferred) {
  234. PredictingProxy.prototype.promise = function(type, target) {
  235. if (typeof type == "object") {
  236. target = type;
  237. type = null;
  238. }
  239. return (this['.callback'] && typeof this['.callback'].promise == "function") ? this['.callback'].promise(type, target) : jQuery.Deferred().resolveWith(this).promise(target);
  240. };
  241. }
  242. /**
  243. * Create and return a new placeholder function on the prototype of PredictingProxy.
  244. */
  245. function extendMockupPrototype(name){
  246. return PredictingProxy.prototype[name] = function(){
  247. this['.methods']._name = name;
  248. this['.methods']._arguments = arguments;
  249. this['.methods'] = this['.methods']._next = {};
  250. return this['.callback'] ? this['.callback'](this, name, arguments) : this;
  251. };
  252. }
  253. /**
  254. * Create replacement methods for .bind(), .on(), .one(), .live(), and .delegate()
  255. * that support chaining instead of giving a callback function.
  256. */
  257. jQuery.each(['bind','on','one','live','delegate'], function(index, name){
  258. if (jQuery.fn[name]) {
  259. var original = jQuery.fn[name];
  260. jQuery.fn[name] = function(){
  261. var i, methodStack, placeholder, timedInvocationChain, deferred, context = this;
  262. for(i=0; i<arguments.length; i++) {
  263. if (typeof arguments[i] == "function" || (arguments[i] && typeof arguments[i] == "object") || arguments[i] === false) {
  264. if (arguments[i] !== jQuery) {
  265. // fix for jQuery 1.6 .one() + .unbind()
  266. if (typeof arguments[i] == "function" && jQuery.guid) {
  267. arguments[i].guid = arguments[i].guid || jQuery.guid++;
  268. }
  269. return original.apply(context, arguments);
  270. }
  271. break;
  272. }
  273. }
  274. Array.prototype.splice.call(arguments, i, 1, function(){
  275. timedInvocationChain = createTimedInvocationChain(context.$(this), methodStack, [{
  276. _count: jQuery.extend(Array.prototype.shift.apply(arguments), arguments),
  277. _allowPromise: true
  278. }], function(elements){
  279. placeholder.length = 0;
  280. Array.prototype.push.apply(placeholder, elements);
  281. });
  282. if (deferred) {
  283. timedInvocationChain.promise().then(deferred.resolve);
  284. deferred = null;
  285. }
  286. return timedInvocationChain();
  287. });
  288. function fire(){
  289. return timedInvocationChain ? timedInvocationChain(placeholder) : placeholder;
  290. }
  291. if (jQuery.Deferred) {
  292. fire.promise = function(type, target){
  293. if (typeof type == "object") {
  294. target = type;
  295. type = null;
  296. }
  297. return (timedInvocationChain && !type) ? timedInvocationChain.promise(type, target) : (deferred = deferred || jQuery.Deferred()).promise(target);
  298. };
  299. }
  300. return placeholder = new PredictingProxy(original.apply(context, arguments), methodStack = {}, fire);
  301. };
  302. }
  303. });
  304. /**
  305. * Create replacement method for .animate() and .load()
  306. * that support chaining if $ is given as callback function.
  307. */
  308. jQuery.each(['animate','load'], function(index, name){
  309. if (jQuery.fn[name]) {
  310. var original = jQuery.fn[name];
  311. jQuery.fn[name] = function(){
  312. while (arguments.length && arguments[arguments.length-1] == null) {
  313. Array.prototype.pop.apply(arguments);
  314. }
  315. if (this.length && arguments.length > 1 && arguments[arguments.length-1] === jQuery) {
  316. var event = '_timing'+tuid++;
  317. arguments[arguments.length-1] = function(){
  318. jQuery(this).trigger(event);
  319. };
  320. return this.each().one(event).all(original.apply(this, arguments));
  321. }
  322. return original.apply(this, arguments);
  323. };
  324. }
  325. });
  326. /**
  327. * Define new methods .wait(), .repeat(), .join(), .then()
  328. * which will always start a new TIC if invoked outside of a TIC.
  329. */
  330. jQuery.each(['wait','repeat','join','then'], function(index, name){
  331. jQuery.fn[name] = function(){
  332. var methodStack = {},
  333. placeholder = new PredictingProxy(this, methodStack, createTimedInvocationChain(this, methodStack, [], function(elements){
  334. placeholder.length = 0;
  335. Array.prototype.push.apply(placeholder, elements);
  336. }));
  337. return placeholder[name].apply(placeholder, arguments);
  338. };
  339. });
  340. /**
  341. * Define to wait for joining all animation queues.
  342. *
  343. * @param timedInvocationChain
  344. * @param executionState
  345. */
  346. jQuery.fn.join.timing = function(timedInvocationChain, executionState) {
  347. var queueName,
  348. promising,
  349. waitingElements = executionState._context.length;
  350. if (typeof executionState._method._arguments[0] == "string") {
  351. queueName = executionState._method._arguments[0];
  352. if (typeof executionState._method._arguments[1] == "function") {
  353. executionState._callback = executionState._method._arguments[1];
  354. } else {
  355. promising = executionState._method._arguments[1];
  356. executionState._callback = executionState._method._arguments[2];
  357. }
  358. } else {
  359. if (typeof executionState._method._arguments[0] == "function") {
  360. executionState._callback = executionState._method._arguments[0];
  361. } else {
  362. promising = executionState._method._arguments[0];
  363. executionState._callback = executionState._method._arguments[1];
  364. }
  365. }
  366. executionState._next = executionState._context;
  367. executionState._canContinue = !waitingElements;
  368.  
  369. // wait for each element to reach the current end of its queue
  370. if (promising) {
  371. executionState._context.promise(queueName == null ? 'fx' : queueName).then(function(){
  372. executionState._canContinue = true;
  373. timedInvocationChain();
  374. });
  375. } else {
  376. executionState._context.queue(queueName == null ? 'fx' : queueName, function(next){
  377. executionState._canContinue = !--waitingElements;
  378. timedInvocationChain();
  379. next();
  380. });
  381. }
  382. };
  383.  
  384. /**
  385. * Define to simply run callback method for .then()
  386. *
  387. * @param timedInvocationChain
  388. * @param executionState
  389. */
  390. jQuery.fn.then.timing = function(timedInvocationChain, executionState){
  391. executionState._callback = executionState._method._arguments[0];
  392. executionState._next = executionState._context;
  393. executionState._canContinue = true;
  394. if (executionState._method._arguments[1]) {
  395. Array.prototype.shift.apply(executionState._method._arguments);
  396. }
  397. };
  398. /**
  399. * Define timeout or binding to wait for.
  400. *
  401. * @param timedInvocationChain
  402. * @param executionState
  403. */
  404. jQuery.fn.wait.timing = function(timedInvocationChain, executionState, ongoingLoops) {
  405. var trigger, event, timeout, context = executionState._context;
  406. trigger = executionState._method._arguments[0];
  407. executionState._callback = executionState._method._arguments[1];
  408.  
  409. function triggerAction() {
  410. originalOff.call(event ? originalOff.call(context, event, triggerAction) : context, 'unwait', unwaitAction);
  411. executionState._canContinue = true;
  412. executionState._next = sameOrNextJQuery(executionState._context, executionState._next);
  413. timedInvocationChain();
  414. }
  415. function unwaitAction(evt, skipWait){
  416. originalOff.call(event ? originalOff.call(jQuery(this), event, triggerAction) : jQuery(this), 'unwait', unwaitAction);
  417. context = context.not(this);
  418. if (!skipWait) {
  419. executionState._next = executionState._next.not(this);
  420. }
  421. if (!context.length) {
  422. executionState._canContinue = executionState._next.length;
  423. executionState._next = sameOrNextJQuery(executionState._context, executionState._next);
  424. window.clearTimeout(timeout);
  425. executionState = { _context: context };
  426. }
  427. // just update the snapshot info
  428. timedInvocationChain();
  429. }
  430.  
  431. originalOn.call(context, 'unwait', unwaitAction);
  432. executionState._next = context;
  433.  
  434. if (trigger == null || trigger == jQuery) {
  435. trigger = context;
  436. }
  437. if (typeof trigger == "function") {
  438. trigger = trigger.apply(context, loopCounts(ongoingLoops));
  439. }
  440. if (typeof trigger == "string") {
  441.  
  442. originalOn.call(context, event = trigger, triggerAction);
  443.  
  444. } else if (trigger && typeof trigger.promise == "function") {
  445. trigger.promise().then(triggerAction);
  446. } else if (trigger && typeof trigger.then == "function") {
  447. trigger.then(triggerAction, true);
  448. } else {
  449.  
  450. timeout = window.setTimeout(triggerAction, Math.max(0,trigger));
  451.  
  452. }
  453. };
  454.  
  455. /**
  456. * Define to simply run callback method for .then()
  457. *
  458. * @param timedInvocationChain
  459. * @param executionState
  460. */
  461. jQuery.fn.each = function(callback){
  462. if (!callback || callback === jQuery) {
  463. var methodStack = {},
  464. placeholder = new PredictingProxy(this, methodStack, createTimedInvocationChain(this, methodStack, [], function(elements){
  465. placeholder.length = 0;
  466. Array.prototype.push.apply(placeholder, elements);
  467. }));
  468. return placeholder.each(callback);
  469. }
  470. return originalEach.apply(this, arguments);
  471. };
  472. /**
  473. * Define interval or binding to repeat.
  474. *
  475. * @param timedInvocationChain
  476. * @param executionState
  477. */
  478. jQuery.fn.each.timing = function(timedInvocationChain, executionState, ongoingLoops, onStepCallback) {
  479. if (executionState._method._arguments[0] && executionState._method._arguments[0] !== jQuery) {
  480. executionState._canContinue = true;
  481. executionState._next = originalEach.apply(executionState._context, executionState._method._arguments);
  482. return;
  483. }
  484. var size = Math.max(executionState._context.length, 1),
  485. finished = 0,
  486. key, methodToGoOn, openLoopTimeout,
  487. innerTICs = [],
  488. innerElements = [],
  489. proxyPlaceholder = jQuery.extend({}, executionState._context),
  490. stepByStep = executionState._method._arguments[0] === jQuery;
  491.  
  492. if (stepByStep) {
  493. window.setTimeout(function(){
  494. openLoopTimeout = true;
  495. timedInvocationChain();
  496. },0);
  497. }
  498. function spreadAction(){
  499. if (stepByStep) {
  500. if (finished < size) {
  501. (innerTICs[finished])();
  502. }
  503. } else {
  504. for (var i=0; i<size; i++) {
  505. (innerTICs[i])();
  506. }
  507. }
  508. return proxyPlaceholder;
  509. }
  510. for (key in PredictingProxy.prototype) {
  511. proxyPlaceholder[key] = spreadAction;
  512. }
  513. proxyPlaceholder.length = size;
  514. for(key=0; key<size; key++) (function(index){
  515. var innerLoops = ongoingLoops.slice(),
  516. context = executionState._context.eq(index);
  517. innerElements[index] = context.get();
  518. innerLoops.unshift({
  519. _count: index,
  520. _allAction: function(state){
  521. finished++;
  522. if (finished == size) {
  523. methodToGoOn = state._method._next;
  524. }
  525. timedInvocationChain();
  526. },
  527. _fixOpenLoop: loopEndMethods.all,
  528. _openEndAction: function(tic, state){
  529. if (openLoopTimeout) {
  530. finished++;
  531. if (finished == size) {
  532. methodToGoOn = state._method;
  533. }
  534. timedInvocationChain();
  535. }
  536. }
  537. });
  538. innerTICs[index] = createTimedInvocationChain(context, executionState._method._next, innerLoops, function(elements){
  539. innerElements[index] = elements;
  540. proxyPlaceholder.length = 0;
  541. for (var i=0; i<size; i++) {
  542. Array.prototype.push.apply(proxyPlaceholder, innerElements[i]);
  543. }
  544. if (onStepCallback)
  545. onStepCallback(jQuery.makeArray(proxyPlaceholder));
  546. });
  547. })(key);
  548.  
  549. executionState._next = proxyPlaceholder;
  550. executionState._canContinue = true;
  551. executionState._openEndAction = function(tic, state){
  552. if (finished == size) {
  553. ongoingLoops.shift();
  554. return {
  555. _context: sameOrNextJQuery(executionState._context, proxyPlaceholder),
  556. _method: methodToGoOn
  557. };
  558. }
  559. var finishedBefore = finished;
  560. spreadAction();
  561. if (finished != finishedBefore) {
  562. return state;
  563. }
  564. };
  565. executionState._count = size;
  566. ongoingLoops.unshift(executionState);
  567. };
  568.  
  569. loopEndMethods.all = function(executionState){
  570. jQuery.extend(executionState._method, {
  571. _next: jQuery.extend({}, executionState._method),
  572. _name: 'all',
  573. _arguments: []
  574. });
  575. executionState._canContinue = null;
  576. };
  577. loopEndMethods.all.timing = function(timedInvocationChain, executionState, ongoingLoops) {
  578. if (!ongoingLoops.length || !ongoingLoops[0]._fixOpenLoop) {
  579. throw '.all() method must be used after .each() only';
  580. }
  581. if (!ongoingLoops[0]._allAction) {
  582. ongoingLoops[0]._fixOpenLoop(executionState);
  583. return;
  584. }
  585. ongoingLoops[0]._allAction(executionState);
  586. };
  587. /**
  588. * Define interval or binding to repeat.
  589. *
  590. * @param timedInvocationChain
  591. * @param executionState
  592. */
  593. jQuery.fn.repeat.timing = function(timedInvocationChain, executionState, ongoingLoops) {
  594. var trigger,
  595. firstRunNow,
  596. openLoopTimeout,
  597. event,
  598. interval;
  599.  
  600. if (typeof executionState._method._arguments[0] == "function") {
  601. executionState._callback = executionState._method._arguments[0];
  602. } else if (typeof executionState._method._arguments[1] == "function") {
  603. trigger = executionState._method._arguments[0];
  604. executionState._callback = executionState._method._arguments[1];
  605. } else {
  606. trigger = executionState._method._arguments[0];
  607. firstRunNow = executionState._method._arguments[1];
  608. executionState._callback = executionState._method._arguments[2];
  609. }
  610. function triggerAction() {
  611. executionState._next = executionState._next || executionState._context;
  612. executionState._canContinue = true;
  613. timedInvocationChain();
  614. }
  615. function unrepeatAction(){
  616. originalOff.call(event ? originalOff.call(jQuery(this), event, triggerAction) : jQuery(this), 'unrepeat', unrepeatAction);
  617. var context = executionState._context.not(this);
  618. executionState._next = (executionState._next == executionState._context) ? context : executionState._next;
  619. executionState._context = context;
  620. executionState._canContinue = executionState._context.length && executionState._canContinue;
  621. trigger = executionState._context.length && trigger;
  622. window.clearInterval(!executionState._context.length && interval);
  623. // just update the snapshot info
  624. timedInvocationChain();
  625. }
  626. executionState._openEndAction = function(tic, state){
  627. if (executionState._canContinue || openLoopTimeout) {
  628. executionState._count++;
  629. executionState._next = executionState._next || executionState._context;
  630. executionState._canContinue = executionState._canContinue || (trigger && state._context && state._context.length);
  631. return executionState;
  632. }
  633. };
  634.  
  635. if (trigger == null) {
  636. firstRunNow = trigger = true;
  637. window.setTimeout(function(){
  638. openLoopTimeout = true;
  639. timedInvocationChain();
  640. },0);
  641. } else {
  642. if (typeof trigger == "string") {
  643. originalOn.call(executionState._context, event = trigger, triggerAction);
  644. } else {
  645. interval = window.setInterval(triggerAction, Math.max(0, trigger));
  646. }
  647. trigger = false;
  648. }
  649.  
  650. originalOn.call(executionState._context, 'unrepeat', unrepeatAction);
  651. executionState._next = executionState._context;
  652. executionState._count = 0;
  653. executionState._untilAction = function(end){
  654. if (end) {
  655. unrepeatAction.apply(executionState._context);
  656. }
  657. if (trigger) {
  658. triggerAction();
  659. }
  660. };
  661. executionState._fixOpenLoop = loopEndMethods.until;
  662.  
  663. if (firstRunNow) {
  664. triggerAction();
  665. }
  666. ongoingLoops.unshift(executionState);
  667. };
  668.  
  669. /**
  670. * Defined to evaluate condition when calling .until()
  671. */
  672. loopEndMethods.until = function(executionState){
  673. jQuery.extend(executionState._method, {
  674. _next: jQuery.extend({}, executionState._method),
  675. _name: 'until',
  676. _arguments: []
  677. });
  678. executionState._canContinue = null;
  679. };
  680. loopEndMethods.until.timing = function(timedInvocationChain, executionState, ongoingLoops) {
  681. if (!ongoingLoops.length || !ongoingLoops[0]._fixOpenLoop) {
  682. throw '.until() method must be used after .repeat() only';
  683. }
  684. if (!ongoingLoops[0]._untilAction) {
  685. ongoingLoops[0]._fixOpenLoop(executionState);
  686. return;
  687. }
  688.  
  689. var condition = executionState._method._arguments[0],
  690. loopContext = executionState._method._arguments[1];
  691. if (condition === jQuery) {
  692. condition = null;
  693. loopContext = executionState._method._arguments.length <= 1 || loopContext;
  694. }
  695. if (typeof condition == "function") {
  696. condition = condition.apply(executionState._context, loopCounts(ongoingLoops));
  697. }
  698. if (condition == null) {
  699. condition = !executionState._context.size();
  700. }
  701. if (typeof condition == "object") {
  702. condition = condition.toString();
  703. }
  704. if (typeof condition == "number") {
  705. condition = ongoingLoops[0]._count >= condition-1;
  706. }
  707. if (condition) {
  708. executionState._canContinue = true;
  709. executionState._next = executionState._context;
  710. ongoingLoops.shift()._untilAction(condition);
  711. } else {
  712. if (loopContext) {
  713. ongoingLoops[0]._next = executionState._context;
  714. }
  715. executionState = ongoingLoops[0];
  716. executionState._count++;
  717. executionState._untilAction(condition);
  718. return executionState;
  719. }
  720. };
  721. // support .until() and .all()
  722. new PredictingProxy(loopEndMethods);
  723. /**
  724. * Define unwait and unrepeat methods.
  725. */
  726. jQuery.each(['unwait','unrepeat'], function(index, name){
  727. jQuery.fn[name] = function(){
  728. return this.trigger(name, arguments);
  729. };
  730. });
  731. /**
  732. * define all static timing methods:
  733. * $.wait, $.repeat ,$.join, $.then, $.unwait, $.unrepeat
  734. */
  735. jQuery.each(['wait','repeat','join','then','unwait','unrepeat'], function(index, name){
  736. jQuery[name] = function(){
  737. var group = typeof arguments[0] == "string" ? Array.prototype.shift.apply(arguments) : '';
  738. return jQuery.fn[name].apply(THREAD_GROUPS[group] = (THREAD_GROUPS[group] || jQuery('<div>').text(group)), arguments);
  739. };
  740. });
  741.  
  742. /**
  743. * X defines deferred variables that can be used in timed invocation chains
  744. *
  745. * @author CreativeCouple
  746. * @author Peter Liske
  747. */
  748. function X(compute, Var, calculation){
  749. if (typeof compute == "string") {
  750. calculation = new Function('x','return ['+compute+'\n,x]');
  751. compute = function(x, result){
  752. result = calculation(x);
  753. callbackVariable.x = result[1];
  754. return result[0];
  755. };
  756. }
  757. var hasRelatedVariable = typeof Var == "function",
  758. hasComputation = typeof compute == "function",
  759. callbackVariable = function(value) {
  760. if (arguments.length == 1) {
  761. callbackVariable.x = value;
  762. if (hasRelatedVariable) {
  763. Var(value);
  764. }
  765. } else {
  766. return evaluate();
  767. }
  768. };
  769. function evaluate(value){
  770. value = hasRelatedVariable ? Var() : callbackVariable.x;
  771. return hasComputation ? compute(value) : value;
  772. }
  773. callbackVariable.x = 0;
  774. callbackVariable._ = { toString: callbackVariable.$ = callbackVariable.toString = evaluate.toString = evaluate };
  775. callbackVariable.mod = function(val){
  776. return X(function(x){
  777. return x % val;
  778. }, callbackVariable);
  779. };
  780. callbackVariable.add = function(val){
  781. return X(function(x){
  782. return x + val;
  783. }, callbackVariable);
  784. };
  785. callbackVariable.neg = function(){
  786. return X('-x', callbackVariable);
  787. };
  788. // $$ only for backward compatibility
  789. callbackVariable.$$ = callbackVariable.X = function(compute){
  790. return X(compute, callbackVariable);
  791. };
  792. jQuery.each(['a','b','c','d','e','f','g','h','i','j'], function(index, character){
  793. callbackVariable[index] = callbackVariable[character] = function(){
  794. callbackVariable(arguments[index]);
  795. };
  796. });
  797. return callbackVariable;
  798. };
  799. // $$ only for backward compatibility
  800. window.$$ = jQuery.$$ = jQuery.X = X;
  801. /**
  802. * Define chained version of $().
  803. * This allows to use .end() to come back to previous jQuery selection.
  804. */
  805. jQuery.fn.$ = function(){
  806. var ret = jQuery.apply(window, arguments);
  807. ret.prevObject = this;
  808. return ret;
  809. };
  810. })(jQuery, window);