PluginProbe
WPIDE – File Manager & Code Editor / 2.0.6
WPIDE – File Manager & Code Editor v2.0.6
3.5.8 3.5.7 2.0.14 2.0.15 2.0.16 2.0.2 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1 2.2 2.3 2.3.1 2.3.2 2.4.0 2.5 2.6 3.0 3.1 3.2 3.3 3.4 All 54 releases
wpide / js / load-editor.js

load-editor.js in WPIDE – File Manager & Code Editor 2.0.6, at js/load-editor.js

733 lines 20.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 var autocompleting = false;
2 var autocompletelength = 2;
3 var editor = '';
4
5 var saved_editor_sessions = [];
6 var saved_undo_manager = [];
7 var last_added_editor_session = 0;
8 var current_editor_session = 0;
9
10 var EditSession = require('ace/edit_session').EditSession;
11 var UndoManager = require('ace/undomanager').UndoManager;
12 var Search = require("ace/search").Search;
13 var TokenIterator = require("ace/token_iterator").TokenIterator;
14
15 var oHandler;
16
17 function onSessionChange(e) {
18 //don't continue with autocomplete if /n entered
19 try {
20 if ( e.data.text.charCodeAt(0) === 10 ){
21 return;
22 }
23 }catch(error){}
24
25
26
27 try {
28 if ( e.data.action == 'removeText' ){
29
30 if (autocompleting) {
31 autocompletelength = (autocompletelength - 1) ;
32 }else{
33 return;
34 }
35 }
36 }catch(error){}
37
38
39 //get current cursor position
40 range = editor.getSelectionRange();
41 //take note of selection row to compare with search
42 cursor_row = range.start.row;
43
44 try{
45 //quit autocomplete if we are writing a "string"
46 var iterator = new TokenIterator(editor.getSession(), range.start.row, range.start.column);
47 var current_token_type = iterator.getCurrentToken().type;
48 if(current_token_type == "string" || current_token_type == "comment"){
49 return;
50 }
51 }catch(error){}
52
53 if (range.start.column > 0){
54
55 //search for command text user has entered that we need to try match functions against
56 var search = new Search().set({
57 needle: "[\\n \.\)\(]",
58 backwards: true,
59 wrap: false,
60 caseSensitive: false,
61 wholeWord: false,
62 regExp: true
63 });
64 //console.log(search.find(editor.getSession()));
65
66 range = search.find(editor.getSession());
67
68 if (range) range.start.column++;
69
70 }else{ //change this to look char position, if it's starting at 0 then do this
71
72 range.start.column = 0;
73 }
74
75 if (! range || range.start.row < cursor_row ){
76 //forse the autocomplete check on this row starting at column 0
77 range = editor.getSelectionRange();
78 range.start.column = 0;
79 }
80
81
82 //console.log("search result - start row " + range.start.row + "-" + range.end.row + ", column " + range.start.column+ "-" + range.end.column);
83 //console.log(editor.getSelection().getRange());
84
85 range.end.column = editor.getSession().getSelection().getCursor().column +1;//set end column as cursor pos
86
87 //console.log("[ \.] based: " + editor.getSession().doc.getTextRange(range));
88
89 //no column lower than 1 thanks
90 if (range.start.column < 1) {
91 range.start.column = 0;
92 }
93
94 //console.log("after row " + range.start.row + "-" + range.end.row + ", column " + range.start.column+ "-" + range.end.column);
95 //get the editor text based on that range
96 var text = editor.getSession().doc.getTextRange(range);
97 $quit_onchange = false;
98
99 //console.log(text);
100
101 //console.log("Searching for text \""+text+"\" length: "+ text.length);
102 if (text.length < 3){
103
104 wpide_close_autocomplete();
105 return;
106 }
107
108 autocompletelength = text.length;
109
110 //create the dropdown for autocomplete
111 var sel = editor.getSelection();
112 var session = editor.getSession();
113 var lead = sel.getSelectionLead();
114
115 var pos = editor.renderer.textToScreenCoordinates(lead.row, lead.column);
116 var ac; // #ac is auto complete html select element
117
118
119
120 if( document.getElementById('ac') ){
121 ac=document.getElementById('ac');
122
123 //add editor click listener
124 //editor clicks should hide the autocomplete dropdown
125 editor.container.addEventListener('click', function(e){
126
127 wpide_close_autocomplete();
128
129 autocompleting=false;
130 autocompletelength = 2;
131
132 }, false);
133
134 } //end - create initial autocomplete dropdown and related actions
135
136
137 //calulate the editor container offset
138 var obj=editor.container;
139
140 var curleft = 0;
141 var curtop = 0;
142
143 if (obj.offsetParent) {
144
145 do {
146 curleft += obj.offsetLeft;
147 curtop += obj.offsetTop;
148 } while (obj = obj.offsetParent);
149
150 }
151
152
153 //position autocomplete
154 ac.style.top= ((pos.pageY - curtop)+20) + "px";
155 ac.style.left= ((pos.pageX - curleft)+10) + "px";
156 ac.style.display='block';
157 ac.style.background='white';
158
159
160 //remove all options, starting a fresh list
161 ac.options.length = 0;
162
163
164 //loop through WP tags and check for a match
165 if (autocomplete_wordpress){
166 var tag;
167 for(i in autocomplete_wordpress) {
168 //if(!html_tags.hasOwnProperty(i) ){
169 // continue;
170 //}
171
172 tag= i;
173 //see if the tag is a match
174 if( text !== tag.substr(0,text.length) ){
175 continue;
176 }
177
178 //add parentheses
179 tag = tag + "()";
180
181 var option = document.createElement('option');
182 option.text = tag;
183 option.value = tag;
184 option.setAttribute('title', wpide_app_path + 'images/wpac.png');//path to icon image or wpac.png
185
186
187 try {
188 ac.add(option, null); // standards compliant; doesn't work in IE
189 }
190 catch(ex) {
191 ac.add(option); // IE only
192 }
193
194 }//end for
195 }//end php autocomplete
196
197 //loop through PHP tags and check for a match
198 if (autocomplete_php){
199 var tag;
200 for(i in autocomplete_php) {
201 //if(!html_tags.hasOwnProperty(i) ){
202 // continue;
203 //}
204
205 tag= i;
206 //see if the tag is a match
207 if( text !== tag.substr(0,text.length) ){
208 continue;
209 }
210
211 //add parentheses
212 tag = tag + "()";
213
214 var option = document.createElement('option');
215 option.text = tag;
216 option.value = tag;
217 option.setAttribute('title', wpide_app_path + 'images/phpac.png');//path to icon image or wpac.png
218
219 try {
220 ac.add(option, null); // standards compliant; doesn't work in IE
221 }
222 catch(ex) {
223 ac.add(option); // IE only
224 }
225
226
227 }//end for
228 }//end php autocomplete
229
230
231 //check for matches
232 if ( ac.length === 0 ) {
233 wpide_close_autocomplete();
234 } else {
235
236 ac.selectedIndex=0;
237 autocompleting=true;
238 oHandler = jQuery("#ac").msDropDown({visibleRows:10, rowHeight:20}).data("dd");
239
240 jQuery("#ac_child").click(function(item){
241 //console.log(item.srcElement.textContent);
242 selectACitem(item.srcElement.textContent);
243 });
244
245 jQuery("#ac_child a").mouseover(function(item){
246 //show the code in the info panel
247
248 //if this command item is enabled
249 if (jQuery("#"+item.srcElement.id).hasClass("enabled")){
250
251 var selected_item_index = jQuery("#"+item.srcElement.id).index();
252
253 if (selected_item_index > -1){ //if select item is valid
254
255 //set the selected menu item
256 oHandler.selectedIndex(selected_item_index);
257 //show command help panel for this command
258 wpide_function_help();
259
260 }
261 }
262
263 });
264
265
266 jQuery("#ac_child").css("z-index", "9999");
267 jQuery("#ac_child").css("background-color", "#ffffff");
268 jQuery("#ac_msdd").css("z-index", "9999");
269 jQuery("#ac_msdd").css("position", "absolute");
270 jQuery("#ac_msdd").css("top", ac.style.top);
271 jQuery("#ac_msdd").css("left", ac.style.left);
272
273 //show command help panel for this command
274 wpide_function_help();
275
276 }
277
278 }
279
280 function token_test(){
281
282 var iterator = new TokenIterator(editor.getSession(), range.start.row, range.start.column);
283 var current_token_type = iterator.getCurrentToken().type;
284 return iterator.getCurrentToken();
285 }
286
287 function wpide_close_autocomplete(){
288 if (ac) ac.style.display='none';
289 if (oHandler) oHandler.close();
290
291 autocompleting = false;
292
293 //clear the text in the command help panel
294 //jQuery("#wpide_info_content").html("");
295 }
296
297 function wpide_function_help() {
298 //mouse over
299
300 try
301 {
302 var selected_command_item = jQuery("#ac_child a.selected");
303
304
305 key = selected_command_item.find("span.ddTitleText").text().replace("()","");
306
307 //wordpress autocomplete
308 if ( selected_command_item.find("img").attr("src").indexOf("wpac.png") >= 0){
309
310 if (autocomplete_wordpress[key].desc != undefined){
311
312 //compose the param info
313 var param_text ="";
314 for(i=0; i<autocomplete_wordpress[key].params.length; i++) {
315
316 //wrap params in a span to highlight not required
317 if (autocomplete_wordpress[key].params[i].required == "no"){
318 param_text = param_text + "<span class='wpide_func_arg_notrequired'>" + autocomplete_wordpress[key].params[i]['param'] + "<em>optional</em></span><br /> <br />";
319 }else{
320 param_text = param_text + autocomplete_wordpress[key].params[i]['param'] + "<br /> <br />";
321 }
322
323 }
324 //compose returns text
325 if (autocomplete_wordpress[key].returns.length > 0){
326 returns_text = "<br /><br /><strong>Returns:</strong> " + autocomplete_wordpress[key].returns;
327 }else{
328 returns_text = "";
329 }
330
331
332 //output command info
333 jQuery("#wpide_info_content").html(
334 "<strong class='wpide_func_highlight_black'>Function: </strong><strong class='wpide_func_highlight'>" + key + "(</strong><br />" +
335 "<span class='wpide_func_desc'>" + autocomplete_wordpress[key].desc + "</span><br /><br /><em class='wpide_func_params'>" +
336 param_text + "</em>"+
337 "<strong class='wpide_func_highlight'>)</strong> " +
338 returns_text
339 );
340 }
341
342 }
343
344 //php autocomplete
345 if ( selected_command_item.find("img").attr("src").indexOf("phpac.png") >= 0){
346
347 if (autocomplete_php[key].returns != undefined){
348
349 //params text
350 var param_text ="";
351 for(i=0; i<autocomplete_php[key].params.length; i++) {
352
353 //wrap params in a span to highlight not required
354 if (autocomplete_php[key].params[i].required == "no"){
355 param_text = param_text + "<span class='wpide_func_arg_notrequired'>" + autocomplete_php[key].params[i]['param'] + "<em>optional</em></span><br /> <br />";
356 }else{
357 param_text = param_text + autocomplete_php[key].params[i]['param'] + "<br /> <br />";
358 }
359
360 }
361 //compose returns text
362 if (autocomplete_php[key].returns.length > 0){
363 returns_text = "<br /><br /><strong>Returns:</strong> " + autocomplete_php[key].returns;
364 }else{
365 returns_text = "";
366 }
367
368 jQuery("#wpide_info_content").html(
369 "<strong class='wpide_func_highlight_black'>Function: </strong><strong class='wpide_func_highlight'>" + key + "(</strong><br />" +
370 autocomplete_php[key].desc + "<br /><br /><em class='wpide_func_params'>" +
371 param_text + "</em>" +
372 "<strong class='wpide_func_highlight'>)</strong>" +
373 returns_text
374 );
375
376 }
377
378 }
379
380
381
382 }
383 catch(err)
384 {
385 //Handle errors here
386 }
387
388 }
389
390 //open another file and add to editor
391 function wpide_set_file_contents(file, callback_func){
392 "use strict";
393
394 //ajax call to get file contents we are about to edit
395 var data = { action: 'wpide_get_file', filename: file, _wpnonce: jQuery('#_wpnonce').val(), _wp_http_referer: jQuery('#_wp_http_referer').val() };
396
397 jQuery.post(ajaxurl, data, function(response) {
398 var the_path = file.replace(/^.*[\\\/]/, '');
399 var the_id = "wpide_tab_" + last_added_editor_session;
400
401 //enable editor now we have a file open
402 jQuery('#fancyeditordiv textarea').removeAttr("disabled");
403
404 jQuery("#wpide_toolbar_tabs").append('<span id="'+the_id+'" sessionrel="'+last_added_editor_session+'" title=" '+file+' " rel="'+file+'" class="wpide_tab">'+ the_path +'</a> <a class="close_tab" href="#">x</a> ');
405
406 saved_editor_sessions[last_added_editor_session] = new EditSession(response);//set saved session
407 saved_editor_sessions[last_added_editor_session].on('change', onSessionChange);
408 saved_undo_manager[last_added_editor_session] = new UndoManager(editor.getSession().getUndoManager());//new undo manager for this session
409
410 last_added_editor_session++; //increment session counter
411
412 //add click event for the new tab.
413 //We are actually clearing the click event and adding it again for all tab elements, it's the only way I could get the click handler listening on all dynamically added tabs
414 jQuery(".wpide_tab").off('click').on("click", function(event){
415 event.preventDefault();
416
417 jQuery('input[name=filename]').val( jQuery(this).attr('rel') );
418
419 //save current editor into session
420 //get old editor out of session and apply to editor
421 var clicksesh = jQuery(this).attr('sessionrel'); //editor id number
422 saved_editor_sessions[ clicksesh ].setUndoManager(saved_undo_manager[ clicksesh ]);
423 editor.setSession( saved_editor_sessions[ clicksesh ] );
424
425 //set this tab as active
426 jQuery(".wpide_tab").removeClass('active');
427 jQuery(this).addClass('active');
428
429 var currentFilename = jQuery(this).attr('rel');
430 var mode;
431
432 //set the editor mode based on file name
433 if (/\.css$/.test(currentFilename)) {
434 mode = require("ace/mode/css").Mode;
435 }
436 else if (/\.less$/.test(currentFilename)) {
437 mode = require("ace/mode/css").Mode;
438 }
439 else if (/\.js$/.test(currentFilename)) {
440 mode = require("ace/mode/javascript").Mode;
441 }
442 else {
443 mode = require("ace/mode/php").Mode; //default to php
444 }
445 editor.getSession().setMode(new mode());
446
447 editor.getSession().on('change', onSessionChange);
448 editor.resize();
449 editor.focus();
450 //make a note of current editor
451 current_editor_session = clicksesh;
452
453 });
454
455 //add click event for tab close.
456 //We are actually clearing the click event and adding it again for all tab elements, it's the only way I could get the click handler listening on all dynamically added tabs
457 jQuery(".close_tab").off('click').on("click", function(event){
458 event.preventDefault();
459 var clicksesh = jQuery(this).parent().attr('sessionrel');
460 var activeFallback;
461
462 //if the currently selected tab is being removed then remember to make the first tab active
463 if ( jQuery("#wpide_tab_"+clicksesh).hasClass('active') ) {
464 activeFallback = true;
465 }else{
466 activeFallback = false;
467 }
468
469 //remove tab
470 jQuery(this).parent().remove();
471
472 //clear session and undo
473 saved_undo_manager[clicksesh] = undefined;
474 saved_editor_sessions[clicksesh] = undefined;
475
476
477 //Clear the active editor if all tabs closed or activate first tab if required since the active tab may have been deleted
478 if (jQuery(".wpide_tab").length == 0){
479 editor.getSession().setValue( "" );
480 }else if ( activeFallback ){
481 jQuery(".wpide_tab")[0].click();
482 }
483
484 });
485
486 jQuery("#"+the_id).click();
487
488 if (callback_func != null) {
489 callback_func(response);
490 }
491
492 });
493
494
495 }
496
497 function saveDocument() {
498 //ajax call to save the file and generate a backup if needed
499 var data = { action: 'wpide_save_file', filename: jQuery('input[name=filename]').val(), _wpnonce: jQuery('#_wpnonce').val(), _wp_http_referer: jQuery('#_wp_http_referer').val(), content: editor.getSession().getValue() };
500 jQuery.post(ajaxurl, data, function(response) {
501 if (response === 'success') {
502 jQuery("#wpide_message").html('<span>File saved.</span>');
503 jQuery("#wpide_message").show();
504 jQuery("#wpide_message").fadeOut(5000);
505 } else {
506 alert("error: " + response);
507 }
508 });
509 }
510
511 //enter/return command
512 function selectACitem (item) {
513 if( document.getElementById('ac').style.display === 'block' ){
514 var ac_dropdwn = document.getElementById('ac');
515 var tag = ac_dropdwn.options[ac_dropdwn.selectedIndex].value;
516 var sel = editor.selection.getRange();
517 var line = editor.getSession().getLine(sel.start.row);
518 sel.start.column = sel.start.column - autocompletelength;
519
520 if (item.length){
521 tag = item; //get tag from new msdropdown passed as arg
522 }else{
523 tag = jQuery("#ac_msdd a.selected").children("span.ddTitleText").text(); //get tag from new msdropdown
524 }
525
526 //clean up the tag/command
527 tag = tag.replace(")", ""); //remove end parenthesis
528
529
530 editor.selection.setSelectionRange(sel);
531 editor.insert(tag);
532
533 wpide_close_autocomplete();
534 } else {
535 editor.insert('\n');
536 }
537 }
538
539
540 jQuery(document).ready(function($) {
541 $("#wpide_save").click(saveDocument);
542
543
544
545 //add div for ace editor to latch on to
546 //$('#template').prepend("<div style='width:80%;height:500px;margin-right:0!important;' id='fancyeditordiv'></div>");
547 //create the editor instance
548 editor = ace.edit("fancyeditordiv");
549 //set the editor theme
550 editor.setTheme("ace/theme/dawn");
551 //get a copy of the initial file contents (the file being edited)
552 //var intialData = $('#newcontent').val()
553 var intialData = "Use the file manager to find a file you wish edit, click the file name to edit. \n\n";
554
555
556 //startup info - usefull for debugging
557 var data = { action: 'wpide_startup_check', _wpnonce: jQuery('#_wpnonce').val(), _wp_http_referer: jQuery('#_wp_http_referer').val() };
558
559 jQuery.post(ajaxurl, data, function(response) {
560 if (response == "-1"){
561 intialData = intialData + "Permission/security problem with ajax request. Refresh WPide and try again. \n\n";
562 }else{
563 intialData = intialData + response;
564 }
565
566 editor.getSession().setValue( intialData );
567
568 });
569
570
571
572 //make initial editor read only
573 $('#fancyeditordiv textarea').attr("disabled", "disabled");
574
575 //use editors php mode
576 var phpMode = require("ace/mode/php").Mode;
577 editor.getSession().setMode(new phpMode());
578
579 //START AUTOCOMPLETE
580 //create the autocomplete dropdown
581 var ac = document.createElement('select');
582 ac.id = 'ac';
583 ac.name = 'ac';
584 ac.style.position='absolute';
585 ac.style.zIndex=100;
586 ac.style.width='auto';
587 ac.style.display='none';
588 ac.style.height='auto';
589 ac.size=10;
590 editor.container.appendChild(ac);
591
592 //hook onto any change in editor contents
593 editor.getSession().on('change', onSessionChange);//end editor change event
594
595
596
597 //START COMMANDS
598
599 //Key up command
600 editor.commands.addCommand({
601 name: "up",
602 bindKey: {
603 win: "Up",
604 mac: "Up",
605 sender: "editor"
606 },
607
608 exec: function(env, args, request) {
609 if (oHandler && oHandler.visible() === 'block'){
610 oHandler.previous();
611
612 //show command help panel for this command
613 wpide_function_help();
614
615 }else if( document.getElementById('ac').style.display === 'block' ) {
616 var select=document.getElementById('ac');
617 if( select.selectedIndex === 0 ) {
618 select.selectedIndex = select.options.length-1;
619 } else {
620 select.selectedIndex = select.selectedIndex-1;
621 }
622 } else {
623 var range = editor.getSelectionRange();
624 editor.clearSelection();
625 editor.moveCursorTo(range.end.row - 1, range.end.column);
626 }
627 }
628 });
629
630
631 //key down command
632 editor.commands.addCommand({
633 name: "down",
634 bindKey: {
635 win: "Down",
636 mac: "Down",
637 sender: "editor"
638 },
639 exec: function(env, args, request) {
640
641 if (oHandler && oHandler.visible() === 'block'){
642 oHandler.next();
643
644 //show command help panel for this command
645 wpide_function_help();
646
647 }else if ( document.getElementById('ac').style.display === 'block' ) {
648 var select=document.getElementById('ac');
649 if ( select.selectedIndex === select.options.length-1 ) {
650 select.selectedIndex=0;
651 } else {
652 select.selectedIndex=select.selectedIndex+1;
653 }
654 } else {
655 var range = editor.getSelectionRange();
656 editor.clearSelection();
657 editor.moveCursorTo(range.end.row +1, range.end.column);
658 }
659 }
660 });
661
662
663
664 editor.commands.addCommand({
665 name: "enter",
666 bindKey: {
667 win: "Return",
668 mac: "Return",
669 sender: "editor"
670 },
671 exec: selectACitem
672 });
673
674 // save command:
675 editor.commands.addCommand({
676 name: "save",
677 bindKey: {
678 win: "Ctrl-S",
679 mac: "Command-S",
680 sender: "editor"
681 },
682 exec: saveDocument
683 });
684
685 //END COMMANDS
686
687
688 //click action for new directory/file submit link
689 $("#wpide_create_new_directory, #wpide_create_new_file").click(function(e){
690 e.preventDefault();
691
692 var data_input = jQuery(this).parent().find("input.has_data");
693 var item = eval('('+ data_input.attr("rel") +')');
694
695 //item.path file|directory
696 var data = { action: 'wpide_create_new', path: item.path, type: item.type, file: data_input.val(), _wpnonce: jQuery('#_wpnonce').val(), _wp_http_referer: jQuery('#_wp_http_referer').val() };
697
698 jQuery.post(ajaxurl, data, function(response) {
699
700 if (response == "1"){
701 //remove the file/dir name from the text input
702 data_input.val("");
703
704 if ( jQuery("ul.jqueryFileTree a[rel='"+ item.path +"']").length == 0){
705
706 //if no parent then we are adding something to the wp-content folder so regenerate the whole filetree
707 the_filetree();
708
709 }
710
711 //click the parent once to hide
712 jQuery("ul.jqueryFileTree a[rel='"+ item.path +"']").click();
713
714 //hide the parent input block
715 data_input.parent().hide();
716
717 //click the parent once again to show with new folder and focus on this area
718 jQuery("ul.jqueryFileTree a[rel='"+ item.path +"']").click();
719 jQuery("ul.jqueryFileTree a[rel='"+ item.path +"']").focus();
720
721 }else if (response == "-1"){
722 alert("Permission/security problem. Refresh WPide and try again.");
723 }else{
724 alert(response);
725 }
726
727
728 });
729
730 });
731
732 });//end jquery load
733