Magpleasure_Filesystem - Version 1.0.0

Version Notes

Ready to stable use

Download this release

Release Info

Developer Magento Core Team
Extension Magpleasure_Filesystem
Version 1.0.0
Comparing to
See all releases


Version 1.0.0

Files changed (175) hide show
  1. app/code/community/Magpleasure/Filesystem/Block/Adminhtml/Ide.php +27 -0
  2. app/code/community/Magpleasure/Filesystem/Block/Adminhtml/Ide/Editor.php +31 -0
  3. app/code/community/Magpleasure/Filesystem/Block/Adminhtml/Ide/Tree.php +43 -0
  4. app/code/community/Magpleasure/Filesystem/Helper/Data.php +20 -0
  5. app/code/community/Magpleasure/Filesystem/Model/Tree.php +102 -0
  6. app/code/community/Magpleasure/Filesystem/controllers/Adminhtml/FilesystemController.php +310 -0
  7. app/code/community/Magpleasure/Filesystem/etc/adminhtml.xml +70 -0
  8. app/code/community/Magpleasure/Filesystem/etc/config.xml +137 -0
  9. app/code/community/Magpleasure/Filesystem/etc/system.xml +42 -0
  10. app/code/community/Magpleasure/Filesystem/sql/filesystem_setup/mysql4-install-1.0.php +20 -0
  11. app/design/adminhtml/default/default/layout/filesystem.xml +19 -0
  12. app/design/adminhtml/default/default/template/filesystem/ide.phtml +28 -0
  13. app/design/adminhtml/default/default/template/filesystem/ide/editor.phtml +46 -0
  14. app/design/adminhtml/default/default/template/filesystem/ide/tree.phtml +35 -0
  15. app/design/adminhtml/default/default/template/filesystem/wrapper.phtml +17 -0
  16. app/etc/modules/Magpleasure_Filesystem.xml +9 -0
  17. js/editarea/autocompletion.js +491 -0
  18. js/editarea/edit_area.css +530 -0
  19. js/editarea/edit_area.js +527 -0
  20. js/editarea/edit_area_compressor.php +428 -0
  21. js/editarea/edit_area_full.gz +0 -0
  22. js/editarea/edit_area_full.js +38 -0
  23. js/editarea/edit_area_functions.js +1202 -0
  24. js/editarea/edit_area_loader.js +1081 -0
  25. js/editarea/elements_functions.js +336 -0
  26. js/editarea/highlight.js +407 -0
  27. js/editarea/images/autocompletion.gif +0 -0
  28. js/editarea/images/close.gif +0 -0
  29. js/editarea/images/fullscreen.gif +0 -0
  30. js/editarea/images/go_to_line.gif +0 -0
  31. js/editarea/images/help.gif +0 -0
  32. js/editarea/images/highlight.gif +0 -0
  33. js/editarea/images/load.gif +0 -0
  34. js/editarea/images/move.gif +0 -0
  35. js/editarea/images/newdocument.gif +0 -0
  36. js/editarea/images/opacity.png +0 -0
  37. js/editarea/images/processing.gif +0 -0
  38. js/editarea/images/redo.gif +0 -0
  39. js/editarea/images/reset_highlight.gif +0 -0
  40. js/editarea/images/save.gif +0 -0
  41. js/editarea/images/search.gif +0 -0
  42. js/editarea/images/smooth_selection.gif +0 -0
  43. js/editarea/images/spacer.gif +0 -0
  44. js/editarea/images/statusbar_resize.gif +0 -0
  45. js/editarea/images/undo.gif +0 -0
  46. js/editarea/images/word_wrap.gif +0 -0
  47. js/editarea/keyboard.js +145 -0
  48. js/editarea/langs/bg.js +54 -0
  49. js/editarea/langs/cs.js +48 -0
  50. js/editarea/langs/de.js +48 -0
  51. js/editarea/langs/dk.js +48 -0
  52. js/editarea/langs/en.js +48 -0
  53. js/editarea/langs/eo.js +48 -0
  54. js/editarea/langs/es.js +48 -0
  55. js/editarea/langs/fi.js +48 -0
  56. js/editarea/langs/fr.js +48 -0
  57. js/editarea/langs/hr.js +48 -0
  58. js/editarea/langs/it.js +48 -0
  59. js/editarea/langs/ja.js +48 -0
  60. js/editarea/langs/mk.js +48 -0
  61. js/editarea/langs/nl.js +48 -0
  62. js/editarea/langs/pl.js +48 -0
  63. js/editarea/langs/pt.js +48 -0
  64. js/editarea/langs/ru.js +48 -0
  65. js/editarea/langs/sk.js +48 -0
  66. js/editarea/langs/zh.js +48 -0
  67. js/editarea/license_apache.txt +7 -0
  68. js/editarea/license_bsd.txt +10 -0
  69. js/editarea/license_lgpl.txt +458 -0
  70. js/editarea/manage_area.js +623 -0
  71. js/editarea/plugins/charmap/charmap.js +90 -0
  72. js/editarea/plugins/charmap/css/charmap.css +64 -0
  73. js/editarea/plugins/charmap/images/charmap.gif +0 -0
  74. js/editarea/plugins/charmap/jscripts/map.js +373 -0
  75. js/editarea/plugins/charmap/langs/bg.js +12 -0
  76. js/editarea/plugins/charmap/langs/cs.js +6 -0
  77. js/editarea/plugins/charmap/langs/de.js +6 -0
  78. js/editarea/plugins/charmap/langs/dk.js +6 -0
  79. js/editarea/plugins/charmap/langs/en.js +6 -0
  80. js/editarea/plugins/charmap/langs/eo.js +6 -0
  81. js/editarea/plugins/charmap/langs/es.js +6 -0
  82. js/editarea/plugins/charmap/langs/fr.js +6 -0
  83. js/editarea/plugins/charmap/langs/hr.js +6 -0
  84. js/editarea/plugins/charmap/langs/it.js +6 -0
  85. js/editarea/plugins/charmap/langs/ja.js +6 -0
  86. js/editarea/plugins/charmap/langs/mk.js +6 -0
  87. js/editarea/plugins/charmap/langs/nl.js +6 -0
  88. js/editarea/plugins/charmap/langs/pl.js +6 -0
  89. js/editarea/plugins/charmap/langs/pt.js +6 -0
  90. js/editarea/plugins/charmap/langs/ru.js +6 -0
  91. js/editarea/plugins/charmap/langs/sk.js +6 -0
  92. js/editarea/plugins/charmap/langs/zh.js +6 -0
  93. js/editarea/plugins/charmap/popup.html +24 -0
  94. js/editarea/plugins/test/css/test.css +3 -0
  95. js/editarea/plugins/test/images/Thumbs.db +0 -0
  96. js/editarea/plugins/test/images/test.gif +0 -0
  97. js/editarea/plugins/test/langs/bg.js +10 -0
  98. js/editarea/plugins/test/langs/cs.js +4 -0
  99. js/editarea/plugins/test/langs/de.js +4 -0
  100. js/editarea/plugins/test/langs/dk.js +4 -0
  101. js/editarea/plugins/test/langs/en.js +4 -0
  102. js/editarea/plugins/test/langs/eo.js +4 -0
  103. js/editarea/plugins/test/langs/es.js +4 -0
  104. js/editarea/plugins/test/langs/fr.js +4 -0
  105. js/editarea/plugins/test/langs/hr.js +4 -0
  106. js/editarea/plugins/test/langs/it.js +4 -0
  107. js/editarea/plugins/test/langs/ja.js +4 -0
  108. js/editarea/plugins/test/langs/mk.js +4 -0
  109. js/editarea/plugins/test/langs/nl.js +4 -0
  110. js/editarea/plugins/test/langs/pl.js +4 -0
  111. js/editarea/plugins/test/langs/pt.js +4 -0
  112. js/editarea/plugins/test/langs/ru.js +4 -0
  113. js/editarea/plugins/test/langs/sk.js +4 -0
  114. js/editarea/plugins/test/langs/zh.js +4 -0
  115. js/editarea/plugins/test/test.js +110 -0
  116. js/editarea/plugins/test/test2.js +1 -0
  117. js/editarea/reg_syntax.js +166 -0
  118. js/editarea/reg_syntax/basic.js +70 -0
  119. js/editarea/reg_syntax/brainfuck.js +45 -0
  120. js/editarea/reg_syntax/c.js +63 -0
  121. js/editarea/reg_syntax/coldfusion.js +120 -0
  122. js/editarea/reg_syntax/cpp.js +66 -0
  123. js/editarea/reg_syntax/css.js +85 -0
  124. js/editarea/reg_syntax/html.js +51 -0
  125. js/editarea/reg_syntax/java.js +57 -0
  126. js/editarea/reg_syntax/js.js +94 -0
  127. js/editarea/reg_syntax/pas.js +83 -0
  128. js/editarea/reg_syntax/perl.js +88 -0
  129. js/editarea/reg_syntax/php.js +157 -0
  130. js/editarea/reg_syntax/phtml.js +157 -0
  131. js/editarea/reg_syntax/python.js +145 -0
  132. js/editarea/reg_syntax/robotstxt.js +25 -0
  133. js/editarea/reg_syntax/ruby.js +68 -0
  134. js/editarea/reg_syntax/sql.js +56 -0
  135. js/editarea/reg_syntax/tsql.js +88 -0
  136. js/editarea/reg_syntax/vb.js +53 -0
  137. js/editarea/reg_syntax/xml.js +57 -0
  138. js/editarea/regexp.js +139 -0
  139. js/editarea/resize_area.js +73 -0
  140. js/editarea/search_replace.js +174 -0
  141. js/editarea/template.html +100 -0
  142. js/filesystem/base64.js +153 -0
  143. js/filesystem/jquery-1.4.2.min.js +157 -0
  144. js/filesystem/jqueryfiletree.js +95 -0
  145. js/filesystem/script.coffee +149 -0
  146. js/filesystem/script.js +146 -0
  147. package.xml +20 -0
  148. skin/adminhtml/default/default/filesystem/css/jqueryfiletree.css +92 -0
  149. skin/adminhtml/default/default/filesystem/css/styles.css +52 -0
  150. skin/adminhtml/default/default/filesystem/images/application.png +0 -0
  151. skin/adminhtml/default/default/filesystem/images/code.png +0 -0
  152. skin/adminhtml/default/default/filesystem/images/css.png +0 -0
  153. skin/adminhtml/default/default/filesystem/images/db.png +0 -0
  154. skin/adminhtml/default/default/filesystem/images/directory.png +0 -0
  155. skin/adminhtml/default/default/filesystem/images/doc.png +0 -0
  156. skin/adminhtml/default/default/filesystem/images/file.png +0 -0
  157. skin/adminhtml/default/default/filesystem/images/film.png +0 -0
  158. skin/adminhtml/default/default/filesystem/images/flash.png +0 -0
  159. skin/adminhtml/default/default/filesystem/images/folder_open.png +0 -0
  160. skin/adminhtml/default/default/filesystem/images/html.png +0 -0
  161. skin/adminhtml/default/default/filesystem/images/java.png +0 -0
  162. skin/adminhtml/default/default/filesystem/images/linux.png +0 -0
  163. skin/adminhtml/default/default/filesystem/images/music.png +0 -0
  164. skin/adminhtml/default/default/filesystem/images/pdf.png +0 -0
  165. skin/adminhtml/default/default/filesystem/images/php.png +0 -0
  166. skin/adminhtml/default/default/filesystem/images/phtml.png +0 -0
  167. skin/adminhtml/default/default/filesystem/images/picture.png +0 -0
  168. skin/adminhtml/default/default/filesystem/images/ppt.png +0 -0
  169. skin/adminhtml/default/default/filesystem/images/psd.png +0 -0
  170. skin/adminhtml/default/default/filesystem/images/ruby.png +0 -0
  171. skin/adminhtml/default/default/filesystem/images/script.png +0 -0
  172. skin/adminhtml/default/default/filesystem/images/spinner.gif +0 -0
  173. skin/adminhtml/default/default/filesystem/images/txt.png +0 -0
  174. skin/adminhtml/default/default/filesystem/images/xls.png +0 -0
  175. skin/adminhtml/default/default/filesystem/images/zip.png +0 -0
app/code/community/Magpleasure/Filesystem/Block/Adminhtml/Ide.php ADDED
@@ -0,0 +1,27 @@
1
+ <?php
2
+ /**
3
+ * MagPleasure Co.
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the EULA
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www.magpleasure.com/LICENSE.txt
11
+ *
12
+ * @category Magpleasure
13
+ * @package Magpleasure_Filesystem
14
+ * @copyright Copyright (c) 2011 Magpleasure Co. (http://www.magpleasure.com)
15
+ * @license http://www.magpleasure.com/LICENSE.txt
16
+ */
17
+
18
+
19
+ class Magpleasure_Filesystem_Block_Adminhtml_Ide extends Mage_Adminhtml_Block_Abstract
20
+ {
21
+ public function __construct()
22
+ {
23
+ parent::__construct();
24
+
25
+
26
+ }
27
+ }
app/code/community/Magpleasure/Filesystem/Block/Adminhtml/Ide/Editor.php ADDED
@@ -0,0 +1,31 @@
1
+ <?php
2
+ /**
3
+ * MagPleasure Co.
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the EULA
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www.magpleasure.com/LICENSE.txt
11
+ *
12
+ * @category Magpleasure
13
+ * @package Magpleasure_Filesystem
14
+ * @copyright Copyright (c) 2011 Magpleasure Co. (http://www.magpleasure.com)
15
+ * @license http://www.magpleasure.com/LICENSE.txt
16
+ */
17
+
18
+
19
+ class Magpleasure_Filesystem_Block_Adminhtml_Ide_Editor extends Mage_Adminhtml_Block_Abstract
20
+ {
21
+ /**
22
+ * Template path
23
+ */
24
+ const TEMPLATE_PATH = 'filesystem/ide/editor.phtml';
25
+
26
+ protected function _construct()
27
+ {
28
+ parent::_construct();
29
+ $this->setTemplate(self::TEMPLATE_PATH);
30
+ }
31
+ }
app/code/community/Magpleasure/Filesystem/Block/Adminhtml/Ide/Tree.php ADDED
@@ -0,0 +1,43 @@
1
+ <?php
2
+ /**
3
+ * MagPleasure Co.
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the EULA
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www.magpleasure.com/LICENSE.txt
11
+ *
12
+ * @category Magpleasure
13
+ * @package Magpleasure_Filesystem
14
+ * @copyright Copyright (c) 2011 Magpleasure Co. (http://www.magpleasure.com)
15
+ * @license http://www.magpleasure.com/LICENSE.txt
16
+ */
17
+
18
+
19
+ class Magpleasure_Filesystem_Block_Adminhtml_Ide_Tree extends Mage_Adminhtml_Block_Abstract
20
+ {
21
+ /**
22
+ * Template path
23
+ */
24
+ const TEMPLATE_PATH = 'filesystem/ide/tree.phtml';
25
+
26
+ protected function _construct()
27
+ {
28
+ parent::_construct();
29
+ $this->setTemplate(self::TEMPLATE_PATH);
30
+ }
31
+
32
+ public function getTreeHtml()
33
+ {
34
+ $url = $this->getUrl("filesystem/adminhtml_filesystem/load", array('fn'=>"{{filename}}"));
35
+ return Mage::getModel('filesystem/tree')->php_file_tree(Mage::getBaseDir(), "javascript:openFile('{$url}','[link]');");
36
+ }
37
+
38
+ public function getFormKey()
39
+ {
40
+ return Mage::getSingleton('core/session')->getFormKey();
41
+ }
42
+
43
+ }
app/code/community/Magpleasure/Filesystem/Helper/Data.php ADDED
@@ -0,0 +1,20 @@
1
+ <?php
2
+ /**
3
+ * MagPleasure Co.
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the EULA
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www.magpleasure.com/LICENSE.txt
11
+ *
12
+ * @category Magpleasure
13
+ * @package Magpleasure_Filesystem
14
+ * @copyright Copyright (c) 2011 Magpleasure Co. (http://www.magpleasure.com)
15
+ * @license http://www.magpleasure.com/LICENSE.txt
16
+ */
17
+ class Magpleasure_Filesystem_Helper_Data extends Mage_Core_Helper_Abstract
18
+ {
19
+
20
+ }
app/code/community/Magpleasure/Filesystem/Model/Tree.php ADDED
@@ -0,0 +1,102 @@
1
+ <?php
2
+ /**
3
+ * MagPleasure Co.
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the EULA
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www.magpleasure.com/LICENSE.txt
11
+ *
12
+ * @category Magpleasure
13
+ * @package Magpleasure_Filesystem
14
+ * @copyright Copyright (c) 2011 Magpleasure Co. (http://www.magpleasure.com)
15
+ * @license http://www.magpleasure.com/LICENSE.txt
16
+ */
17
+ class Magpleasure_Filesystem_Model_Tree extends Mage_Core_Model_Abstract
18
+ {
19
+ public function _construct()
20
+ {
21
+ parent::_construct();
22
+ $this->_init('filesystem/tree');
23
+ }
24
+
25
+ public function php_file_tree($directory, $return_link, $extensions = array()) {
26
+ // Generates a valid XHTML list of all directories, sub-directories, and files in $directory
27
+ // Remove trailing slash
28
+ $code = "";
29
+ if( substr($directory, -1) == "/" ) $directory = substr($directory, 0, strlen($directory) - 1);
30
+ $code .= $this->php_file_tree_dir($directory, $return_link, $extensions);
31
+ return $code;
32
+ }
33
+
34
+ public function php_file_tree_dir($directory, $return_link, $extensions = array(), $first_call = true) {
35
+ // Recursive function called by php_file_tree() to list directories/files
36
+ $php_file_tree = '';
37
+
38
+ ///@TODO temporary placeholder
39
+ /// missing media and var directories
40
+ $nonGratte = array(Mage::getBaseDir().DS."media",Mage::getBaseDir().DS."var");
41
+ if (in_array($directory, $nonGratte)){
42
+ return '';
43
+ }
44
+ /// End temparary part
45
+
46
+ // Get and sort directories/files
47
+ if( function_exists("scandir") ) $file = scandir($directory); else $file = $this->php4_scandir($directory);
48
+ natcasesort($file);
49
+ // Make directories first
50
+ $files = $dirs = array();
51
+ foreach($file as $this_file) {
52
+ if( is_dir("$directory/$this_file" ) ) $dirs[] = $this_file; else $files[] = $this_file;
53
+ }
54
+ $file = array_merge($dirs, $files);
55
+
56
+ // Filter unwanted extensions
57
+ if( !empty($extensions) ) {
58
+ foreach( array_keys($file) as $key ) {
59
+ if( !is_dir("$directory/$file[$key]") ) {
60
+ $ext = substr($file[$key], strrpos($file[$key], ".") + 1);
61
+ if( !in_array($ext, $extensions) ) unset($file[$key]);
62
+ }
63
+ }
64
+ }
65
+
66
+ if( count($file) > 2 ) { // Use 2 instead of 0 to account for . and .. "directories"
67
+ $php_file_tree = "<ul";
68
+ if( $first_call ) { $php_file_tree .= " class=\"php-file-tree\""; $first_call = false; }
69
+ $php_file_tree .= ">";
70
+ foreach( $file as $this_file ) {
71
+ if( $this_file != "." && $this_file != ".." ) {
72
+ if( is_dir("$directory/$this_file") ) {
73
+ // Directory
74
+ $php_file_tree .= "<li class=\"pft-directory\"><a href=\"#\">" . htmlspecialchars($this_file) . "</a>";
75
+ $php_file_tree .= $this->php_file_tree_dir("$directory/$this_file", $return_link ,$extensions, false);
76
+ $php_file_tree .= "</li>";
77
+ } else {
78
+ // File
79
+ // Get extension (prepend 'ext-' to prevent invalid classes from extensions that begin with numbers)
80
+ $ext = "ext-" . substr($this_file, strrpos($this_file, ".") + 1);
81
+ $link = str_replace("[link]", "$directory/" . urlencode($this_file), $return_link);
82
+ $php_file_tree .= "<li class=\"pft-file " . strtolower($ext) . "\"><a href=\"$link\">" . htmlspecialchars($this_file) . "</a></li>";
83
+ }
84
+ }
85
+ }
86
+ $php_file_tree .= "</ul>";
87
+ }
88
+ return $php_file_tree;
89
+ }
90
+
91
+ // For PHP4 compatibility
92
+ public function php4_scandir($dir) {
93
+ $dh = opendir($dir);
94
+ while( false !== ($filename = readdir($dh)) ) {
95
+ $files[] = $filename;
96
+ }
97
+ sort($files);
98
+ return($files);
99
+ }
100
+
101
+
102
+ }
app/code/community/Magpleasure/Filesystem/controllers/Adminhtml/FilesystemController.php ADDED
@@ -0,0 +1,310 @@
1
+ <?php
2
+ /**
3
+ * MagPleasure Co.
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the EULA
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www.magpleasure.com/LICENSE.txt
11
+ *
12
+ * @category Magpleasure
13
+ * @package Magpleasure_Filesystem
14
+ * @copyright Copyright (c) 2011 Magpleasure Co. (http://www.magpleasure.com)
15
+ * @license http://www.magpleasure.com/LICENSE.txt
16
+ */
17
+
18
+ class Magpleasure_Filesystem_Adminhtml_FilesystemController extends Mage_Adminhtml_Controller_action
19
+ {
20
+
21
+ protected function _isAllowed()
22
+ {
23
+ return Mage::getSingleton('admin/session')->isAllowed('system/filesystem/edit');
24
+ }
25
+
26
+ protected function _initAction()
27
+ {
28
+ $this->loadLayout()
29
+ ->_setActiveMenu('filesystem/items')
30
+ ->_addBreadcrumb(Mage::helper('adminhtml')->__('File Syslem'), Mage::helper('adminhtml')->__('IDE'));
31
+ return $this;
32
+ }
33
+
34
+ /**
35
+ * Response for Ajax Request
36
+ * @param array $result
37
+ */
38
+ protected function _ajaxResponse($result = array())
39
+ {
40
+ $this->getResponse()->setBody(Zend_Json::encode($result));
41
+ }
42
+
43
+ public function indexAction()
44
+ {
45
+ $this->_initAction()
46
+ ->renderLayout();
47
+ }
48
+
49
+ /**
50
+ * Helper
51
+ * @return Magpleasure_Filesystem_Helper_Data
52
+ */
53
+ protected function _helper()
54
+ {
55
+ return Mage::helper('filesystem');
56
+ }
57
+
58
+
59
+ /**
60
+ * Session
61
+ * @return Mage_Adminhtml_Model_Session
62
+ */
63
+ protected function _getSession()
64
+ {
65
+ return Mage::getModel('adminhtml/session');
66
+ }
67
+
68
+ /**
69
+ * File ids
70
+ * @return array
71
+ */
72
+ protected function _getFiles()
73
+ {
74
+ $files = array();
75
+
76
+ if ($this->_getSession()->getFileInfo()){
77
+ $files = $this->_getSession()->getFileInfo();
78
+ } else {
79
+ $this->_getSession()->setFileInfo($files);
80
+ }
81
+ return $files;
82
+ }
83
+
84
+ /**
85
+ * Save store files
86
+ * @param array $files
87
+ * @return Magpleasure_Filesystem_Adminhtml_FilesystemController
88
+ */
89
+ protected function _setFiles($files)
90
+ {
91
+ $this->_getSession()->setFileInfo($files);
92
+ return $this;
93
+ }
94
+
95
+ /**
96
+ * Is file opened
97
+ *
98
+ * @param string $path
99
+ * @return boolean
100
+ */
101
+ protected function _isFileOpened($path)
102
+ {
103
+ if (is_numeric($path)){
104
+ return !!$this->_getPath($path);
105
+ } else {
106
+ return !!$this->_getFile($path);
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Open file, save identifier
112
+ *
113
+ * @param string $path
114
+ * @return int
115
+ */
116
+ protected function _openFile($path)
117
+ {
118
+ $id = 0;
119
+ if (!$this->_isFileOpened($path)){
120
+ $files = $this->_getFiles();
121
+ $id = rand();
122
+ $files[$id] = $path;
123
+ $this->_setFiles($files);
124
+ }
125
+ return $id;
126
+ }
127
+
128
+ /**
129
+ * Close file
130
+ * @param type $id
131
+ * @return Magpleasure_Filesystem_Adminhtml_FilesystemController
132
+ */
133
+ protected function _closeFile($id)
134
+ {
135
+ if ($this->_isFileOpened($id)){
136
+ $files = $this->_getFiles();
137
+ if (isset($files[$id])){
138
+ unset($files[$id]);
139
+ }
140
+ $this->_setFiles($files);
141
+ }
142
+ return $this;
143
+ }
144
+
145
+ /**
146
+ * Get file path
147
+ * @param $file
148
+ * @return string|boolean
149
+ */
150
+ protected function _getPath($file)
151
+ {
152
+ $files = $this->_getFiles();
153
+ if (isset($files[$file]) && $files[$file]){
154
+ return $files[$file];
155
+ }
156
+ return false;
157
+ }
158
+
159
+ /**
160
+ * Get file id
161
+ * @param $file
162
+ * @return int|boolean
163
+ */
164
+ protected function _getFile($path)
165
+ {
166
+ $files = $this->_getFiles();
167
+ foreach ($files as $_file=>$_path){
168
+ if ($path == $_path){
169
+ return $_file;
170
+ }
171
+ }
172
+ return false;
173
+ }
174
+
175
+ public function treeAction()
176
+ {
177
+ $dir = $this->getRequest()->getPost('dir');
178
+ $root = '';
179
+
180
+
181
+ $dir = urldecode($dir);
182
+ $response = "";
183
+
184
+ if( file_exists($root . $dir) ) {
185
+ $files = scandir($root . $dir);
186
+ natcasesort($files);
187
+ if( count($files) > 2 ) { /* The 2 accounts for . and .. */
188
+ $response .= "<ul class=\"jqueryFileTree\" style=\"display: none;\">";
189
+ // All dirs
190
+ foreach( $files as $file ) {
191
+ if( file_exists($root . $dir . $file) && $file != '.' && $file != '..' && is_dir($root . $dir . $file) ) {
192
+ $response .= "<li class=\"directory collapsed\"><a href=\"#\" rel=\"" . htmlentities($dir . $file) . "/\">" . htmlentities($file) . "</a></li>";
193
+ }
194
+ }
195
+ // All files
196
+ foreach( $files as $file ) {
197
+ if( file_exists($root . $dir . $file) && $file != '.' && $file != '..' && !is_dir($root . $dir . $file) ) {
198
+ $ext = preg_replace('/^.*\./', '', $file);
199
+ $response .= "<li class=\"file ext_$ext\"><a href=\"#\" rel=\"" . htmlentities($dir . $file) . "\">" . htmlentities($file) . "</a></li>";
200
+ }
201
+ }
202
+ $response .= "</ul>";
203
+ }
204
+ }
205
+
206
+ $this->getResponse()->setBody($response);
207
+ }
208
+
209
+ protected function _preparePathToShow($path)
210
+ {
211
+ return (str_replace(Mage::getBaseDir()."/", "", $path));
212
+ }
213
+
214
+ public function loadAction()
215
+ {
216
+ $result = array();
217
+ if ($filename = $this->getRequest()->getParam('fn')){
218
+ $filename = base64_decode($filename);
219
+ try {
220
+ if (file_exists($filename)){
221
+
222
+ if (!$this->_isFileOpened($filename)){
223
+ $path_parts = pathinfo($filename);
224
+
225
+ $content['id'] = $this->_openFile($filename);
226
+ $content['syntax'] = ($path_parts['extension'] == 'phtml') ? 'php' : $path_parts['extension'];
227
+ $content['text'] = file_get_contents($filename);
228
+ $content['title'] = $path_parts['basename'];
229
+
230
+ $result['path'] = $this->_preparePathToShow($filename);
231
+ $result['success'] = true;
232
+ $result['content'] = Zend_Json_Encoder::encode($content);
233
+ } else {
234
+ $result['error'] = $this->_helper()->__('This file is opened already');
235
+ }
236
+
237
+ }
238
+ } catch (Exception $e) {
239
+ $result['error'] = $e->getMessage();
240
+ }
241
+ }
242
+ $this->_ajaxResponse($result);
243
+ }
244
+
245
+ public function saveAction()
246
+ {
247
+ $result = array();
248
+ $content = $this->getRequest()->getPost('content');
249
+ $file = $this->getRequest()->getParam('file');
250
+ if ($file && $this->_isFileOpened($file) && !is_null($content)){
251
+ try {
252
+ file_put_contents($this->_getPath($file), $content);
253
+ $result['success'] = true;
254
+ } catch (Exception $e) {
255
+ $result['error'] = $e->getMessage();
256
+ }
257
+ } else {
258
+ $result['error'] = $this->_helper()->__('Wrong file id');
259
+ }
260
+ $this->_ajaxResponse($result);
261
+ }
262
+
263
+ public function closeAction()
264
+ {
265
+ $result = array();
266
+ $file = $this->getRequest()->getParam('file');
267
+ if ($file && $this->_isFileOpened($file)){
268
+ $this->_closeFile($file);
269
+ $result['success'] = true;
270
+ } else {
271
+ $result['error'] = $this->_helper()->__('Wrong file id');
272
+ }
273
+ $this->_ajaxResponse($result);
274
+ }
275
+
276
+ public function filesAction()
277
+ {
278
+ $result = array();
279
+ $files = $this->_getFiles();
280
+
281
+ $_files = array();
282
+
283
+ try {
284
+ foreach ($files as $_file=>$_path){
285
+ if (file_exists($_path)){
286
+ $path_parts = pathinfo($_path);
287
+
288
+ $content = array();
289
+ $content['id'] = $_file;
290
+ $content['syntax'] = ($path_parts['extension'] == 'phtml') ? 'php' : $path_parts['extension'];
291
+ $content['text'] = file_get_contents($_path);
292
+ $content['title'] = $path_parts['basename'];
293
+ $content['path'] = $this->_preparePathToShow($_path);
294
+
295
+ $_files[] = Zend_Json_Encoder::encode($content);
296
+
297
+ } else {
298
+ $this->_closeFile($_file);
299
+ }
300
+ }
301
+ $result['files'] = $_files;
302
+ $result['success'] = true;
303
+ } catch (Exception $e) {
304
+ $result['error'] = $e->getMessage();
305
+ }
306
+
307
+ $this->_ajaxResponse($result);
308
+ }
309
+
310
+ }
app/code/community/Magpleasure/Filesystem/etc/adminhtml.xml ADDED
@@ -0,0 +1,70 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <menu>
4
+ <system>
5
+ <children>
6
+ <filesystem module="filesystem">
7
+ <title>Filesystem</title>
8
+ <sort_order>70</sort_order>
9
+ <children>
10
+ <edit module="filesystem">
11
+ <title>IDE</title>
12
+ <sort_order>10</sort_order>
13
+ <action>filesystem/adminhtml_filesystem</action>
14
+ </edit>
15
+ <!-- <config module="filesystem">
16
+ <title>Configuration</title>
17
+ <sort_order>20</sort_order>
18
+ <action>adminhtml/system_config/edit/section/filesystem</action>
19
+ </config>-->
20
+ </children>
21
+ </filesystem>
22
+ </children>
23
+ </system>
24
+
25
+ </menu>
26
+ <acl>
27
+ <resources>
28
+ <all>
29
+ <title>Allow Everything</title>
30
+ </all>
31
+ <admin>
32
+ <children>
33
+ <system>
34
+ <children>
35
+ <filesystem>
36
+ <title>File System</title>
37
+ <sort_order>10</sort_order>
38
+ <children>
39
+ <edit>
40
+ <title>IDE</title>
41
+ <sort_order>10</sort_order>
42
+ </edit>
43
+ <!-- <config>
44
+ <title>Configuration</title>
45
+ <sort_order>20</sort_order>
46
+ </config>-->
47
+ </children>
48
+ </filesystem>
49
+ <config>
50
+ <children>
51
+ <filesystem>
52
+ <title>MagPleasure - File System Configuration</title>
53
+ </filesystem>
54
+ </children>
55
+ </config>
56
+ </children>
57
+ </system>
58
+
59
+ </children>
60
+ </admin>
61
+ </resources>
62
+ </acl>
63
+ <layout>
64
+ <updates>
65
+ <filesystem>
66
+ <file>filesystem.xml</file>
67
+ </filesystem>
68
+ </updates>
69
+ </layout>
70
+ </config>
app/code/community/Magpleasure/Filesystem/etc/config.xml ADDED
@@ -0,0 +1,137 @@
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Magpleasure_Filesystem>
5
+ <version>1.0</version>
6
+ </Magpleasure_Filesystem>
7
+ </modules>
8
+ <frontend>
9
+
10
+ </frontend>
11
+ <admin>
12
+ <routers>
13
+ <filesystem>
14
+ <use>admin</use>
15
+ <args>
16
+ <module>Magpleasure_Filesystem</module>
17
+ <frontName>filesystem</frontName>
18
+ </args>
19
+ </filesystem>
20
+ </routers>
21
+ </admin>
22
+ <adminhtml>
23
+ <menu>
24
+ <system>
25
+ <children>
26
+ <filesystem module="filesystem">
27
+ <title>Filesystem</title>
28
+ <sort_order>70</sort_order>
29
+ <children>
30
+ <edit module="filesystem">
31
+ <title>IDE</title>
32
+ <sort_order>10</sort_order>
33
+ <action>filesystem/adminhtml_filesystem</action>
34
+ </edit>
35
+ <!-- <config module="filesystem">
36
+ <title>Configuration</title>
37
+ <sort_order>20</sort_order>
38
+ <action>adminhtml/system_config/edit/section/filesystem</action>
39
+ </config>-->
40
+ </children>
41
+ </filesystem>
42
+ </children>
43
+ </system>
44
+
45
+ </menu>
46
+ <acl>
47
+ <resources>
48
+ <all>
49
+ <title>Allow Everything</title>
50
+ </all>
51
+ <admin>
52
+ <children>
53
+ <system>
54
+ <children>
55
+ <filesystem>
56
+ <title>File System</title>
57
+ <sort_order>10</sort_order>
58
+ <children>
59
+ <edit>
60
+ <title>IDE</title>
61
+ <sort_order>10</sort_order>
62
+ </edit>
63
+ <!-- <config>
64
+ <title>Configuration</title>
65
+ <sort_order>20</sort_order>
66
+ </config>-->
67
+ </children>
68
+ </filesystem>
69
+ <config>
70
+ <children>
71
+ <filesystem>
72
+ <title>MagPleasure - File System Configuration</title>
73
+ </filesystem>
74
+ </children>
75
+ </config>
76
+ </children>
77
+ </system>
78
+
79
+ </children>
80
+ </admin>
81
+ </resources>
82
+ </acl>
83
+ <layout>
84
+ <updates>
85
+ <filesystem>
86
+ <file>filesystem.xml</file>
87
+ </filesystem>
88
+ </updates>
89
+ </layout>
90
+ </adminhtml>
91
+ <global>
92
+ <models>
93
+ <filesystem>
94
+ <class>Magpleasure_Filesystem_Model</class>
95
+ <resourceModel>filesystem_mysql4</resourceModel>
96
+ </filesystem>
97
+ <filesystem_mysql4>
98
+ <class>Magpleasure_Filesystem_Model_Mysql4</class>
99
+ <entities>
100
+ <filesystem>
101
+ <table>filesystem</table>
102
+ </filesystem>
103
+ </entities>
104
+ </filesystem_mysql4>
105
+ </models>
106
+ <resources>
107
+ <filesystem_setup>
108
+ <setup>
109
+ <module>Magpleasure_Filesystem</module>
110
+ </setup>
111
+ <connection>
112
+ <use>core_setup</use>
113
+ </connection>
114
+ </filesystem_setup>
115
+ <filesystem_write>
116
+ <connection>
117
+ <use>core_write</use>
118
+ </connection>
119
+ </filesystem_write>
120
+ <filesystem_read>
121
+ <connection>
122
+ <use>core_read</use>
123
+ </connection>
124
+ </filesystem_read>
125
+ </resources>
126
+ <blocks>
127
+ <filesystem>
128
+ <class>Magpleasure_Filesystem_Block</class>
129
+ </filesystem>
130
+ </blocks>
131
+ <helpers>
132
+ <filesystem>
133
+ <class>Magpleasure_Filesystem_Helper</class>
134
+ </filesystem>
135
+ </helpers>
136
+ </global>
137
+ </config>
app/code/community/Magpleasure/Filesystem/etc/system.xml ADDED
@@ -0,0 +1,42 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <tabs>
4
+ <magpleasure translate="label" module="filesystem">
5
+ <label>MagPleasure Extensions</label>
6
+ <sort_order>300</sort_order>
7
+ </magpleasure>
8
+ </tabs>
9
+ <sections>
10
+ <filesystem translate="label" module="filesystem">
11
+ <label>File System</label>
12
+ <tab>magpleasure</tab>
13
+ <frontend_type>text</frontend_type>
14
+ <sort_order>150</sort_order>
15
+ <show_in_default>1</show_in_default>
16
+ <show_in_website>1</show_in_website>
17
+ <show_in_store>1</show_in_store>
18
+ <groups>
19
+ <general>
20
+ <label>General</label>
21
+ <frontend_type>text</frontend_type>
22
+ <sort_order>10</sort_order>
23
+ <show_in_default>1</show_in_default>
24
+ <show_in_website>1</show_in_website>
25
+ <show_in_store>1</show_in_store>
26
+ <fields>
27
+ <!-- <show translate="label">
28
+ <label>Show block</label>
29
+ <comment></comment>
30
+ <frontend_type>select</frontend_type>
31
+ <sort_order>10</sort_order>
32
+ <show_in_default>1</show_in_default>
33
+ <show_in_website>1</show_in_website>
34
+ <show_in_store>1</show_in_store>
35
+ <source_model>adminhtml/system_config_source_yesno</source_model>
36
+ </show> -->
37
+ </fields>
38
+ </general>
39
+ </groups>
40
+ </filesystem>
41
+ </sections>
42
+ </config>
app/code/community/Magpleasure/Filesystem/sql/filesystem_setup/mysql4-install-1.0.php ADDED
@@ -0,0 +1,20 @@
1
+ <?php
2
+ /**
3
+ * MagPleasure Co.
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the EULA
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www.magpleasure.com/LICENSE.txt
11
+ *
12
+ * @category Magpleasure
13
+ * @package Magpleasure_Filesystem
14
+ * @copyright Copyright (c) 2011 Magpleasure Co. (http://www.magpleasure.com)
15
+ * @license http://www.magpleasure.com/LICENSE.txt
16
+ */
17
+ $installer = $this;
18
+
19
+ $installer->startSetup();
20
+ $installer->endSetup();
app/design/adminhtml/default/default/layout/filesystem.xml ADDED
@@ -0,0 +1,19 @@
1
+ <?xml version="1.0"?>
2
+ <layout version="0.1.0">
3
+ <filesystem_adminhtml_filesystem_index>
4
+ <reference name="head">
5
+ <action method="addJs"><script>filesystem/jquery-1.4.2.min.js</script></action>
6
+ <action method="addJs"><script>filesystem/base64.js</script></action>
7
+ <action method="addJs"><script>filesystem/script.js</script></action>
8
+ <action method="addJs"><script>filesystem/jqueryfiletree.js</script></action>
9
+ <action method="addCss"><script>filesystem/css/styles.css</script></action>
10
+ <action method="addCss"><script>filesystem/css/jqueryfiletree.css</script></action>
11
+ </reference>
12
+ <reference name="content">
13
+ <block type="filesystem/adminhtml_ide" name="filesystem" template="filesystem/ide.phtml" >
14
+ <block type="filesystem/adminhtml_ide_tree" name="filesystem.tree" as="filesystem.tree" />
15
+ <block type="filesystem/adminhtml_ide_editor" name="filesystem.editor" as="filesystem.editor" />
16
+ </block>
17
+ </reference>
18
+ </filesystem_adminhtml_filesystem_index>
19
+ </layout>
app/design/adminhtml/default/default/template/filesystem/ide.phtml ADDED
@@ -0,0 +1,28 @@
1
+ <?php
2
+ /**
3
+ * MagPleasure Co.
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the EULA
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www.magpleasure.com/LICENSE.txt
11
+ *
12
+ * @category Magpleasure
13
+ * @package Magpleasure_Filesystem
14
+ * @copyright Copyright (c) 2011 Magpleasure Co. (http://www.magpleasure.com)
15
+ * @license http://www.magpleasure.com/LICENSE.txt
16
+ */
17
+ ?>
18
+
19
+ <div class="ide">
20
+ <div class="tree">
21
+ <h2><?php echo $this->__('File System') ?></h2>
22
+ <?php echo $this->getChildHtml('filesystem.tree'); ?>
23
+ </div>
24
+ <div class="editor">
25
+ <?php echo $this->getChildHtml('filesystem.editor'); ?>
26
+ </div>
27
+ </div>
28
+
app/design/adminhtml/default/default/template/filesystem/ide/editor.phtml ADDED
@@ -0,0 +1,46 @@
1
+ <?php
2
+ /**
3
+ * MagPleasure Co.
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the EULA
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www.magpleasure.com/LICENSE.txt
11
+ *
12
+ * @category Magpleasure
13
+ * @package Magpleasure_Filesystem
14
+ * @copyright Copyright (c) 2011 Magpleasure Co. (http://www.magpleasure.com)
15
+ * @license http://www.magpleasure.com/LICENSE.txt
16
+ */
17
+ ?>
18
+ <div class="path" id="path">
19
+ <?php echo $this->getPath(); ?>
20
+ </div>
21
+ <textarea id="edit_area"></textarea>
22
+
23
+ <script type="text/javascript" src="<?php echo Mage::getBaseUrl('web').'js/editarea/edit_area_full.js'; ?>"></script>
24
+
25
+ <script language="javascript" type="text/javascript">
26
+
27
+ _closeUrl = '<?php echo $this->getUrl('filesystem/adminhtml_filesystem/close', array('file'=>'{{file}}')) ?>';
28
+ _saveUrl = '<?php echo $this->getUrl('filesystem/adminhtml_filesystem/save', array('file'=>'{{file}}')) ?>';
29
+ _filesUrl = '<?php echo $this->getUrl('filesystem/adminhtml_filesystem/files', array('file'=>'{{file}}')) ?>';
30
+
31
+ editAreaLoader.init({
32
+ id : "edit_area",
33
+ syntax: "css",
34
+ syntax_selection_allow: "css,html,js,php,python,xml,sql",
35
+ start_highlight: true,
36
+ toolbar: "save, |, search, go_to_line, |, undo, redo, |, select_font, |, syntax_selection, |, change_smooth_selection, highlight, reset_highlight, |, help",
37
+ save_callback: "saveFile",
38
+ EA_file_switch_on_callback: "switchOn",
39
+ EA_file_close_callback: "closeFile",
40
+ replace_tab_by_spaces: 4,
41
+ allow_resize: true,
42
+ EA_load_callback: "getFiles"
43
+ });
44
+
45
+ </script>
46
+
app/design/adminhtml/default/default/template/filesystem/ide/tree.phtml ADDED
@@ -0,0 +1,35 @@
1
+ <?php
2
+ /**
3
+ * MagPleasure Co.
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the EULA
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www.magpleasure.com/LICENSE.txt
11
+ *
12
+ * @category Magpleasure
13
+ * @package Magpleasure_Filesystem
14
+ * @copyright Copyright (c) 2011 Magpleasure Co. (http://www.magpleasure.com)
15
+ * @license http://www.magpleasure.com/LICENSE.txt
16
+ */
17
+ ?>
18
+
19
+ <div class="file-tree-wrapper">
20
+ <div class="file-tree" id="file_tree"></div>
21
+ </div>
22
+
23
+ <script type="text/javascript">
24
+ jQuery(document).ready( function() {
25
+ jQuery('#file_tree').fileTree({
26
+ root: '<?php echo Mage::getBaseDir(); ?>/',
27
+ script: '<?php echo $this->getUrl('filesystem/adminhtml_filesystem/tree', array('isAjax'=> true, 'form_key'=>$this->getFormKey())) ?>',
28
+ expandSpeed: 200,
29
+ collapseSpeed: 200
30
+ }, function(file) {
31
+ var url = '<?php echo $this->getUrl("filesystem/adminhtml_filesystem/load", array("fn"=>"{{filename}}")) ?>';
32
+ openFile(url, file);
33
+ });
34
+ });
35
+ </script>
app/design/adminhtml/default/default/template/filesystem/wrapper.phtml ADDED
@@ -0,0 +1,17 @@
1
+ <?php
2
+ /**
3
+ * MagPleasure Co.
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the EULA
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www.magpleasure.com/LICENSE.txt
11
+ *
12
+ * @category Magpleasure
13
+ * @package Magpleasure_Filesystem
14
+ * @copyright Copyright (c) 2011 Magpleasure Co. (http://www.magpleasure.com)
15
+ * @license http://www.magpleasure.com/LICENSE.txt
16
+ */
17
+ ?>
app/etc/modules/Magpleasure_Filesystem.xml ADDED
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Magpleasure_Filesystem>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ </Magpleasure_Filesystem>
8
+ </modules>
9
+ </config>
js/editarea/autocompletion.js ADDED
@@ -0,0 +1,491 @@
1
+ /**
2
+ * Autocompletion class
3
+ *
4
+ * An auto completion box appear while you're writing. It's possible to force it to appear with Ctrl+Space short cut
5
+ *
6
+ * Loaded as a plugin inside editArea (everything made here could have been made in the plugin directory)
7
+ * But is definitly linked to syntax selection (no need to do 2 different files for color and auto complete for each syntax language)
8
+ * and add a too important feature that many people would miss if included as a plugin
9
+ *
10
+ * - init param: autocompletion_start
11
+ * - Button name: "autocompletion"
12
+ */
13
+
14
+ var EditArea_autocompletion= {
15
+
16
+ /**
17
+ * Get called once this file is loaded (editArea still not initialized)
18
+ *
19
+ * @return nothing
20
+ */
21
+ init: function(){
22
+ // alert("test init: "+ this._someInternalFunction(2, 3));
23
+
24
+ if(editArea.settings["autocompletion"])
25
+ this.enabled= true;
26
+ else
27
+ this.enabled= false;
28
+ this.current_word = false;
29
+ this.shown = false;
30
+ this.selectIndex = -1;
31
+ this.forceDisplay = false;
32
+ this.isInMiddleWord = false;
33
+ this.autoSelectIfOneResult = false;
34
+ this.delayBeforeDisplay = 100;
35
+ this.checkDelayTimer = false;
36
+ this.curr_syntax_str = '';
37
+
38
+ this.file_syntax_datas = {};
39
+ }
40
+ /**
41
+ * Returns the HTML code for a specific control string or false if this plugin doesn't have that control.
42
+ * A control can be a button, select list or any other HTML item to present in the EditArea user interface.
43
+ * Language variables such as {$lang_somekey} will also be replaced with contents from
44
+ * the language packs.
45
+ *
46
+ * @param {string} ctrl_name: the name of the control to add
47
+ * @return HTML code for a specific control or false.
48
+ * @type string or boolean
49
+ */
50
+ /*,get_control_html: function(ctrl_name){
51
+ switch( ctrl_name ){
52
+ case 'autocompletion':
53
+ // Control id, button img, command
54
+ return parent.editAreaLoader.get_button_html('autocompletion_but', 'autocompletion.gif', 'toggle_autocompletion', false, this.baseURL);
55
+ break;
56
+ }
57
+ return false;
58
+ }*/
59
+ /**
60
+ * Get called once EditArea is fully loaded and initialised
61
+ *
62
+ * @return nothing
63
+ */
64
+ ,onload: function(){
65
+ if(this.enabled)
66
+ {
67
+ var icon= document.getElementById("autocompletion");
68
+ if(icon)
69
+ editArea.switchClassSticky(icon, 'editAreaButtonSelected', true);
70
+ }
71
+
72
+ this.container = document.createElement('div');
73
+ this.container.id = "auto_completion_area";
74
+ editArea.container.insertBefore( this.container, editArea.container.firstChild );
75
+
76
+ // add event detection for hiding suggestion box
77
+ parent.editAreaLoader.add_event( document, "click", function(){ editArea.plugins['autocompletion']._hide();} );
78
+ parent.editAreaLoader.add_event( editArea.textarea, "blur", function(){ editArea.plugins['autocompletion']._hide();} );
79
+
80
+ }
81
+
82
+ /**
83
+ * Is called each time the user touch a keyboard key.
84
+ *
85
+ * @param (event) e: the keydown event
86
+ * @return true - pass to next handler in chain, false - stop chain execution
87
+ * @type boolean
88
+ */
89
+ ,onkeydown: function(e){
90
+ if(!this.enabled)
91
+ return true;
92
+
93
+ if (EA_keys[e.keyCode])
94
+ letter=EA_keys[e.keyCode];
95
+ else
96
+ letter=String.fromCharCode(e.keyCode);
97
+ // shown
98
+ if( this._isShown() )
99
+ {
100
+ // if escape, hide the box
101
+ if(letter=="Esc")
102
+ {
103
+ this._hide();
104
+ return false;
105
+ }
106
+ // Enter
107
+ else if( letter=="Entrer")
108
+ {
109
+ var as = this.container.getElementsByTagName('A');
110
+ // select a suggested entry
111
+ if( this.selectIndex >= 0 && this.selectIndex < as.length )
112
+ {
113
+ as[ this.selectIndex ].onmousedown();
114
+ return false
115
+ }
116
+ // simply add an enter in the code
117
+ else
118
+ {
119
+ this._hide();
120
+ return true;
121
+ }
122
+ }
123
+ else if( letter=="Tab" || letter=="Down")
124
+ {
125
+ this._selectNext();
126
+ return false;
127
+ }
128
+ else if( letter=="Up")
129
+ {
130
+ this._selectBefore();
131
+ return false;
132
+ }
133
+ }
134
+ // hidden
135
+ else
136
+ {
137
+
138
+ }
139
+
140
+ // show current suggestion list and do autoSelect if possible (no matter it's shown or hidden)
141
+ if( letter=="Space" && CtrlPressed(e) )
142
+ {
143
+ //parent.console.log('SHOW SUGGEST');
144
+ this.forceDisplay = true;
145
+ this.autoSelectIfOneResult = true;
146
+ this._checkLetter();
147
+ return false;
148
+ }
149
+
150
+ // wait a short period for check that the cursor isn't moving
151
+ setTimeout("editArea.plugins['autocompletion']._checkDelayAndCursorBeforeDisplay();", editArea.check_line_selection_timer +5 );
152
+ this.checkDelayTimer = false;
153
+ return true;
154
+ }
155
+ /**
156
+ * Executes a specific command, this function handles plugin commands.
157
+ *
158
+ * @param {string} cmd: the name of the command being executed
159
+ * @param {unknown} param: the parameter of the command
160
+ * @return true - pass to next handler in chain, false - stop chain execution
161
+ * @type boolean
162
+ */
163
+ ,execCommand: function(cmd, param){
164
+ switch( cmd ){
165
+ case 'toggle_autocompletion':
166
+ var icon= document.getElementById("autocompletion");
167
+ if(!this.enabled)
168
+ {
169
+ if(icon != null){
170
+ editArea.restoreClass(icon);
171
+ editArea.switchClassSticky(icon, 'editAreaButtonSelected', true);
172
+ }
173
+ this.enabled= true;
174
+ }
175
+ else
176
+ {
177
+ this.enabled= false;
178
+ if(icon != null)
179
+ editArea.switchClassSticky(icon, 'editAreaButtonNormal', false);
180
+ }
181
+ return true;
182
+ }
183
+ return true;
184
+ }
185
+ ,_checkDelayAndCursorBeforeDisplay: function()
186
+ {
187
+ this.checkDelayTimer = setTimeout("if(editArea.textarea.selectionStart == "+ editArea.textarea.selectionStart +") EditArea_autocompletion._checkLetter();", this.delayBeforeDisplay - editArea.check_line_selection_timer - 5 );
188
+ }
189
+ // hide the suggested box
190
+ ,_hide: function(){
191
+ this.container.style.display="none";
192
+ this.selectIndex = -1;
193
+ this.shown = false;
194
+ this.forceDisplay = false;
195
+ this.autoSelectIfOneResult = false;
196
+ }
197
+ // display the suggested box
198
+ ,_show: function(){
199
+ if( !this._isShown() )
200
+ {
201
+ this.container.style.display="block";
202
+ this.selectIndex = -1;
203
+ this.shown = true;
204
+ }
205
+ }
206
+ // is the suggested box displayed?
207
+ ,_isShown: function(){
208
+ return this.shown;
209
+ }
210
+ // setter and getter
211
+ ,_isInMiddleWord: function( new_value ){
212
+ if( typeof( new_value ) == "undefined" )
213
+ return this.isInMiddleWord;
214
+ else
215
+ this.isInMiddleWord = new_value;
216
+ }
217
+ // select the next element in the suggested box
218
+ ,_selectNext: function()
219
+ {
220
+ var as = this.container.getElementsByTagName('A');
221
+
222
+ // clean existing elements
223
+ for( var i=0; i<as.length; i++ )
224
+ {
225
+ if( as[i].className )
226
+ as[i].className = as[i].className.replace(/ focus/g, '');
227
+ }
228
+
229
+ this.selectIndex++;
230
+ this.selectIndex = ( this.selectIndex >= as.length || this.selectIndex < 0 ) ? 0 : this.selectIndex;
231
+ as[ this.selectIndex ].className += " focus";
232
+ }
233
+ // select the previous element in the suggested box
234
+ ,_selectBefore: function()
235
+ {
236
+ var as = this.container.getElementsByTagName('A');
237
+
238
+ // clean existing elements
239
+ for( var i=0; i<as.length; i++ )
240
+ {
241
+ if( as[i].className )
242
+ as[i].className = as[ i ].className.replace(/ focus/g, '');
243
+ }
244
+
245
+ this.selectIndex--;
246
+
247
+ this.selectIndex = ( this.selectIndex >= as.length || this.selectIndex < 0 ) ? as.length-1 : this.selectIndex;
248
+ as[ this.selectIndex ].className += " focus";
249
+ }
250
+ ,_select: function( content )
251
+ {
252
+ cursor_forced_position = content.indexOf( '{@}' );
253
+ content = content.replace(/{@}/g, '' );
254
+ editArea.getIESelection();
255
+
256
+ // retrive the number of matching characters
257
+ var start_index = Math.max( 0, editArea.textarea.selectionEnd - content.length );
258
+
259
+ line_string = editArea.textarea.value.substring( start_index, editArea.textarea.selectionEnd + 1);
260
+ limit = line_string.length -1;
261
+ nbMatch = 0;
262
+ for( i =0; i<limit ; i++ )
263
+ {
264
+ if( line_string.substring( limit - i - 1, limit ) == content.substring( 0, i + 1 ) )
265
+ nbMatch = i + 1;
266
+ }
267
+ // if characters match, we should include them in the selection that will be replaced
268
+ if( nbMatch > 0 )
269
+ parent.editAreaLoader.setSelectionRange(editArea.id, editArea.textarea.selectionStart - nbMatch , editArea.textarea.selectionEnd);
270
+
271
+ parent.editAreaLoader.setSelectedText(editArea.id, content );
272
+ range= parent.editAreaLoader.getSelectionRange(editArea.id);
273
+
274
+ if( cursor_forced_position != -1 )
275
+ new_pos = range["end"] - ( content.length-cursor_forced_position );
276
+ else
277
+ new_pos = range["end"];
278
+ parent.editAreaLoader.setSelectionRange(editArea.id, new_pos, new_pos);
279
+ this._hide();
280
+ }
281
+
282
+
283
+ /**
284
+ * Parse the AUTO_COMPLETION part of syntax definition files
285
+ */
286
+ ,_parseSyntaxAutoCompletionDatas: function(){
287
+ //foreach syntax loaded
288
+ for(var lang in parent.editAreaLoader.load_syntax)
289
+ {
290
+ if(!parent.editAreaLoader.syntax[lang]['autocompletion']) // init the regexp if not already initialized
291
+ {
292
+ parent.editAreaLoader.syntax[lang]['autocompletion']= {};
293
+ // the file has auto completion datas
294
+ if(parent.editAreaLoader.load_syntax[lang]['AUTO_COMPLETION'])
295
+ {
296
+ // parse them
297
+ for(var i in parent.editAreaLoader.load_syntax[lang]['AUTO_COMPLETION'])
298
+ {
299
+ datas = parent.editAreaLoader.load_syntax[lang]['AUTO_COMPLETION'][i];
300
+ tmp = {};
301
+ if(datas["CASE_SENSITIVE"]!="undefined" && datas["CASE_SENSITIVE"]==false)
302
+ tmp["modifiers"]="i";
303
+ else
304
+ tmp["modifiers"]="";
305
+ tmp["prefix_separator"]= datas["REGEXP"]["prefix_separator"];
306
+ tmp["match_prefix_separator"]= new RegExp( datas["REGEXP"]["prefix_separator"] +"quot;, tmp["modifiers"]);
307
+ tmp["match_word"]= new RegExp("(?:"+ datas["REGEXP"]["before_word"] +")("+ datas["REGEXP"]["possible_words_letters"] +")quot;, tmp["modifiers"]);
308
+ tmp["match_next_letter"]= new RegExp("^("+ datas["REGEXP"]["letter_after_word_must_match"] +")quot;, tmp["modifiers"]);
309
+ tmp["keywords"]= {};
310
+ //console.log( datas["KEYWORDS"] );
311
+ for( var prefix in datas["KEYWORDS"] )
312
+ {
313
+ tmp["keywords"][prefix]= {
314
+ prefix: prefix,
315
+ prefix_name: prefix,
316
+ prefix_reg: new RegExp("(?:"+ parent.editAreaLoader.get_escaped_regexp( prefix ) +")(?:"+ tmp["prefix_separator"] +")quot;, tmp["modifiers"] ),
317
+ datas: []
318
+ };
319
+ for( var j=0; j<datas["KEYWORDS"][prefix].length; j++ )
320
+ {
321
+ tmp["keywords"][prefix]['datas'][j]= {
322
+ is_typing: datas["KEYWORDS"][prefix][j][0],
323
+ // if replace with is empty, replace with the is_typing value
324
+ replace_with: datas["KEYWORDS"][prefix][j][1] ? datas["KEYWORDS"][prefix][j][1].replace('�', datas["KEYWORDS"][prefix][j][0] ) : '',
325
+ comment: datas["KEYWORDS"][prefix][j][2] ? datas["KEYWORDS"][prefix][j][2] : ''
326
+ };
327
+
328
+ // the replace with shouldn't be empty
329
+ if( tmp["keywords"][prefix]['datas'][j]['replace_with'].length == 0 )
330
+ tmp["keywords"][prefix]['datas'][j]['replace_with'] = tmp["keywords"][prefix]['datas'][j]['is_typing'];
331
+
332
+ // if the comment is empty, display the replace_with value
333
+ if( tmp["keywords"][prefix]['datas'][j]['comment'].length == 0 )
334
+ tmp["keywords"][prefix]['datas'][j]['comment'] = tmp["keywords"][prefix]['datas'][j]['replace_with'].replace(/{@}/g, '' );
335
+ }
336
+
337
+ }
338
+ tmp["max_text_length"]= datas["MAX_TEXT_LENGTH"];
339
+ parent.editAreaLoader.syntax[lang]['autocompletion'][i] = tmp;
340
+ }
341
+ }
342
+ }
343
+ }
344
+ }
345
+
346
+ ,_checkLetter: function(){
347
+ // check that syntax hasn't changed
348
+ if( this.curr_syntax_str != editArea.settings['syntax'] )
349
+ {
350
+ if( !parent.editAreaLoader.syntax[editArea.settings['syntax']]['autocompletion'] )
351
+ this._parseSyntaxAutoCompletionDatas();
352
+ this.curr_syntax= parent.editAreaLoader.syntax[editArea.settings['syntax']]['autocompletion'];
353
+ this.curr_syntax_str = editArea.settings['syntax'];
354
+ //console.log( this.curr_syntax );
355
+ }
356
+
357
+ if( editArea.is_editable )
358
+ {
359
+ time=new Date;
360
+ t1= time.getTime();
361
+ editArea.getIESelection();
362
+ this.selectIndex = -1;
363
+ start=editArea.textarea.selectionStart;
364
+ var str = editArea.textarea.value;
365
+ var results= [];
366
+
367
+
368
+ for(var i in this.curr_syntax)
369
+ {
370
+ var last_chars = str.substring(Math.max(0, start-this.curr_syntax[i]["max_text_length"]), start);
371
+ var matchNextletter = str.substring(start, start+1).match( this.curr_syntax[i]["match_next_letter"]);
372
+ // if not writting in the middle of a word or if forcing display
373
+ if( matchNextletter || this.forceDisplay )
374
+ {
375
+ // check if the last chars match a separator
376
+ var match_prefix_separator = last_chars.match(this.curr_syntax[i]["match_prefix_separator"]);
377
+
378
+ // check if it match a possible word
379
+ var match_word= last_chars.match(this.curr_syntax[i]["match_word"]);
380
+
381
+ //console.log( match_word );
382
+ if( match_word )
383
+ {
384
+ var begin_word= match_word[1];
385
+ var match_curr_word= new RegExp("^"+ parent.editAreaLoader.get_escaped_regexp( begin_word ), this.curr_syntax[i]["modifiers"]);
386
+ //console.log( match_curr_word );
387
+ for(var prefix in this.curr_syntax[i]["keywords"])
388
+ {
389
+ // parent.console.log( this.curr_syntax[i]["keywords"][prefix] );
390
+ for(var j=0; j<this.curr_syntax[i]["keywords"][prefix]['datas'].length; j++)
391
+ {
392
+ // parent.console.log( this.curr_syntax[i]["keywords"][prefix]['datas'][j]['is_typing'] );
393
+ // the key word match or force display
394
+ if( this.curr_syntax[i]["keywords"][prefix]['datas'][j]['is_typing'].match(match_curr_word) )
395
+ {
396
+ // parent.console.log('match');
397
+ hasMatch = false;
398
+ var before = last_chars.substr( 0, last_chars.length - begin_word.length );
399
+
400
+ // no prefix to match => it's valid
401
+ if( !match_prefix_separator && this.curr_syntax[i]["keywords"][prefix]['prefix'].length == 0 )
402
+ {
403
+ if( ! before.match( this.curr_syntax[i]["keywords"][prefix]['prefix_reg'] ) )
404
+ hasMatch = true;
405
+ }
406
+ // we still need to check the prefix if there is one
407
+ else if( this.curr_syntax[i]["keywords"][prefix]['prefix'].length > 0 )
408
+ {
409
+ if( before.match( this.curr_syntax[i]["keywords"][prefix]['prefix_reg'] ) )
410
+ hasMatch = true;
411
+ }
412
+
413
+ if( hasMatch )
414
+ results[results.length]= [ this.curr_syntax[i]["keywords"][prefix], this.curr_syntax[i]["keywords"][prefix]['datas'][j] ];
415
+ }
416
+ }
417
+ }
418
+ }
419
+ // it doesn't match any possible word but we want to display something
420
+ // we'll display to list of all available words
421
+ else if( this.forceDisplay || match_prefix_separator )
422
+ {
423
+ for(var prefix in this.curr_syntax[i]["keywords"])
424
+ {
425
+ for(var j=0; j<this.curr_syntax[i]["keywords"][prefix]['datas'].length; j++)
426
+ {
427
+ hasMatch = false;
428
+ // no prefix to match => it's valid
429
+ if( !match_prefix_separator && this.curr_syntax[i]["keywords"][prefix]['prefix'].length == 0 )
430
+ {
431
+ hasMatch = true;
432
+ }
433
+ // we still need to check the prefix if there is one
434
+ else if( match_prefix_separator && this.curr_syntax[i]["keywords"][prefix]['prefix'].length > 0 )
435
+ {
436
+ var before = last_chars; //.substr( 0, last_chars.length );
437
+ if( before.match( this.curr_syntax[i]["keywords"][prefix]['prefix_reg'] ) )
438
+ hasMatch = true;
439
+ }
440
+
441
+ if( hasMatch )
442
+ results[results.length]= [ this.curr_syntax[i]["keywords"][prefix], this.curr_syntax[i]["keywords"][prefix]['datas'][j] ];
443
+ }
444
+ }
445
+ }
446
+ }
447
+ }
448
+
449
+ // there is only one result, and we can select it automatically
450
+ if( results.length == 1 && this.autoSelectIfOneResult )
451
+ {
452
+ // console.log( results );
453
+ this._select( results[0][1]['replace_with'] );
454
+ }
455
+ else if( results.length == 0 )
456
+ {
457
+ this._hide();
458
+ }
459
+ else
460
+ {
461
+ // build the suggestion box content
462
+ var lines=[];
463
+ for(var i=0; i<results.length; i++)
464
+ {
465
+ var line= "<li><a href=\"#\" class=\"entry\" onmousedown=\"EditArea_autocompletion._select('"+ results[i][1]['replace_with'].replace(new RegExp('"', "g"), "&quot;") +"');return false;\">"+ results[i][1]['comment'];
466
+ if(results[i][0]['prefix_name'].length>0)
467
+ line+='<span class="prefix">'+ results[i][0]['prefix_name'] +'</span>';
468
+ line+='</a></li>';
469
+ lines[lines.length]=line;
470
+ }
471
+ // sort results
472
+ this.container.innerHTML = '<ul>'+ lines.sort().join('') +'</ul>';
473
+
474
+ var cursor = _$("cursor_pos");
475
+ this.container.style.top = ( cursor.cursor_top + editArea.lineHeight ) +"px";
476
+ this.container.style.left = ( cursor.cursor_left + 8 ) +"px";
477
+ this._show();
478
+ }
479
+
480
+ this.autoSelectIfOneResult = false;
481
+ time=new Date;
482
+ t2= time.getTime();
483
+
484
+ //parent.console.log( begin_word +"\n"+ (t2-t1) +"\n"+ html );
485
+ }
486
+ }
487
+ };
488
+
489
+ // Load as a plugin
490
+ editArea.settings['plugins'][ editArea.settings['plugins'].length ] = 'autocompletion';
491
+ editArea.add_plugin('autocompletion', EditArea_autocompletion);
js/editarea/edit_area.css ADDED
@@ -0,0 +1,530 @@
1
+ body, html{
2
+ margin: 0;
3
+ padding: 0;
4
+ height: 100%;
5
+ border: none;
6
+ overflow: hidden;
7
+ background-color: #FFF;
8
+ }
9
+
10
+ body, html, table, form, textarea{
11
+ font: 12px monospace, sans-serif;
12
+ }
13
+
14
+ #editor{
15
+ border: solid #888 1px;
16
+ overflow: hidden;
17
+ }
18
+
19
+ #result{
20
+ z-index: 4;
21
+ overflow-x: auto;
22
+ overflow-y: scroll;
23
+ border-top: solid #888 1px;
24
+ border-bottom: solid #888 1px;
25
+ position: relative;
26
+ clear: both;
27
+ }
28
+
29
+ #result.empty{
30
+ overflow: hidden;
31
+ }
32
+
33
+ #container{
34
+ overflow: hidden;
35
+ border: solid blue 0;
36
+ position: relative;
37
+ z-index: 10;
38
+ padding: 0 5px 0 45px;
39
+ /*padding-right: 5px;*/
40
+ }
41
+
42
+ #textarea{
43
+ position: relative;
44
+ top: 0;
45
+ left: 0;
46
+ margin: 0;
47
+ padding: 0;
48
+ width: 100%;
49
+ height: 100%;
50
+ overflow: hidden;
51
+ z-index: 7;
52
+ border-width: 0;
53
+ background-color: transparent;
54
+ resize: none;
55
+ }
56
+
57
+ #textarea, #textarea:hover{
58
+ outline: none; /* safari outline fix */
59
+ }
60
+
61
+ #content_highlight{
62
+ white-space: pre;
63
+ margin: 0;
64
+ padding: 0;
65
+ position : absolute;
66
+ z-index: 4;
67
+ overflow: visible;
68
+ }
69
+
70
+
71
+ #selection_field, #selection_field_text{
72
+ margin: 0;
73
+ background-color: #E1F2F9;
74
+ /* height: 1px; */
75
+ position: absolute;
76
+ z-index: 5;
77
+ top: -100px;
78
+ padding: 0;
79
+ white-space: pre;
80
+ overflow: hidden;
81
+ }
82
+
83
+ #selection_field.show_colors {
84
+ z-index: 3;
85
+ background-color:#EDF9FC;
86
+
87
+ }
88
+
89
+ #selection_field strong{
90
+ font-weight:normal;
91
+ }
92
+
93
+ #selection_field.show_colors *, #selection_field_text * {
94
+ visibility: hidden;
95
+ }
96
+
97
+ #selection_field_text{
98
+ background-color:transparent;
99
+ }
100
+
101
+ #selection_field_text strong{
102
+ font-weight:normal;
103
+ background-color:#3399FE;
104
+ color: #FFF;
105
+ visibility:visible;
106
+ }
107
+
108
+ #container.word_wrap #content_highlight,
109
+ #container.word_wrap #selection_field,
110
+ #container.word_wrap #selection_field_text,
111
+ #container.word_wrap #test_font_size{
112
+ white-space: pre-wrap; /* css-3 */
113
+ white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
114
+ white-space: -pre-wrap; /* Opera 4-6 */
115
+ white-space: -o-pre-wrap; /* Opera 7 */
116
+ word-wrap: break-word; /* Internet Explorer 5.5+ */
117
+ width: 99%;
118
+ }
119
+
120
+ #line_number{
121
+ position: absolute;
122
+ overflow: hidden;
123
+ border-right: solid black 1px;
124
+ z-index:8;
125
+ width: 38px;
126
+ padding: 0 5px 0 0;
127
+ margin: 0 0 0 -45px;
128
+ text-align: right;
129
+ color: #AAAAAA;
130
+ }
131
+
132
+ #test_font_size{
133
+ padding: 0;
134
+ margin: 0;
135
+ visibility: hidden;
136
+ position: absolute;
137
+ white-space: pre;
138
+ }
139
+
140
+ pre{