0a6ee174c218b5e3a09f3fb5f7f0c5cf29fb466e
[Packages/TYPO3.CMS.git] / typo3 / sysext / t3editor / Resources / Public / JavaScript / Plugins / CodeCompletion / TsCodeCompletion.js
1 /*
2 * This file is part of the TYPO3 CMS project.
3 *
4 * It is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, either version 2
6 * of the License, or any later version.
7 *
8 * For the full copyright and license information, please read the
9 * LICENSE.txt file that was distributed with this source code.
10 *
11 * The TYPO3 project - inspiring people to share!
12 */
13
14 /**
15 * Module: TYPO3/CMS/T3editor/CodeCompletion/TsCodeCompletion
16 * Contains the TsCodeCompletion class
17 */
18 define([
19 'jquery',
20 'TYPO3/CMS/T3editor/Plugins/CodeCompletion/TsRef',
21 'TYPO3/CMS/T3editor/Plugins/CodeCompletion/TsParser',
22 'TYPO3/CMS/T3editor/Plugins/CodeCompletion/CompletionResult'
23 ], function ($, TsRef, TsParser, CompletionResult) {
24 /**
25 *
26 * @type {{tsRef: *, outerDiv: null, options: {ccWords: number}, index: number, currWord: number, cc_up: null, cc_down: null, mousePos: {x: number, y: number}, proposals: null, compResult: null, cc: number, linefeedsPrepared: boolean, currentCursorPosition: null, extTsObjTree: {}, latestCursorNode: null, codemirror: null, parser: null, plugins: string[], $codeCompleteBox: (*|jQuery)}}
27 * @exports TYPO3/CMS/T3editor/CodeCompletion/TsCodeCompletion
28 */
29 var TsCodeCompletion = {
30 tsRef: TsRef,
31 outerDiv: null,
32 options: {
33 ccWords : 10
34 },
35 index: 0,
36 currWord: 0,
37 cc_up: null,
38 cc_down: null,
39 mousePos: {
40 x:0,
41 y:0
42 },
43 proposals: null,
44 compResult: null,
45 cc: 0,
46 linefeedsPrepared: false,
47 currentCursorPosition: null,
48 extTsObjTree: {},
49 latestCursorNode: null,
50 codemirror: null,
51 parser: null,
52 plugins: [
53 'TYPO3/CMS/T3editor/Plugins/CodeCompletion/DescriptionPlugin'
54 ],
55 $codeCompleteBox: $('<div />', {class: 't3e_codeCompleteWrap'}).append(
56 $('<div />', {class: 't3e_codeCompleteBox'})
57 )
58 };
59
60 /**
61 * All external templates along the rootline have to be loaded,
62 * this function retrieves the JSON code by comitting a AJAX request
63 */
64 TsCodeCompletion.loadExtTemplatesAsync = function() {
65 var id = TsCodeCompletion.getGetVar('id');
66 if (id === '') {
67 return;
68 }
69 $.ajax({
70 url: TYPO3.settings.ajaxUrls['t3editor_codecompletion_loadtemplates'],
71 data: {
72 pageId: id
73 },
74 success: function(response) {
75 TsCodeCompletion.extTsObjTree.c = response;
76 TsCodeCompletion.resolveExtReferencesRec(TsCodeCompletion.extTsObjTree.c);
77 }
78 });
79 };
80
81 /**
82 * Load registered plugins
83 */
84 TsCodeCompletion.loadPluginArray = function() {
85 $.ajax({
86 url: TYPO3.settings.ajaxUrls['t3editor_get_plugins'],
87 success: function(response) {
88 TsCodeCompletion.plugins = $.merge(TsCodeCompletion.plugins, response);
89 // register an internal plugin
90 TsCodeCompletion.loadPlugins();
91 }
92 });
93 };
94
95 /**
96 * Load and initialize the plugins fetched by TsCodeCompletion.loadPluginArray()
97 */
98 TsCodeCompletion.loadPlugins = function() {
99 for (var i = 0; i < TsCodeCompletion.plugins.length; i++) {
100 require([TsCodeCompletion.plugins[i]], function(plugin) {
101 if (typeof plugin.init === 'function') {
102 plugin.init({
103 tsRef: TsCodeCompletion.tsRef,
104 codeCompleteBox: TsCodeCompletion.$codeCompleteBox,
105 codemirror: TsCodeCompletion.codemirror
106 });
107 } else {
108 console.warn('Cannot initialize plugin ' + TsCodeCompletion.plugins[i] + ', missing "init" method');
109 }
110 });
111 }
112 };
113
114 /**
115 * Get the value of a given GET parameter
116 *
117 * @param {String} name
118 * @return {String}
119 */
120 TsCodeCompletion.getGetVar = function(name) {
121 var get_string = document.location.search,
122 return_value = '',
123 value;
124
125 do { //This loop is made to catch all instances of any get variable.
126 var name_index = get_string.indexOf(name + '=');
127 if (name_index !== -1) {
128 get_string = get_string.substr(name_index + name.length + 1, get_string.length - name_index);
129 var end_of_value = get_string.indexOf('&');
130 if (end_of_value !== -1) {
131 value = get_string.substr(0, end_of_value);
132 } else {
133 value = get_string;
134 }
135
136 if (return_value === '' || value === '') {
137 return_value += value;
138 } else {
139 return_value += ', ' + value;
140 }
141 }
142 } while (name_index !== -1);
143
144 // Restores all the blank spaces.
145 var space = return_value.indexOf('+');
146 while (space !== -1) {
147 return_value = return_value.substr(0, space) + ' ' + return_value.substr(space + 1, return_value.length);
148 space = return_value.indexOf('+');
149 }
150
151 return return_value;
152 };
153
154 /**
155 * Since the references are not resolved server side we have to do it client-side
156 * Benefit: less loading time due to less data which has to be transmitted
157 *
158 * @param {Array} childNodes
159 */
160 TsCodeCompletion.resolveExtReferencesRec = function(childNodes) {
161 for (var key in childNodes) {
162 var childNode;
163 // if the childnode has a value and there is a part of a reference operator ('<')
164 // and it does not look like a html tag ('>')
165 if (childNodes[key].v && childNodes[key].v[0] === '<' && childNodes[key].v.indexOf('>') === -1 ) {
166 var path = $.trim(childNodes[key].v.replace(/</, ''));
167 // if there are still whitespaces it's no path
168 if (path.indexOf(' ') === -1) {
169 childNode = TsCodeCompletion.getExtChildNode(path);
170 // if the node was found - reference it
171 if (childNode !== null) {
172 childNodes[key] = childNode;
173 }
174 }
175 }
176 // if there was no reference-resolving then we go deeper into the tree
177 if (!childNode && childNodes[key].c) {
178 TsCodeCompletion.resolveExtReferencesRec(childNodes[key].c);
179 }
180 }
181 };
182
183 /**
184 * Get the child node of given path
185 *
186 * @param {String} path
187 * @returns {Object}
188 */
189 TsCodeCompletion.getExtChildNode = function(path) {
190 var extTree = TsCodeCompletion.extTsObjTree,
191 path = path.split('.'),
192 pathSeg;
193
194 for (var i = 0; i < path.length; i++) {
195 pathSeg = path[i];
196 if (typeof extTree.c === 'undefined' || typeof extTree.c[pathSeg] === 'undefined') {
197 return null;
198 }
199 extTree = extTree.c[pathSeg];
200 }
201 return extTree;
202 };
203
204 /**
205 * Replaces editor functions insertNewlineAtCursor and indentAtCursor
206 * with modified ones that only execute when codecompletion box is not shown
207 * @todo check if this works correctly after updating the codemirror base
208 */
209 TsCodeCompletion.prepareLinefeeds = function() {
210 TsCodeCompletion.codemirror.win.select.insertNewlineAtCursor_original = TsCodeCompletion.codemirror.win.select.insertNewlineAtCursor;
211 TsCodeCompletion.codemirror.win.select.insertNewlineAtCursor = function(window) {
212 if (TsCodeCompletion.cc === 0) {
213 TsCodeCompletion.codemirror.win.select.insertNewlineAtCursor_original(window);
214 }
215 };
216 TsCodeCompletion.codemirror.editor.indentAtCursor_original = TsCodeCompletion.codemirror.editor.indentAtCursor;
217 TsCodeCompletion.codemirror.editor.indentAtCursor = function() {
218 if (TsCodeCompletion.cc === 0) {
219 TsCodeCompletion.codemirror.editor.indentAtCursor_original();
220 }
221 };
222 TsCodeCompletion.linefeedsPrepared = true;
223 };
224
225 /**
226 *
227 */
228 TsCodeCompletion.click = function() {
229 TsCodeCompletion.endAutoCompletion();
230 };
231
232 /**
233 *
234 * @param cursorNode
235 * @returns {*}
236 */
237 TsCodeCompletion.getFilter = function(cursorNode) {
238 if (cursorNode.currentText) {
239 var filter = cursorNode.currentText.replace('.', '');
240 return filter.replace(/\s/g, '');
241 }
242 return '';
243 };
244
245 /**
246 * @returns {*}
247 */
248 TsCodeCompletion.getCursorNode = function() {
249 var cursorNode = TsCodeCompletion.codemirror.win.select.selectionTopNode(TsCodeCompletion.codemirror.win.document.body, false);
250 // cursorNode is null if the cursor is positioned at the beginning of the first line
251 if (cursorNode === null) {
252 cursorNode = TsCodeCompletion.codemirror.editor.container.firstChild;
253 } else if (cursorNode.tagName === 'BR') {
254 // if cursor is at the end of the line -> jump to beginning of the next line
255 cursorNode = cursorNode.nextSibling;
256 }
257 return cursorNode;
258 };
259
260 /**
261 *
262 * @param {Object} cursor
263 * @returns {String}
264 */
265 TsCodeCompletion.getCurrentLine = function(cursor) {
266 var line = '',
267 currentNode = cursor.start.node.parentNode;
268
269 while (currentNode.tagName !== 'BR') {
270 if (currentNode.hasChildNodes()
271 && currentNode.firstChild.nodeType === 3
272 && currentNode.currentText.length > 0)
273 {
274 line = currentNode.currentText + line;
275 }
276 if (typeof currentNode.previousSibling === 'undefined') {
277 break;
278 } else {
279 currentNode = currentNode.previousSibling;
280 }
281 }
282 return line;
283 };
284
285 /**
286 * Eventhandler function executed after keystroke release
287 * triggers CC on pressed dot and typing on
288 *
289 * @param {Event} e fired prototype event object
290 * @type void
291 */
292 TsCodeCompletion.keyUp = function(e) {
293 // 190 = .
294 if (e.which === 190) {
295 TsCodeCompletion.initCodeCompletion();
296 TsCodeCompletion.refreshCodeCompletion();
297 } else if (TsCodeCompletion.cc === 1) {
298 // 38 = KEYUP, 40 = KEYDOWN
299 if (e.which !== 40 && e.which !== 38) {
300 if (e.which === 13) {
301 // return
302 e.preventDefault();
303 if (TsCodeCompletion.currWord !== -1) {
304 TsCodeCompletion.insertCurrWordAtCursor();
305 }
306 TsCodeCompletion.endAutoCompletion();
307 } else {
308 TsCodeCompletion.refreshCodeCompletion();
309 }
310 }
311 }
312 };
313
314 /**
315 * Highlights entry in codecomplete box by id
316 *
317 * @param {Number} id
318 */
319 TsCodeCompletion.mouseOver = function(id) {
320 TsCodeCompletion.highlightCurrWord(id);
321 for (var i = 0; i < TsCodeCompletion.plugins.length; i++) {
322 require([TsCodeCompletion.plugins[i]], function(plugin) {
323 if (typeof plugin.afterMouseOver === 'function') {
324 plugin.afterMouseOver(TsCodeCompletion.proposals[TsCodeCompletion.currWord], TsCodeCompletion.compResult);
325 }
326 });
327 }
328 };
329
330 /**
331 * Event handler function executed after clicking in the editor.
332 */
333 TsCodeCompletion.click = function() {
334 if (TsCodeCompletion.latestCursorNode !== TsCodeCompletion.getCursorNode()) {
335 TsCodeCompletion.endAutoCompletion();
336 }
337 };
338
339 /**
340 * Eventhandler function executed after keystroke release
341 * triggers CC on pressed dot and typing on
342 *
343 * @param {Event} e fired prototype event object
344 */
345 TsCodeCompletion.keyDown = function(e) {
346 if (!TsCodeCompletion.linefeedsPrepared) {
347 TsCodeCompletion.prepareLinefeeds();
348 }
349 if (TsCodeCompletion.cc === 1) {
350 if (e.which === 38) {
351 // Arrow up: move up cursor in codecomplete box
352 e.preventDefault();
353 TsCodeCompletion.codeCompleteBoxMoveUpCursor();
354 for (var i = 0; i < TsCodeCompletion.plugins.length; i++) {
355 require([TsCodeCompletion.plugins[i]], function(plugin) {
356 if (typeof plugin.afterKeyUp === 'function') {
357 plugin.afterKeyUp(TsCodeCompletion.proposals[TsCodeCompletion.currWord], TsCodeCompletion.compResult);
358 }
359 });
360 }
361 } else if (e.which === 40) {
362 // Arrow down: move down cursor in codecomplete box
363 e.preventDefault();
364 TsCodeCompletion.codeCompleteBoxMoveDownCursor();
365 for (var i = 0; i < TsCodeCompletion.plugins.length; i++) {
366 require([TsCodeCompletion.plugins[i]], function(plugin) {
367 if (typeof plugin.afterKeyDown === 'function') {
368 plugin.afterKeyDown(TsCodeCompletion.proposals[TsCodeCompletion.currWord], TsCodeCompletion.compResult);
369 }
370 });
371 }
372 } else if (e.which === 27 || e.which === 37 || e.which === 39) {
373 // Esc, Arrow Left, Arrow Right: if codecomplete box is showing, hide it
374 TsCodeCompletion.endAutoCompletion();
375 } else if (e.which === 32 && (!e.ctrlKey || !e.metaKey)) {
376 // space
377 TsCodeCompletion.endAutoCompletion();
378 } else if (e.which === 32 && (e.ctrlKey || e.metaKey)) {
379 // CTRL + space
380 TsCodeCompletion.refreshCodeCompletion();
381 } else if (e.which === 8) {
382 // backspace
383 var cursorNode = TsCodeCompletion.codemirror.win.select.selectionTopNode(TsCodeCompletion.codemirror.win.document.body, false);
384 if (cursorNode.innerHTML === '.') {
385 // force full refresh at keyUp
386 TsCodeCompletion.compResult = null;
387 }
388 }
389 } else { // if autocompletion is deactivated and ctrl+space is pressed
390 if (e.which === 32 && (e.ctrlKey || e.metaKey)) {
391 e.preventDefault();
392 TsCodeCompletion.initCodeCompletion();
393 TsCodeCompletion.refreshCodeCompletion();
394 }
395 }
396 };
397
398 /**
399 * Initializes the code completion
400 */
401 TsCodeCompletion.initCodeCompletion = function() {
402 if (TsCodeCompletion.outerDiv.has(TsCodeCompletion.$codeCompleteBox).length === 0) {
403 TsCodeCompletion.outerDiv.append(TsCodeCompletion.$codeCompleteBox);
404 }
405 };
406
407 /**
408 * Refreshes the code completion list based on the cursor's position
409 */
410 TsCodeCompletion.refreshCodeCompletion = function() {
411 // init vars for up/down moving in word list
412 TsCodeCompletion.cc_up = 0;
413 TsCodeCompletion.cc_down = TsCodeCompletion.options.ccWords-1;
414
415 // clear the last completion wordposition
416 TsCodeCompletion.currWord = -1;
417 TsCodeCompletion.codemirror.editor.highlightAtCursor();
418
419 // retrieves the node right to the cursor
420 TsCodeCompletion.currentCursorPosition = TsCodeCompletion.codemirror.win.select.markSelection(TsCodeCompletion.codemirror);
421 TsCodeCompletion.latestCursorNode = TsCodeCompletion.getCursorNode();
422
423 // the cursornode has to be stored cause inserted breaks have to be deleted after pressing enter if the codecompletion is active
424 var filter = TsCodeCompletion.getFilter(TsCodeCompletion.latestCursorNode);
425
426 if (TsCodeCompletion.compResult === null || TsCodeCompletion.latestCursorNode.innerHTML === '.') {
427 // TODO: implement cases: operatorCompletion reference/copy path completion (formerly found in getCompletionResults())
428 var currentTsTreeNode = TsCodeCompletion.parser.buildTsObjTree(TsCodeCompletion.codemirror.editor.container.firstChild, TsCodeCompletion.latestCursorNode);
429 TsCodeCompletion.compResult = CompletionResult.init({
430 tsRef: TsRef,
431 tsTreeNode: currentTsTreeNode
432 });
433 }
434
435 TsCodeCompletion.proposals = TsCodeCompletion.compResult.getFilteredProposals(filter);
436
437 // if proposals are found - show box
438 if (TsCodeCompletion.proposals.length > 0) {
439 // TODO: Drop instance dependency
440 var index = 0;
441 // make UL list of completation proposals
442 var $ul = $('<ul />');
443 for (var i = 0; i < TsCodeCompletion.proposals.length; i++) {
444 var $li = $('<li />', {id: 'cc_word_' + i}).data('item', i).append(
445 $('<span />', {class: 'word_' + TsCodeCompletion.proposals[i].cssClass}).text(TsCodeCompletion.proposals[i].word)
446 ).on('click', function() {
447 TsCodeCompletion.insertCurrWordAtCursor($(this).data('item'));
448 TsCodeCompletion.endAutoCompletion();
449 }).on('mouseover', function() {
450 TsCodeCompletion.mouseOver($(this).data('item'));
451 });
452
453 $ul.append($li);
454 }
455
456 // put HTML and show box
457 var $codeCompleteBox = TsCodeCompletion.$codeCompleteBox.find('.t3e_codeCompleteBox');
458 $codeCompleteBox.html($ul);
459 $codeCompleteBox.scrollTop(0);
460
461 // init styles
462 $codeCompleteBox.css({
463 overflow: 'scroll',
464 height: ((TsCodeCompletion.options.ccWords + 1) * $('#cc_word_0').height()) + 'px'
465 });
466
467 var wrapOffset = TsCodeCompletion.codemirror.options.originalTextarea.parent().find('.t3e_iframe_wrap').offset(),
468 $cursorNode = $(TsCodeCompletion.latestCursorNode),
469 nodeOffset = $cursorNode.offset();
470
471 var leftpos = Math.round(wrapOffset.left + nodeOffset.left + TsCodeCompletion.latestCursorNode.offsetWidth) + 'px',
472 toppos = Math.round($cursorNode.position().top + TsCodeCompletion.latestCursorNode.offsetHeight - $cursorNode.scrollTop()) + 'px';
473
474 TsCodeCompletion.$codeCompleteBox.css({
475 left: leftpos,
476 top: toppos
477 });
478
479 // set flag to 1 - needed for continue typing word.
480 TsCodeCompletion.cc = 1;
481
482 // highlight first word in list
483 TsCodeCompletion.highlightCurrWord(0);
484 for (var i = 0; i < TsCodeCompletion.plugins.length; i++) {
485 require([TsCodeCompletion.plugins[i]], function(plugin) {
486 if (typeof plugin.afterCCRefresh === 'function') {
487 plugin.afterCCRefresh(TsCodeCompletion.proposals[TsCodeCompletion.currWord], TsCodeCompletion.compResult);
488 }
489 });
490 }
491 } else {
492 TsCodeCompletion.endAutoCompletion();
493 }
494 };
495
496 /**
497 * Stop code completion and call hooks
498 */
499 TsCodeCompletion.endAutoCompletion = function() {
500 TsCodeCompletion.cc = 0;
501 TsCodeCompletion.$codeCompleteBox.remove();
502 // force full refresh
503 TsCodeCompletion.compResult = null;
504 for (var i = 0; i < TsCodeCompletion.plugins.length; i++) {
505 require([TsCodeCompletion.plugins[i]], function(plugin) {
506 if (typeof plugin.endCodeCompletion === 'function') {
507 plugin.endCodeCompletion();
508 }
509 });
510 }
511 };
512
513 /**
514 * Move cursor in autocomplete box up
515 */
516 TsCodeCompletion.codeCompleteBoxMoveUpCursor = function() {
517 var id;
518 // if previous position was first or position not initialized - then move cursor to last word, else decrease position
519 if (TsCodeCompletion.currWord === 0 || TsCodeCompletion.currWord === -1) {
520 id = TsCodeCompletion.proposals.length - 1;
521 } else {
522 id = TsCodeCompletion.currWord - 1;
523 }
524 // hightlight new cursor position
525 TsCodeCompletion.highlightCurrWord(id);
526 // update id of first and last showing proposals and scroll box
527 if (TsCodeCompletion.currWord < TsCodeCompletion.cc_up || TsCodeCompletion.currWord === (TsCodeCompletion.proposals.length - 1)) {
528 TsCodeCompletion.cc_up = TsCodeCompletion.currWord;
529 TsCodeCompletion.cc_down = TsCodeCompletion.currWord + (TsCodeCompletion.options.ccWords - 1);
530 if (TsCodeCompletion.cc_up === (TsCodeCompletion.proposals.length - 1)) {
531 TsCodeCompletion.cc_down = TsCodeCompletion.proposals.length - 1;
532 TsCodeCompletion.cc_up = TsCodeCompletion.cc_down - (TsCodeCompletion.options.ccWords - 1);
533 }
534 TsCodeCompletion.$codeCompleteBox.find('.t3e_codeCompleteBox').scrollTop(TsCodeCompletion.cc_up * 18);
535 }
536 };
537
538 /**
539 * Move cursor in codecomplete box down
540 */
541 TsCodeCompletion.codeCompleteBoxMoveDownCursor = function() {
542 var id;
543 // if previous position was last word in list - then move cursor to first word if not than position ++
544 if (TsCodeCompletion.currWord === TsCodeCompletion.proposals.length - 1) {
545 id = 0;
546 } else {
547 id = TsCodeCompletion.currWord + 1;
548 }
549 // highlight new cursor position
550 TsCodeCompletion.highlightCurrWord(id);
551
552 // update id of first and last showing proposals and scroll box
553 if (TsCodeCompletion.currWord > TsCodeCompletion.cc_down || TsCodeCompletion.currWord === 0) {
554 TsCodeCompletion.cc_down = TsCodeCompletion.currWord;
555 TsCodeCompletion.cc_up = TsCodeCompletion.currWord - (TsCodeCompletion.options.ccWords - 1);
556 if (TsCodeCompletion.cc_down == 0) {
557 TsCodeCompletion.cc_up = 0;
558 TsCodeCompletion.cc_down = TsCodeCompletion.options.ccWords - 1;
559 }
560 TsCodeCompletion.$codeCompleteBox.find('.t3e_codeCompleteBox').scrollTop(TsCodeCompletion.cc_up * 18);
561 }
562 };
563
564 /**
565 * Highlight the active word in the code completion list
566 *
567 * @param {Number} id
568 */
569 TsCodeCompletion.highlightCurrWord = function(id) {
570 if (TsCodeCompletion.currWord !== -1) {
571 $('#cc_word_' + TsCodeCompletion.currWord).removeClass('active');
572 }
573 $('#cc_word_' + id).addClass('active');
574 TsCodeCompletion.currWord = id;
575 };
576
577 /**
578 * Insert selected word into text from codecompletebox
579 */
580 TsCodeCompletion.insertCurrWordAtCursor = function() {
581 var word = TsCodeCompletion.proposals[TsCodeCompletion.currWord].word;
582 // tokenize current line
583 TsCodeCompletion.codemirror.editor.highlightAtCursor();
584 var select = TsCodeCompletion.codemirror.win.select;
585 var cursorNode = TsCodeCompletion.getCursorNode();
586
587 if (cursorNode.currentText
588 && cursorNode.currentText !== '.'
589 && $.trim(cursorNode.currentText) !== '' ) {
590 // if there is some typed text already, left to the "." -> simply replace node content with the word
591 cursorNode.innerHTML = word;
592 cursorNode.currentText = word;
593 select.setCursorPos(TsCodeCompletion.codemirror.editor.container, {node: cursorNode, offset: 0});
594 } else { // if there is no text there, insert the word at the cursor position
595 TsCodeCompletion.codemirror.replaceSelection(word);
596 }
597 };
598
599 /**
600 * Save the mouse position
601 *
602 * @param {Event} e
603 */
604 TsCodeCompletion.saveMousePos = function(e) {
605 TsCodeCompletion.mousePos.x = e.clientX;
606 TsCodeCompletion.mousePos.y = e.clientY;
607 };
608
609 $(document).on('t3editor:init', function(e, codemirror, $outerDiv) {
610 TsCodeCompletion.codemirror = codemirror;
611 TsCodeCompletion.outerDiv = $outerDiv;
612
613 TsCodeCompletion.parser = TsParser.init(TsCodeCompletion.tsRef, TsCodeCompletion.extTsObjTree);
614 TsCodeCompletion.tsRef.loadTsrefAsync();
615
616 $(codemirror.win)
617 .on('click', TsCodeCompletion.click)
618 .on('mousemove', TsCodeCompletion.saveMousePos)
619 .on('keydown', function(e) {
620 TsCodeCompletion.codemirror = codemirror;
621 TsCodeCompletion.outerDiv = $outerDiv;
622 TsCodeCompletion.keyDown(e);
623 })
624 .on('keyup', function(e) {
625 TsCodeCompletion.codemirror = codemirror;
626 TsCodeCompletion.outerDiv = $outerDiv;
627 TsCodeCompletion.keyUp(e);
628 });
629
630 TsCodeCompletion.loadExtTemplatesAsync();
631 TsCodeCompletion.loadPluginArray();
632 });
633
634 return TsCodeCompletion;
635 });