]> git.proxmox.com Git - extjs.git/blame - extjs/packages/core/src/env/Ready.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / core / src / env / Ready.js
CommitLineData
6527f429
DM
1/**\r
2 * This class manages ready detection and handling. Direct use of this class is not\r
3 * recommended. Instead use `Ext.onReady`:\r
4 * \r
5 * Ext.onReady(function () {\r
6 * // DOM and Framework are ready...\r
7 * });\r
8 *\r
9 * ## DOM Ready\r
10 *\r
11 * The lowest-level of readiness is DOM readiness. This level implies only that the document\r
12 * body exists. Many things require the DOM to be ready for manipulation. If that is all\r
13 * that is required, the `Ext.onDocumentReady` method can be called to register a callback\r
14 * to be called as soon as the DOM is ready:\r
15 *\r
16 * Ext.onDocumentReady(function () {\r
17 * // the document body is ready\r
18 * });\r
19 *\r
20 * ## Framework Ready\r
21 *\r
22 * In production builds of applications it is common to have all of the code loaded before\r
23 * DOM ready, so the need to wait for "onReady" is often confused with only that concern.\r
24 * This is easy to understand, at least in part because historically `Ext.onReady` only\r
25 * waited for DOM ready.\r
26 *\r
27 * With the introduction of `Ext.Loader`, however, it became common for DOM ready to occur\r
28 * in the middle of dynamically loading code. If application code were executed at that\r
29 * time, any use of the yet-to-be-loaded classes would throw errors. As a consequence of\r
30 * this, the `Ext.onReady` mechanism was extended to wait for both DOM ready *and* all of\r
31 * the required classes to be loaded.\r
32 *\r
33 * When the framework enters or leaves a state where it is not ready (for example, the\r
34 * first dynamic load is requested or last load completes), `Ext.env.Ready` is informed.\r
35 * For example:\r
36 *\r
37 * Ext.env.Ready.block();\r
38 *\r
39 * //...\r
40 *\r
41 * Ext.env.Ready.unblock();\r
42 *\r
43 * When there are no blocks and the DOM is ready, the Framework is ready and the "onReady"\r
44 * callbacks are called.\r
45 *\r
46 * Priority can be used to control the ordering of onReady listeners, for example:\r
47 *\r
48 * Ext.onReady(function() {\r
49 *\r
50 * }, null, {\r
51 * priority: 100\r
52 * });\r
53 *\r
54 * Ready listeners with higher priorities will run sooner than those with lower priorities,\r
55 * the default priority being `0`. Internally the framework reserves priorities of 1000\r
56 * or greater, and -1000 or lesser for onReady handlers that must run before or after\r
57 * any application code. Applications should stick to using priorities in the -999 - 999\r
58 * range. The following priorities are currently in use by the framework:\r
59 *\r
60 * - Element_scroll rtl override: `1001`\r
61 * - Event system initialization: `2000`\r
62 * - Ext.dom.Element: `1500`\r
63 *\r
64 * @class Ext.env.Ready\r
65 * @singleton\r
66 * @private\r
67 * @since 5.0.0\r
68 */\r
69Ext.env.Ready = {\r
70// @define Ext.env.Ready\r
71// @require Ext.env.Browser\r
72// @require Ext.env.OS\r
73// @require Ext.env.Feature\r
74\r
75 /**\r
76 * @property {Number} blocks The number of Framework readiness blocks.\r
77 * @private\r
78 */\r
79 blocks: (location.search || '').indexOf('ext-pauseReadyFire') > 0 ? 1 : 0,\r
80\r
81 /**\r
82 * @property {Number} bound This property stores the state of event listeners bound\r
83 * to the document or window to detect ready state.\r
84 * @private\r
85 */\r
86 bound: 0,\r
87\r
88 /**\r
89 * @property {Number} [delay=1]\r
90 * This allows the DOM listener thread to complete (usually desirable with mobWebkit,\r
91 * Gecko) before firing the entire onReady chain (high stack load on Loader). For mobile\r
92 * devices when running from Home Screen, the splash screen will not disappear until\r
93 * all external resource requests finish. This delay clears the splash screen.\r
94 * @private\r
95 */\r
96 delay: 1,\r
97\r
98 //<debug>\r
99 /**\r
100 * @property {Event[]} events An array of events that have triggered ready state. This\r
101 * is for diagnostic purposes only and is only available in debug builds.\r
102 * An array\r
103 * @private\r
104 */\r
105 events: [],\r
106 //</debug>\r
107\r
108 /**\r
109 * @property {Boolean} firing This property is `true` when we currently calling the\r
110 * listeners.\r
111 * @private\r
112 */\r
113 firing: false,\r
114\r
115 /**\r
116 * @property {Number} generation A counter of the number of mutations of `listeners`.\r
117 * @private\r
118 */\r
119 generation: 0,\r
120\r
121 /**\r
122 * @property {Object[]} listeners The set of listeners waiting for ready.\r
123 * @private\r
124 */\r
125 listeners: [],\r
126\r
127 /**\r
128 * @property {Number} nextId A counter so we can assign listeners an `id` to keep\r
129 * them in FIFO order.\r
130 * @private\r
131 */\r
132 nextId: 0,\r
133\r
134 /**\r
135 * @property {Number} sortGeneration A captured value of `generation` that indicates\r
136 * when the `listeners` were last sorted.\r
137 * @private\r
138 */\r
139 sortGeneration: 0,\r
140\r
141 /**\r
142 * @property {Number} state\r
143 * Holds the current ready state as managed by this class. The values possible are:\r
144 * \r
145 * * 0 - Not ready.\r
146 * * 1 - Ready detected but listeners are not yet notified.\r
147 * * 2 - Ready detected and listeners are notified. See also `firing`.\r
148 * \r
149 * @private\r
150 */\r
151 state: 0,\r
152\r
153 /**\r
154 * @property {Object} timer The handle from `setTimeout` for the delayed notification\r
155 * of ready.\r
156 * @private\r
157 */\r
158 timer: null,\r
159\r
160 /**\r
161 * Binds the appropriate browser event for checking if the DOM has loaded.\r
162 * @private\r
163 */\r
164 bind: function () {\r
165 var me = Ext.env.Ready,\r
166 doc = document;\r
167\r
168 if (!me.bound) {\r
169 // Test scenario where load is dynamic AFTER window.load\r
170 if (doc.readyState === 'complete') {\r
171 // Firefox4+ got support for this state, others already do.\r
172 me.onReadyEvent({\r
173 type: doc.readyState || 'body'\r
174 });\r
175 } else {\r
176 me.bound = 1;\r
177 if (Ext.browser.is.PhoneGap && !Ext.os.is.Desktop) {\r
178 me.bound = 2;\r
179 doc.addEventListener('deviceready', me.onReadyEvent, false);\r
180 }\r
181 doc.addEventListener('DOMContentLoaded', me.onReadyEvent, false);\r
182 window.addEventListener('load', me.onReadyEvent, false);\r
183 }\r
184 }\r
185 },\r
186\r
187 block: function () {\r
188 ++this.blocks;\r
189 Ext.isReady = false;\r
190 },\r
191\r
192 /**\r
193 * This method starts the process of firing the ready event. This may be delayed based\r
194 * on the `delay` property.\r
195 * @private\r
196 */\r
197 fireReady: function () {\r
198 var me = Ext.env.Ready;\r
199\r
200 if (!me.state) {\r
201 Ext._readyTime = Ext.ticks();\r
202 Ext.isDomReady = true;\r
203 me.state = 1;\r
204\r
205 // As soon as we transition to domready, complete the feature detection:\r
206 Ext.feature.detect(true);\r
207\r
208 if (!me.delay) {\r
209 me.handleReady();\r
210 } else if (navigator.standalone) {\r
211 // When running from Home Screen, the splash screen will not disappear\r
212 // until all external resource requests finish.\r
213 // The first timeout clears the splash screen\r
214 // The second timeout allows inital HTML content to be displayed\r
215 me.timer = Ext.defer(function() {\r
216 me.timer = null;\r
217 me.handleReadySoon();\r
218 }, 1);\r
219 } else {\r
220 me.handleReadySoon();\r
221 }\r
222 }\r
223 },\r
224\r
225 /**\r
226 * This method iterates over the `listeners` and invokes them. This advances the\r
227 * `state` from 1 to 2 and ensure the proper subset of `listeners` are invoked.\r
228 * @private\r
229 */\r
230 handleReady: function () {\r
231 var me = this;\r
232\r
233 if (me.state === 1) {\r
234 me.state = 2;\r
235\r
236 Ext._beforeReadyTime = Ext.ticks();\r
237 me.invokeAll();\r
238 Ext._afterReadyTime = Ext.ticks();\r
239 }\r
240 },\r
241\r
242 /**\r
243 * This method is called to schedule a call to `handleReady` using a `setTimeout`. It\r
244 * ensures that only one timer is pending.\r
245 * @param {Number} [delay] If passed, this overrides the `delay` property.\r
246 * @private\r
247 */\r
248 handleReadySoon: function (delay) {\r
249 var me = this;\r
250\r
251 if (!me.timer) {\r
252 me.timer = Ext.defer(function () {\r
253 me.timer = null;\r
254 me.handleReady();\r
255 }, delay || me.delay);\r
256 }\r
257 },\r
258\r
259 /**\r
260 * This method invokes the given `listener` instance based on its options.\r
261 * @param {Object} listener\r
262 */\r
263 invoke: function (listener) {\r
264 var delay = listener.delay;\r
265\r
266 if (delay) {\r
267 Ext.defer(listener.fn, delay, listener.scope);\r
268 } else {\r
269 if (Ext.elevateFunction) {\r
270 Ext.elevateFunction(listener.fn, listener.scope);\r
271 } else {\r
272 listener.fn.call(listener.scope);\r
273 }\r
274 }\r
275 },\r
276\r
277 /**\r
278 * Invokes as many listeners as are appropriate given the current state. This should\r
279 * only be called when DOM ready is achieved. The remaining business of `blocks` is\r
280 * handled here.\r
281 */\r
282 invokeAll: function() {\r
283 if (Ext.elevateFunction) {\r
284 Ext.elevateFunction(this.doInvokeAll, this);\r
285 } else {\r
286 this.doInvokeAll();\r
287 }\r
288 },\r
289\r
290 doInvokeAll: function () {\r
291 var me = this,\r
292 listeners = me.listeners,\r
293 listener;\r
294\r
295 if (!me.blocks) {\r
296 // Since DOM is ready and we have no blocks, we mark the framework as ready.\r
297 Ext.isReady = true;\r
298 }\r
299 me.firing = true;\r
300\r
301 // NOTE: We cannot cache this length because each time through the loop a callback\r
302 // may have added new callbacks.\r
303 while (listeners.length) {\r
304 if (me.sortGeneration !== me.generation) {\r
305 me.sortGeneration = me.generation;\r
306\r
307 // This will happen just once on the first pass... if nothing is being\r
308 // added as we call the callbacks. This sorts the listeners such that the\r
309 // highest priority listener is at the *end* of the array ... so we can\r
310 // use pop (as opposed to shift) to extract it.\r
311 listeners.sort(me.sortFn);\r
312 }\r
313\r
314 listener = listeners.pop();\r
315 if (me.blocks && !listener.dom) {\r
316 // If we are blocked (i.e., only DOM ready) and this listener is not a\r
317 // DOM-ready listener we have reached the end of the line. The remaining\r
318 // listeners are Framework ready listeners.\r
319 listeners.push(listener);\r
320 break;\r
321 }\r
322\r
323 me.invoke(listener);\r
324 }\r
325\r
326 me.firing = false;\r
327 },\r
328\r
329 /**\r
330 * This method wraps the given listener pieces in a proper object for the `listeners`\r
331 * array and `invoke` methods.\r
332 * @param {Function} fn The method to call.\r
333 * @param {Object} [scope] The scope (`this` reference) in which the `fn` executes.\r
334 * Defaults to the browser window.\r
335 * @param {Object} [options] An object with extra options.\r
336 * @param {Number} [options.delay=0] A number of milliseconds to delay.\r
337 * @param {Number} [options.priority=0] Relative priority of this callback. A larger\r
338 * number will result in the callback being sorted before the others. Priorities\r
339 * 1000 or greater and -1000 or lesser are reserved for internal framework use only.\r
340 * @param {Boolean} [options.dom=false] Pass `true` to only wait for DOM ready, `false`\r
341 * means full Framework and DOM readiness.\r
342 * @return {Object} The listener instance.\r
343 * @private\r
344 */\r
345 makeListener: function (fn, scope, options) {\r
346 var ret = {\r
347 fn: fn,\r
348 id: ++this.nextId, // so sortFn can respect FIFO\r
349 scope: scope,\r
350 dom: false,\r
351 priority: 0\r
352 };\r
353 if (options) {\r
354 Ext.apply(ret, options);\r
355 }\r
356 ret.phase = ret.dom ? 0 : 1; // to simplify the sortFn\r
357 return ret;\r
358 },\r
359\r
360 /**\r
361 * Adds a listener to be notified when the document is ready (before onload and before\r
362 * images are loaded).\r
363 *\r
364 * @param {Function} fn The method to call.\r
365 * @param {Object} [scope] The scope (`this` reference) in which the `fn` executes.\r
366 * Defaults to the browser window.\r
367 * @param {Object} [options] An object with extra options.\r
368 * @param {Number} [options.delay=0] A number of milliseconds to delay.\r
369 * @param {Number} [options.priority=0] Relative priority of this callback. A larger\r
370 * number will result in the callback being sorted before the others. Priorities\r
371 * 1000 or greater and -1000 or lesser are reserved for internal framework use only.\r
372 * @param {Boolean} [options.dom=false] Pass `true` to only wait for DOM ready, `false`\r
373 * means full Framework and DOM readiness.\r
374 * @private\r
375 */\r
376 on: function (fn, scope, options) {\r
377 var me = Ext.env.Ready,\r
378 listener = me.makeListener(fn, scope, options);\r
379\r
380 if (me.state === 2 && !me.firing && (listener.dom || !me.blocks)) {\r
381 // If we are DOM ready (state === 2) and not currently in invokeAll (!firing)\r
382 // and this listener is ready to call (either a DOM ready listener or there\r
383 // are no blocks), then we need to invoke the listener now.\r
384 //\r
385 // Otherwise we can fall to the else block and push the listener. The eventual\r
386 // (or currently executing) call to handleReady or unblock will trigger its\r
387 // delivery in proper priority order.\r
388 me.invoke(listener);\r
389 } else {\r
390 me.listeners.push(listener);\r
391 ++me.generation;\r
392\r
393 if (!me.bound) {\r
394 // If we have never bound then bind the ready event now. If we have unbound\r
395 // the event then me.bound == -1 and we don't want to rebind it as the DOM\r
396 // is ready.\r
397 me.bind();\r
398 }\r
399 }\r
400 },\r
401\r
402 /**\r
403 * This is a generic event handler method attached to all of the various events that\r
404 * may indicate ready state. The first call to this method indicates ready state has\r
405 * been achieved.\r
406 * @param {Event} [ev] The event instance.\r
407 * @private\r
408 */\r
409 onReadyEvent: function (ev) {\r
410 var me = Ext.env.Ready;\r
411\r
412 if (Ext.elevateFunction) {\r
413 Ext.elevateFunction(me.doReadyEvent, me, arguments);\r
414 } else {\r
415 me.doReadyEvent(ev);\r
416 }\r
417 },\r
418\r
419 doReadyEvent: function (ev) {\r
420 var me = this;\r
421\r
422 //<debug>\r
423 if (ev && ev.type) {\r
424 me.events.push(ev);\r
425 }\r
426 //</debug>\r
427\r
428 if (me.bound > 0) {\r
429 me.unbind();\r
430 me.bound = -1; // NOTE: *not* 0 or false - we never want to rebind!\r
431 }\r
432\r
433 if (!me.state) {\r
434 me.fireReady();\r
435 }\r
436 },\r
437\r
438 /**\r
439 * Sorts the `listeners` array by `phase` and `priority` such that the first listener\r
440 * to fire can be determined using `pop` on the `listeners` array.\r
441 * @private\r
442 */\r
443 sortFn: function (a, b) {\r
444 return -((a.phase - b.phase) || (b.priority - a.priority) || (a.id - b.id));\r
445 },\r
446\r
447 unblock: function () {\r
448 var me = this;\r
449\r
450 if (me.blocks) {\r
451 if (! --me.blocks) {\r
452 if (me.state === 2 && !me.firing) {\r
453 // We have already finished handleReady (the DOM ready handler) so\r
454 // this trigger just needs to dispatch all the remaining listeners.\r
455 me.invokeAll();\r
456 }\r
457 // if we are currently firing then invokeAll will pick up the Framework\r
458 // ready listeners automatically.\r
459 //\r
460 // If me.state < 2 then we are waiting for DOM ready so it will eventually\r
461 // call handleReady and invokeAll when everything is ready.\r
462 }\r
463 }\r
464 },\r
465\r
466 /**\r
467 * This method is called to remove all event listeners that may have been set up to\r
468 * detect ready state.\r
469 * @private\r
470 */\r
471 unbind: function () {\r
472 var me = this,\r
473 doc = document;\r
474\r
475 if (me.bound > 1) {\r
476 doc.removeEventListener('deviceready', me.onReadyEvent, false);\r
477 }\r
478\r
479 doc.removeEventListener('DOMContentLoaded', me.onReadyEvent, false);\r
480 window.removeEventListener('load', me.onReadyEvent, false);\r
481 }\r
482};\r
483\r
484(function () {\r
485 var Ready = Ext.env.Ready;\r
486\r
487 //<feature legacyBrowser>\r
488\r
489 /*\r
490 * EXTJS-13522\r
491 * Although IE 9 has the DOMContentLoaded event available, usage of that causes\r
492 * timing issues when attempting to access document.namespaces (VmlCanvas.js).\r
493 * Consequently, even in IE 9 we need to use the legacy bind override for ready\r
494 * detection. This defers ready firing enough to allow access to the\r
495 * document.namespaces property.\r
496 *\r
497 * NOTE: this issue is very timing sensitive, and typically only displays itself\r
498 * when there is a large amount of latency between the browser and the server, and\r
499 * when testing against a built page (ext-all.js) and not a dev mode page.\r
500 */\r
501 if (Ext.isIE9m) {\r
502 /* Customized implementation for Legacy IE. The default implementation is \r
503 * configured for use with all other 'standards compliant' agents.\r
504 * References: http://javascript.nwbox.com/IEContentLoaded/\r
505 * licensed courtesy of http://developer.yahoo.com/yui/license.html\r
506 */\r
507 Ext.apply(Ready, {\r
508 /**\r
509 * Timer for doScroll polling\r
510 * @private\r
511 */\r
512 scrollTimer: null,\r
513\r
514 /**\r
515 * @private\r
516 */\r
517 readyStatesRe : /complete/i,\r
518\r
519 /**\r
520 * This strategy has minimal benefits for Sencha solutions that build\r
521 * themselves (ie. minimal initial page markup). However, progressively-enhanced\r
522 * pages (with image content and/or embedded frames) will benefit the most\r
523 * from it. Browser timer resolution is too poor to ensure a doScroll check\r
524 * more than once on a page loaded with minimal assets (the readystatechange\r
525 * event 'complete' usually beats the doScroll timer on a 'lightly-loaded'\r
526 * initial document).\r
527 * @private\r
528 */\r
529 pollScroll : function() {\r
530 var scrollable = true;\r
531\r
532 try {\r
533 document.documentElement.doScroll('left');\r
534 } catch(e) {\r
535 scrollable = false;\r
536 }\r
537\r
538 // on IE8, when running within an iFrame, document.body is not immediately\r
539 // available\r
540 if (scrollable && document.body) {\r
541 Ready.onReadyEvent({\r
542 type: 'doScroll'\r
543 });\r
544 } else {\r
545 // Minimize thrashing --\r
546 // adjusted for setTimeout's close-to-minimums (not too low),\r
547 // as this method SHOULD always be called once initially\r
548 Ready.scrollTimer = Ext.defer(Ready.pollScroll, 20);\r
549 }\r
550\r
551 return scrollable;\r
552 },\r
553\r
554 bind: function () {\r
555 if (Ready.bound) {\r
556 return;\r
557 }\r
558\r
559 var doc = document,\r
560 topContext;\r
561\r
562 // See if we are in an IFRAME? (doScroll ineffective here)\r
563 try {\r
564 topContext = window.frameElement === undefined;\r
565 } catch(e) {\r
566 // If we throw an exception, it means we're probably getting access\r
567 // denied, which means we're in an iframe cross domain.\r
568 }\r
569\r
570 if (!topContext || !doc.documentElement.doScroll) {\r
571 Ready.pollScroll = Ext.emptyFn; //then noop this test altogether\r
572 }\r
573 else if (Ready.pollScroll()) { // starts scroll polling if necessary\r
574 return;\r
575 }\r
576\r
577 if (doc.readyState === 'complete') {\r
578 // Loaded AFTER initial document write/load...\r
579 Ready.onReadyEvent({\r
580 type: 'already ' + (doc.readyState || 'body')\r
581 });\r
582 } else {\r
583 doc.attachEvent('onreadystatechange', Ready.onReadyStateChange);\r
584 window.attachEvent('onload', Ready.onReadyEvent);\r
585 Ready.bound = 1;\r
586 }\r
587 },\r
588\r
589 unbind : function () {\r
590 document.detachEvent('onreadystatechange', Ready.onReadyStateChange);\r
591 window.detachEvent('onload', Ready.onReadyEvent);\r
592\r
593 if (Ext.isNumber(Ready.scrollTimer)) {\r
594 clearTimeout(Ready.scrollTimer);\r
595 Ready.scrollTimer = null;\r
596 }\r
597 },\r
598\r
599 /**\r
600 * This event handler is called when the readyState changes.\r
601 * @private\r
602 */\r
603 onReadyStateChange: function() {\r
604 var state = document.readyState;\r
605\r
606 if (Ready.readyStatesRe.test(state)) {\r
607 Ready.onReadyEvent({\r
608 type: state\r
609 });\r
610 }\r
611 }\r
612 });\r
613 }\r
614 //</feature>\r
615\r
616 /**\r
617 * @property {Boolean} isDomReady\r
618 * `true` when the document body is ready for use.\r
619 * @member Ext\r
620 * @readonly\r
621 */\r
622\r
623 /**\r
624 * @property {Boolean} isReady\r
625 * `true` when `isDomReady` is true and the Framework is ready for use.\r
626 * @member Ext\r
627 * @readonly\r
628 */\r
629\r
630 /**\r
631 * @method onDocumentReady\r
632 * @member Ext\r
633 * Adds a listener to be notified when the document is ready (before onload and before\r
634 * images are loaded).\r
635 *\r
636 * @param {Function} fn The method to call.\r
637 * @param {Object} [scope] The scope (`this` reference) in which the handler function\r
638 * executes. Defaults to the browser window.\r
639 * @param {Object} [options] An object with extra options.\r
640 * @param {Number} [options.delay=0] A number of milliseconds to delay.\r
641 * @param {Number} [options.priority=0] Relative priority of this callback. A larger\r
642 * number will result in the callback being sorted before the others. Priorities\r
643 * 1000 or greater and -1000 or lesser are reserved for internal framework use only.\r
644 * @private\r
645 */\r
646 Ext.onDocumentReady = function (fn, scope, options) {\r
647 var opt = {\r
648 dom: true\r
649 };\r
650\r
651 if (options) {\r
652 Ext.apply(opt, options);\r
653 }\r
654\r
655 Ready.on(fn, scope, opt);\r
656 };\r
657\r
658 /**\r
659 * @method onReady\r
660 * @member Ext\r
661 * Adds a listener to be notified when the document is ready (before onload and before\r
662 * images are loaded).\r
663 *\r
664 * @param {Function} fn The method to call.\r
665 * @param {Object} [scope] The scope (`this` reference) in which the handler function\r
666 * executes. Defaults to the browser window.\r
667 * @param {Object} [options] An object with extra options.\r
668 * @param {Number} [options.delay=0] A number of milliseconds to delay.\r
669 * @param {Number} [options.priority=0] Relative priority of this callback. A larger\r
670 * number will result in the callback being sorted before the others. Priorities\r
671 * 1000 or greater and -1000 or lesser are reserved for internal framework use only.\r
672 * @param {Boolean} [options.dom=false] Pass `true` to only wait for DOM ready, `false`\r
673 * means full Framework and DOM readiness.\r
674 * numbers are reserved.\r
675 */\r
676 Ext.onReady = function (fn, scope, options) {\r
677 Ready.on(fn, scope, options);\r
678 };\r
679\r
680 // A shortcut method for onReady with a high priority\r
681 Ext.onInternalReady = function(fn, scope, options) {\r
682 Ready.on(fn, scope, Ext.apply({\r
683 priority: 1000\r
684 }, options));\r
685 }\r
686\r
687 Ready.bind();\r
688}());\r