drg_elfinder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (185) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/drg_elfinder_manifest.js +1 -0
  6. data/app/assets/javascripts/drg_elfinder.js +15 -0
  7. data/app/assets/javascripts/elfinder/Changelog +1283 -0
  8. data/app/assets/javascripts/elfinder/LICENSE.md +15 -0
  9. data/app/assets/javascripts/elfinder/README.md +216 -0
  10. data/app/assets/javascripts/elfinder/bower.json +28 -0
  11. data/app/assets/javascripts/elfinder/composer.json +39 -0
  12. data/app/assets/javascripts/elfinder/css/elfinder.full.css +5350 -0
  13. data/app/assets/javascripts/elfinder/css/elfinder.min.css +9 -0
  14. data/app/assets/javascripts/elfinder/css/theme.css +430 -0
  15. data/app/assets/javascripts/elfinder/elfinder.html +74 -0
  16. data/app/assets/javascripts/elfinder/elfinder.legacy.html +94 -0
  17. data/app/assets/javascripts/elfinder/img/arrows-active.png +0 -0
  18. data/app/assets/javascripts/elfinder/img/arrows-normal.png +0 -0
  19. data/app/assets/javascripts/elfinder/img/crop.gif +0 -0
  20. data/app/assets/javascripts/elfinder/img/dialogs.png +0 -0
  21. data/app/assets/javascripts/elfinder/img/edit_aceeditor.png +0 -0
  22. data/app/assets/javascripts/elfinder/img/edit_ckeditor.png +0 -0
  23. data/app/assets/javascripts/elfinder/img/edit_ckeditor5.png +0 -0
  24. data/app/assets/javascripts/elfinder/img/edit_codemirror.png +0 -0
  25. data/app/assets/javascripts/elfinder/img/edit_creativecloud.png +0 -0
  26. data/app/assets/javascripts/elfinder/img/edit_onlineconvert.png +0 -0
  27. data/app/assets/javascripts/elfinder/img/edit_pixlreditor.png +0 -0
  28. data/app/assets/javascripts/elfinder/img/edit_pixlrexpress.png +0 -0
  29. data/app/assets/javascripts/elfinder/img/edit_simplemde.png +0 -0
  30. data/app/assets/javascripts/elfinder/img/edit_tinymce.png +0 -0
  31. data/app/assets/javascripts/elfinder/img/edit_tuiimgedit.png +0 -0
  32. data/app/assets/javascripts/elfinder/img/edit_zohooffice.png +0 -0
  33. data/app/assets/javascripts/elfinder/img/editor-icons.png +0 -0
  34. data/app/assets/javascripts/elfinder/img/icons-big.png +0 -0
  35. data/app/assets/javascripts/elfinder/img/icons-big.svg +1 -0
  36. data/app/assets/javascripts/elfinder/img/icons-small.png +0 -0
  37. data/app/assets/javascripts/elfinder/img/logo.png +0 -0
  38. data/app/assets/javascripts/elfinder/img/progress.gif +0 -0
  39. data/app/assets/javascripts/elfinder/img/quicklook-bg.png +0 -0
  40. data/app/assets/javascripts/elfinder/img/quicklook-icons.png +0 -0
  41. data/app/assets/javascripts/elfinder/img/resize.png +0 -0
  42. data/app/assets/javascripts/elfinder/img/spinner-mini.gif +0 -0
  43. data/app/assets/javascripts/elfinder/img/toolbar.png +0 -0
  44. data/app/assets/javascripts/elfinder/img/trashmesh.png +0 -0
  45. data/app/assets/javascripts/elfinder/img/tui-icon-a.svg +235 -0
  46. data/app/assets/javascripts/elfinder/img/tui-icon-b.svg +224 -0
  47. data/app/assets/javascripts/elfinder/img/tui-icon-c.svg +224 -0
  48. data/app/assets/javascripts/elfinder/img/tui-icon-d.svg +224 -0
  49. data/app/assets/javascripts/elfinder/img/ui-icons_ffffff_256x240.png +0 -0
  50. data/app/assets/javascripts/elfinder/img/volume_icon_box.png +0 -0
  51. data/app/assets/javascripts/elfinder/img/volume_icon_box.svg +1 -0
  52. data/app/assets/javascripts/elfinder/img/volume_icon_dropbox.png +0 -0
  53. data/app/assets/javascripts/elfinder/img/volume_icon_dropbox.svg +1 -0
  54. data/app/assets/javascripts/elfinder/img/volume_icon_ftp.png +0 -0
  55. data/app/assets/javascripts/elfinder/img/volume_icon_ftp.svg +1 -0
  56. data/app/assets/javascripts/elfinder/img/volume_icon_googledrive.png +0 -0
  57. data/app/assets/javascripts/elfinder/img/volume_icon_googledrive.svg +1 -0
  58. data/app/assets/javascripts/elfinder/img/volume_icon_local.png +0 -0
  59. data/app/assets/javascripts/elfinder/img/volume_icon_local.svg +1 -0
  60. data/app/assets/javascripts/elfinder/img/volume_icon_network.png +0 -0
  61. data/app/assets/javascripts/elfinder/img/volume_icon_network.svg +1 -0
  62. data/app/assets/javascripts/elfinder/img/volume_icon_onedrive.png +0 -0
  63. data/app/assets/javascripts/elfinder/img/volume_icon_onedrive.svg +1 -0
  64. data/app/assets/javascripts/elfinder/img/volume_icon_sql.png +0 -0
  65. data/app/assets/javascripts/elfinder/img/volume_icon_sql.svg +1 -0
  66. data/app/assets/javascripts/elfinder/img/volume_icon_trash.png +0 -0
  67. data/app/assets/javascripts/elfinder/img/volume_icon_trash.svg +1 -0
  68. data/app/assets/javascripts/elfinder/img/volume_icon_zip.png +0 -0
  69. data/app/assets/javascripts/elfinder/img/volume_icon_zip.svg +1 -0
  70. data/app/assets/javascripts/elfinder/js/elfinder.full.js +36019 -0
  71. data/app/assets/javascripts/elfinder/js/elfinder.min.js +25 -0
  72. data/app/assets/javascripts/elfinder/js/extras/editors.default.js +2643 -0
  73. data/app/assets/javascripts/elfinder/js/extras/editors.default.min.js +2 -0
  74. data/app/assets/javascripts/elfinder/js/extras/quicklook.googledocs.js +75 -0
  75. data/app/assets/javascripts/elfinder/js/extras/quicklook.googledocs.min.js +1 -0
  76. data/app/assets/javascripts/elfinder/js/i18n/elfinder.LANG.js +587 -0
  77. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ar.js +580 -0
  78. data/app/assets/javascripts/elfinder/js/i18n/elfinder.bg.js +559 -0
  79. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ca.js +375 -0
  80. data/app/assets/javascripts/elfinder/js/i18n/elfinder.cs.js +581 -0
  81. data/app/assets/javascripts/elfinder/js/i18n/elfinder.da.js +580 -0
  82. data/app/assets/javascripts/elfinder/js/i18n/elfinder.de.js +582 -0
  83. data/app/assets/javascripts/elfinder/js/i18n/elfinder.el.js +374 -0
  84. data/app/assets/javascripts/elfinder/js/i18n/elfinder.es.js +546 -0
  85. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fa.js +580 -0
  86. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fallback.js +11 -0
  87. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fo.js +419 -0
  88. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fr.js +578 -0
  89. data/app/assets/javascripts/elfinder/js/i18n/elfinder.fr_CA.js +580 -0
  90. data/app/assets/javascripts/elfinder/js/i18n/elfinder.he.js +375 -0
  91. data/app/assets/javascripts/elfinder/js/i18n/elfinder.hr.js +434 -0
  92. data/app/assets/javascripts/elfinder/js/i18n/elfinder.hu.js +580 -0
  93. data/app/assets/javascripts/elfinder/js/i18n/elfinder.id.js +498 -0
  94. data/app/assets/javascripts/elfinder/js/i18n/elfinder.it.js +552 -0
  95. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ja.js +581 -0
  96. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ko.js +582 -0
  97. data/app/assets/javascripts/elfinder/js/i18n/elfinder.nl.js +581 -0
  98. data/app/assets/javascripts/elfinder/js/i18n/elfinder.no.js +374 -0
  99. data/app/assets/javascripts/elfinder/js/i18n/elfinder.pl.js +580 -0
  100. data/app/assets/javascripts/elfinder/js/i18n/elfinder.pt_BR.js +580 -0
  101. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ro.js +417 -0
  102. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ru.js +582 -0
  103. data/app/assets/javascripts/elfinder/js/i18n/elfinder.si.js +537 -0
  104. data/app/assets/javascripts/elfinder/js/i18n/elfinder.sk.js +581 -0
  105. data/app/assets/javascripts/elfinder/js/i18n/elfinder.sl.js +374 -0
  106. data/app/assets/javascripts/elfinder/js/i18n/elfinder.sr.js +374 -0
  107. data/app/assets/javascripts/elfinder/js/i18n/elfinder.sv.js +375 -0
  108. data/app/assets/javascripts/elfinder/js/i18n/elfinder.tr.js +583 -0
  109. data/app/assets/javascripts/elfinder/js/i18n/elfinder.ug_CN.js +374 -0
  110. data/app/assets/javascripts/elfinder/js/i18n/elfinder.uk.js +580 -0
  111. data/app/assets/javascripts/elfinder/js/i18n/elfinder.vi.js +579 -0
  112. data/app/assets/javascripts/elfinder/js/i18n/elfinder.zh_CN.js +585 -0
  113. data/app/assets/javascripts/elfinder/js/i18n/elfinder.zh_TW.js +582 -0
  114. data/app/assets/javascripts/elfinder/js/i18n/help/cs.html.js +10 -0
  115. data/app/assets/javascripts/elfinder/js/i18n/help/de.html.js +15 -0
  116. data/app/assets/javascripts/elfinder/js/i18n/help/en.html.js +10 -0
  117. data/app/assets/javascripts/elfinder/js/i18n/help/es.html.js +10 -0
  118. data/app/assets/javascripts/elfinder/js/i18n/help/ja.html.js +10 -0
  119. data/app/assets/javascripts/elfinder/js/i18n/help/ko.html.js +10 -0
  120. data/app/assets/javascripts/elfinder/js/i18n/help/pl.html.js +10 -0
  121. data/app/assets/javascripts/elfinder/js/i18n/help/ru.html.js +10 -0
  122. data/app/assets/javascripts/elfinder/js/i18n/help/sk.html.js +10 -0
  123. data/app/assets/javascripts/elfinder/js/i18n/help/tr.html.js +10 -0
  124. data/app/assets/javascripts/elfinder/js/proxy/elFinderSupportVer1.js +408 -0
  125. data/app/assets/javascripts/elfinder/js/worker/calcfilehash.js +20 -0
  126. data/app/assets/javascripts/elfinder/js/worker/quicklook.tiff.js +7 -0
  127. data/app/assets/javascripts/elfinder/js/worker/quicklook.unzip.js +55 -0
  128. data/app/assets/javascripts/elfinder/main.default.js +175 -0
  129. data/app/assets/javascripts/elfinder/package.json +13 -0
  130. data/app/assets/javascripts/elfinder/php/MySQLStorage.sql +47 -0
  131. data/app/assets/javascripts/elfinder/php/autoload.php +56 -0
  132. data/app/assets/javascripts/elfinder/php/connector.maximal.php-dist +449 -0
  133. data/app/assets/javascripts/elfinder/php/connector.minimal.php-dist +180 -0
  134. data/app/assets/javascripts/elfinder/php/editors/OnlineConvert/editor.php +113 -0
  135. data/app/assets/javascripts/elfinder/php/editors/ZipArchive/editor.php +12 -0
  136. data/app/assets/javascripts/elfinder/php/editors/ZohoOffice/editor.php +206 -0
  137. data/app/assets/javascripts/elfinder/php/editors/editor.php +79 -0
  138. data/app/assets/javascripts/elfinder/php/elFinder.class.php +5401 -0
  139. data/app/assets/javascripts/elfinder/php/elFinderConnector.class.php +380 -0
  140. data/app/assets/javascripts/elfinder/php/elFinderFlysystemGoogleDriveNetmount.php +380 -0
  141. data/app/assets/javascripts/elfinder/php/elFinderPlugin.php +113 -0
  142. data/app/assets/javascripts/elfinder/php/elFinderSession.php +335 -0
  143. data/app/assets/javascripts/elfinder/php/elFinderSessionInterface.php +57 -0
  144. data/app/assets/javascripts/elfinder/php/elFinderVolumeBox.class.php +1972 -0
  145. data/app/assets/javascripts/elfinder/php/elFinderVolumeDriver.class.php +7651 -0
  146. data/app/assets/javascripts/elfinder/php/elFinderVolumeDropbox.class.php +1464 -0
  147. data/app/assets/javascripts/elfinder/php/elFinderVolumeDropbox2.class.php +1516 -0
  148. data/app/assets/javascripts/elfinder/php/elFinderVolumeFTP.class.php +1810 -0
  149. data/app/assets/javascripts/elfinder/php/elFinderVolumeGoogleDrive.class.php +2163 -0
  150. data/app/assets/javascripts/elfinder/php/elFinderVolumeGroup.class.php +315 -0
  151. data/app/assets/javascripts/elfinder/php/elFinderVolumeLocalFileSystem.class.php +1477 -0
  152. data/app/assets/javascripts/elfinder/php/elFinderVolumeMySQL.class.php +1022 -0
  153. data/app/assets/javascripts/elfinder/php/elFinderVolumeOneDrive.class.php +2131 -0
  154. data/app/assets/javascripts/elfinder/php/elFinderVolumeSFTPphpseclib.class.php +838 -0
  155. data/app/assets/javascripts/elfinder/php/elFinderVolumeTrash.class.php +51 -0
  156. data/app/assets/javascripts/elfinder/php/elFinderVolumeTrashMySQL.class.php +51 -0
  157. data/app/assets/javascripts/elfinder/php/libs/GdBmp.php +473 -0
  158. data/app/assets/javascripts/elfinder/php/mime.types +781 -0
  159. data/app/assets/javascripts/elfinder/php/plugins/AutoResize/plugin.php +151 -0
  160. data/app/assets/javascripts/elfinder/php/plugins/AutoRotate/plugin.php +148 -0
  161. data/app/assets/javascripts/elfinder/php/plugins/Normalizer/plugin.php +204 -0
  162. data/app/assets/javascripts/elfinder/php/plugins/Sanitizer/plugin.php +157 -0
  163. data/app/assets/javascripts/elfinder/php/plugins/Watermark/logo.png +0 -0
  164. data/app/assets/javascripts/elfinder/php/plugins/Watermark/plugin.php +432 -0
  165. data/app/assets/javascripts/elfinder/php/plugins/WinRemoveTailDots/plugin.php +114 -0
  166. data/app/assets/javascripts/elfinder/php/resources/image.png +0 -0
  167. data/app/assets/javascripts/elfinder/php/resources/video.png +0 -0
  168. data/app/assets/javascripts/elfinder/sounds/rm.wav +0 -0
  169. data/app/controllers/dc_elfinder_controller.rb +63 -0
  170. data/app/models/drgcms_form_fields/elfinder.rb +85 -0
  171. data/changelog.md +0 -0
  172. data/lib/drg_elfinder/engine.rb +5 -0
  173. data/lib/drg_elfinder/version.rb +3 -0
  174. data/lib/drg_elfinder.rb +9 -0
  175. data/lib/el_finder/action.rb +19 -0
  176. data/lib/el_finder/base64.rb +24 -0
  177. data/lib/el_finder/connector.rb +625 -0
  178. data/lib/el_finder/image.rb +33 -0
  179. data/lib/el_finder/mime_type.rb +86 -0
  180. data/lib/el_finder/pathname.rb +185 -0
  181. data/lib/el_finder/version.rb +5 -0
  182. data/lib/el_finder.rb +8 -0
  183. data/lib/patches/patch_for_elfinder.rb +115 -0
  184. data/lib/tasks/drg_elfinder_tasks.rake +10 -0
  185. metadata +245 -0
@@ -0,0 +1,2643 @@
1
+ (function(editors, elFinder) {
2
+ if (typeof define === 'function' && define.amd) {
3
+ define(['elfinder'], editors);
4
+ } else if (elFinder) {
5
+ var optEditors = elFinder.prototype._options.commandsOptions.edit.editors;
6
+ elFinder.prototype._options.commandsOptions.edit.editors = optEditors.concat(editors(elFinder));
7
+ }
8
+ }(function(elFinder) {
9
+ "use strict";
10
+ var apps = {},
11
+ // get query of getfile
12
+ getfile = window.location.search.match(/getfile=([a-z]+)/),
13
+ useRequire = elFinder.prototype.hasRequire,
14
+ ext2mime = {
15
+ bmp: 'image/x-ms-bmp',
16
+ dng: 'image/x-adobe-dng',
17
+ gif: 'image/gif',
18
+ jpeg: 'image/jpeg',
19
+ jpg: 'image/jpeg',
20
+ pdf: 'application/pdf',
21
+ png: 'image/png',
22
+ ppm: 'image/x-portable-pixmap',
23
+ psd: 'image/vnd.adobe.photoshop',
24
+ pxd: 'image/x-pixlr-data',
25
+ svg: 'image/svg+xml',
26
+ tiff: 'image/tiff',
27
+ webp: 'image/webp',
28
+ xcf: 'image/x-xcf',
29
+ sketch: 'application/x-sketch',
30
+ ico: 'image/x-icon',
31
+ dds: 'image/vnd-ms.dds',
32
+ emf: 'application/x-msmetafile'
33
+ },
34
+ mime2ext,
35
+ getExtention = function(mime, fm, jpeg) {
36
+ if (!mime2ext) {
37
+ mime2ext = fm.arrayFlip(ext2mime);
38
+ }
39
+ var ext = mime2ext[mime] || fm.mimeTypes[mime];
40
+ if (!jpeg) {
41
+ if (ext === 'jpeg') {
42
+ ext = 'jpg';
43
+ }
44
+ } else {
45
+ if (ext === 'jpg') {
46
+ ext = 'jpeg';
47
+ }
48
+ }
49
+ return ext;
50
+ },
51
+ changeImageType = function(src, toMime) {
52
+ var dfd = $.Deferred();
53
+ try {
54
+ var canvas = document.createElement('canvas'),
55
+ ctx = canvas.getContext('2d'),
56
+ img = new Image(),
57
+ conv = function() {
58
+ var url = canvas.toDataURL(toMime),
59
+ mime, m;
60
+ if (m = url.match(/^data:([a-z0-9]+\/[a-z0-9.+-]+)/i)) {
61
+ mime = m[1];
62
+ } else {
63
+ mime = '';
64
+ }
65
+ if (mime.toLowerCase() === toMime.toLowerCase()) {
66
+ dfd.resolve(canvas.toDataURL(toMime), canvas);
67
+ } else {
68
+ dfd.reject();
69
+ }
70
+ };
71
+
72
+ img.src = src;
73
+ $(img).on('load', function() {
74
+ try {
75
+ canvas.width = img.width;
76
+ canvas.height = img.height;
77
+ ctx.drawImage(img, 0, 0);
78
+ conv();
79
+ } catch(e) {
80
+ dfd.reject();
81
+ }
82
+ }).on('error', function () {
83
+ dfd.reject();
84
+ });
85
+ return dfd;
86
+ } catch(e) {
87
+ return dfd.reject();
88
+ }
89
+ },
90
+ initImgTag = function(id, file, content, fm) {
91
+ var node = $(this).children('img:first').data('ext', getExtention(file.mime, fm)),
92
+ spnr = $('<div class="elfinder-edit-spinner elfinder-edit-image"></div>')
93
+ .html('<span class="elfinder-spinner-text">' + fm.i18n('ntfloadimg') + '</span><span class="elfinder-spinner"></span>')
94
+ .hide()
95
+ .appendTo(this),
96
+ setup = function() {
97
+ node.attr('id', id+'-img')
98
+ .attr('src', url || content)
99
+ .css({'height':'', 'max-width':'100%', 'max-height':'100%', 'cursor':'pointer'})
100
+ .data('loading', function(done) {
101
+ var btns = node.closest('.elfinder-dialog').find('button,.elfinder-titlebar-button');
102
+ btns.prop('disabled', !done)[done? 'removeClass' : 'addClass']('ui-state-disabled');
103
+ node.css('opacity', done? '' : '0.3');
104
+ spnr[done? 'hide' : 'show']();
105
+ return node;
106
+ });
107
+ },
108
+ url;
109
+
110
+ if (!content.match(/^data:/)) {
111
+ fm.openUrl(file.hash, false, function(v) {
112
+ url = v;
113
+ node.attr('_src', content);
114
+ setup();
115
+ });
116
+ } else {
117
+ setup();
118
+ }
119
+ },
120
+ imgBase64 = function(node, mime) {
121
+ var style = node.attr('style'),
122
+ img, canvas, ctx, data;
123
+ try {
124
+ // reset css for getting image size
125
+ node.attr('style', '');
126
+ // img node
127
+ img = node.get(0);
128
+ // New Canvas
129
+ canvas = document.createElement('canvas');
130
+ canvas.width = img.width;
131
+ canvas.height = img.height;
132
+ // restore css
133
+ node.attr('style', style);
134
+ // Draw Image
135
+ canvas.getContext('2d').drawImage(img, 0, 0);
136
+ // To Base64
137
+ data = canvas.toDataURL(mime);
138
+ } catch(e) {
139
+ data = node.attr('src');
140
+ }
141
+ return data;
142
+ },
143
+ iframeClose = function(ifm) {
144
+ var $ifm = $(ifm),
145
+ dfd = $.Deferred().always(function() {
146
+ $ifm.off('load', load);
147
+ }),
148
+ ab = 'about:blank',
149
+ chk = function() {
150
+ tm = setTimeout(function() {
151
+ var src;
152
+ try {
153
+ src = base.contentWindow.location.href;
154
+ } catch(e) {
155
+ src = null;
156
+ }
157
+ if (src === ab) {
158
+ dfd.resolve();
159
+ } else if (--cnt > 0){
160
+ chk();
161
+ } else {
162
+ dfd.reject();
163
+ }
164
+ }, 500);
165
+ },
166
+ load = function() {
167
+ tm && clearTimeout(tm);
168
+ dfd.resolve();
169
+ },
170
+ cnt = 20, // 500ms * 20 = 10sec wait
171
+ tm;
172
+ $ifm.one('load', load);
173
+ ifm.src = ab;
174
+ chk();
175
+ return dfd;
176
+ };
177
+
178
+ // check getfile callback function
179
+ if (getfile) {
180
+ getfile = getfile[1];
181
+ if (getfile === 'ckeditor') {
182
+ elFinder.prototype._options.getFileCallback = function(file, fm) {
183
+ window.opener.CKEDITOR.tools.callFunction((function() {
184
+ var reParam = new RegExp('(?:[?&]|&amp;)CKEditorFuncNum=([^&]+)', 'i'),
185
+ match = window.location.search.match(reParam);
186
+ return (match && match.length > 1) ? match[1] : '';
187
+ })(), fm.convAbsUrl(file.url));
188
+ fm.destroy();
189
+ window.close();
190
+ };
191
+ }
192
+ }
193
+
194
+ // return editors Array
195
+ return [
196
+ {
197
+ // tui.image-editor - https://github.com/nhnent/tui.image-editor
198
+ info : {
199
+ id: 'tuiimgedit',
200
+ name: 'TUI Image Editor',
201
+ iconImg: 'img/editor-icons.png 0 -48',
202
+ dataScheme: true,
203
+ schemeContent: true,
204
+ openMaximized: true,
205
+ canMakeEmpty: false,
206
+ integrate: {
207
+ title: 'TOAST UI Image Editor',
208
+ link: 'http://ui.toast.com/tui-image-editor/'
209
+ }
210
+ },
211
+ // MIME types to accept
212
+ mimes : ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/x-ms-bmp'],
213
+ // HTML of this editor
214
+ html : '<div class="elfinder-edit-imageeditor"><canvas></canvas></div>',
215
+ // called on initialization of elFinder cmd edit (this: this editor's config object)
216
+ setup : function(opts, fm) {
217
+ if (fm.UA.ltIE8 || fm.UA.Mobile) {
218
+ this.disabled = true;
219
+ } else {
220
+ this.opts = Object.assign({
221
+ version: 'v3.15.2'
222
+ }, opts.extraOptions.tuiImgEditOpts || {}, {
223
+ iconsPath : fm.baseUrl + 'img/tui-',
224
+ theme : {}
225
+ });
226
+ if (!fm.isSameOrigin(this.opts.iconsPath)) {
227
+ this.disabled = true;
228
+ fm.debug('warning', 'Setting `commandOptions.edit.extraOptions.tuiImgEditOpts.iconsPath` MUST follow the same origin policy.');
229
+ }
230
+ }
231
+ },
232
+ // Initialization of editing node (this: this editors HTML node)
233
+ init : function(id, file, content, fm) {
234
+ this.data('url', content);
235
+ },
236
+ load : function(base) {
237
+ var self = this,
238
+ fm = this.fm,
239
+ dfrd = $.Deferred(),
240
+ cdns = fm.options.cdns,
241
+ ver = self.confObj.opts.version,
242
+ init = function(editor) {
243
+ var $base = $(base),
244
+ bParent = $base.parent(),
245
+ opts = self.confObj.opts,
246
+ iconsPath = opts.iconsPath,
247
+ tmpContainer = $('<div class="tui-image-editor-container">').appendTo(bParent),
248
+ tmpDiv = [
249
+ $('<div class="tui-image-editor-submenu"></div>').appendTo(tmpContainer),
250
+ $('<div class="tui-image-editor-controls"></div>').appendTo(tmpContainer)
251
+ ],
252
+ iEditor = new editor(base, {
253
+ includeUI: {
254
+ loadImage: {
255
+ path: $base.data('url'),
256
+ name: self.file.name
257
+ },
258
+ theme: opts.theme,
259
+ initMenu: 'filter',
260
+ menuBarPosition: 'bottom'
261
+ },
262
+ cssMaxWidth: Math.max(300, bParent.width()),
263
+ cssMaxHeight: Math.max(200, bParent.height() - (tmpDiv[0].height() + tmpDiv[1].height() + 3 /*margin*/)),
264
+ usageStatistics: false
265
+ }),
266
+ canvas = $base.find('canvas:first').get(0),
267
+ zoom = function(v) {
268
+ if (typeof v !== 'undefined') {
269
+ var c = $(canvas),
270
+ w = parseInt(c.attr('width')),
271
+ h = parseInt(c.attr('height')),
272
+ a = w / h,
273
+ z, mw, mh;
274
+ if (v === 0) {
275
+ mw = w;
276
+ mh = h;
277
+ } else {
278
+ mw = parseInt(c.css('max-width')) + Number(v);
279
+ mh = mw / a;
280
+ if (mw > w && mh > h) {
281
+ mw = w;
282
+ mh = h;
283
+ }
284
+ }
285
+ z = Math.round(mw / w * 100);
286
+ // Control zoom button of TUI Image Editor
287
+ if (z < 100) {
288
+ iEditor.resetZoom();
289
+ iEditor.stopDrawingMode();
290
+ tuiZoomCtrls.hide();
291
+ } else {
292
+ tuiZoomCtrls.show();
293
+ }
294
+ per.text(z + '%');
295
+ iEditor.resizeCanvasDimension({width: mw, height: mh});
296
+ // continually change more
297
+ if (zoomMore) {
298
+ setTimeout(function() {
299
+ zoomMore && zoom(v);
300
+ }, 50);
301
+ }
302
+ }
303
+ },
304
+ zup = $('<span class="ui-icon ui-icon-plusthick"></span>').data('val', 10),
305
+ zdown = $('<span class="ui-icon ui-icon-minusthick"></span>').data('val', -10),
306
+ per = $('<button></button>').css('width', '4em').text('%').attr('title', '100%').data('val', 0),
307
+ tuiZoomCtrls,
308
+ quty, qutyTm, zoomTm, zoomMore;
309
+
310
+ tmpContainer.remove();
311
+ $base.removeData('url').data('mime', self.file.mime);
312
+ // jpeg quality controls
313
+ if (self.file.mime === 'image/jpeg') {
314
+ $base.data('quality', fm.storage('jpgQuality') || fm.option('jpgQuality'));
315
+ quty = $('<input type="number" class="ui-corner-all elfinder-resize-quality elfinder-tabstop"/>')
316
+ .attr('min', '1')
317
+ .attr('max', '100')
318
+ .attr('title', '1 - 100')
319
+ .on('change', function() {
320
+ var q = quty.val();
321
+ $base.data('quality', q);
322
+ qutyTm && cancelAnimationFrame(qutyTm);
323
+ qutyTm = requestAnimationFrame(function() {
324
+ canvas.toBlob(function(blob) {
325
+ blob && quty.next('span').text(' (' + fm.formatSize(blob.size) + ')');
326
+ }, 'image/jpeg', Math.max(Math.min(q, 100), 1) / 100);
327
+ });
328
+ })
329
+ .val($base.data('quality'));
330
+ $('<div class="ui-dialog-buttonset elfinder-edit-extras elfinder-edit-extras-quality"></div>')
331
+ .append(
332
+ $('<span>').html(fm.i18n('quality') + ' : '), quty, $('<span></span>')
333
+ )
334
+ .prependTo($base.parent().next());
335
+ } else if (self.file.mime === 'image/svg+xml') {
336
+ $base.closest('.ui-dialog').trigger('changeType', {
337
+ extention: 'png',
338
+ mime : 'image/png',
339
+ keepEditor: true
340
+ });
341
+ }
342
+ // zoom scale controls
343
+ $('<div class="ui-dialog-buttonset elfinder-edit-extras"></div>')
344
+ .append(
345
+ zdown, per, zup
346
+ )
347
+ .attr('title', fm.i18n('scale'))
348
+ .on('click', 'span,button', function() {
349
+ zoom($(this).data('val'));
350
+ })
351
+ .on('mousedown mouseup mouseleave', 'span', function(e) {
352
+ zoomMore = false;
353
+ zoomTm && clearTimeout(zoomTm);
354
+ if (e.type === 'mousedown') {
355
+ zoomTm = setTimeout(function() {
356
+ zoomMore = true;
357
+ zoom($(e.target).data('val'));
358
+ }, 500);
359
+ }
360
+ })
361
+ .prependTo($base.parent().next());
362
+
363
+ // wait canvas ready
364
+ setTimeout(function() {
365
+ dfrd.resolve(iEditor);
366
+ if (quty) {
367
+ quty.trigger('change');
368
+ iEditor.on('redoStackChanged undoStackChanged', function() {
369
+ quty.trigger('change');
370
+ });
371
+ }
372
+ // ZOOM controls of TUI Image Editor
373
+ tuiZoomCtrls = $base.find('.tie-btn-zoomIn,.tie-btn-zoomOut,.tie-btn-hand');
374
+ // show initial scale
375
+ zoom(null);
376
+ }, 100);
377
+
378
+ // show color slider (maybe TUI-Image-Editor's bug)
379
+ // see https://github.com/nhn/tui.image-editor/issues/153
380
+ $base.find('.tui-colorpicker-palette-container').on('click', '.tui-colorpicker-palette-preview', function() {
381
+ $(this).closest('.color-picker-control').height('auto').find('.tui-colorpicker-slider-container').toggle();
382
+ });
383
+ $base.on('click', function() {
384
+ $base.find('.tui-colorpicker-slider-container').hide();
385
+ });
386
+ },
387
+ loader;
388
+
389
+ if (!self.confObj.editor) {
390
+ loader = $.Deferred();
391
+ fm.loadCss([
392
+ cdns.tui + '/tui-color-picker/latest/tui-color-picker.css',
393
+ cdns.tui + '/tui-image-editor/'+ver+'/tui-image-editor.css'
394
+ ]);
395
+ if (fm.hasRequire) {
396
+ require.config({
397
+ paths : {
398
+ 'fabric/dist/fabric.require' : cdns.fabric + '/fabric.require.min', // for fabric < 2.0.1
399
+ 'fabric' : cdns.fabric + '/fabric.min', // for fabric >= 2.0.1
400
+ 'tui-code-snippet' : cdns.tui + '/tui.code-snippet/latest/tui-code-snippet.min',
401
+ 'tui-color-picker' : cdns.tui + '/tui-color-picker/latest/tui-color-picker.min',
402
+ 'tui-image-editor' : cdns.tui + '/tui-image-editor/'+ver+'/tui-image-editor.min'
403
+ }
404
+ });
405
+ require(['tui-image-editor'], function(ImageEditor) {
406
+ loader.resolve(ImageEditor);
407
+ });
408
+ } else {
409
+ fm.loadScript([
410
+ cdns.fabric + '/fabric.min.js',
411
+ cdns.tui + '/tui.code-snippet/latest/tui-code-snippet.min.js'
412
+ ], function() {
413
+ fm.loadScript([
414
+ cdns.tui + '/tui-color-picker/latest/tui-color-picker.min.js'
415
+ ], function() {
416
+ fm.loadScript([
417
+ cdns.tui + '/tui-image-editor/'+ver+'/tui-image-editor.min.js'
418
+ ], function() {
419
+ loader.resolve(window.tui.ImageEditor);
420
+ }, {
421
+ loadType: 'tag'
422
+ });
423
+ }, {
424
+ loadType: 'tag'
425
+ });
426
+ }, {
427
+ loadType: 'tag'
428
+ });
429
+ }
430
+ loader.done(function(editor) {
431
+ self.confObj.editor = editor;
432
+ init(editor);
433
+ });
434
+ } else {
435
+ init(self.confObj.editor);
436
+ }
437
+ return dfrd;
438
+ },
439
+ getContent : function(base) {
440
+ var editor = this.editor,
441
+ fm = editor.fm,
442
+ $base = $(base),
443
+ quality = $base.data('quality');
444
+ if (editor.instance) {
445
+ if ($base.data('mime') === 'image/jpeg') {
446
+ quality = quality || fm.storage('jpgQuality') || fm.option('jpgQuality');
447
+ quality = Math.max(0.1, Math.min(1, quality / 100));
448
+ }
449
+ return editor.instance.toDataURL({
450
+ format: getExtention($base.data('mime'), fm, true),
451
+ quality: quality
452
+ });
453
+ }
454
+ },
455
+ save : function(base) {
456
+ var $base = $(base),
457
+ quality = $base.data('quality'),
458
+ hash = $base.data('hash'),
459
+ file;
460
+ this.instance.deactivateAll();
461
+ if (typeof quality !== 'undefined') {
462
+ this.fm.storage('jpgQuality', quality);
463
+ }
464
+ if (hash) {
465
+ file = this.fm.file(hash);
466
+ $base.data('mime', file.mime);
467
+ }
468
+ }
469
+ },
470
+ {
471
+ // Photopea advanced image editor
472
+ info : {
473
+ id : 'photopea',
474
+ name : 'Photopea',
475
+ iconImg : 'img/editor-icons.png 0 -160',
476
+ single: true,
477
+ noContent: true,
478
+ arrayBufferContent: true,
479
+ openMaximized: true,
480
+ // Disable file types that cannot be saved on Photopea.
481
+ canMakeEmpty: ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/x-ms-bmp', 'image/tiff', /*'image/x-adobe-dng',*/ 'image/webp', /*'image/x-xcf',*/ 'image/vnd.adobe.photoshop', 'application/pdf', 'image/x-portable-pixmap', 'image/x-sketch', 'image/x-icon', 'image/vnd-ms.dds', /*'application/x-msmetafile'*/],
482
+ integrate: {
483
+ title: 'Photopea',
484
+ link: 'https://www.photopea.com/learn/'
485
+ }
486
+ },
487
+ mimes : ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/x-ms-bmp', 'image/tiff', 'image/x-adobe-dng', 'image/webp', 'image/x-xcf', 'image/vnd.adobe.photoshop', 'application/pdf', 'image/x-portable-pixmap', 'image/x-sketch', 'image/x-icon', 'image/vnd-ms.dds', 'application/x-msmetafile'],
488
+ html : '<iframe style="width:100%;height:100%;border:none;"></iframe>',
489
+ // setup on elFinder bootup
490
+ setup : function(opts, fm) {
491
+ if (fm.UA.IE || fm.UA.Mobile) {
492
+ this.disabled = true;
493
+ }
494
+ },
495
+ // Initialization of editing node (this: this editors HTML node)
496
+ init : function(id, file, dum, fm) {
497
+ var orig = 'https://www.photopea.com',
498
+ ifm = $(this).hide()
499
+ //.css('box-sizing', 'border-box')
500
+ .on('load', function() {
501
+ //spnr.remove();
502
+ ifm.show();
503
+ })
504
+ .on('error', function() {
505
+ spnr.remove();
506
+ ifm.show();
507
+ }),
508
+ editor = this.editor,
509
+ confObj = editor.confObj,
510
+ spnr = $('<div class="elfinder-edit-spinner elfinder-edit-photopea"></div>')
511
+ .html('<span class="elfinder-spinner-text">' + fm.i18n('nowLoading') + '</span><span class="elfinder-spinner"></span>')
512
+ .appendTo(ifm.parent()),
513
+ saveMimes = fm.arrayFlip(confObj.info.canMakeEmpty),
514
+ getType = function(mime) {
515
+ var ext = getExtention(mime, fm),
516
+ extmime = ext2mime[ext];
517
+
518
+ if (!confObj.mimesFlip[extmime]) {
519
+ ext = '';
520
+ } else if (ext === 'jpeg') {
521
+ ext = 'jpg';
522
+ }
523
+ if (!ext || !saveMimes[extmime]) {
524
+ ext = 'psd';
525
+ extmime = ext2mime[ext];
526
+ ifm.closest('.ui-dialog').trigger('changeType', {
527
+ extention: ext,
528
+ mime : extmime,
529
+ keepEditor: true
530
+ });
531
+ }
532
+ return ext;
533
+ },
534
+ mime = file.mime,
535
+ liveMsg, type, quty;
536
+
537
+ if (!confObj.mimesFlip) {
538
+ confObj.mimesFlip = fm.arrayFlip(confObj.mimes, true);
539
+ }
540
+ if (!confObj.liveMsg) {
541
+ confObj.liveMsg = function(ifm, spnr, file) {
542
+ var wnd = ifm.get(0).contentWindow,
543
+ phase = 0,
544
+ data = null,
545
+ dfdIni = $.Deferred().done(function() {
546
+ spnr.remove();
547
+ phase = 1;
548
+ wnd.postMessage(data, orig);
549
+ }),
550
+ dfdGet;
551
+
552
+ this.load = function() {
553
+ return fm.getContents(file.hash, 'arraybuffer').done(function(d) {
554
+ data = d;
555
+ });
556
+ };
557
+
558
+ this.receive = function(e) {
559
+ var ev = e.originalEvent,
560
+ state;
561
+ if (ev.origin === orig && ev.source === wnd) {
562
+ if (ev.data === 'done') {
563
+ if (phase === 0) {
564
+ dfdIni.resolve();
565
+ } else if (phase === 1) {
566
+ phase = 2;
567
+ ifm.trigger('contentsloaded');
568
+ } else {
569
+ if (dfdGet && dfdGet.state() === 'pending') {
570
+ dfdGet.reject('errDataEmpty');
571
+ }
572
+ }
573
+ } else if (ev.data === 'Save') {
574
+ editor.doSave();
575
+ } else {
576
+ if (dfdGet && dfdGet.state() === 'pending') {
577
+ if (typeof ev.data === 'object') {
578
+ dfdGet.resolve('data:' + mime + ';base64,' + fm.arrayBufferToBase64(ev.data));
579
+ } else {
580
+ dfdGet.reject('errDataEmpty');
581
+ }
582
+ }
583
+ }
584
+ }
585
+ };
586
+
587
+ this.getContent = function() {
588
+ var type, q;
589
+ if (phase > 1) {
590
+ dfdGet && dfdGet.state() === 'pending' && dfdGet.reject();
591
+ dfdGet = null;
592
+ dfdGet = $.Deferred();
593
+ if (phase === 2) {
594
+ phase = 3;
595
+ dfdGet.resolve('data:' + mime + ';base64,' + fm.arrayBufferToBase64(data));
596
+ data = null;
597
+ return dfdGet;
598
+ }
599
+ if (ifm.data('mime')) {
600
+ mime = ifm.data('mime');
601
+ type = getType(mime);
602
+ }
603
+ if (q = ifm.data('quality')) {
604
+ type += ':' + (q / 100);
605
+ }
606
+ wnd.postMessage('app.activeDocument.saveToOE("' + type + '")', orig);
607
+ return dfdGet;
608
+ }
609
+ };
610
+ };
611
+ }
612
+
613
+ ifm.parent().css('padding', 0);
614
+ type = getType(file.mime);
615
+ liveMsg = editor.liveMsg = new confObj.liveMsg(ifm, spnr, file);
616
+ $(window).on('message.' + fm.namespace, liveMsg.receive);
617
+ liveMsg.load().done(function() {
618
+ var d = JSON.stringify({
619
+ files : [],
620
+ environment : {
621
+ lang: fm.lang.replace(/_/g, '-'),
622
+ customIO: {"save": "app.echoToOE(\"Save\");"}
623
+ }
624
+ });
625
+ ifm.attr('src', orig + '/#' + encodeURI(d));
626
+ }).fail(function(err) {
627
+ err && fm.error(err);
628
+ editor.initFail = true;
629
+ });
630
+
631
+ // jpeg quality controls
632
+ if (file.mime === 'image/jpeg' || file.mime === 'image/webp') {
633
+ ifm.data('quality', fm.storage('jpgQuality') || fm.option('jpgQuality'));
634
+ quty = $('<input type="number" class="ui-corner-all elfinder-resize-quality elfinder-tabstop"/>')
635
+ .attr('min', '1')
636
+ .attr('max', '100')
637
+ .attr('title', '1 - 100')
638
+ .on('change', function() {
639
+ var q = quty.val();
640
+ ifm.data('quality', q);
641
+ })
642
+ .val(ifm.data('quality'));
643
+ $('<div class="ui-dialog-buttonset elfinder-edit-extras elfinder-edit-extras-quality"></div>')
644
+ .append(
645
+ $('<span>').html(fm.i18n('quality') + ' : '), quty, $('<span></span>')
646
+ )
647
+ .prependTo(ifm.parent().next());
648
+ }
649
+ },
650
+ load : function(base) {
651
+ var dfd = $.Deferred(),
652
+ self = this,
653
+ fm = this.fm,
654
+ $base = $(base);
655
+ if (self.initFail) {
656
+ dfd.reject();
657
+ } else {
658
+ $base.on('contentsloaded', function() {
659
+ dfd.resolve(self.liveMsg);
660
+ });
661
+ }
662
+ return dfd;
663
+ },
664
+ getContent : function() {
665
+ return this.editor.liveMsg? this.editor.liveMsg.getContent() : void(0);
666
+ },
667
+ save : function(base, liveMsg) {
668
+ var $base = $(base),
669
+ quality = $base.data('quality'),
670
+ hash = $base.data('hash'),
671
+ file;
672
+ if (typeof quality !== 'undefined') {
673
+ this.fm.storage('jpgQuality', quality);
674
+ }
675
+ if (hash) {
676
+ file = this.fm.file(hash);
677
+ $base.data('mime', file.mime);
678
+ } else {
679
+ $base.removeData('mime');
680
+ }
681
+ },
682
+ // On dialog closed
683
+ close : function(base, liveMsg) {
684
+ $(base).attr('src', '');
685
+ liveMsg && $(window).off('message.' + this.fm.namespace, liveMsg.receive);
686
+ }
687
+ },
688
+ {
689
+ // Pixo is cross-platform image editor
690
+ info : {
691
+ id : 'pixo',
692
+ name : 'Pixo Editor',
693
+ iconImg : 'img/editor-icons.png 0 -208',
694
+ dataScheme: true,
695
+ schemeContent: true,
696
+ single: true,
697
+ canMakeEmpty: false,
698
+ integrate: {
699
+ title: 'Pixo Editor',
700
+ link: 'https://pixoeditor.com/privacy-policy/'
701
+ }
702
+ },
703
+ // MIME types to accept
704
+ mimes : ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/x-ms-bmp'],
705
+ // HTML of this editor
706
+ html : '<div class="elfinder-edit-imageeditor"><img/></div>',
707
+ // called on initialization of elFinder cmd edit (this: this editor's config object)
708
+ setup : function(opts, fm) {
709
+ if (fm.UA.ltIE8 || !opts.extraOptions || !opts.extraOptions.pixo || !opts.extraOptions.pixo.apikey) {
710
+ this.disabled = true;
711
+ } else {
712
+ this.editorOpts = opts.extraOptions.pixo;
713
+ }
714
+ },
715
+ // Initialization of editing node (this: this editors HTML node)
716
+ init : function(id, file, content, fm) {
717
+ initImgTag.call(this, id, file, content, fm);
718
+ },
719
+ // Get data uri scheme (this: this editors HTML node)
720
+ getContent : function() {
721
+ return $(this).children('img:first').attr('src');
722
+ },
723
+ // Launch Pixo editor when dialog open
724
+ load : function(base) {
725
+ var self = this,
726
+ fm = this.fm,
727
+ $base = $(base),
728
+ node = $base.children('img:first'),
729
+ dialog = $base.closest('.ui-dialog'),
730
+ elfNode = fm.getUI(),
731
+ dfrd = $.Deferred(),
732
+ container = $('#elfinder-pixo-container'),
733
+ init = function(onload) {
734
+ var opts;
735
+
736
+ if (!container.length) {
737
+ container = $('<div id="elfinder-pixo-container" class="ui-front"></div>').css({
738
+ position: 'fixed',
739
+ top: 0,
740
+ right: 0,
741
+ width: '100%',
742
+ height: $(window).height(),
743
+ overflow: 'hidden'
744
+ }).hide().appendTo(elfNode.hasClass('elfinder-fullscreen')? elfNode : 'body');
745
+ // bind switch fullscreen event
746
+ elfNode.on('resize.'+fm.namespace, function(e, data) {
747
+ e.preventDefault();
748
+ e.stopPropagation();
749
+ data && data.fullscreen && container.appendTo(data.fullscreen === 'on'? elfNode : 'body');
750
+ });
751
+ fm.bind('destroy', function() {
752
+ editor && editor.cancelEditing();
753
+ container.remove();
754
+ });
755
+ } else {
756
+ // always moves to last
757
+ container.appendTo(container.parent());
758
+ }
759
+ node.on('click', launch);
760
+ // Constructor options
761
+ opts = Object.assign({
762
+ type: 'child',
763
+ parent: container.get(0),
764
+ output: {format: 'png'},
765
+ onSave: function(arg) {
766
+ // Check current file.hash, all callbacks are called on multiple instances
767
+ var mime = arg.toBlob().type,
768
+ ext = getExtention(mime, fm),
769
+ draw = function(url) {
770
+ node.one('load error', function() {
771
+ node.data('loading') && node.data('loading')(true);
772
+ })
773
+ .attr('crossorigin', 'anonymous')
774
+ .attr('src', url);
775
+ },
776
+ url = arg.toDataURL();
777
+ node.data('loading')();
778
+ delete base._canvas;
779
+ if (node.data('ext') !== ext) {
780
+ changeImageType(url, self.file.mime).done(function(res, cv) {
781
+ if (cv) {
782
+ base._canvas = canvas = cv;
783
+ quty.trigger('change');
784
+ qBase && qBase.show();
785
+ }
786
+ draw(res);
787
+ }).fail(function() {
788
+ dialog.trigger('changeType', {
789
+ extention: ext,
790
+ mime : mime
791
+ });
792
+ draw(url);
793
+ });
794
+ } else {
795
+ draw(url);
796
+ }
797
+ },
798
+ onClose: function() {
799
+ dialog.removeClass(fm.res('class', 'preventback'));
800
+ fm.toggleMaximize(container, false);
801
+ container.hide();
802
+ fm.toFront(dialog);
803
+ }
804
+ }, self.confObj.editorOpts);
805
+ // trigger event 'editEditorPrepare'
806
+ self.trigger('Prepare', {
807
+ node: base,
808
+ editorObj: Pixo,
809
+ instance: void(0),
810
+ opts: opts
811
+ });
812
+ // make editor instance
813
+ editor = new Pixo.Bridge(opts);
814
+ dfrd.resolve(editor);
815
+ $base.on('saveAsFail', launch);
816
+ if (onload) {
817
+ onload();
818
+ }
819
+ },
820
+ launch = function() {
821
+ dialog.addClass(fm.res('class', 'preventback'));
822
+ fm.toggleMaximize(container, true);
823
+ fm.toFront(container);
824
+ container.show().data('curhash', self.file.hash);
825
+ editor.edit(node.get(0));
826
+ node.data('loading')(true);
827
+ },
828
+ qBase, quty, qutyTm, canvas, editor;
829
+
830
+ node.data('loading')();
831
+
832
+ // jpeg quality controls
833
+ if (self.file.mime === 'image/jpeg') {
834
+ quty = $('<input type="number" class="ui-corner-all elfinder-resize-quality elfinder-tabstop"/>')
835
+ .attr('min', '1')
836
+ .attr('max', '100')
837
+ .attr('title', '1 - 100')
838
+ .on('change', function() {
839
+ var q = quty.val();
840
+ qutyTm && cancelAnimationFrame(qutyTm);
841
+ qutyTm = requestAnimationFrame(function() {
842
+ if (canvas) {
843
+ canvas.toBlob(function(blob) {
844
+ blob && quty.next('span').text(' (' + fm.formatSize(blob.size) + ')');
845
+ }, 'image/jpeg', Math.max(Math.min(q, 100), 1) / 100);
846
+ }
847
+ });
848
+ })
849
+ .val(fm.storage('jpgQuality') || fm.option('jpgQuality'));
850
+ qBase = $('<div class="ui-dialog-buttonset elfinder-edit-extras elfinder-edit-extras-quality"></div>')
851
+ .hide()
852
+ .append(
853
+ $('<span>').html(fm.i18n('quality') + ' : '), quty, $('<span></span>')
854
+ )
855
+ .prependTo($base.parent().next());
856
+ $base.data('quty', quty);
857
+ }
858
+
859
+ // load script then init
860
+ if (typeof Pixo === 'undefined') {
861
+ fm.loadScript(['https://pixoeditor.com:8443/editor/scripts/bridge.m.js'], function() {
862
+ init(launch);
863
+ }, {loadType: 'tag'});
864
+ } else {
865
+ init();
866
+ launch();
867
+ }
868
+ return dfrd;
869
+ },
870
+ // Convert content url to data uri scheme to save content
871
+ save : function(base) {
872
+ var self = this,
873
+ $base = $(base),
874
+ node = $base.children('img:first'),
875
+ q;
876
+ if (base._canvas) {
877
+ if ($base.data('quty')) {
878
+ q = $base.data('quty').val();
879
+ q && this.fm.storage('jpgQuality', q);
880
+ }
881
+ node.attr('src', base._canvas.toDataURL(self.file.mime, q? Math.max(Math.min(q, 100), 1) / 100 : void(0)));
882
+ } else if (node.attr('src').substr(0, 5) !== 'data:') {
883
+ node.attr('src', imgBase64(node, this.file.mime));
884
+ }
885
+ },
886
+ close : function(base, editor) {
887
+ editor && editor.destroy();
888
+ }
889
+ },
890
+ {
891
+ // ACE Editor
892
+ // called on initialization of elFinder cmd edit (this: this editor's config object)
893
+ setup : function(opts, fm) {
894
+ if (fm.UA.ltIE8 || !fm.options.cdns.ace) {
895
+ this.disabled = true;
896
+ }
897
+ },
898
+ // `mimes` is not set for support everything kind of text file
899
+ info : {
900
+ id : 'aceeditor',
901
+ name : 'ACE Editor',
902
+ iconImg : 'img/editor-icons.png 0 -96'
903
+ },
904
+ load : function(textarea) {
905
+ var self = this,
906
+ fm = this.fm,
907
+ dfrd = $.Deferred(),
908
+ cdn = fm.options.cdns.ace,
909
+ start = function() {
910
+ var editor, editorBase, mode,
911
+ ta = $(textarea),
912
+ taBase = ta.parent(),
913
+ dialog = taBase.parent(),
914
+ id = textarea.id + '_ace',
915
+ ext = self.file.name.replace(/^.+\.([^.]+)|(.+)$/, '$1$2').toLowerCase(),
916
+ // MIME/mode map
917
+ mimeMode = {
918
+ 'text/x-php' : 'php',
919
+ 'application/x-php' : 'php',
920
+ 'text/html' : 'html',
921
+ 'application/xhtml+xml' : 'html',
922
+ 'text/javascript' : 'javascript',
923
+ 'application/javascript' : 'javascript',
924
+ 'text/css' : 'css',
925
+ 'text/x-c' : 'c_cpp',
926
+ 'text/x-csrc' : 'c_cpp',
927
+ 'text/x-chdr' : 'c_cpp',
928
+ 'text/x-c++' : 'c_cpp',
929
+ 'text/x-c++src' : 'c_cpp',
930
+ 'text/x-c++hdr' : 'c_cpp',
931
+ 'text/x-shellscript' : 'sh',
932
+ 'application/x-csh' : 'sh',
933
+ 'text/x-python' : 'python',
934
+ 'text/x-java' : 'java',
935
+ 'text/x-java-source' : 'java',
936
+ 'text/x-ruby' : 'ruby',
937
+ 'text/x-perl' : 'perl',
938
+ 'application/x-perl' : 'perl',
939
+ 'text/x-sql' : 'sql',
940
+ 'text/xml' : 'xml',
941
+ 'application/docbook+xml' : 'xml',
942
+ 'application/xml' : 'xml'
943
+ };
944
+
945
+ // set base height
946
+ taBase.height(taBase.height());
947
+
948
+ // set basePath of ace
949
+ ace.config.set('basePath', cdn);
950
+
951
+ // Base node of Ace editor
952
+ editorBase = $('<div id="'+id+'" style="width:100%; height:100%;"></div>').text(ta.val()).insertBefore(ta.hide());
953
+
954
+ // Editor flag
955
+ ta.data('ace', true);
956
+
957
+ // Aceeditor instance
958
+ editor = ace.edit(id);
959
+
960
+ // Ace editor configure
961
+ editor.$blockScrolling = Infinity;
962
+ editor.setOptions({
963
+ theme: 'ace/theme/monokai',
964
+ fontSize: '14px',
965
+ wrap: true,
966
+ });
967
+ ace.config.loadModule('ace/ext/modelist', function() {
968
+ // detect mode
969
+ mode = ace.require('ace/ext/modelist').getModeForPath('/' + self.file.name).name;
970
+ if (mode === 'text') {
971
+ if (mimeMode[self.file.mime]) {
972
+ mode = mimeMode[self.file.mime];
973
+ }
974
+ }
975
+ // show MIME:mode in title bar
976
+ taBase.prev().children('.elfinder-dialog-title').append(' (' + self.file.mime + ' : ' + mode.split(/[\/\\]/).pop() + ')');
977
+ editor.setOptions({
978
+ mode: 'ace/mode/' + mode
979
+ });
980
+ if (dfrd.state() === 'resolved') {
981
+ dialog.trigger('resize');
982
+ }
983
+ });
984
+ ace.config.loadModule('ace/ext/language_tools', function() {
985
+ ace.require('ace/ext/language_tools');
986
+ editor.setOptions({
987
+ enableBasicAutocompletion: true,
988
+ enableSnippets: true,
989
+ enableLiveAutocompletion: false
990
+ });
991
+ });
992
+ ace.config.loadModule('ace/ext/settings_menu', function() {
993
+ ace.require('ace/ext/settings_menu').init(editor);
994
+ });
995
+
996
+ // Short cuts
997
+ editor.commands.addCommand({
998
+ name : "saveFile",
999
+ bindKey: {
1000
+ win : 'Ctrl-s',
1001
+ mac : 'Command-s'
1002
+ },
1003
+ exec: function(editor) {
1004
+ self.doSave();
1005
+ }
1006
+ });
1007
+ editor.commands.addCommand({
1008
+ name : "closeEditor",
1009
+ bindKey: {
1010
+ win : 'Ctrl-w|Ctrl-q',
1011
+ mac : 'Command-w|Command-q'
1012
+ },
1013
+ exec: function(editor) {
1014
+ self.doCancel();
1015
+ }
1016
+ });
1017
+
1018
+ editor.resize();
1019
+
1020
+ // TextArea button and Setting button
1021
+ $('<div class="ui-dialog-buttonset"></div>').css('float', 'left')
1022
+ .append(
1023
+ $('<button></button>').html(self.fm.i18n('TextArea'))
1024
+ .button()
1025
+ .on('click', function(){
1026
+ if (ta.data('ace')) {
1027
+ ta.removeData('ace');
1028
+ editorBase.hide();
1029
+ ta.val(editor.session.getValue()).show().trigger('focus');
1030
+ $(this).text('AceEditor');
1031
+ } else {
1032
+ ta.data('ace', true);
1033
+ editorBase.show();
1034
+ editor.setValue(ta.hide().val(), -1);
1035
+ editor.focus();
1036
+ $(this).html(self.fm.i18n('TextArea'));
1037
+ }
1038
+ })
1039
+ )
1040
+ .append(
1041
+ $('<button>Ace editor setting</button>')
1042
+ .button({
1043
+ icons: {
1044
+ primary: 'ui-icon-gear',
1045
+ secondary: 'ui-icon-triangle-1-e'
1046
+ },
1047
+ text: false
1048
+ })
1049
+ .on('click', function(){
1050
+ editor.showSettingsMenu();
1051
+ $('#ace_settingsmenu')
1052
+ .css('font-size', '80%')
1053
+ .find('div[contains="setOptions"]').hide().end()
1054
+ .parent().appendTo($('#elfinder'));
1055
+ })
1056
+ )
1057
+ .prependTo(taBase.next());
1058
+
1059
+ // trigger event 'editEditorPrepare'
1060
+ self.trigger('Prepare', {
1061
+ node: textarea,
1062
+ editorObj: ace,
1063
+ instance: editor,
1064
+ opts: {}
1065
+ });
1066
+
1067
+ //dialog.trigger('resize');
1068
+ dfrd.resolve(editor);
1069
+ };
1070
+
1071
+ // check ace & start
1072
+ if (!self.confObj.loader) {
1073
+ self.confObj.loader = $.Deferred();
1074
+ self.fm.loadScript([ cdn+'/ace.js' ], function() {
1075
+ self.confObj.loader.resolve();
1076
+ }, void 0, {obj: window, name: 'ace'});
1077
+ }
1078
+ self.confObj.loader.done(start);
1079
+
1080
+ return dfrd;
1081
+ },
1082
+ close : function(textarea, instance) {
1083
+ instance && instance.destroy();
1084
+ },
1085
+ save : function(textarea, instance) {
1086
+ instance && $(textarea).data('ace') && (textarea.value = instance.session.getValue());
1087
+ },
1088
+ focus : function(textarea, instance) {
1089
+ instance && $(textarea).data('ace') && instance.focus();
1090
+ },
1091
+ resize : function(textarea, instance, e, data) {
1092
+ instance && instance.resize();
1093
+ }
1094
+ },
1095
+ {
1096
+ // CodeMirror
1097
+ // called on initialization of elFinder cmd edit (this: this editor's config object)
1098
+ setup : function(opts, fm) {
1099
+ if (fm.UA.ltIE10 || !fm.options.cdns.codemirror) {
1100
+ this.disabled = true;
1101
+ }
1102
+ },
1103
+ // `mimes` is not set for support everything kind of text file
1104
+ info : {
1105
+ id : 'codemirror',
1106
+ name : 'CodeMirror',
1107
+ iconImg : 'img/editor-icons.png 0 -176'
1108
+ },
1109
+ load : function(textarea) {
1110
+ var fm = this.fm,
1111
+ cmUrl = fm.convAbsUrl(fm.options.cdns.codemirror),
1112
+ dfrd = $.Deferred(),
1113
+ self = this,
1114
+ start = function(CodeMirror) {
1115
+ var ta = $(textarea),
1116
+ base = ta.parent(),
1117
+ editor, editorBase, opts;
1118
+
1119
+ // set base height
1120
+ base.height(base.height());
1121
+
1122
+ // CodeMirror configure options
1123
+ opts = {
1124
+ lineNumbers: true,
1125
+ lineWrapping: true,
1126
+ extraKeys : {
1127
+ 'Ctrl-S': function() { self.doSave(); },
1128
+ 'Ctrl-Q': function() { self.doCancel(); },
1129
+ 'Ctrl-W': function() { self.doCancel(); }
1130
+ }
1131
+ };
1132
+
1133
+ // trigger event 'editEditorPrepare'
1134
+ self.trigger('Prepare', {
1135
+ node: textarea,
1136
+ editorObj: CodeMirror,
1137
+ instance: void(0),
1138
+ opts: opts
1139
+ });
1140
+
1141
+ // CodeMirror configure
1142
+ editor = CodeMirror.fromTextArea(textarea, opts);
1143
+
1144
+ // return editor instance
1145
+ dfrd.resolve(editor);
1146
+
1147
+ // Auto mode set
1148
+ var info, m, mode, spec;
1149
+ if (! info) {
1150
+ info = CodeMirror.findModeByMIME(self.file.mime);
1151
+ }
1152
+ if (! info && (m = self.file.name.match(/.+\.([^.]+)$/))) {
1153
+ info = CodeMirror.findModeByExtension(m[1]);
1154
+ }
1155
+ if (info) {
1156
+ CodeMirror.modeURL = useRequire? 'codemirror/mode/%N/%N.min' : cmUrl + '/mode/%N/%N.min.js';
1157
+ mode = info.mode;
1158
+ spec = info.mime;
1159
+ editor.setOption('mode', spec);
1160
+ CodeMirror.autoLoadMode(editor, mode);
1161
+ // show MIME:mode in title bar
1162
+ base.prev().children('.elfinder-dialog-title').append(' (' + spec + (mode != 'null'? ' : ' + mode : '') + ')');
1163
+ }
1164
+
1165
+ // editor base node
1166
+ editorBase = $(editor.getWrapperElement()).css({
1167
+ // fix CSS conflict to SimpleMDE
1168
+ padding: 0,
1169
+ border: 'none'
1170
+ });
1171
+ ta.data('cm', true);
1172
+
1173
+ // fit height to base
1174
+ editorBase.height('100%');
1175
+
1176
+ // TextArea button and Setting button
1177
+ $('<div class="ui-dialog-buttonset"></div>').css('float', 'left')
1178
+ .append(
1179
+ $('<button></button>').html(self.fm.i18n('TextArea'))
1180
+ .button()
1181
+ .on('click', function(){
1182
+ if (ta.data('cm')) {
1183
+ ta.removeData('cm');
1184
+ editorBase.hide();
1185
+ ta.val(editor.getValue()).show().trigger('focus');
1186
+ $(this).text('CodeMirror');
1187
+ } else {
1188
+ ta.data('cm', true);
1189
+ editorBase.show();
1190
+ editor.setValue(ta.hide().val());
1191
+ editor.refresh();
1192
+ editor.focus();
1193
+ $(this).html(self.fm.i18n('TextArea'));
1194
+ }
1195
+ })
1196
+ )
1197
+ .prependTo(base.next());
1198
+ };
1199
+ // load script then start
1200
+ if (!self.confObj.loader) {
1201
+ self.confObj.loader = $.Deferred();
1202
+ if (useRequire) {
1203
+ require.config({
1204
+ packages: [{
1205
+ name: 'codemirror',
1206
+ location: cmUrl,
1207
+ main: 'codemirror.min'
1208
+ }],
1209
+ map: {
1210
+ 'codemirror': {
1211
+ 'codemirror/lib/codemirror': 'codemirror'
1212
+ }
1213
+ }
1214
+ });
1215
+ require([
1216
+ 'codemirror',
1217
+ 'codemirror/addon/mode/loadmode.min',
1218
+ 'codemirror/mode/meta.min'
1219
+ ], function(CodeMirror) {
1220
+ self.confObj.loader.resolve(CodeMirror);
1221
+ });
1222
+ } else {
1223
+ self.fm.loadScript([
1224
+ cmUrl + '/codemirror.min.js'
1225
+ ], function() {
1226
+ self.fm.loadScript([
1227
+ cmUrl + '/addon/mode/loadmode.min.js',
1228
+ cmUrl + '/mode/meta.min.js'
1229
+ ], function() {
1230
+ self.confObj.loader.resolve(CodeMirror);
1231
+ });
1232
+ }, {loadType: 'tag'});
1233
+ }
1234
+ self.fm.loadCss(cmUrl + '/codemirror.css');
1235
+ }
1236
+ self.confObj.loader.done(start);
1237
+ return dfrd;
1238
+ },
1239
+ close : function(textarea, instance) {
1240
+ instance && instance.toTextArea();
1241
+ },
1242
+ save : function(textarea, instance) {
1243
+ instance && $(textarea).data('cm') && (textarea.value = instance.getValue());
1244
+ },
1245
+ focus : function(textarea, instance) {
1246
+ instance && $(textarea).data('cm') && instance.focus();
1247
+ },
1248
+ resize : function(textarea, instance, e, data) {
1249
+ instance && instance.refresh();
1250
+ }
1251
+ },
1252
+ {
1253
+ // SimpleMDE
1254
+ // called on initialization of elFinder cmd edit (this: this editor's config object)
1255
+ setup : function(opts, fm) {
1256
+ if (fm.UA.ltIE10 || !fm.options.cdns.simplemde) {
1257
+ this.disabled = true;
1258
+ }
1259
+ },
1260
+ info : {
1261
+ id : 'simplemde',
1262
+ name : 'SimpleMDE',
1263
+ iconImg : 'img/editor-icons.png 0 -80'
1264
+ },
1265
+ exts : ['md'],
1266
+ load : function(textarea) {
1267
+ var self = this,
1268
+ fm = this.fm,
1269
+ base = $(textarea).parent(),
1270
+ dfrd = $.Deferred(),
1271
+ cdn = fm.options.cdns.simplemde,
1272
+ start = function(SimpleMDE) {
1273
+ var h = base.height(),
1274
+ delta = base.outerHeight(true) - h + 14,
1275
+ editor, editorBase, opts;
1276
+
1277
+ // fit height function
1278
+ textarea._setHeight = function(height) {
1279
+ var h = height || base.height(),
1280
+ ctrH = 0,
1281
+ areaH;
1282
+ base.children('.editor-toolbar,.editor-statusbar').each(function() {
1283
+ ctrH += $(this).outerHeight(true);
1284
+ });
1285
+ areaH = h - ctrH - delta;
1286
+ editorBase.height(areaH);
1287
+ editor.codemirror.refresh();
1288
+ return areaH;
1289
+ };
1290
+
1291
+ // set base height
1292
+ base.height(h);
1293
+
1294
+ opts = {
1295
+ element: textarea,
1296
+ autofocus: true
1297
+ };
1298
+
1299
+ // trigger event 'editEditorPrepare'
1300
+ self.trigger('Prepare', {
1301
+ node: textarea,
1302
+ editorObj: SimpleMDE,
1303
+ instance: void(0),
1304
+ opts: opts
1305
+ });
1306
+
1307
+ // make editor
1308
+ editor = new SimpleMDE(opts);
1309
+ dfrd.resolve(editor);
1310
+
1311
+ // editor base node
1312
+ editorBase = $(editor.codemirror.getWrapperElement());
1313
+
1314
+ // fit height to base
1315
+ editorBase.css('min-height', '50px')
1316
+ .children('.CodeMirror-scroll').css('min-height', '50px');
1317
+ textarea._setHeight(h);
1318
+ };
1319
+
1320
+ // check SimpleMDE & start
1321
+ if (!self.confObj.loader) {
1322
+ self.confObj.loader = $.Deferred();
1323
+ self.fm.loadCss(cdn+'/simplemde.min.css');
1324
+ if (useRequire) {
1325
+ require([
1326
+ cdn+'/simplemde.min.js'
1327
+ ], function(SimpleMDE) {
1328
+ self.confObj.loader.resolve(SimpleMDE);
1329
+ });
1330
+ } else {
1331
+ self.fm.loadScript([cdn+'/simplemde.min.js'], function() {
1332
+ self.confObj.loader.resolve(SimpleMDE);
1333
+ }, {loadType: 'tag'});
1334
+ }
1335
+ }
1336
+ self.confObj.loader.done(start);
1337
+
1338
+ return dfrd;
1339
+ },
1340
+ close : function(textarea, instance) {
1341
+ instance && instance.toTextArea();
1342
+ instance = null;
1343
+ },
1344
+ save : function(textarea, instance) {
1345
+ instance && (textarea.value = instance.value());
1346
+ },
1347
+ focus : function(textarea, instance) {
1348
+ instance && instance.codemirror.focus();
1349
+ },
1350
+ resize : function(textarea, instance, e, data) {
1351
+ instance && textarea._setHeight();
1352
+ }
1353
+ },
1354
+ {
1355
+ // CKEditor for html file
1356
+ info : {
1357
+ id : 'ckeditor',
1358
+ name : 'CKEditor',
1359
+ iconImg : 'img/editor-icons.png 0 0'
1360
+ },
1361
+ exts : ['htm', 'html', 'xhtml'],
1362
+ setup : function(opts, fm) {
1363
+ var confObj = this;
1364
+ if (!fm.options.cdns.ckeditor) {
1365
+ confObj.disabled = true;
1366
+ } else {
1367
+ confObj.ckeOpts = {};
1368
+ if (opts.extraOptions) {
1369
+ confObj.ckeOpts = Object.assign({}, opts.extraOptions.ckeditor || {});
1370
+ if (opts.extraOptions.managerUrl) {
1371
+ confObj.managerUrl = opts.extraOptions.managerUrl;
1372
+ }
1373
+ }
1374
+ }
1375
+ },
1376
+ load : function(textarea) {
1377
+ var self = this,
1378
+ fm = this.fm,
1379
+ dfrd = $.Deferred(),
1380
+ init = function() {
1381
+ var base = $(textarea).parent(),
1382
+ dlg = base.closest('.elfinder-dialog'),
1383
+ h = base.height(),
1384
+ reg = /([&?]getfile=)[^&]+/,
1385
+ loc = self.confObj.managerUrl || window.location.href.replace(/#.*$/, ''),
1386
+ name = 'ckeditor',
1387
+ opts;
1388
+
1389
+ // make manager location
1390
+ if (reg.test(loc)) {
1391
+ loc = loc.replace(reg, '$1' + name);
1392
+ } else {
1393
+ loc += '?getfile=' + name;
1394
+ }
1395
+ // set base height
1396
+ base.height(h);
1397
+
1398
+ // CKEditor configure options
1399
+ opts = {
1400
+ startupFocus : true,
1401
+ fullPage: true,
1402
+ allowedContent: true,
1403
+ filebrowserBrowseUrl : loc,
1404
+ toolbarCanCollapse: true,
1405
+ toolbarStartupExpanded: !fm.UA.Mobile,
1406
+ removePlugins: 'resize',
1407
+ extraPlugins: 'colorbutton,justify,docprops',
1408
+ on: {
1409
+ 'instanceReady' : function(e) {
1410
+ var editor = e.editor;
1411
+ editor.resize('100%', h);
1412
+ // re-build on dom move
1413
+ dlg.one('beforedommove.'+fm.namespace, function() {
1414
+ editor.destroy();
1415
+ }).one('dommove.'+fm.namespace, function() {
1416
+ self.load(textarea).done(function(editor) {
1417
+ self.instance = editor;
1418
+ });
1419
+ });
1420
+ // return editor instance
1421
+ dfrd.resolve(e.editor);
1422
+ }
1423
+ }
1424
+ };
1425
+
1426
+ // trigger event 'editEditorPrepare'
1427
+ self.trigger('Prepare', {
1428
+ node: textarea,
1429
+ editorObj: CKEDITOR,
1430
+ instance: void(0),
1431
+ opts: opts
1432
+ });
1433
+
1434
+ // CKEditor configure
1435
+ CKEDITOR.replace(textarea.id, Object.assign(opts, self.confObj.ckeOpts));
1436
+ CKEDITOR.on('dialogDefinition', function(e) {
1437
+ var dlg = e.data.definition.dialog;
1438
+ dlg.on('show', function(e) {
1439
+ fm.getUI().append($('.cke_dialog_background_cover')).append(this.getElement().$);
1440
+ });
1441
+ dlg.on('hide', function(e) {
1442
+ $('body:first').append($('.cke_dialog_background_cover')).append(this.getElement().$);
1443
+ });
1444
+ });
1445
+ };
1446
+
1447
+ if (!self.confObj.loader) {
1448
+ self.confObj.loader = $.Deferred();
1449
+ window.CKEDITOR_BASEPATH = fm.options.cdns.ckeditor + '/';
1450
+ $.getScript(fm.options.cdns.ckeditor + '/ckeditor.js', function() {
1451
+ self.confObj.loader.resolve();
1452
+ });
1453
+ }
1454
+ self.confObj.loader.done(init);
1455
+ return dfrd;
1456
+ },
1457
+ close : function(textarea, instance) {
1458
+ instance && instance.destroy();
1459
+ },
1460
+ save : function(textarea, instance) {
1461
+ instance && (textarea.value = instance.getData());
1462
+ },
1463
+ focus : function(textarea, instance) {
1464
+ instance && instance.focus();
1465
+ },
1466
+ resize : function(textarea, instance, e, data) {
1467
+ var self;
1468
+ if (instance) {
1469
+ if (instance.status === 'ready') {
1470
+ instance.resize('100%', $(textarea).parent().height());
1471
+ }
1472
+ }
1473
+ }
1474
+ },
1475
+ {
1476
+ // CKEditor5 balloon mode for html file
1477
+ info : {
1478
+ id : 'ckeditor5',
1479
+ name : 'CKEditor5',
1480
+ iconImg : 'img/editor-icons.png 0 -16'
1481
+ },
1482
+ exts : ['htm', 'html', 'xhtml'],
1483
+ html : '<div class="edit-editor-ckeditor5"></div>',
1484
+ setup : function(opts, fm) {
1485
+ var confObj = this;
1486
+ // check cdn and ES6 support
1487
+ if (!fm.options.cdns.ckeditor5 || typeof window.Symbol !== 'function' || typeof Symbol() !== 'symbol') {
1488
+ confObj.disabled = true;
1489
+ } else {
1490
+ confObj.ckeOpts = {};
1491
+ if (opts.extraOptions) {
1492
+ // @deprecated option extraOptions.ckeditor5Mode
1493
+ if (opts.extraOptions.ckeditor5Mode) {
1494
+ confObj.ckeditor5Mode = opts.extraOptions.ckeditor5Mode;
1495
+ }
1496
+ confObj.ckeOpts = Object.assign({}, opts.extraOptions.ckeditor5 || {});
1497
+ if (confObj.ckeOpts.mode) {
1498
+ confObj.ckeditor5Mode = confObj.ckeOpts.mode;
1499
+ delete confObj.ckeOpts.mode;
1500
+ }
1501
+ if (opts.extraOptions.managerUrl) {
1502
+ confObj.managerUrl = opts.extraOptions.managerUrl;
1503
+ }
1504
+ }
1505
+ }
1506
+ fm.bind('destroy', function() {
1507
+ confObj.editor = null;
1508
+ });
1509
+ },
1510
+ // Prepare on before show dialog
1511
+ prepare : function(base, dialogOpts, file) {
1512
+ $(base).height(base.editor.fm.getUI().height() - 100);
1513
+ },
1514
+ init : function(id, file, data, fm) {
1515
+ var m = data.match(/^([\s\S]*<body[^>]*>)([\s\S]+)(<\/body>[\s\S]*)$/i),
1516
+ header = '',
1517
+ body = '',
1518
+ footer ='';
1519
+ this.css({
1520
+ width: '100%',
1521
+ height: '100%',
1522
+ 'box-sizing': 'border-box'
1523
+ });
1524
+ if (m) {
1525
+ header = m[1];
1526
+ body = m[2];
1527
+ footer = m[3];
1528
+ } else {
1529
+ body = data;
1530
+ }
1531
+ this.data('data', {
1532
+ header: header,
1533
+ body: body,
1534
+ footer: footer
1535
+ });
1536
+ this._setupSelEncoding(data);
1537
+ },
1538
+ load : function(editnode) {
1539
+ var self = this,
1540
+ fm = this.fm,
1541
+ dfrd = $.Deferred(),
1542
+ mode = self.confObj.ckeditor5Mode || 'decoupled-document',
1543
+ lang = (function() {
1544
+ var l = fm.lang.toLowerCase().replace('_', '-');
1545
+ if (l.substr(0, 2) === 'zh' && l !== 'zh-cn') {
1546
+ l = 'zh';
1547
+ }
1548
+ return l;
1549
+ })(),
1550
+ init = function(cEditor) {
1551
+ var base = $(editnode).parent(),
1552
+ opts;
1553
+
1554
+ // set base height
1555
+ base.height(fm.getUI().height() - 100);
1556
+
1557
+ // CKEditor5 configure options
1558
+ opts = Object.assign({
1559
+ toolbar: ["heading", "|", "fontSize", "fontFamily", "|", "bold", "italic", "underline", "strikethrough", "highlight", "|", "alignment", "|", "numberedList", "bulletedList", "blockQuote", "indent", "outdent", "|", "ckfinder", "link", "imageUpload", "insertTable", "mediaEmbed", "|", "undo", "redo"],
1560
+ language: lang
1561
+ }, self.confObj.ckeOpts);
1562
+
1563
+ // trigger event 'editEditorPrepare'
1564
+ self.trigger('Prepare', {
1565
+ node: editnode,
1566
+ editorObj: cEditor,
1567
+ instance: void(0),
1568
+ opts: opts
1569
+ });
1570
+
1571
+ cEditor
1572
+ .create(editnode, opts)
1573
+ .then(function(editor) {
1574
+ var ckf = editor.commands.get('ckfinder'),
1575
+ fileRepo = editor.plugins.get('FileRepository'),
1576
+ prevVars = {}, isImage, insertImages;
1577
+ if (editor.ui.view.toolbar && (mode === 'classic' || mode === 'decoupled-document')) {
1578
+ $(editnode).closest('.elfinder-dialog').children('.ui-widget-header').append($(editor.ui.view.toolbar.element).css({marginRight:'-1em',marginLeft:'-1em'}));
1579
+ }
1580
+ if (mode === 'classic') {
1581
+ $(editnode).closest('.elfinder-edit-editor').css('overflow', 'auto');
1582
+ }
1583
+ // Set up this elFinder instead of CKFinder
1584
+ if (ckf) {
1585
+ isImage = function(f) {
1586
+ return f && f.mime.match(/^image\//i);
1587
+ };
1588
+ insertImages = function(urls) {
1589
+ var imgCmd = editor.commands.get('imageUpload');
1590
+ if (!imgCmd.isEnabled) {
1591
+ var ntf = editor.plugins.get('Notification'),
1592
+ i18 = editor.locale.t;
1593
+ ntf.showWarning(i18('Could not insert image at the current position.'), {
1594
+ title: i18('Inserting image failed'),
1595
+ namespace: 'ckfinder'
1596
+ });
1597
+ return;
1598
+ }
1599
+ editor.execute('imageInsert', { source: urls });
1600
+ };
1601
+ // Take over ckfinder execute()
1602
+ ckf.execute = function() {
1603
+ var dlg = base.closest('.elfinder-dialog'),
1604
+ gf = fm.getCommand('getfile'),
1605
+ rever = function() {
1606
+ if (prevVars.hasVar) {
1607
+ dlg.off('resize close', rever);
1608
+ gf.callback = prevVars.callback;
1609
+ gf.options.folders = prevVars.folders;
1610
+ gf.options.multiple = prevVars.multi;
1611
+ fm.commandMap.open = prevVars.open;
1612
+ prevVars.hasVar = false;
1613
+ }
1614
+ };
1615
+ dlg.trigger('togleminimize').one('resize close', rever);
1616
+ prevVars.callback = gf.callback;
1617
+ prevVars.folders = gf.options.folders;
1618
+ prevVars.multi = gf.options.multiple;
1619
+ prevVars.open = fm.commandMap.open;
1620
+ prevVars.hasVar = true;
1621
+ gf.callback = function(files) {
1622
+ var imgs = [];
1623
+ if (files.length === 1 && files[0].mime === 'directory') {
1624
+ fm.one('open', function() {
1625
+ fm.commandMap.open = 'getfile';
1626
+ }).getCommand('open').exec(files[0].hash);
1627
+ return;
1628
+ }
1629
+ fm.getUI('cwd').trigger('unselectall');
1630
+ $.each(files, function(i, f) {
1631
+ if (isImage(f)) {
1632
+ imgs.push(fm.convAbsUrl(f.url));
1633
+ } else {
1634
+ editor.execute('link', fm.convAbsUrl(f.url));
1635
+ }
1636
+ });
1637
+ if (imgs.length) {
1638
+ insertImages(imgs);
1639
+ }
1640
+ dlg.trigger('togleminimize');
1641
+ };
1642
+ gf.options.folders = true;
1643
+ gf.options.multiple = true;
1644
+ fm.commandMap.open = 'getfile';
1645
+ fm.toast({
1646
+ mode: 'info',
1647
+ msg: fm.i18n('dblclickToSelect')
1648
+ });
1649
+ };
1650
+ }
1651
+ // Set up image uploader
1652
+ fileRepo.createUploadAdapter = function(loader) {
1653
+ return new uploder(loader);
1654
+ };
1655
+ editor.setData($(editnode).data('data').body);
1656
+ // move .ck-body to elFinder node for fullscreen mode
1657
+ fm.getUI().append($('body > div.ck-body'));
1658
+ $('div.ck-balloon-panel').css({
1659
+ 'z-index': fm.getMaximizeCss().zIndex + 1
1660
+ });
1661
+ dfrd.resolve(editor);
1662
+ /*fm.log({
1663
+ defaultConfig: cEditor.defaultConfig,
1664
+ plugins: cEditor.builtinPlugins.map(function(p) { return p.pluginName; }),
1665
+ toolbars: Array.from(editor.ui.componentFactory.names())
1666
+ });*/
1667
+ })
1668
+ ['catch'](function(error) { // ['cache'] instead .cache for fix error on ie8
1669
+ fm.error(error);
1670
+ });
1671
+ },
1672
+ uploder = function(loader) {
1673
+ var upload = function(file, resolve, reject) {
1674
+ fm.exec('upload', {files: [file]}, void(0), fm.cwd().hash)
1675
+ .done(function(data){
1676
+ if (data.added && data.added.length) {
1677
+ fm.url(data.added[0].hash, { async: true }).done(function(url) {
1678
+ resolve({
1679
+ 'default': fm.convAbsUrl(url)
1680
+ });
1681
+ }).fail(function() {
1682
+ reject('errFileNotFound');
1683
+ });
1684
+ } else {
1685
+ reject(fm.i18n(data.error? data.error : 'errUpload'));
1686
+ }
1687
+ })
1688
+ .fail(function(err) {
1689
+ var error = fm.parseError(err);
1690
+ reject(fm.i18n(error? (error === 'userabort'? 'errAbort' : error) : 'errUploadNoFiles'));
1691
+ })
1692
+ .progress(function(data) {
1693
+ loader.uploadTotal = data.total;
1694
+ loader.uploaded = data.progress;
1695
+ });
1696
+ };
1697
+ this.upload = function() {
1698
+ return new Promise(function(resolve, reject) {
1699
+ if (loader.file instanceof Promise || (loader.file && typeof loader.file.then === 'function')) {
1700
+ loader.file.then(function(file) {
1701
+ upload(file, resolve, reject);
1702
+ });
1703
+ } else {
1704
+ upload(loader.file, resolve, reject);
1705
+ }
1706
+ });
1707
+ };
1708
+ this.abort = function() {
1709
+ fm.getUI().trigger('uploadabort');
1710
+ };
1711
+ }, loader;
1712
+
1713
+ if (!self.confObj.editor) {
1714
+ loader = $.Deferred();
1715
+ self.fm.loadScript([
1716
+ fm.options.cdns.ckeditor5 + '/' + mode + '/ckeditor.js'
1717
+ ], function(editor) {
1718
+ if (!editor) {
1719
+ editor = window.BalloonEditor || window.InlineEditor || window.ClassicEditor || window.DecoupledEditor;
1720
+ }
1721
+ if (fm.lang !== 'en') {
1722
+ self.fm.loadScript([
1723
+ fm.options.cdns.ckeditor5 + '/' + mode + '/translations/' + lang + '.js'
1724
+ ], function(obj) {
1725
+ loader.resolve(editor);
1726
+ }, {
1727
+ tryRequire: true,
1728
+ loadType: 'tag',
1729
+ error: function(obj) {
1730
+ lang = 'en';
1731
+ loader.resolve(editor);
1732
+ }
1733
+ });
1734
+ } else {
1735
+ loader.resolve(editor);
1736
+ }
1737
+ }, {
1738
+ tryRequire: true,
1739
+ loadType: 'tag'
1740
+ });
1741
+ loader.done(function(editor) {
1742
+ self.confObj.editor = editor;
1743
+ init(editor);
1744
+ });
1745
+ } else {
1746
+ init(self.confObj.editor);
1747
+ }
1748
+ return dfrd;
1749
+ },
1750
+ getContent : function() {
1751
+ var data = $(this).data('data');
1752
+ return data.header + data.body + data.footer;
1753
+ },
1754
+ close : function(editnode, instance) {
1755
+ instance && instance.destroy();
1756
+ },
1757
+ save : function(editnode, instance) {
1758
+ var elm = $(editnode),
1759
+ data = elm.data('data');
1760
+ if (instance) {
1761
+ data.body = instance.getData();
1762
+ elm.data('data', data);
1763
+ }
1764
+ },
1765
+ focus : function(editnode, instance) {
1766
+ $(editnode).trigger('focus');
1767
+ }
1768
+ },
1769
+ {
1770
+ // TinyMCE for html file
1771
+ info : {
1772
+ id : 'tinymce',
1773
+ name : 'TinyMCE',
1774
+ iconImg : 'img/editor-icons.png 0 -64'
1775
+ },
1776
+ exts : ['htm', 'html', 'xhtml'],
1777
+ setup : function(opts, fm) {
1778
+ var confObj = this;
1779
+ if (!fm.options.cdns.tinymce) {
1780
+ confObj.disabled = true;
1781
+ } else {
1782
+ confObj.mceOpts = {};
1783
+ if (opts.extraOptions) {
1784
+ confObj.uploadOpts = Object.assign({}, opts.extraOptions.uploadOpts || {});
1785
+ confObj.mceOpts = Object.assign({}, opts.extraOptions.tinymce || {});
1786
+ } else {
1787
+ confObj.uploadOpts = {};
1788
+ }
1789
+ }
1790
+ },
1791
+ load : function(textarea) {
1792
+ var self = this,
1793
+ fm = this.fm,
1794
+ dfrd = $.Deferred(),
1795
+ init = function() {
1796
+ var base = $(textarea).show().parent(),
1797
+ dlg = base.closest('.elfinder-dialog'),
1798
+ h = base.height(),
1799
+ delta = base.outerHeight(true) - h,
1800
+ // hide MCE dialog and modal block
1801
+ hideMceDlg = function() {
1802
+ var mceW;
1803
+ if (tinymce.activeEditor.windowManager.windows) {
1804
+ mceW = tinymce.activeEditor.windowManager.windows[0];
1805
+ mceDlg = $(mceW? mceW.getEl() : void(0)).hide();
1806
+ mceCv = $('#mce-modal-block').hide();
1807
+ } else {
1808
+ mceDlg = $('.tox-dialog-wrap').hide();
1809
+ }
1810
+ },
1811
+ // Show MCE dialog and modal block
1812
+ showMceDlg = function() {
1813
+ mceCv && mceCv.show();
1814
+ mceDlg && mceDlg.show();
1815
+ },
1816
+ tVer = tinymce.majorVersion,
1817
+ opts, mceDlg, mceCv;
1818
+
1819
+ // set base height
1820
+ base.height(h);
1821
+ // fit height function
1822
+ textarea._setHeight = function(height) {
1823
+ if (tVer < 5) {
1824
+ var base = $(this).parent(),
1825
+ h = height || base.innerHeight(),
1826
+ ctrH = 0,
1827
+ areaH;
1828
+ base.find('.mce-container-body:first').children('.mce-top-part,.mce-statusbar').each(function() {
1829
+ ctrH += $(this).outerHeight(true);
1830
+ });
1831
+ areaH = h - ctrH - delta;
1832
+ base.find('.mce-edit-area iframe:first').height(areaH);
1833
+ }
1834
+ };
1835
+
1836
+ // TinyMCE configure options
1837
+ opts = {
1838
+ selector: '#' + textarea.id,
1839
+ resize: false,
1840
+ plugins: 'print preview fullpage searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap hr pagebreak nonbreaking anchor toc insertdatetime advlist lists wordcount imagetools textpattern help',
1841
+ toolbar: 'formatselect | bold italic strikethrough forecolor backcolor | link image media | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat',
1842
+ image_advtab: true,
1843
+ init_instance_callback : function(editor) {
1844
+ // fit height on init
1845
+ textarea._setHeight(h);
1846
+ // re-build on dom move
1847
+ dlg.one('beforedommove.'+fm.namespace, function() {
1848
+ tinymce.execCommand('mceRemoveEditor', false, textarea.id);
1849
+ }).one('dommove.'+fm.namespace, function() {
1850
+ self.load(textarea).done(function(editor) {
1851
+ self.instance = editor;
1852
+ });
1853
+ });
1854
+ // return editor instance
1855
+ dfrd.resolve(editor);
1856
+ },
1857
+ file_picker_callback : function (callback, value, meta) {
1858
+ var gf = fm.getCommand('getfile'),
1859
+ revar = function() {
1860
+ if (prevVars.hasVar) {
1861
+ gf.callback = prevVars.callback;
1862
+ gf.options.folders = prevVars.folders;
1863
+ gf.options.multiple = prevVars.multi;
1864
+ fm.commandMap.open = prevVars.open;
1865
+ prevVars.hasVar = false;
1866
+ }
1867
+ dlg.off('resize close', revar);
1868
+ showMceDlg();
1869
+ },
1870
+ prevVars = {};
1871
+ prevVars.callback = gf.callback;
1872
+ prevVars.folders = gf.options.folders;
1873
+ prevVars.multi = gf.options.multiple;
1874
+ prevVars.open = fm.commandMap.open;
1875
+ prevVars.hasVar = true;
1876
+ gf.callback = function(file) {
1877
+ var url, info;
1878
+
1879
+ if (file.mime === 'directory') {
1880
+ fm.one('open', function() {
1881
+ fm.commandMap.open = 'getfile';
1882
+ }).getCommand('open').exec(file.hash);
1883
+ return;
1884
+ }
1885
+
1886
+ // URL normalization
1887
+ url = fm.convAbsUrl(file.url);
1888
+
1889
+ // Make file info
1890
+ info = file.name + ' (' + fm.formatSize(file.size) + ')';
1891
+
1892
+ // Provide file and text for the link dialog
1893
+ if (meta.filetype == 'file') {
1894
+ callback(url, {text: info, title: info});
1895
+ }
1896
+
1897
+ // Provide image and alt text for the image dialog
1898
+ if (meta.filetype == 'image') {
1899
+ callback(url, {alt: info});
1900
+ }
1901
+
1902
+ // Provide alternative source and posted for the media dialog
1903
+ if (meta.filetype == 'media') {
1904
+ callback(url);
1905
+ }
1906
+ dlg.trigger('togleminimize');
1907
+ };
1908
+ gf.options.folders = true;
1909
+ gf.options.multiple = false;
1910
+ fm.commandMap.open = 'getfile';
1911
+
1912
+ hideMceDlg();
1913
+ dlg.trigger('togleminimize').one('resize close', revar);
1914
+ fm.toast({
1915
+ mode: 'info',
1916
+ msg: fm.i18n('dblclickToSelect')
1917
+ });
1918
+
1919
+ return false;
1920
+ },
1921
+ images_upload_handler : function (blobInfo, success, failure) {
1922
+ var file = blobInfo.blob(),
1923
+ err = function(e) {
1924
+ var dlg = e.data.dialog || {};
1925
+ if (dlg.hasClass('elfinder-dialog-error') || dlg.hasClass('elfinder-confirm-upload')) {
1926
+ hideMceDlg();
1927
+ dlg.trigger('togleminimize').one('resize close', revert);
1928
+ fm.unbind('dialogopened', err);
1929
+ }
1930
+ },
1931
+ revert = function() {
1932
+ dlg.off('resize close', revert);
1933
+ showMceDlg();
1934
+ },
1935
+ clipdata = true;
1936
+
1937
+ // check file object
1938
+ if (file.name) {
1939
+ // file blob of client side file object
1940
+ clipdata = void(0);
1941
+ }
1942
+ fm.bind('dialogopened', err).exec('upload', Object.assign({
1943
+ files: [file],
1944
+ clipdata: clipdata // to get unique name on connector
1945
+ }, self.confObj.uploadOpts), void(0), fm.cwd().hash).done(function(data) {
1946
+ if (data.added && data.added.length) {
1947
+ fm.url(data.added[0].hash, { async: true }).done(function(url) {
1948
+ showMceDlg();
1949
+ success(fm.convAbsUrl(url));
1950
+ }).fail(function() {
1951
+ failure(fm.i18n('errFileNotFound'));
1952
+ });
1953
+ } else {
1954
+ failure(fm.i18n(data.error? data.error : 'errUpload'));
1955
+ }
1956
+ }).fail(function(err) {
1957
+ var error = fm.parseError(err);
1958
+ if (error) {
1959
+ if (error === 'errUnknownCmd') {
1960
+ error = 'errPerm';
1961
+ } else if (error === 'userabort') {
1962
+ error = 'errAbort';
1963
+ }
1964
+ }
1965
+ failure(fm.i18n(error? error : 'errUploadNoFiles'));
1966
+ });
1967
+ }
1968
+ };
1969
+
1970
+ // TinyMCE 5 supports "height: 100%"
1971
+ if (tVer >= 5) {
1972
+ opts.height = '100%';
1973
+ }
1974
+
1975
+ // trigger event 'editEditorPrepare'
1976
+ self.trigger('Prepare', {
1977
+ node: textarea,
1978
+ editorObj: tinymce,
1979
+ instance: void(0),
1980
+ opts: opts
1981
+ });
1982
+
1983
+ // TinyMCE configure
1984
+ tinymce.init(Object.assign(opts, self.confObj.mceOpts));
1985
+ };
1986
+
1987
+ if (!self.confObj.loader) {
1988
+ self.confObj.loader = $.Deferred();
1989
+ self.fm.loadScript([fm.options.cdns.tinymce + (fm.options.cdns.tinymce.match(/\.js/)? '' : '/tinymce.min.js')], function() {
1990
+ self.confObj.loader.resolve();
1991
+ }, {
1992
+ loadType: 'tag'
1993
+ });
1994
+ }
1995
+ self.confObj.loader.done(init);
1996
+ return dfrd;
1997
+ },
1998
+ close : function(textarea, instance) {
1999
+ instance && tinymce.execCommand('mceRemoveEditor', false, textarea.id);
2000
+ },
2001
+ save : function(textarea, instance) {
2002
+ instance && instance.save();
2003
+ },
2004
+ focus : function(textarea, instance) {
2005
+ instance && instance.focus();
2006
+ },
2007
+ resize : function(textarea, instance, e, data) {
2008
+ // fit height to base node on dialog resize
2009
+ instance && textarea._setHeight();
2010
+ }
2011
+ },
2012
+ {
2013
+ info : {
2014
+ id : 'zohoeditor',
2015
+ name : 'Zoho Editor',
2016
+ iconImg : 'img/editor-icons.png 0 -32',
2017
+ cmdCheck : 'ZohoOffice',
2018
+ preventGet: true,
2019
+ hideButtons: true,
2020
+ syncInterval : 15000,
2021
+ canMakeEmpty: true,
2022
+ integrate: {
2023
+ title: 'Zoho Office API',
2024
+ link: 'https://www.zoho.com/officeapi/'
2025
+ }
2026
+ },
2027
+ mimes : [
2028
+ 'application/msword',
2029
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
2030
+ //'application/pdf',
2031
+ 'application/vnd.oasis.opendocument.text',
2032
+ 'application/rtf',
2033
+ 'text/html',
2034
+ 'application/vnd.ms-excel',
2035
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
2036
+ 'application/vnd.oasis.opendocument.spreadsheet',
2037
+ 'application/vnd.sun.xml.calc',
2038
+ 'text/csv',
2039
+ 'text/tab-separated-values',
2040
+ 'application/vnd.ms-powerpoint',
2041
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
2042
+ 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
2043
+ 'application/vnd.oasis.opendocument.presentation',
2044
+ 'application/vnd.sun.xml.impress'
2045
+ ],
2046
+ html : '<iframe style="width:100%;max-height:100%;border:none;"></iframe>',
2047
+ // setup on elFinder bootup
2048
+ setup : function(opts, fm) {
2049
+ if (fm.UA.Mobile || fm.UA.ltIE8) {
2050
+ this.disabled = true;
2051
+ }
2052
+ },
2053
+ // Prepare on before show dialog
2054
+ prepare : function(base, dialogOpts, file) {
2055
+ var elfNode = base.editor.fm.getUI();
2056
+ $(base).height(elfNode.height());
2057
+ dialogOpts.width = Math.max(dialogOpts.width || 0, elfNode.width() * 0.8);
2058
+ },
2059
+ // Initialization of editing node (this: this editors HTML node)
2060
+ init : function(id, file, dum, fm) {
2061
+ var ta = this,
2062
+ ifm = $(this).hide(),
2063
+ uiToast = fm.getUI('toast'),
2064
+ spnr = $('<div class="elfinder-edit-spinner elfinder-edit-zohoeditor"></div>')
2065
+ .html('<span class="elfinder-spinner-text">' + fm.i18n('nowLoading') + '</span><span class="elfinder-spinner"></span>')
2066
+ .appendTo(ifm.parent()),
2067
+ cdata = function() {
2068
+ var data = '';
2069
+ $.each(fm.customData, function(key, val) {
2070
+ data += '&' + encodeURIComponent(key) + '=' + encodeURIComponent(val);
2071
+ });
2072
+ return data;
2073
+ };
2074
+
2075
+ $(ta).data('xhr', fm.request({
2076
+ data: {
2077
+ cmd: 'editor',
2078
+ name: ta.editor.confObj.info.cmdCheck,
2079
+ method: 'init',
2080
+ 'args[target]': file.hash,
2081
+ 'args[lang]' : fm.lang,
2082
+ 'args[cdata]' : cdata()
2083
+ },
2084
+ preventDefault : true
2085
+ }).done(function(data) {
2086
+ var opts;
2087
+ if (data.zohourl) {
2088
+ opts = {
2089
+ css: {
2090
+ height: '100%'
2091
+ }
2092
+ };
2093
+ // trigger event 'editEditorPrepare'
2094
+ ta.editor.trigger('Prepare', {
2095
+ node: ta,
2096
+ editorObj: void(0),
2097
+ instance: ifm,
2098
+ opts: opts
2099
+ });
2100
+
2101
+ ifm.attr('src', data.zohourl).show().css(opts.css);
2102
+ if (data.warning) {
2103
+ uiToast.appendTo(ta.closest('.ui-dialog'));
2104
+ fm.toast({
2105
+ msg: fm.i18n(data.warning),
2106
+ mode: 'warning',
2107
+ timeOut: 0,
2108
+ onHidden: function() {
2109
+ uiToast.children().length === 1 && uiToast.appendTo(fm.getUI());
2110
+ },
2111
+ button: {
2112
+ text: 'btnYes'
2113
+ }
2114
+ });
2115
+ }
2116
+ } else {
2117
+ data.error && fm.error(data.error);
2118
+ ta.elfinderdialog('destroy');
2119
+ }
2120
+ }).fail(function(error) {
2121
+ error && fm.error(error);
2122
+ ta.elfinderdialog('destroy');
2123
+ }).always(function() {
2124
+ spnr.remove();
2125
+ }));
2126
+ },
2127
+ load : function() {},
2128
+ getContent : function() {},
2129
+ save : function() {},
2130
+ // Before dialog close
2131
+ beforeclose : iframeClose,
2132
+ // On dialog closed
2133
+ close : function(ta) {
2134
+ var fm = this.fm,
2135
+ xhr = $(ta).data('xhr');
2136
+ if (xhr.state() === 'pending') {
2137
+ xhr.reject();
2138
+ }
2139
+ }
2140
+ },
2141
+ {
2142
+ // Zip Archive with FlySystem
2143
+ info : {
2144
+ id : 'ziparchive',
2145
+ name : 'btnMount',
2146
+ iconImg : 'img/toolbar.png 0 -416',
2147
+ cmdCheck : 'ZipArchive',
2148
+ edit : function(file, editor) {
2149
+ var fm = this,
2150
+ dfrd = $.Deferred();
2151
+ fm.request({
2152
+ data:{
2153
+ cmd: 'netmount',
2154
+ protocol: 'ziparchive',
2155
+ host: file.hash,
2156
+ path: file.phash
2157
+ },
2158
+ preventFail: true,
2159
+ notify : {type : 'netmount', cnt : 1, hideCnt : true}
2160
+ }).done(function(data) {
2161
+ var pdir;
2162
+ if (data.added && data.added.length) {
2163
+ if (data.added[0].phash) {
2164
+ if (pdir = fm.file(data.added[0].phash)) {
2165
+ if (! pdir.dirs) {
2166
+ pdir.dirs = 1;
2167
+ fm.change({ changed: [ pdir ] });
2168
+ }
2169
+ }
2170
+ }
2171
+ fm.one('netmountdone', function() {
2172
+ fm.exec('open', data.added[0].hash);
2173
+ fm.one('opendone', function() {
2174
+ data.toast && fm.toast(data.toast);
2175
+ });
2176
+ });
2177
+ }
2178
+ dfrd.resolve();
2179
+ })
2180
+ .fail(function(error) {
2181
+ dfrd.reject(error);
2182
+ });
2183
+ return dfrd;
2184
+ }
2185
+ },
2186
+ mimes : ['application/zip'],
2187
+ load : function() {},
2188
+ save : function(){}
2189
+ },
2190
+ {
2191
+ // Simple Text (basic textarea editor)
2192
+ info : {
2193
+ id : 'textarea',
2194
+ name : 'TextArea',
2195
+ useTextAreaEvent : true
2196
+ },
2197
+ load : function(textarea) {
2198
+ // trigger event 'editEditorPrepare'
2199
+ this.trigger('Prepare', {
2200
+ node: textarea,
2201
+ editorObj: void(0),
2202
+ instance: void(0),
2203
+ opts: {}
2204
+ });
2205
+ textarea.setSelectionRange && textarea.setSelectionRange(0, 0);
2206
+ $(textarea).trigger('focus').show();
2207
+ },
2208
+ save : function(){}
2209
+ },
2210
+ {
2211
+ // File converter with online-convert.com
2212
+ info : {
2213
+ id : 'onlineconvert',
2214
+ name : 'Online Convert',
2215
+ iconImg : 'img/editor-icons.png 0 -144',
2216
+ cmdCheck : 'OnlineConvert',
2217
+ preventGet: true,
2218
+ hideButtons: true,
2219
+ single: true,
2220
+ converter: true,
2221
+ canMakeEmpty: false,
2222
+ integrate: {
2223
+ title: 'ONLINE-CONVERT.COM',
2224
+ link: 'https://online-convert.com'
2225
+ }
2226
+ },
2227
+ mimes : ['*'],
2228
+ html : '<div style="width:100%;max-height:100%;"></div>',
2229
+ // setup on elFinder bootup
2230
+ setup : function(opts, fm) {
2231
+ var mOpts = opts.extraOptions.onlineConvert || {maxSize:100,showLink:true};
2232
+ if (mOpts.maxSize) {
2233
+ this.info.maxSize = mOpts.maxSize * 1048576;
2234
+ }
2235
+ this.set = Object.assign({
2236
+ url : 'https://%s.online-convert.com%s?external_url=',
2237
+ conv : {
2238
+ Archive: {'7Z':{}, 'BZ2':{ext:'bz'}, 'GZ':{}, 'ZIP':{}},
2239
+ Audio: {'MP3':{}, 'OGG':{ext:'oga'}, 'WAV':{}, 'WMA':{}, 'AAC':{}, 'AIFF':{ext:'aif'}, 'FLAC':{}, 'M4A':{}, 'MMF':{}, 'OPUS':{ext:'oga'}},
2240
+ Document: {'DOC':{}, 'DOCX':{}, 'HTML':{}, 'ODT':{}, 'PDF':{}, 'PPT':{}, 'PPTX':{}, 'RTF':{}, 'SWF':{}, 'TXT':{}},
2241
+ eBook: {'AZW3':{ext:'azw'}, 'ePub':{}, 'FB2':{ext:'xml'}, 'LIT':{}, 'LRF':{}, 'MOBI':{}, 'PDB':{}, 'PDF':{},'PDF-eBook':{ext:'pdf'}, 'TCR':{}},
2242
+ Hash: {'Adler32':{}, 'Apache-htpasswd':{}, 'Blowfish':{}, 'CRC32':{}, 'CRC32B':{}, 'Gost':{}, 'Haval128':{},'MD4':{}, 'MD5':{}, 'RIPEMD128':{}, 'RIPEMD160':{}, 'SHA1':{}, 'SHA256':{}, 'SHA384':{}, 'SHA512':{}, 'Snefru':{}, 'Std-DES':{}, 'Tiger128':{}, 'Tiger128-calculator':{}, 'Tiger128-converter':{}, 'Tiger160':{}, 'Tiger192':{}, 'Whirlpool':{}},
2243
+ Image: {'BMP':{}, 'EPS':{ext:'ai'}, 'GIF':{}, 'EXR':{}, 'ICO':{}, 'JPG':{}, 'PNG':{}, 'SVG':{}, 'TGA':{}, 'TIFF':{ext:'tif'}, 'WBMP':{}, 'WebP':{}},
2244
+ Video: {'3G2':{}, '3GP':{}, 'AVI':{}, 'FLV':{}, 'HLS':{ext:'m3u8'}, 'MKV':{}, 'MOV':{}, 'MP4':{}, 'MPEG-1':{ext:'mpeg'}, 'MPEG-2':{ext:'mpeg'}, 'OGG':{ext:'ogv'}, 'OGV':{}, 'WebM':{}, 'WMV':{}, 'Android':{link:'/convert-video-for-%s',ext:'mp4'}, 'Blackberry':{link:'/convert-video-for-%s',ext:'mp4'}, 'DPG':{link:'/convert-video-for-%s',ext:'avi'}, 'iPad':{link:'/convert-video-for-%s',ext:'mp4'}, 'iPhone':{link:'/convert-video-for-%s',ext:'mp4'}, 'iPod':{link:'/convert-video-for-%s',ext:'mp4'}, 'Nintendo-3DS':{link:'/convert-video-for-%s',ext:'avi'}, 'Nintendo-DS':{link:'/convert-video-for-%s',ext:'avi'}, 'PS3':{link:'/convert-video-for-%s',ext:'mp4'}, 'Wii':{link:'/convert-video-for-%s',ext:'avi'}, 'Xbox':{link:'/convert-video-for-%s',ext:'wmv'}}
2245
+ },
2246
+ catExts : {
2247
+ Hash: 'txt'
2248
+ },
2249
+ link : '<div class="elfinder-edit-onlineconvert-link"><a href="https://www.online-convert.com" target="_blank"><span class="elfinder-button-icon"></span>ONLINE-CONVERT.COM</a></div>',
2250
+ useTabs : ($.fn.tabs && !fm.UA.iOS)? true : false // Can't work on iOS, I don't know why.
2251
+ }, mOpts);
2252
+ },
2253
+ // Prepare on before show dialog
2254
+ prepare : function(base, dialogOpts, file) {
2255
+ var elfNode = base.editor.fm.getUI();
2256
+ $(base).height(elfNode.height());
2257
+ dialogOpts.width = Math.max(dialogOpts.width || 0, elfNode.width() * 0.8);
2258
+ },
2259
+ // Initialization of editing node (this: this editors HTML node)
2260
+ init : function(id, file, dum, fm) {
2261
+ var ta = this,
2262
+ confObj = ta.editor.confObj,
2263
+ set = confObj.set,
2264
+ uiToast = fm.getUI('toast'),
2265
+ idxs = {},
2266
+ allowZip = fm.uploadMimeCheck('application/zip', file.phash),
2267
+ selfUrl = $('base').length? document.location.href.replace(/#.*$/, '') : '',
2268
+ getExt = function(cat, con) {
2269
+ var c;
2270
+ if (set.catExts[cat]) {
2271
+ return set.catExts[cat];
2272
+ }
2273
+ if (set.conv[cat] && (c = set.conv[cat][con])) {
2274
+ return (c.ext || con).toLowerCase();
2275
+ }
2276
+ return con.toLowerCase();
2277
+ },
2278
+ setOptions = function(cat, done) {
2279
+ var type, dfdInit, dfd;
2280
+ if (typeof confObj.api === 'undefined') {
2281
+ dfdInit = fm.request({
2282
+ data: {
2283
+ cmd: 'editor',
2284
+ name: 'OnlineConvert',
2285
+ method: 'init'
2286
+ },
2287
+ preventDefault : true
2288
+ });
2289
+ } else {
2290
+ dfdInit = $.Deferred().resolve({api: confObj.api});
2291
+ }
2292
+ cat = cat.toLowerCase();
2293
+ dfdInit.done(function(data) {
2294
+ confObj.api = data.api;
2295
+ if (confObj.api) {
2296
+ if (cat) {
2297
+ type = '?category=' + cat;
2298
+ } else {
2299
+ type = '';
2300
+ cat = 'all';
2301
+ }
2302
+ if (!confObj.conversions) {
2303
+ confObj.conversions = {};
2304
+ }
2305
+ if (!confObj.conversions[cat]) {
2306
+ dfd = $.getJSON('https://api2.online-convert.com/conversions' + type);
2307
+ } else {
2308
+ dfd = $.Deferred().resolve(confObj.conversions[cat]);
2309
+ }
2310
+ dfd.done(function(d) {
2311
+ confObj.conversions[cat] = d;
2312
+ $.each(d, function(i, o) {
2313
+ btns[set.useTabs? 'children' : 'find']('.onlineconvert-category-' + o.category).children('.onlineconvert-' + o.target).trigger('makeoption', o);
2314
+ });
2315
+ done && done();
2316
+ });
2317
+ }
2318
+ });
2319
+ },
2320
+ btns = (function() {
2321
+ var btns = $('<div></div>').on('click', 'button', function() {
2322
+ var b = $(this),
2323
+ opts = b.data('opts') || null,
2324
+ cat = b.closest('.onlineconvert-category').data('cname'),
2325
+ con = b.data('conv');
2326
+ if (confObj.api === true) {
2327
+ api({
2328
+ category: cat,
2329
+ convert: con,
2330
+ options: opts
2331
+ });
2332
+ }
2333
+ }).on('change', function(e) {
2334
+ var t = $(e.target),
2335
+ p = t.parent(),
2336
+ b = t.closest('.elfinder-edit-onlineconvert-button').children('button:first'),
2337
+ o = b.data('opts') || {},
2338
+ v = p.data('type') === 'boolean'? t.is(':checked') : t.val();
2339
+ e.stopPropagation();
2340
+ if (v) {
2341
+ if (p.data('type') === 'integer') {
2342
+ v = parseInt(v);
2343
+ }
2344
+ if (p.data('pattern')) {
2345
+ var reg = new RegExp(p.data('pattern'));
2346
+ if (!reg.test(v)) {
2347
+ requestAnimationFrame(function() {
2348
+ fm.error('"' + fm.escape(v) + '" is not match to "/' + fm.escape(p.data('pattern')) + '/"');
2349
+ });
2350
+ v = null;
2351
+ }
2352
+ }
2353
+ }
2354
+ if (v) {
2355
+ o[t.parent().data('optkey')] = v;
2356
+ } else {
2357
+ delete o[p.data('optkey')];
2358
+ }
2359
+ b.data('opts', o);
2360
+ }),
2361
+ ul = $('<ul></ul>'),
2362
+ oform = function(n, o) {
2363
+ var f = $('<p></p>').data('optkey', n).data('type', o.type),
2364
+ checked = '',
2365
+ disabled = '',
2366
+ nozip = false,
2367
+ opts, btn, elm;
2368
+ if (o.description) {
2369
+ f.attr('title', fm.i18n(o.description));
2370
+ }
2371
+ if (o.pattern) {
2372
+ f.data('pattern', o.pattern);
2373
+ }
2374
+ f.append($('<span></span>').text(fm.i18n(n) + ' : '));
2375
+ if (o.type === 'boolean') {
2376
+ if (o['default'] || (nozip = (n === 'allow_multiple_outputs' && !allowZip))) {
2377
+ checked = ' checked';
2378
+ if (nozip) {
2379
+ disabled = ' disabled';
2380
+ }
2381
+ btn = this.children('button:first');
2382
+ opts = btn.data('opts') || {};
2383
+ opts[n] = true;
2384
+ btn.data('opts', opts);
2385
+ }
2386
+ f.append($('<input type="checkbox" value="true"'+checked+disabled+'/>'));
2387
+ } else if (o['enum']){
2388
+ elm = $('<select></select>').append($('<option value=""></option>').text('Select...'));
2389
+ $.each(o['enum'], function(i, v) {
2390
+ elm.append($('<option value="'+v+'"></option>').text(v));
2391
+ });
2392
+ f.append(elm);
2393
+ } else {
2394
+ f.append($('<input type="text" value=""/>'));
2395
+ }
2396
+ return f;
2397
+ },
2398
+ makeOption = function(o) {
2399
+ var elm = this,
2400
+ b = $('<span class="elfinder-button-icon elfinder-button-icon-preference"></span>').on('click', function() {
2401
+ f.toggle();
2402
+ }),
2403
+ f = $('<div class="elfinder-edit-onlinconvert-options"></div>').hide();
2404
+ if (o.options) {
2405
+ $.each(o.options, function(k, v) {
2406
+ k !== 'download_password' && f.append(oform.call(elm, k, v));
2407
+ });
2408
+ }
2409
+ elm.append(b, f);
2410
+ },
2411
+ ts = (+new Date()),
2412
+ i = 0;
2413
+
2414
+ if (!confObj.ext2mime) {
2415
+ confObj.ext2mime = Object.assign(fm.arrayFlip(fm.mimeTypes), ext2mime);
2416
+ }
2417
+ $.each(set.conv, function(t, c) {
2418
+ var cname = t.toLowerCase(),
2419
+ id = 'elfinder-edit-onlineconvert-' + cname + ts,
2420
+ type = $('<div id="' + id + '" class="onlineconvert-category onlineconvert-category-'+cname+'"></div>').data('cname', t),
2421
+ cext;
2422
+ $.each(c, function(n, o) {
2423
+ var nl = n.toLowerCase(),
2424
+ ext = getExt(t, n);
2425
+ if (!confObj.ext2mime[ext]) {
2426
+ if (cname === 'audio' || cname === 'image' || cname === 'video') {
2427
+ confObj.ext2mime[ext] = cname + '/x-' + nl;
2428
+ } else {
2429
+ confObj.ext2mime[ext] = 'application/octet-stream';
2430
+ }
2431
+ }
2432
+ if (fm.uploadMimeCheck(confObj.ext2mime[ext], file.phash)) {
2433
+ type.append($('<div class="elfinder-edit-onlineconvert-button onlineconvert-'+nl+'"></div>').on('makeoption', function(e, data) {
2434
+ var elm = $(this);
2435
+ if (!elm.children('.elfinder-button-icon-preference').length) {
2436
+ makeOption.call(elm, data);
2437
+ }
2438
+ }).append($('<button></button>').text(n).data('conv', n)));
2439
+ }
2440
+ });
2441
+ if (type.children().length) {
2442
+ ul.append($('<li></li>').append($('<a></a>').attr('href', selfUrl + '#' + id).text(t)));
2443
+ btns.append(type);
2444
+ idxs[cname] = i++;
2445
+ }
2446
+ });
2447
+ if (set.useTabs) {
2448
+ btns.prepend(ul).tabs({
2449
+ beforeActivate: function(e, ui) {
2450
+ setOptions(ui.newPanel.data('cname'));
2451
+ }
2452
+ });
2453
+ } else {
2454
+ $.each(set.conv, function(t) {
2455
+ var tl = t.toLowerCase();
2456
+ btns.append($('<fieldset class="onlineconvert-fieldset-' + tl + '"></fieldset>').append($('<legend></legend>').text(t)).append(btns.children('.onlineconvert-category-' + tl)));
2457
+ });
2458
+ }
2459
+ return btns;
2460
+ })(),
2461
+ select = $(this)
2462
+ .append(
2463
+ btns,
2464
+ (set.showLink? $(set.link) : null)
2465
+ ),
2466
+ spnr = $('<div class="elfinder-edit-spinner elfinder-edit-onlineconvert"></div>')
2467
+ .hide()
2468
+ .html('<span class="elfinder-spinner-text">' + fm.i18n('nowLoading') + '</span><span class="elfinder-spinner"></span>')
2469
+ .appendTo(select.parent()),
2470
+ prog = $('<div class="elfinder-quicklook-info-progress"></div>').appendTo(spnr),
2471
+ _url = null,
2472
+ url = function() {
2473
+ var onetime;
2474
+ if (_url) {
2475
+ return $.Deferred().resolve(_url);
2476
+ } else {
2477
+ spnr.show();
2478
+ return fm.forExternalUrl(file.hash, { progressBar: prog }).done(function(url) {
2479
+ _url = url;
2480
+ }).fail(function(error) {
2481
+ error && fm.error(error);
2482
+ ta.elfinderdialog('destroy');
2483
+ }).always(function() {
2484
+ spnr.hide();
2485
+ });
2486
+ }
2487
+ },
2488
+ api = function(opts) {
2489
+ $(ta).data('dfrd', url().done(function(url) {
2490
+ select.fadeOut();
2491
+ setStatus({info: 'Start conversion request.'});
2492
+ fm.request({
2493
+ data: {
2494
+ cmd: 'editor',
2495
+ name: 'OnlineConvert',
2496
+ method: 'api',
2497
+ 'args[category]' : opts.category.toLowerCase(),
2498
+ 'args[convert]' : opts.convert.toLowerCase(),
2499
+ 'args[options]' : JSON.stringify(opts.options),
2500
+ 'args[source]' : fm.convAbsUrl(url),
2501
+ 'args[filename]' : fm.splitFileExtention(file.name)[0] + '.' + getExt(opts.category, opts.convert),
2502
+ 'args[mime]' : file.mime
2503
+ },
2504
+ preventDefault : true
2505
+ }).done(function(data) {
2506
+ checkRes(data.apires, opts.category, opts.convert);
2507
+ }).fail(function(error) {
2508
+ error && fm.error(error);
2509
+ ta.elfinderdialog('destroy');
2510
+ });
2511
+ }));
2512
+ },
2513
+ checkRes = function(res, cat, con) {
2514
+ var status, err = [];
2515
+ if (res && res.id) {
2516
+ status = res.status;
2517
+ if (status.code === 'failed') {
2518
+ spnr.hide();
2519
+ if (res.errors && res.errors.length) {
2520
+ $.each(res.errors, function(i, o) {
2521
+ o.message && err.push(o.message);
2522
+ });
2523
+ }
2524
+ fm.error(err.length? err : status.info);
2525
+ select.fadeIn();
2526
+ } else if (status.code === 'completed') {
2527
+ upload(res);
2528
+ } else {
2529
+ setStatus(status);
2530
+ setTimeout(function() {
2531
+ polling(res.id);
2532
+ }, 1000);
2533
+ }
2534
+ } else {
2535
+ uiToast.appendTo(ta.closest('.ui-dialog'));
2536
+ if (res.message) {
2537
+ fm.toast({
2538
+ msg: fm.i18n(res.message),
2539
+ mode: 'error',
2540
+ timeOut: 5000,
2541
+ onHidden: function() {
2542
+ uiToast.children().length === 1 && uiToast.appendTo(fm.getUI());
2543
+ }
2544
+ });
2545
+ }
2546
+ fm.toast({
2547
+ msg: fm.i18n('editorConvNoApi'),
2548
+ mode: 'error',
2549
+ timeOut: 3000,
2550
+ onHidden: function() {
2551
+ uiToast.children().length === 1 && uiToast.appendTo(fm.getUI());
2552
+ }
2553
+ });
2554
+ spnr.hide();
2555
+ select.show();
2556
+ }
2557
+ },
2558
+ setStatus = function(status) {
2559
+ spnr.show().children('.elfinder-spinner-text').text(status.info);
2560
+ },
2561
+ polling = function(jobid) {
2562
+ fm.request({
2563
+ data: {
2564
+ cmd: 'editor',
2565
+ name: 'OnlineConvert',
2566
+ method: 'api',
2567
+ 'args[jobid]': jobid
2568
+ },
2569
+ preventDefault : true
2570
+ }).done(function(data) {
2571
+ checkRes(data.apires);
2572
+ }).fail(function(error) {
2573
+ error && fm.error(error);
2574
+ ta.elfinderdialog('destroy');
2575
+ });
2576
+ },
2577
+ upload = function(res) {
2578
+ var output = res.output,
2579
+ id = res.id,
2580
+ url = '';
2581
+ spnr.hide();
2582
+ if (output && output.length) {
2583
+ ta.elfinderdialog('destroy');
2584
+ $.each(output, function(i, o) {
2585
+ if (o.uri) {
2586
+ url += o.uri + '\n';
2587
+ }
2588
+ });
2589
+ fm.upload({
2590
+ target: file.phash,
2591
+ files: [url],
2592
+ type: 'text',
2593
+ extraData: {
2594
+ contentSaveId: 'OnlineConvert-' + res.id
2595
+ }
2596
+ });
2597
+ }
2598
+ },
2599
+ mode = 'document',
2600
+ cl, m;
2601
+ select.parent().css({overflow: 'auto'}).addClass('overflow-scrolling-touch');
2602
+ if (m = file.mime.match(/^(audio|image|video)/)) {
2603
+ mode = m[1];
2604
+ }
2605
+ if (set.useTabs) {
2606
+ if (idxs[mode]) {
2607
+ btns.tabs('option', 'active', idxs[mode]);
2608
+ }
2609
+ } else {
2610
+ cl = Object.keys(set.conv).length;
2611
+ $.each(set.conv, function(t) {
2612
+ if (t.toLowerCase() === mode) {
2613
+ setOptions(t, function() {
2614
+ $.each(set.conv, function(t0) {
2615
+ t0.toLowerCase() !== mode && setOptions(t0);
2616
+ });
2617
+ });
2618
+ return false;
2619
+ }
2620
+ cl--;
2621
+ });
2622
+ if (!cl) {
2623
+ $.each(set.conv, function(t) {
2624
+ setOptions(t);
2625
+ });
2626
+ }
2627
+ select.parent().scrollTop(btns.children('.onlineconvert-fieldset-' + mode).offset().top);
2628
+ }
2629
+ },
2630
+ load : function() {},
2631
+ getContent : function() {},
2632
+ save : function() {},
2633
+ // On dialog closed
2634
+ close : function(ta) {
2635
+ var fm = this.fm,
2636
+ dfrd = $(ta).data('dfrd');
2637
+ if (dfrd && dfrd.state() === 'pending') {
2638
+ dfrd.reject();
2639
+ }
2640
+ }
2641
+ }
2642
+ ];
2643
+ }, window.elFinder));