|
1 // $Id: imce.js,v 1.15.2.9 2008/07/13 11:34:49 ufku Exp $ |
|
2 |
|
3 //Global container. |
|
4 var imce = {tree: {}, findex: [], fids: {}, selected: {}, selcount: 0, ops: {}, cache: {}, |
|
5 vars: {previewImages: 1, cache: 1}, |
|
6 hooks: {load: [], list: [], navigate: [], cache: []}, |
|
7 |
|
8 //initiate imce. |
|
9 initiate: function() { |
|
10 imce.conf = Drupal.settings.imce || {}; |
|
11 if (imce.conf.error != false) return; |
|
12 imce.FLW = imce.el('file-list-wrapper'); |
|
13 imce.prepareMsgs();//process initial status messages |
|
14 imce.initiateTree();//build directory tree |
|
15 imce.hooks.list.unshift(imce.processRow);//set the default list-hook. |
|
16 imce.initiateList();//process file list |
|
17 imce.initiateOps();//prepare operation tabs |
|
18 imce.refreshOps(); |
|
19 if (window['imceOnLoad']) imceOnLoad(window); |
|
20 imce.invoke('load', window);//run functions set by external applications. |
|
21 }, |
|
22 |
|
23 /**************** DIRECTORIES ********************/ |
|
24 |
|
25 //process navigation tree |
|
26 initiateTree: function() { |
|
27 $('#navigation-tree li').each(function(i) { |
|
28 var a = this.firstChild; |
|
29 a.firstChild.data = imce.decode(a.firstChild.data); |
|
30 var branch = imce.tree[a.title] = {'a': a, li: this, ul: this.lastChild.tagName == 'UL' ? this.lastChild : null}; |
|
31 if (a.href) imce.dirClickable(branch); |
|
32 imce.dirCollapsible(branch); |
|
33 }); |
|
34 }, |
|
35 |
|
36 //Add a dir to the tree under parent |
|
37 dirAdd: function(dir, parent, clickable) { |
|
38 if (imce.tree[dir]) return clickable ? imce.dirClickable(imce.tree[dir]) : imce.tree[dir]; |
|
39 var parent = parent || imce.tree['.']; |
|
40 parent.ul = parent.ul ? parent.ul : parent.li.appendChild(document.createElement('ul')); |
|
41 var branch = imce.dirCreate(dir, imce.decode(dir.substr(dir.lastIndexOf('/')+1)), clickable); |
|
42 parent.ul.appendChild(branch.li); |
|
43 return branch; |
|
44 }, |
|
45 |
|
46 //create list item for navigation tree |
|
47 dirCreate: function(dir, text, clickable) { |
|
48 if (imce.tree[dir]) return imce.tree[dir]; |
|
49 var branch = imce.tree[dir] = {li: document.createElement('li'), a: document.createElement('a')}; |
|
50 $(branch.a).addClass('folder').text(text).attr('title', dir).appendTo(branch.li); |
|
51 imce.dirCollapsible(branch); |
|
52 return clickable ? imce.dirClickable(branch) : branch; |
|
53 }, |
|
54 |
|
55 //change currently active directory |
|
56 dirActivate: function(dir) { |
|
57 if (dir != imce.conf.dir) { |
|
58 if (imce.tree[imce.conf.dir]){ |
|
59 $(imce.tree[imce.conf.dir].a).removeClass('active'); |
|
60 } |
|
61 $(imce.tree[dir].a).addClass('active'); |
|
62 imce.conf.dir = dir; |
|
63 } |
|
64 return imce.tree[imce.conf.dir]; |
|
65 }, |
|
66 |
|
67 //make a dir accessible |
|
68 dirClickable: function(branch) { |
|
69 if (branch.clkbl) return branch; |
|
70 $(branch.a).attr('href', '#').removeClass('disabled').click(function() {imce.navigate(this.title); return false;}); |
|
71 branch.clkbl = true; |
|
72 return branch; |
|
73 }, |
|
74 |
|
75 //sub-directories expand-collapse ability |
|
76 dirCollapsible: function (branch) { |
|
77 if (branch.clpsbl) return branch; |
|
78 $(document.createElement('span')).addClass('expander').html(' ').click(function() { |
|
79 if (branch.ul) { |
|
80 $(branch.ul).toggle(); |
|
81 $(branch.li).toggleClass('expanded'); |
|
82 } |
|
83 else if (branch.clkbl){ |
|
84 $(branch.a).click(); |
|
85 } |
|
86 }).prependTo(branch.li); |
|
87 branch.clpsbl = true; |
|
88 return branch; |
|
89 }, |
|
90 |
|
91 //update navigation tree after getting subdirectories. |
|
92 dirSubdirs: function(dir, subdirs) { |
|
93 var branch = imce.tree[dir]; |
|
94 if (subdirs && subdirs.length) { |
|
95 var prefix = dir == '.' ? '' : dir +'/'; |
|
96 for (var i in subdirs) {//add subdirectories |
|
97 imce.dirAdd(prefix + subdirs[i], branch, true); |
|
98 } |
|
99 $(branch.li).removeClass('leaf').addClass('expanded'); |
|
100 $(branch.ul).show(); |
|
101 } |
|
102 else if (!branch.ul){//no subdirs->leaf |
|
103 $(branch.li).removeClass('expanded').addClass('leaf'); |
|
104 } |
|
105 }, |
|
106 |
|
107 /**************** FILES ********************/ |
|
108 |
|
109 //process file list |
|
110 initiateList: function(cached) { |
|
111 var L = imce.hooks.list, dir = imce.conf.dir, token = {'%dir': dir == '.' ? $(imce.tree['.'].a).text() : imce.decode(dir)} |
|
112 imce.findex = [], imce.fids = {}, imce.selected = {}, imce.selcount = 0, imce.vars.lastfid = null; |
|
113 imce.tbody = imce.el('file-list').tBodies[0]; |
|
114 if (imce.tbody.rows.length) { |
|
115 for (var row, i = 0; row = imce.tbody.rows[i]; i++) { |
|
116 var fid = row.id; |
|
117 imce.findex[i] = imce.fids[fid] = row; |
|
118 if (cached) { |
|
119 if (imce.hasC(row, 'selected')) { |
|
120 imce.selected[imce.vars.lastfid = fid] = row; |
|
121 imce.selcount++; |
|
122 } |
|
123 } |
|
124 else { |
|
125 for (var func, j = 0; func = L[j]; j++) func(row);//invoke list-hook |
|
126 } |
|
127 } |
|
128 imce.setMessage(Drupal.t('Directory %dir is loaded.', token)); |
|
129 } |
|
130 else if (imce.conf.perm.browse) imce.setMessage(Drupal.t('Directory %dir is empty.', token), 'warning'); |
|
131 else imce.setMessage(Drupal.t('File browsing is disabled in directory %dir.', token), 'error'); |
|
132 }, |
|
133 |
|
134 //add a file to the list. (having properties name,size,formatted size,width,height,date,formatted date) |
|
135 fileAdd: function(file) { |
|
136 var row, fid = file.name, i = imce.findex.length, attr = ['name', 'size', 'width', 'height', 'date']; |
|
137 if (!(row = imce.fids[fid])) { |
|
138 row = imce.findex[i] = imce.fids[fid] = imce.tbody.insertRow(i); |
|
139 for (var i in attr) row.insertCell(i).className = attr[i]; |
|
140 } |
|
141 row.cells[0].innerHTML = row.id = fid; |
|
142 row.cells[1].innerHTML = file.fsize; row.cells[1].id = file.size; |
|
143 row.cells[2].innerHTML = file.width; |
|
144 row.cells[3].innerHTML = file.height; |
|
145 row.cells[4].innerHTML = file.fdate; row.cells[4].id = file.date; |
|
146 imce.invoke('list', row); |
|
147 if (imce.vars.prvfid == fid) imce.setPreview(fid); |
|
148 }, |
|
149 |
|
150 //remove a file from the list |
|
151 fileRemove: function(fid) { |
|
152 if (!(row = imce.fids[fid])) return; |
|
153 imce.fileDeSelect(fid); |
|
154 imce.findex.splice(row.rowIndex, 1); |
|
155 $(row).remove(); |
|
156 delete imce.fids[fid]; |
|
157 if (imce.vars.prvfid == fid) imce.setPreview(); |
|
158 }, |
|
159 |
|
160 //return a file object containing all properties. |
|
161 fileGet: function (fid) { |
|
162 var row = imce.fids[fid]; |
|
163 return row ? { |
|
164 name: imce.decode(fid), |
|
165 url: imce.getURL(fid), |
|
166 size: row.cells[1].innerHTML, |
|
167 bytes: row.cells[1].id * 1, |
|
168 width: row.cells[2].innerHTML * 1, |
|
169 height: row.cells[3].innerHTML * 1, |
|
170 date: row.cells[4].innerHTML, |
|
171 time: row.cells[4].id * 1 |
|
172 } : null; |
|
173 }, |
|
174 |
|
175 //simulate row click. selection-highlighting |
|
176 fileClick: function(row, ctrl, shft) { |
|
177 if (!row) return; |
|
178 var fid = typeof(row) == 'string' ? row : row.id; |
|
179 if (ctrl || fid == imce.vars.prvfid) { |
|
180 imce.fileToggleSelect(fid); |
|
181 } |
|
182 else if (shft) { |
|
183 var last = imce.lastFid(); |
|
184 var start = last ? imce.fids[last].rowIndex : -1; |
|
185 var end = imce.fids[fid].rowIndex; |
|
186 var step = start > end ? -1 : 1; |
|
187 while (start != end) { |
|
188 start += step; |
|
189 imce.fileSelect(imce.findex[start].id); |
|
190 } |
|
191 } |
|
192 else { |
|
193 for (var fname in imce.selected) { |
|
194 imce.fileDeSelect(fname); |
|
195 } |
|
196 imce.fileSelect(fid); |
|
197 } |
|
198 //set preview |
|
199 imce.setPreview(imce.selcount == 1 ? imce.lastFid() : null); |
|
200 }, |
|
201 |
|
202 //file select/deselect functions |
|
203 fileSelect: function (fid) { |
|
204 if (imce.selected[fid] || !imce.fids[fid]) return; |
|
205 imce.selected[fid] = imce.fids[imce.vars.lastfid=fid]; |
|
206 $(imce.selected[fid]).addClass('selected'); |
|
207 imce.selcount++; |
|
208 }, |
|
209 fileDeSelect: function (fid) { |
|
210 if (!imce.selected[fid] || !imce.fids[fid]) return; |
|
211 if (imce.vars.lastfid == fid) imce.vars.lastfid = null; |
|
212 $(imce.selected[fid]).removeClass('selected'); |
|
213 delete imce.selected[fid]; |
|
214 imce.selcount--; |
|
215 }, |
|
216 fileToggleSelect: function (fid) { |
|
217 imce['file'+ (imce.selected[fid] ? 'De' : '') +'Select'](fid); |
|
218 }, |
|
219 |
|
220 /**************** OPERATIONS ********************/ |
|
221 |
|
222 //process file operation form and create operation tabs. |
|
223 initiateOps: function() { |
|
224 imce.setHtmlOps(); |
|
225 imce.setUploadOp();//upload |
|
226 imce.setFileOps();//thumb, delete, resize |
|
227 }, |
|
228 |
|
229 //process existing html ops. |
|
230 setHtmlOps: function () { |
|
231 $('#ops-list>li').each(function() { |
|
232 var name = this.id.substr(8); |
|
233 var Op = imce.ops[name] = {div: imce.el('op-content-'+ name), li: imce.el('op-item-'+ name)}; |
|
234 Op.a = Op.li.firstChild; |
|
235 Op.title = Op.a.innerHTML; |
|
236 $(Op.a).click(function() {imce.opClick(name); return false;}); |
|
237 }); |
|
238 }, |
|
239 |
|
240 //convert upload form to an op. |
|
241 setUploadOp: function () { |
|
242 if (!imce.el('imce-upload-form')) return; |
|
243 var form = $(imce.el('imce-upload-form')); |
|
244 form.find('fieldset').each(function() {//clean up fieldsets |
|
245 this.removeChild(this.firstChild); |
|
246 $(this).after(this.childNodes); |
|
247 }).remove(); |
|
248 form.ajaxForm(imce.uploadSettings());//set ajax |
|
249 imce.opAdd({name: 'upload', title: Drupal.t('Upload'), content: form});//add op |
|
250 }, |
|
251 |
|
252 //convert fileop form submit buttons to ops. |
|
253 setFileOps: function () { |
|
254 $(imce.el('edit-filenames-wrapper')).remove(); |
|
255 $('#imce-fileop-form fieldset').each(function() {//remove fieldsets |
|
256 var sbmt = $('input:submit', this); |
|
257 if (!sbmt.size()) return; |
|
258 var Op = {name: sbmt.attr('id').substr(5)}; |
|
259 var func = function() {imce.fopSubmit(Op.name); return false;}; |
|
260 sbmt.click(func); |
|
261 Op.title = this.firstChild.innerHTML; |
|
262 this.removeChild(this.firstChild); |
|
263 Op.name == 'delete' ? (Op.func = func) : (Op.content = this.childNodes); |
|
264 imce.opAdd(Op); |
|
265 }).remove(); |
|
266 imce.vars.opform = $(imce.el('imce-fileop-form')).serialize();//serialize remaining parts. |
|
267 }, |
|
268 |
|
269 //refresh ops states. enable/disable |
|
270 refreshOps: function() { |
|
271 for (var p in imce.conf.perm) { |
|
272 if (imce.conf.perm[p]) imce.opEnable(p); |
|
273 else imce.opDisable(p); |
|
274 } |
|
275 }, |
|
276 |
|
277 //add a new file operation |
|
278 opAdd: function (op) { |
|
279 var name = op.name || ('op-'+ $('#ops-list>li').size()); |
|
280 var Op = imce.ops[name] = {title: op.title||'Untitled'}; |
|
281 if (op.content) { |
|
282 Op.div = document.createElement('div'); |
|
283 $(Op.div).attr('id', 'op-content-'+ name).addClass('op-content').append(op.content).appendTo(imce.el('op-contents')); |
|
284 } |
|
285 Op.a = document.createElement('a'); |
|
286 Op.li = document.createElement('li'); |
|
287 $(Op.a).attr({href: '#', 'name': name}).html(op.title).click(function() {imce.opClick(this.name); return false;}); |
|
288 $(Op.li).attr('id', 'op-item-'+ op.name).append(Op.a).appendTo(imce.el('ops-list')); |
|
289 Op.func = op.func || function(){}; |
|
290 return Op; |
|
291 }, |
|
292 |
|
293 //perform op click |
|
294 opClick: function(name) { |
|
295 if (!(Op = imce.ops[name]) || Op.disabled) return imce.setMessage(Drupal.t('You can\'t perform this operation.'), 'error'); |
|
296 if (Op.div) { |
|
297 if (imce.vars.op) { |
|
298 var oldOp = imce.ops[imce.vars.op]; |
|
299 $(oldOp.div).slideUp(); |
|
300 $(oldOp.li).removeClass('active'); |
|
301 oldOp.func(false); |
|
302 if (imce.vars.op == name) { |
|
303 imce.vars.op = null; |
|
304 return false; |
|
305 } |
|
306 } |
|
307 $(Op.div).slideDown('normal', function(){setTimeout("$('input:first', imce.ops[imce.vars.op].div).focus()", 10)}); |
|
308 $(Op.li).addClass('active'); |
|
309 imce.vars.op = name; |
|
310 } |
|
311 Op.func(true); |
|
312 return true; |
|
313 }, |
|
314 |
|
315 //enable a file operation |
|
316 opEnable: function(name) { |
|
317 if ((Op = imce.ops[name]) && Op.disabled) { |
|
318 Op.disabled = false; |
|
319 $(Op.li).show(); |
|
320 } |
|
321 }, |
|
322 |
|
323 //disable a file operation |
|
324 opDisable: function(name) { |
|
325 if ((Op = imce.ops[name]) && !Op.disabled) { |
|
326 Op.disabled = true; |
|
327 $(Op.li).hide(); |
|
328 if (imce.vars.op == name) { |
|
329 imce.vars.op = null; |
|
330 $(Op.div).hide(); |
|
331 $(Op.li).removeClass('active'); |
|
332 } |
|
333 } |
|
334 }, |
|
335 |
|
336 /**************** AJAX OPERATIONS ********************/ |
|
337 |
|
338 //navigate to dir |
|
339 navigate: function(dir) { |
|
340 if (imce.vars.navbusy || (dir == imce.conf.dir && !confirm(Drupal.t('Do you want to refresh the current directory?')))) return; |
|
341 var cache = imce.vars.cache && dir != imce.conf.dir; |
|
342 var set = imce.navSet(dir, cache); |
|
343 if (cache && imce.cache[dir]) {//load from the cache |
|
344 set.success({data: imce.cache[dir]}); |
|
345 set.complete(); |
|
346 } |
|
347 else $.ajax(set);//live load |
|
348 }, |
|
349 //ajax navigation settings |
|
350 navSet: function (dir, cache) { |
|
351 $(imce.tree[dir].li).addClass('loading'); |
|
352 imce.vars.navbusy = dir; |
|
353 return {url: imce.ajaxURL('navigate', dir), |
|
354 type: 'GET', |
|
355 dataType: 'json', |
|
356 success: function(response) { |
|
357 if (response.data && !response.data.error) { |
|
358 if (cache) imce.navCache(imce.conf.dir, dir);//cache the current dir |
|
359 imce.navUpdate(response.data, dir); |
|
360 } |
|
361 imce.processResponse(response); |
|
362 }, |
|
363 complete: function () { |
|
364 $(imce.tree[dir].li).removeClass('loading'); |
|
365 imce.vars.navbusy = null; |
|
366 } |
|
367 }; |
|
368 }, |
|
369 |
|
370 //update directory using the given data |
|
371 navUpdate: function(data, dir) { |
|
372 var cached = data == imce.cache[dir], olddir = imce.conf.dir; |
|
373 if (cached) data.files.id = 'file-list'; |
|
374 $(imce.FLW).html(data.files); |
|
375 imce.dirActivate(dir); |
|
376 imce.dirSubdirs(dir, data.subdirectories); |
|
377 $.extend(imce.conf.perm, data.perm); |
|
378 imce.refreshOps(); |
|
379 imce.initiateList(cached); |
|
380 imce.setPreview(imce.selcount == 1 ? imce.lastFid() : null); |
|
381 imce.invoke('navigate', data, olddir, cached); |
|
382 }, |
|
383 |
|
384 //set cache |
|
385 navCache: function (dir, newdir) { |
|
386 var C = imce.cache[dir] = {'dir': dir, files: imce.el('file-list'), dirsize: imce.el('dir-size').innerHTML, perm: $.extend({}, imce.conf.perm)}; |
|
387 C.files.id = 'cached-list-'+ dir; |
|
388 imce.el('forms-wrapper').appendChild(C.files); |
|
389 imce.invoke('cache', C, newdir); |
|
390 }, |
|
391 |
|
392 /**************** UPLOAD ********************/ |
|
393 //validate upload form |
|
394 uploadValidate: function (data, form, options) { |
|
395 var path = data[0].value; |
|
396 if (!path) return false; |
|
397 if (imce.conf.extensions != '*') { |
|
398 var ext = path.substr(path.lastIndexOf('.') + 1); |
|
399 if ((' '+ imce.conf.extensions +' ').indexOf(' '+ ext.toLowerCase() +' ') == -1) { |
|
400 return imce.setMessage(Drupal.t('Only files with the following extensions are allowed: %files-allowed.', {'%files-allowed': imce.conf.extensions}), 'error'); |
|
401 } |
|
402 } |
|
403 var sep = path.indexOf('/') == -1 ? '\\' : '/'; |
|
404 imce.setMessage(Drupal.t('Uploading %filename...', {'%filename': path.substr(path.lastIndexOf(sep) + 1)})); |
|
405 options.url = imce.ajaxURL('upload');//make url contain current dir. |
|
406 imce.fopLoading('upload', true); |
|
407 return true; |
|
408 }, |
|
409 |
|
410 //settings for upload |
|
411 uploadSettings: function () { |
|
412 return {beforeSubmit: imce.uploadValidate, success: function (response) {imce.processResponse(Drupal.parseJson(response));}, complete: function () {imce.fopLoading('upload', false);}, resetForm: true}; |
|
413 }, |
|
414 |
|
415 /**************** FILE OPS ********************/ |
|
416 //validate default ops(delete, thumb, resize) |
|
417 fopValidate: function(fop) { |
|
418 if (!imce.validateSelCount(1, imce.conf.filenum)) return false; |
|
419 switch (fop) { |
|
420 case 'delete': |
|
421 return confirm(Drupal.t('Delete selected files?')); |
|
422 case 'thumb': |
|
423 if (!$('input:checked', imce.ops['thumb'].div).size()) { |
|
424 return imce.setMessage(Drupal.t('Please select a thumbnail.'), 'error'); |
|
425 } |
|
426 return imce.validateImage(); |
|
427 case 'resize': |
|
428 var w = imce.el('edit-width').value, h = imce.el('edit-height').value; |
|
429 var maxDim = imce.conf.dimensions.split('x'); |
|
430 var maxW = maxDim[0]*1, maxH = maxW ? maxDim[1]*1 : 0; |
|
431 if (w.search(/^[1-9][0-9]*$/) == -1 || h.search(/^[1-9][0-9]*$/) == -1 || (maxW && (maxW < w*1 || maxH < h*1))) { |
|
432 return imce.setMessage(Drupal.t('Please specify dimensions within the allowed range that is from 1x1 to @dimensions.', {'@dimensions': maxW ? imce.conf.dimensions : Drupal.t('unlimited')}), 'error'); |
|
433 } |
|
434 return imce.validateImage(); |
|
435 } |
|
436 |
|
437 var func = fop +'OpValidate'; |
|
438 if (imce[func]) return imce[func](fop); |
|
439 return true; |
|
440 }, |
|
441 |
|
442 //submit wrapper for default ops |
|
443 fopSubmit: function(fop) { |
|
444 switch (fop) { |
|
445 case 'thumb': case 'delete': case 'resize': return imce.commonSubmit(fop); |
|
446 } |
|
447 var func = fop +'OpSubmit'; |
|
448 if (imce[func]) return imce[func](fop); |
|
449 }, |
|
450 |
|
451 //common submit function shared by default ops |
|
452 commonSubmit: function(fop) { |
|
453 if (!imce.fopValidate(fop)) return false; |
|
454 imce.fopLoading(fop, true); |
|
455 $.ajax(imce.fopSettings(fop)); |
|
456 }, |
|
457 |
|
458 //settings for default file operations |
|
459 fopSettings: function (fop) { |
|
460 return {url: imce.ajaxURL(fop), type: 'POST', dataType: 'json', success: imce.processResponse, complete: function (response) {imce.fopLoading(fop, false);}, data: imce.vars.opform +'&filenames='+ imce.serialNames() +'&jsop='+ fop + (imce.ops[fop].div ? '&'+ $('input', imce.ops[fop].div).serialize() : '')}; |
|
461 }, |
|
462 |
|
463 //toggle loading state |
|
464 fopLoading: function(fop, state) { |
|
465 var el = imce.el('edit-'+ fop), func = state ? 'addClass' : 'removeClass' |
|
466 if (el) { |
|
467 $(el)[func]('loading').attr('disabled', state); |
|
468 } |
|
469 else { |
|
470 $(imce.ops[fop].li)[func]('loading'); |
|
471 imce.ops[fop].disabled = state; |
|
472 } |
|
473 }, |
|
474 |
|
475 /**************** PREVIEW & SEND TO ********************/ |
|
476 |
|
477 //preview a file. |
|
478 setPreview: function (fid) { |
|
479 var row, html = ''; |
|
480 imce.vars.prvfid = fid; |
|
481 if (fid && (row = imce.fids[fid])) { |
|
482 var width = row.cells[2].innerHTML * 1; |
|
483 html = imce.vars.previewImages && width ? imce.imgHtml(fid, width, row.cells[3].innerHTML) : imce.decode(fid); |
|
484 html = '<a href="#" onclick="imce.send(\''+ fid +'\'); return false;" title="'+ (imce.vars.prvtitle||'') +'">'+ html +'</a>'; |
|
485 } |
|
486 imce.el('file-preview').innerHTML = html; |
|
487 }, |
|
488 |
|
489 //default file send function. sends the file to the new window. |
|
490 send: function (fid) { |
|
491 if (fid) window.open(imce.getURL(fid)); |
|
492 }, |
|
493 |
|
494 //add an operation for an external application to which the files are send. |
|
495 setSendTo: function (title, func) { |
|
496 imce.send = function (fid) { if(fid) func(imce.fileGet(fid), window);}; |
|
497 var opFunc = function () { |
|
498 if (imce.selcount != 1) return alert(Drupal.t('Please select a single file.')); |
|
499 imce.send(imce.vars.prvfid); |
|
500 }; |
|
501 imce.vars.prvtitle = title; |
|
502 return imce.opAdd({'title': title, func: opFunc}); |
|
503 }, |
|
504 |
|
505 /**************** LOG MESSAGES ********************/ |
|
506 |
|
507 //move initial page messages into log |
|
508 prepareMsgs: function () { |
|
509 var msgs; |
|
510 if (msgs = imce.el('imce-messages')) { |
|
511 $('>div', msgs).each(function (){ |
|
512 var type = this.className.split(' ')[1]; |
|
513 var li = $('>ul li', this); |
|
514 if (li.size()) li.each(function () {imce.setMessage(this.innerHTML, type);}); |
|
515 else imce.setMessage(this.innerHTML, type); |
|
516 }); |
|
517 $(msgs).remove(); |
|
518 } |
|
519 //log clearer |
|
520 $(imce.el('log-clearer')).css('display', 'inline').click(function() {$(imce.el('log-wrapper')).empty();return false;}); |
|
521 }, |
|
522 |
|
523 //insert log message |
|
524 setMessage: function (msg, type) { |
|
525 var logs = imce.el('log-wrapper'), div = document.createElement('div'); |
|
526 div.className = type || 'status'; |
|
527 div.innerHTML = '<span class="time">'+ imce.logTime() +'</span> ' + msg; |
|
528 logs.appendChild(div); |
|
529 $(logs).animate({scrollTop: logs.scrollHeight}, 'slow'); |
|
530 return false; |
|
531 }, |
|
532 |
|
533 //return time in HH:MM:SS format for log |
|
534 logTime: function () { |
|
535 var t = new Date(), h = t.getHours(), m = t.getMinutes(), s = t.getSeconds(); |
|
536 return (h < 10 ? '0' : '') + h +':'+ (m < 10 ? '0' : '') + m +':'+ (s < 10 ? '0' : '') + s; |
|
537 }, |
|
538 |
|
539 /**************** OTHER HELPER FUNCTIONS ********************/ |
|
540 //invoke hooks |
|
541 invoke: function (hook) { |
|
542 var i, args, func, funcs; |
|
543 if ((funcs = imce.hooks[hook]) && funcs.length) { |
|
544 (args = $.makeArray(arguments)).shift(); |
|
545 for (i = 0; func = funcs[i]; i++) func.apply(this, args); |
|
546 } |
|
547 }, |
|
548 |
|
549 //process response |
|
550 processResponse: function (response) { |
|
551 if (response.data) imce.resData(response.data); |
|
552 if (response.messages) imce.resMsgs(response.messages); |
|
553 }, |
|
554 //process response data |
|
555 resData: function (data) { |
|
556 var i, added, removed; |
|
557 if (added = data.added) { |
|
558 var cnt = imce.findex.length; |
|
559 for (i in added) {//add new files or update existing |
|
560 imce.fileAdd(added[i]); |
|
561 } |
|
562 if (added.length == 1) {//if it is a single file operation |
|
563 imce.highlight(added[0].name);//highlight |
|
564 } |
|
565 if (imce.findex.length != cnt) {//if new files added |
|
566 $(imce.FLW).animate({scrollTop: imce.FLW.scrollHeight}).focus();//scroll to bottom. |
|
567 } |
|
568 } |
|
569 if (removed = data.removed) for (i in removed) { |
|
570 imce.fileRemove(removed[i]); |
|
571 } |
|
572 imce.conf.dirsize = data.dirsize; |
|
573 imce.updateStat(); |
|
574 }, |
|
575 //set response messages |
|
576 resMsgs: function (msgs) { |
|
577 for (var type in msgs) for (var i in msgs[type]) { |
|
578 imce.setMessage(msgs[type][i], type); |
|
579 } |
|
580 }, |
|
581 |
|
582 //return img markup |
|
583 imgHtml: function (fid, width, height) { |
|
584 return '<img src="'+ imce.getURL(fid) +'" width="'+ width +'" height="'+ height +'" alt="'+ imce.decode(fid) +'">'; |
|
585 }, |
|
586 //check if the file is an image |
|
587 isImage: function (fid) { |
|
588 return imce.fids[fid].cells[2].innerHTML * 1; |
|
589 }, |
|
590 //find the first non-image in the selection |
|
591 getNonImage: function (selected) { |
|
592 for (var fid in selected) { |
|
593 if (!imce.isImage(fid)) return fid; |
|
594 } |
|
595 return false; |
|
596 }, |
|
597 //validate current selection for images |
|
598 validateImage: function () { |
|
599 var nonImg = imce.getNonImage(imce.selected); |
|
600 return nonImg ? imce.setMessage(Drupal.t('%filename is not an image.', {'%filename': imce.decode(nonImg)}), 'error') : true; |
|
601 }, |
|
602 //validate number of selected files |
|
603 validateSelCount: function (Min, Max) { |
|
604 if (Min && imce.selcount < Min) { |
|
605 return imce.setMessage(Min == 1 ? Drupal.t('Please select a file.') : Drupal.t('You must select at least %num files.', {'%num': Min}), 'error'); |
|
606 } |
|
607 if (Max && Max < imce.selcount) { |
|
608 return imce.setMessage(Drupal.t('You are not allowed to operate on more than %num files.', {'%num': Max}), 'error'); |
|
609 } |
|
610 return true; |
|
611 }, |
|
612 |
|
613 //update file count and dir size |
|
614 updateStat: function () { |
|
615 imce.el('file-count').innerHTML = imce.findex.length; |
|
616 imce.el('dir-size').innerHTML = imce.conf.dirsize; |
|
617 }, |
|
618 //serialize selected files. return fids with a colon between them |
|
619 serialNames: function () { |
|
620 var str = ''; |
|
621 for (var fid in imce.selected) { |
|
622 str += ':'+ fid; |
|
623 } |
|
624 return str.substr(1); |
|
625 }, |
|
626 //get file url. re-encode & and # for mod rewrite |
|
627 getURL: function (fid) { |
|
628 var path = (imce.conf.dir == '.' ? '' : imce.conf.dir +'/') + fid; |
|
629 return imce.conf.furl +'/'+ (imce.conf.clean && imce.conf.prvt ? path.replace(/%(23|26)/g, '%25$1') : path); |
|
630 }, |
|
631 //el. by id |
|
632 el: function (id) { |
|
633 return document.getElementById(id); |
|
634 }, |
|
635 //find the latest selected fid |
|
636 lastFid: function () { |
|
637 if (imce.vars.lastfid) return imce.vars.lastfid; |
|
638 for (var fid in imce.selected); |
|
639 return fid; |
|
640 }, |
|
641 //create ajax url |
|
642 ajaxURL: function (op, dir) { |
|
643 return imce.conf.url + (imce.conf.clean ? '?' :'&') +'jsop='+ op +'&dir='+ (dir||imce.conf.dir); |
|
644 }, |
|
645 //fast class check |
|
646 hasC: function (el, name) { |
|
647 return el.className && (' '+ el.className +' ').indexOf(' '+ name +' ') != -1; |
|
648 }, |
|
649 //highlight a single file |
|
650 highlight: function (fid) { |
|
651 if (imce.vars.prvfid) imce.fileClick(imce.vars.prvfid); |
|
652 imce.fileClick(fid); |
|
653 }, |
|
654 //process a row |
|
655 processRow: function (row) { |
|
656 row.cells[0].innerHTML = imce.decode(row.id); |
|
657 row.onmousedown = function(e) {var e = e||window.event; imce.fileClick(this, e.ctrlKey, e.shiftKey);}; |
|
658 }, |
|
659 //decode urls. uses unescape. can be overridden to use decodeURIComponent |
|
660 decode: function (str) { |
|
661 return unescape(str); |
|
662 }, |
|
663 //global ajax error function |
|
664 ajaxError: function (e, response, settings, thrown) { |
|
665 imce.setMessage(Drupal.ahahError(response, settings.url).replace('\n', '<br />'), 'error'); |
|
666 } |
|
667 }; |
|
668 |
|
669 //initiate |
|
670 $(document).ready(imce.initiate).ajaxError(imce.ajaxError); |