1 |
|
2 | define([
|
3 | 'require',
|
4 | 'exports',
|
5 | 'module',
|
6 | './synthetic',
|
7 | './typeable',
|
8 | './browsers'
|
9 | ], function (require, exports, module) {
|
10 | var syn = require('./synthetic');
|
11 | require('./typeable');
|
12 | require('./browsers');
|
13 | var h = syn.helpers, formElExp = /input|textarea/i, supportsSelection = function (el) {
|
14 | var result;
|
15 | try {
|
16 | result = el.selectionStart !== undefined && el.selectionStart !== null;
|
17 | } catch (e) {
|
18 | result = false;
|
19 | }
|
20 | return result;
|
21 | }, getSelection = function (el) {
|
22 | var real, r, start;
|
23 | if (supportsSelection(el)) {
|
24 | if (document.activeElement && document.activeElement !== el && el.selectionStart === el.selectionEnd && el.selectionStart === 0) {
|
25 | return {
|
26 | start: el.value.length,
|
27 | end: el.value.length
|
28 | };
|
29 | }
|
30 | return {
|
31 | start: el.selectionStart,
|
32 | end: el.selectionEnd
|
33 | };
|
34 | } else {
|
35 | try {
|
36 | if (el.nodeName.toLowerCase() === 'input') {
|
37 | real = h.getWindow(el).document.selection.createRange();
|
38 | r = el.createTextRange();
|
39 | r.setEndPoint('EndToStart', real);
|
40 | start = r.text.length;
|
41 | return {
|
42 | start: start,
|
43 | end: start + real.text.length
|
44 | };
|
45 | } else {
|
46 | real = h.getWindow(el).document.selection.createRange();
|
47 | r = real.duplicate();
|
48 | var r2 = real.duplicate(), r3 = real.duplicate();
|
49 | r2.collapse();
|
50 | r3.collapse(false);
|
51 | r2.moveStart('character', -1);
|
52 | r3.moveStart('character', -1);
|
53 | r.moveToElementText(el);
|
54 | r.setEndPoint('EndToEnd', real);
|
55 | start = r.text.length - real.text.length;
|
56 | var end = r.text.length;
|
57 | if (start !== 0 && r2.text === '') {
|
58 | start += 2;
|
59 | }
|
60 | if (end !== 0 && r3.text === '') {
|
61 | end += 2;
|
62 | }
|
63 | return {
|
64 | start: start,
|
65 | end: end
|
66 | };
|
67 | }
|
68 | } catch (e) {
|
69 | var prop = formElExp.test(el.nodeName) ? 'value' : 'textContent';
|
70 | return {
|
71 | start: el[prop].length,
|
72 | end: el[prop].length
|
73 | };
|
74 | }
|
75 | }
|
76 | }, getFocusable = function (el) {
|
77 | var document = h.getWindow(el).document, res = [];
|
78 | var els = document.getElementsByTagName('*'), len = els.length;
|
79 | for (var i = 0; i < len; i++) {
|
80 | if (syn.isFocusable(els[i]) && els[i] !== document.documentElement) {
|
81 | res.push(els[i]);
|
82 | }
|
83 | }
|
84 | return res;
|
85 | }, textProperty = function () {
|
86 | var el = document.createElement('span');
|
87 | return el.textContent != null ? 'textContent' : 'innerText';
|
88 | }(), getText = function (el) {
|
89 | if (formElExp.test(el.nodeName)) {
|
90 | return el.value;
|
91 | }
|
92 | return el[textProperty];
|
93 | }, setText = function (el, value) {
|
94 | if (formElExp.test(el.nodeName)) {
|
95 | el.value = value;
|
96 | } else {
|
97 | el[textProperty] = value;
|
98 | }
|
99 | };
|
100 | h.extend(syn, {
|
101 | keycodes: {
|
102 | '\b': 8,
|
103 | '\t': 9,
|
104 | '\r': 13,
|
105 | 'shift': 16,
|
106 | 'ctrl': 17,
|
107 | 'alt': 18,
|
108 | 'meta': 91,
|
109 | 'pause-break': 19,
|
110 | 'caps': 20,
|
111 | 'escape': 27,
|
112 | 'num-lock': 144,
|
113 | 'scroll-lock': 145,
|
114 | 'print': 44,
|
115 | 'page-up': 33,
|
116 | 'page-down': 34,
|
117 | 'end': 35,
|
118 | 'home': 36,
|
119 | 'left': 37,
|
120 | 'up': 38,
|
121 | 'right': 39,
|
122 | 'down': 40,
|
123 | 'insert': 45,
|
124 | 'delete': 46,
|
125 | ' ': 32,
|
126 | '0': 48,
|
127 | '1': 49,
|
128 | '2': 50,
|
129 | '3': 51,
|
130 | '4': 52,
|
131 | '5': 53,
|
132 | '6': 54,
|
133 | '7': 55,
|
134 | '8': 56,
|
135 | '9': 57,
|
136 | 'a': 65,
|
137 | 'b': 66,
|
138 | 'c': 67,
|
139 | 'd': 68,
|
140 | 'e': 69,
|
141 | 'f': 70,
|
142 | 'g': 71,
|
143 | 'h': 72,
|
144 | 'i': 73,
|
145 | 'j': 74,
|
146 | 'k': 75,
|
147 | 'l': 76,
|
148 | 'm': 77,
|
149 | 'n': 78,
|
150 | 'o': 79,
|
151 | 'p': 80,
|
152 | 'q': 81,
|
153 | 'r': 82,
|
154 | 's': 83,
|
155 | 't': 84,
|
156 | 'u': 85,
|
157 | 'v': 86,
|
158 | 'w': 87,
|
159 | 'x': 88,
|
160 | 'y': 89,
|
161 | 'z': 90,
|
162 | 'num0': 96,
|
163 | 'num1': 97,
|
164 | 'num2': 98,
|
165 | 'num3': 99,
|
166 | 'num4': 100,
|
167 | 'num5': 101,
|
168 | 'num6': 102,
|
169 | 'num7': 103,
|
170 | 'num8': 104,
|
171 | 'num9': 105,
|
172 | '*': 106,
|
173 | '+': 107,
|
174 | 'subtract': 109,
|
175 | 'decimal': 110,
|
176 | 'divide': 111,
|
177 | ';': 186,
|
178 | '=': 187,
|
179 | ',': 188,
|
180 | 'dash': 189,
|
181 | '-': 189,
|
182 | 'period': 190,
|
183 | '.': 190,
|
184 | 'forward-slash': 191,
|
185 | '/': 191,
|
186 | '`': 192,
|
187 | '[': 219,
|
188 | '\\': 220,
|
189 | ']': 221,
|
190 | '\'': 222,
|
191 | 'left window key': 91,
|
192 | 'right window key': 92,
|
193 | 'select key': 93,
|
194 | 'f1': 112,
|
195 | 'f2': 113,
|
196 | 'f3': 114,
|
197 | 'f4': 115,
|
198 | 'f5': 116,
|
199 | 'f6': 117,
|
200 | 'f7': 118,
|
201 | 'f8': 119,
|
202 | 'f9': 120,
|
203 | 'f10': 121,
|
204 | 'f11': 122,
|
205 | 'f12': 123
|
206 | },
|
207 | selectText: function (el, start, end) {
|
208 | if (supportsSelection(el)) {
|
209 | if (!end) {
|
210 | syn.__tryFocus(el);
|
211 | el.setSelectionRange(start, start);
|
212 | } else {
|
213 | el.selectionStart = start;
|
214 | el.selectionEnd = end;
|
215 | }
|
216 | } else if (el.createTextRange) {
|
217 | var r = el.createTextRange();
|
218 | r.moveStart('character', start);
|
219 | end = end || start;
|
220 | r.moveEnd('character', end - el.value.length);
|
221 | r.select();
|
222 | }
|
223 | },
|
224 | getText: function (el) {
|
225 | if (syn.typeable.test(el)) {
|
226 | var sel = getSelection(el);
|
227 | return el.value.substring(sel.start, sel.end);
|
228 | }
|
229 | var win = syn.helpers.getWindow(el);
|
230 | if (win.getSelection) {
|
231 | return win.getSelection().toString();
|
232 | } else if (win.document.getSelection) {
|
233 | return win.document.getSelection().toString();
|
234 | } else {
|
235 | return win.document.selection.createRange().text;
|
236 | }
|
237 | },
|
238 | getSelection: getSelection
|
239 | });
|
240 | h.extend(syn.key, {
|
241 | data: function (key) {
|
242 | if (syn.key.browser[key]) {
|
243 | return syn.key.browser[key];
|
244 | }
|
245 | for (var kind in syn.key.kinds) {
|
246 | if (h.inArray(key, syn.key.kinds[kind]) > -1) {
|
247 | return syn.key.browser[kind];
|
248 | }
|
249 | }
|
250 | return syn.key.browser.character;
|
251 | },
|
252 | isSpecial: function (keyCode) {
|
253 | var specials = syn.key.kinds.special;
|
254 | for (var i = 0; i < specials.length; i++) {
|
255 | if (syn.keycodes[specials[i]] === keyCode) {
|
256 | return specials[i];
|
257 | }
|
258 | }
|
259 | },
|
260 | options: function (key, event) {
|
261 | var keyData = syn.key.data(key);
|
262 | if (!keyData[event]) {
|
263 | return null;
|
264 | }
|
265 | var charCode = keyData[event][0], keyCode = keyData[event][1], result = {};
|
266 | if (keyCode === 'key') {
|
267 | result.keyCode = syn.keycodes[key];
|
268 | } else if (keyCode === 'char') {
|
269 | result.keyCode = key.charCodeAt(0);
|
270 | } else {
|
271 | result.keyCode = keyCode;
|
272 | }
|
273 | if (charCode === 'char') {
|
274 | result.charCode = key.charCodeAt(0);
|
275 | } else if (charCode !== null) {
|
276 | result.charCode = charCode;
|
277 | }
|
278 | if (result.keyCode) {
|
279 | result.which = result.keyCode;
|
280 | } else {
|
281 | result.which = result.charCode;
|
282 | }
|
283 | return result;
|
284 | },
|
285 | kinds: {
|
286 | special: [
|
287 | 'shift',
|
288 | 'ctrl',
|
289 | 'alt',
|
290 | 'meta',
|
291 | 'caps'
|
292 | ],
|
293 | specialChars: ['\b'],
|
294 | navigation: [
|
295 | 'page-up',
|
296 | 'page-down',
|
297 | 'end',
|
298 | 'home',
|
299 | 'left',
|
300 | 'up',
|
301 | 'right',
|
302 | 'down',
|
303 | 'insert',
|
304 | 'delete'
|
305 | ],
|
306 | 'function': [
|
307 | 'f1',
|
308 | 'f2',
|
309 | 'f3',
|
310 | 'f4',
|
311 | 'f5',
|
312 | 'f6',
|
313 | 'f7',
|
314 | 'f8',
|
315 | 'f9',
|
316 | 'f10',
|
317 | 'f11',
|
318 | 'f12'
|
319 | ]
|
320 | },
|
321 | getDefault: function (key) {
|
322 | if (syn.key.defaults[key]) {
|
323 | return syn.key.defaults[key];
|
324 | }
|
325 | for (var kind in syn.key.kinds) {
|
326 | if (h.inArray(key, syn.key.kinds[kind]) > -1 && syn.key.defaults[kind]) {
|
327 | return syn.key.defaults[kind];
|
328 | }
|
329 | }
|
330 | return syn.key.defaults.character;
|
331 | },
|
332 | defaults: {
|
333 | 'character': function (options, scope, key, force, sel) {
|
334 | if (/num\d+/.test(key)) {
|
335 | key = key.match(/\d+/)[0];
|
336 | }
|
337 | if (force || !syn.support.keyCharacters && syn.typeable.test(this)) {
|
338 | var current = getText(this), before = current.substr(0, sel.start), after = current.substr(sel.end), character = key;
|
339 | setText(this, before + character + after);
|
340 | var charLength = character === '\n' && syn.support.textareaCarriage ? 2 : character.length;
|
341 | syn.selectText(this, before.length + charLength);
|
342 | }
|
343 | },
|
344 | 'c': function (options, scope, key, force, sel) {
|
345 | if (syn.key.ctrlKey) {
|
346 | syn.key.clipboard = syn.getText(this);
|
347 | } else {
|
348 | syn.key.defaults.character.apply(this, arguments);
|
349 | }
|
350 | },
|
351 | 'v': function (options, scope, key, force, sel) {
|
352 | if (syn.key.ctrlKey) {
|
353 | syn.key.defaults.character.call(this, options, scope, syn.key.clipboard, true, sel);
|
354 | } else {
|
355 | syn.key.defaults.character.apply(this, arguments);
|
356 | }
|
357 | },
|
358 | 'a': function (options, scope, key, force, sel) {
|
359 | if (syn.key.ctrlKey) {
|
360 | syn.selectText(this, 0, getText(this).length);
|
361 | } else {
|
362 | syn.key.defaults.character.apply(this, arguments);
|
363 | }
|
364 | },
|
365 | 'home': function () {
|
366 | syn.onParents(this, function (el) {
|
367 | if (el.scrollHeight !== el.clientHeight) {
|
368 | el.scrollTop = 0;
|
369 | return false;
|
370 | }
|
371 | });
|
372 | },
|
373 | 'end': function () {
|
374 | syn.onParents(this, function (el) {
|
375 | if (el.scrollHeight !== el.clientHeight) {
|
376 | el.scrollTop = el.scrollHeight;
|
377 | return false;
|
378 | }
|
379 | });
|
380 | },
|
381 | 'page-down': function () {
|
382 | syn.onParents(this, function (el) {
|
383 | if (el.scrollHeight !== el.clientHeight) {
|
384 | var ch = el.clientHeight;
|
385 | el.scrollTop += ch;
|
386 | return false;
|
387 | }
|
388 | });
|
389 | },
|
390 | 'page-up': function () {
|
391 | syn.onParents(this, function (el) {
|
392 | if (el.scrollHeight !== el.clientHeight) {
|
393 | var ch = el.clientHeight;
|
394 | el.scrollTop -= ch;
|
395 | return false;
|
396 | }
|
397 | });
|
398 | },
|
399 | '\b': function (options, scope, key, force, sel) {
|
400 | if (!syn.support.backspaceWorks && syn.typeable.test(this)) {
|
401 | var current = getText(this), before = current.substr(0, sel.start), after = current.substr(sel.end);
|
402 | if (sel.start === sel.end && sel.start > 0) {
|
403 | setText(this, before.substring(0, before.length - 1) + after);
|
404 | syn.selectText(this, sel.start - 1);
|
405 | } else {
|
406 | setText(this, before + after);
|
407 | syn.selectText(this, sel.start);
|
408 | }
|
409 | }
|
410 | },
|
411 | 'delete': function (options, scope, key, force, sel) {
|
412 | if (!syn.support.backspaceWorks && syn.typeable.test(this)) {
|
413 | var current = getText(this), before = current.substr(0, sel.start), after = current.substr(sel.end);
|
414 | if (sel.start === sel.end && sel.start <= getText(this).length - 1) {
|
415 | setText(this, before + after.substring(1));
|
416 | } else {
|
417 | setText(this, before + after);
|
418 | }
|
419 | syn.selectText(this, sel.start);
|
420 | }
|
421 | },
|
422 | '\r': function (options, scope, key, force, sel) {
|
423 | var nodeName = this.nodeName.toLowerCase();
|
424 | if (nodeName === 'input') {
|
425 | syn.trigger(this, 'change', {});
|
426 | }
|
427 | if (!syn.support.keypressSubmits && nodeName === 'input') {
|
428 | var form = syn.closest(this, 'form');
|
429 | if (form) {
|
430 | syn.trigger(form, 'submit', {});
|
431 | }
|
432 | }
|
433 | if (!syn.support.keyCharacters && nodeName === 'textarea') {
|
434 | syn.key.defaults.character.call(this, options, scope, '\n', undefined, sel);
|
435 | }
|
436 | if (!syn.support.keypressOnAnchorClicks && nodeName === 'a') {
|
437 | syn.trigger(this, 'click', {});
|
438 | }
|
439 | },
|
440 | '\t': function (options, scope) {
|
441 | var focusEls = getFocusable(this), current = null, i = 0, el, firstNotIndexed, orders = [];
|
442 | for (; i < focusEls.length; i++) {
|
443 | orders.push([
|
444 | focusEls[i],
|
445 | i
|
446 | ]);
|
447 | }
|
448 | var sort = function (order1, order2) {
|
449 | var el1 = order1[0], el2 = order2[0], tab1 = syn.tabIndex(el1) || 0, tab2 = syn.tabIndex(el2) || 0;
|
450 | if (tab1 === tab2) {
|
451 | return order1[1] - order2[1];
|
452 | } else {
|
453 | if (tab1 === 0) {
|
454 | return 1;
|
455 | } else if (tab2 === 0) {
|
456 | return -1;
|
457 | } else {
|
458 | return tab1 - tab2;
|
459 | }
|
460 | }
|
461 | };
|
462 | orders.sort(sort);
|
463 | var ordersLength = orders.length;
|
464 | for (i = 0; i < ordersLength; i++) {
|
465 | el = orders[i][0];
|
466 | if (this === el) {
|
467 | var nextIndex = i;
|
468 | if (syn.key.shiftKey) {
|
469 | nextIndex--;
|
470 | current = nextIndex >= 0 && orders[nextIndex][0] || orders[ordersLength - 1][0];
|
471 | } else {
|
472 | nextIndex++;
|
473 | current = nextIndex < ordersLength && orders[nextIndex][0] || orders[0][0];
|
474 | }
|
475 | }
|
476 | }
|
477 | if (!current) {
|
478 | current = firstNotIndexed;
|
479 | } else {
|
480 | syn.__tryFocus(current);
|
481 | }
|
482 | return current;
|
483 | },
|
484 | 'left': function (options, scope, key, force, sel) {
|
485 | if (syn.typeable.test(this)) {
|
486 | if (syn.key.shiftKey) {
|
487 | syn.selectText(this, sel.start === 0 ? 0 : sel.start - 1, sel.end);
|
488 | } else {
|
489 | syn.selectText(this, sel.start === 0 ? 0 : sel.start - 1);
|
490 | }
|
491 | }
|
492 | },
|
493 | 'right': function (options, scope, key, force, sel) {
|
494 | if (syn.typeable.test(this)) {
|
495 | if (syn.key.shiftKey) {
|
496 | syn.selectText(this, sel.start, sel.end + 1 > getText(this).length ? getText(this).length : sel.end + 1);
|
497 | } else {
|
498 | syn.selectText(this, sel.end + 1 > getText(this).length ? getText(this).length : sel.end + 1);
|
499 | }
|
500 | }
|
501 | },
|
502 | 'up': function () {
|
503 | if (/select/i.test(this.nodeName)) {
|
504 | this.selectedIndex = this.selectedIndex ? this.selectedIndex - 1 : 0;
|
505 | }
|
506 | },
|
507 | 'down': function () {
|
508 | if (/select/i.test(this.nodeName)) {
|
509 | syn.changeOnBlur(this, 'selectedIndex', this.selectedIndex);
|
510 | this.selectedIndex = this.selectedIndex + 1;
|
511 | }
|
512 | },
|
513 | 'shift': function () {
|
514 | return null;
|
515 | },
|
516 | 'ctrl': function () {
|
517 | return null;
|
518 | },
|
519 | 'alt': function () {
|
520 | return null;
|
521 | },
|
522 | 'meta': function () {
|
523 | return null;
|
524 | }
|
525 | }
|
526 | });
|
527 | h.extend(syn.create, {
|
528 | keydown: {
|
529 | setup: function (type, options, element) {
|
530 | if (h.inArray(options, syn.key.kinds.special) !== -1) {
|
531 | syn.key[options + 'Key'] = element;
|
532 | }
|
533 | }
|
534 | },
|
535 | keypress: {
|
536 | setup: function (type, options, element) {
|
537 | if (syn.support.keyCharacters && !syn.support.keysOnNotFocused) {
|
538 | syn.__tryFocus(element);
|
539 | }
|
540 | }
|
541 | },
|
542 | keyup: {
|
543 | setup: function (type, options, element) {
|
544 | if (h.inArray(options, syn.key.kinds.special) !== -1) {
|
545 | syn.key[options + 'Key'] = null;
|
546 | }
|
547 | }
|
548 | },
|
549 | key: {
|
550 | options: function (type, options, element) {
|
551 | options = typeof options !== 'object' ? { character: options } : options;
|
552 | options = h.extend({}, options);
|
553 | if (options.character) {
|
554 | h.extend(options, syn.key.options(options.character, type));
|
555 | delete options.character;
|
556 | }
|
557 | options = h.extend({
|
558 | ctrlKey: !!syn.key.ctrlKey,
|
559 | altKey: !!syn.key.altKey,
|
560 | shiftKey: !!syn.key.shiftKey,
|
561 | metaKey: !!syn.key.metaKey
|
562 | }, options);
|
563 | return options;
|
564 | },
|
565 | event: function (type, options, element) {
|
566 | var doc = h.getWindow(element).document || document, event;
|
567 | if (doc.createEvent) {
|
568 | try {
|
569 | event = doc.createEvent('KeyEvents');
|
570 | event.initKeyEvent(type, true, true, window, options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.keyCode, options.charCode);
|
571 | } catch (e) {
|
572 | event = h.createBasicStandardEvent(type, options, doc);
|
573 | }
|
574 | event.synthetic = true;
|
575 | return event;
|
576 | } else {
|
577 | try {
|
578 | event = h.createEventObject.apply(this, arguments);
|
579 | h.extend(event, options);
|
580 | } catch (e) {
|
581 | }
|
582 | return event;
|
583 | }
|
584 | }
|
585 | }
|
586 | });
|
587 | var convert = {
|
588 | 'enter': '\r',
|
589 | 'backspace': '\b',
|
590 | 'tab': '\t',
|
591 | 'space': ' '
|
592 | };
|
593 | h.extend(syn.init.prototype, {
|
594 | _key: function (element, options, callback) {
|
595 | if (/-up$/.test(options) && h.inArray(options.replace('-up', ''), syn.key.kinds.special) !== -1) {
|
596 | syn.trigger(element, 'keyup', options.replace('-up', ''));
|
597 | return callback(true, element);
|
598 | }
|
599 | var activeElement = h.getWindow(element).document.activeElement, caret = syn.typeable.test(element) && getSelection(element), key = convert[options] || options, runDefaults = syn.trigger(element, 'keydown', key), getDefault = syn.key.getDefault, prevent = syn.key.browser.prevent, defaultResult, keypressOptions = syn.key.options(key, 'keypress');
|
600 | if (runDefaults) {
|
601 | if (!keypressOptions) {
|
602 | defaultResult = getDefault(key).call(element, keypressOptions, h.getWindow(element), key, undefined, caret);
|
603 | } else {
|
604 | if (activeElement !== h.getWindow(element).document.activeElement) {
|
605 | element = h.getWindow(element).document.activeElement;
|
606 | }
|
607 | runDefaults = syn.trigger(element, 'keypress', keypressOptions);
|
608 | if (runDefaults) {
|
609 | defaultResult = getDefault(key).call(element, keypressOptions, h.getWindow(element), key, undefined, caret);
|
610 | }
|
611 | }
|
612 | } else {
|
613 | if (keypressOptions && h.inArray('keypress', prevent.keydown) === -1) {
|
614 | if (activeElement !== h.getWindow(element).document.activeElement) {
|
615 | element = h.getWindow(element).document.activeElement;
|
616 | }
|
617 | syn.trigger(element, 'keypress', keypressOptions);
|
618 | }
|
619 | }
|
620 | if (defaultResult && defaultResult.nodeName) {
|
621 | element = defaultResult;
|
622 | }
|
623 | if (defaultResult !== null) {
|
624 | syn.schedule(function () {
|
625 | if (key === '\r' && element.nodeName.toLowerCase() === 'input') {
|
626 | } else if (syn.support.oninput) {
|
627 | syn.trigger(element, 'input', syn.key.options(key, 'input'));
|
628 | }
|
629 | syn.trigger(element, 'keyup', syn.key.options(key, 'keyup'));
|
630 | callback(runDefaults, element);
|
631 | }, 1);
|
632 | } else {
|
633 | callback(runDefaults, element);
|
634 | }
|
635 | return element;
|
636 | },
|
637 | _type: function (element, options, callback) {
|
638 | var parts = (options + '').match(/(\[[^\]]+\])|([^\[])/g), self = this, runNextPart = function (runDefaults, el) {
|
639 | var part = parts.shift();
|
640 | if (!part) {
|
641 | callback(runDefaults, el);
|
642 | return;
|
643 | }
|
644 | el = el || element;
|
645 | if (part.length > 1) {
|
646 | part = part.substr(1, part.length - 2);
|
647 | }
|
648 | self._key(el, part, runNextPart);
|
649 | };
|
650 | runNextPart();
|
651 | }
|
652 | });
|
653 | }); |
\ | No newline at end of file |