PageSourceSearch

https://cityofashburn.net/wp-content/plugins/wp-file-manager-pro/lib/js/commands/rm.js?ver=8.4.3

js cityofashburn.net collected 2026-10-02 22:22:47 UTC 14,761 bytes, 501 lines download raw bytes

1/**
2 * @class  elFinder command "rm"
3 * Delete files
4 *
5 * @author Dmitry (dio) Levashov
6 * @author Naoki Sawada
7 **/
8elFinder.prototype.commands.rm = function() {
9	"use strict";
10	var self = this,
11		fm = this.fm,
12		tpl = '<div class="ui-helper-clearfix elfinder-rm-title"><span class="elfinder-cwd-icon {class} ui-corner-all"></span>{title}<div class="elfinder-rm-desc">{desc}</div></div>',
13		confirm = function(dfrd, targets, files, tHash, addTexts) {
14			var cnt = targets.length,
15				cwd = fm.cwd().hash,
16				descs = [],
17				spinner = fm.i18n('calc') + '<span class="elfinder-spinner"></span>',
18				dialog, text, tmb, size, f, fname;
19			
20			if (cnt > 1) {
21				size = 0;
22				jQuery.each(files, function(h, f) { 
23					if (f.size && f.size != 'unknown' && f.mime !== 'directory') {
24						var s = parseInt(f.size);
25						if (s >= 0 && size >= 0) {
26							size += s;
27						}
28					} else {
29						size = 'unknown';
30						return false;
31					}
32				});
33				getSize = (size === 'unknown');
34				descs.push(fm.i18n('size')+': '+(getSize? spinner : fm.formatSize(size)));
35				text = [jQuery(tpl.replace('{class}', 'elfinder-cwd-icon-group').replace('{title}', '<strong>' + fm.i18n('items')+ ': ' + cnt + '</strong>').replace('{desc}', descs.join('<br>')))];
36			} else {
37				f = files[0];
38				tmb = fm.tmb(f);
39				getSize = (f.mime === 'directory');
40				descs.push(fm.i18n('size')+': '+(getSize? spinner : fm.formatSize(f.size)));
41				descs.push(fm.i18n('modify')+': '+fm.formatDate(f));
42				fname = fm.escape(f.i18 || f.name).replace(/([_.])/g, '&#8203;$1');
43				text = [jQuery(tpl.replace('{class}', fm.mime2class(f.mime)).replace('{title}', '<strong>' + fname + '</strong>').replace('{desc}', descs.join('<br>')))];
44			}
45			
46			if (addTexts) {
47				text = text.concat(addTexts);
48			}
49			
50			text.push(tHash? 'confirmTrash' : 'confirmRm');
51			
52			dialog = fm.confirm({
53				title  : self.title,
54				text   : text,
55				accept : {
56					label    : 'btnRm',
57					callback : function() {  
58						if (tHash) {
59							self.toTrash(dfrd, targets, tHash);
60						} else {
61							remove(dfrd, targets);
62						}
63					}
64				},
65				cancel : {
66					label    : 'btnCancel',
67					callback : function() {
68						fm.unlockfiles({files : targets});
69						if (targets.length === 1 && fm.file(targets[0]).phash !== cwd) {
70							fm.select({selected : targets});
71						} else {
72							fm.selectfiles({files : targets});
73						}
74						dfrd.reject();
75					}
76				}
77			});
78			// load thumbnail
79			if (tmb) {
80				jQuery('<img/>')
81					.on('load', function() { dialog.find('.elfinder-cwd-icon').addClass(tmb.className).css('background-image', "url('"+tmb.url+"')"); })
82					.attr('src', tmb.url);
83			}
84			
85			if (getSize) {
86				getSize = fm.getSize(jQuery.map(files, function(f) { return f.mime === 'directory'? f.hash : null; })).done(function(data) {
87					dialog.find('span.elfinder-spinner').parent().html(fm.i18n('size')+': '+data.formated);
88				}).fail(function() {
89					dialog.find('span.elfinder-spinner').parent().html(fm.i18n('size')+': '+fm.i18n('unknown'));
90				}).always(function() {
91					getSize = false;
92				});
93			}
94		},
95		toTrash = function(dfrd, targets, tHash) {
96			var dsts = {},
97				itemCnt = targets.length,
98				maxCnt = self.options.toTrashMaxItems,
99				checkDirs = [],
100				reqDfd = jQuery.Deferred(),
101				req, dirs, cnt;
102			
103			if (itemCnt > maxCnt) {
104				self.confirm(dfrd, targets, self.files(targets), null, [fm.i18n('tooManyToTrash')]);
105				return;
106			}
107			
108			// Directory preparation preparation and directory enumeration
109			jQuery.each(targets, function(i, h) {
110				var file = fm.file(h),
111					path = fm.path(h).replace(/\\/g, '/'),
112					m = path.match(/^[^\/]+?(\/(?:[^\/]+?\/)*)[^\/]+?$/);
113				
114				if (file) {
115					if (m) {
116						m[1] = m[1].replace(/(^\/.*?)\/?$/, '$1');
117						if (! dsts[m[1]]) {
118							dsts[m[1]] = [];
119						}
120						dsts[m[1]].push(h);
121					}
122					if (file.mime === 'directory') {
123						checkDirs.push(h);
124					}
125				}
126			});
127			
128			// Check directory information
129			if (checkDirs.length) {
130				req = fm.request({
131					data : {cmd : 'size', targets : checkDirs},
132					notify : {type: 'readdir', cnt: 1, hideCnt: true},
133					preventDefault : true
134				}).done(function(data) {
135					var cnt = 0;
136					data.fileCnt && (cnt += parseInt(data.fileCnt));
137					data.dirCnt && (cnt += parseInt(data.dirCnt));
138					reqDfd[cnt > maxCnt ? 'reject' : 'resolve']();
139				}).fail(function() {
140					reqDfd.reject();
141				});
142				setTimeout(function() {
143					var xhr = (req && req.xhr)? req.xhr : null;
144					if (xhr && xhr.state() == 'pending') {
145						req.syncOnFail(false);
146						req.reject();
147						reqDfd.reject();
148					}
149				}, self.options.infoCheckWait * 1000);
150			} else {
151				reqDfd.resolve();
152			}
153			
154			// Directory creation and paste command execution
155			reqDfd.done(function() {
156				dirs = Object.keys(dsts);
157				cnt = dirs.length;
158				if (cnt) {
159					fm.request({
160						data   : {cmd  : 'mkdir', target : tHash, dirs : dirs}, 
161						notify : {type : 'chkdir', cnt : cnt},
162						preventFail : true
163					})
164					.fail(function(error) {
165						dfrd.reject(error);
166						fm.unlockfiles({files : targets});
167					})
168					.done(function(data) {
169						var margeRes = function(data, phash, reqData) {
170								var undo, prevUndo, redo, prevRedo;
171								jQuery.each(data, function(k, v) {
172									if (Array.isArray(v)) {
173										if (res[k]) {
174											res[k] = res[k].concat(v);
175										} else {
176											res[k] = v;
177										}
178									}
179								});
180								if (data.sync) {
181									res.sync = 1;
182								}
183								if (data.added && data.added.length) {
184									undo = function() {
185										var targets = [],
186											dirs    = jQuery.map(data.added, function(f) { return f.mime === 'directory'? f.hash : null; });
187										jQuery.each(data.added, function(i, f) {
188											if (jQuery.inArray(f.phash, dirs) === -1) {
189												targets.push(f.hash);
190											}
191										});
192										return fm.exec('restore', targets, {noToast: true});
193									};
194									redo = function() {
195										return fm.request({
196											data   : reqData,
197											notify : {type : 'redo', cnt : targets.length}
198										});
199									};
200									if (res.undo) {
201										prevUndo = res.undo;
202										res.undo = function() {
203											undo();
204											prevUndo();
205										};
206									} else {
207										res.undo = undo;
208									}
209									if (res.redo) {
210										prevRedo = res.redo;
211										res.redo = function() {
212											redo();
213											prevRedo();
214										};
215									} else {
216										res.redo = redo;
217									}
218								}
219							},
220							err = ['errTrash'],
221							res = {},
222							hasNtf = function() {
223								return fm.ui.notify.children('.elfinder-notify-trash').length;
224							},
225							hashes, tm, prg, prgSt;
226						
227						if (hashes = data.hashes) {
228							prg = 1 / cnt * 100;
229							prgSt = cnt === 1? 100 : 5;
230							tm = setTimeout(function() {
231								fm.notify({type : 'trash', cnt : 1, hideCnt : true, progress : prgSt});
232							}, fm.notifyDelay);
233							jQuery.each(dsts, function(dir, files) {
234								var phash = fm.file(files[0]).phash,
235									reqData;
236								if (hashes[dir]) {
237									reqData = {cmd : 'paste', dst : hashes[dir], targets : files, cut : 1};
238									fm.request({
239										data : reqData,
240										preventDefault : true
241									})
242									.fail(function(error) {
243										if (error) {
244											err = err.concat(error);
245										}
246									})
247									.done(function(data) {
248										data = fm.normalize(data);
249										fm.updateCache(data);
250										margeRes(data, phash, reqData);
251										if (data.warning) {
252											err = err.concat(data.warning);
253											delete data.warning;
254										}
255										// fire some event to update cache/ui
256										data.removed && data.removed.length && fm.remove(data);
257										data.added   && data.added.length   && fm.add(data);
258										data.changed && data.changed.length && fm.change(data);
259										// fire event with command name
260										fm.trigger('paste', data);
261										// fire event with command name + 'done'
262										fm.trigger('pastedone');
263										// force update content
264										data.sync && fm.sync();
265									})
266									.always(function() {
267										var hashes = [], addTexts, end = 2;
268										if (hasNtf()) {
269											fm.notify({type : 'trash', cnt : 0, hideCnt : true, progress : prg});
270										} else {
271											prgSt+= prg;
272										}
273										if (--cnt < 1) {
274											tm && clearTimeout(tm);
275											hasNtf() && fm.notify({type : 'trash', cnt  : -1});
276											fm.unlockfiles({files : targets});
277											if (Object.keys(res).length) {
278												if (err.length > 1) {
279													if (res.removed || res.removed.length) {
280														hashes = jQuery.grep(targets, function(h) {
281															return jQuery.inArray(h, res.removed) === -1? true : false;
282														});
283													}
284													if (hashes.length) {
285														if (err.length > end) {
286															end = (fm.messages[err[end-1]] || '').indexOf('$') === -1? end : end + 1;
287														}
288														dfrd.reject();
289														fm.exec('rm', hashes, { addTexts: err.slice(0, end), forceRm: true });
290													} else {
291														fm.error(err);
292													}
293												}
294												res._noSound = true;
295												if (res.undo && res.redo) {
296													res.undo = {
297														cmd : 'trash',
298														callback : res.undo,
299													};
300													res.redo = {
301														cmd : 'trash',
302														callback : res.redo
303													};
304												}
305												dfrd.resolve(res);
306											} else {
307												dfrd.reject(err);
308											}
309										}
310									});
311								}
312							});
313						} else {
314							dfrd.reject('errFolderNotFound');
315							fm.unlockfiles({files : targets});
316						}
317					});
318				} else {
319					dfrd.reject(['error', 'The folder hierarchy to be deleting can not be determined.']);
320					fm.unlockfiles({files : targets});
321				}
322			}).fail(function() {
323				self.confirm(dfrd, targets, self.files(targets), null, [fm.i18n('tooManyToTrash')]);
324			});
325		},
326		remove = function(dfrd, targets, quiet) {
327			var notify = quiet? {} : {type : 'rm', cnt : targets.length};
328			fm.request({
329				data   : {cmd  : 'rm', targets : targets}, 
330				notify : notify,
331				preventFail : true
332			})
333			.fail(function(error) {
334				dfrd.reject(error);
335			})
336			.done(function(data) {
337				if (data.error || data.warning) {
338					data.sync = true;
339				}
340				dfrd.resolve(data);
341			})
342			.always(function() {
343				fm.unlockfiles({files : targets});
344			});
345		},
346		getTHash = function(targets) {
347			var thash = null,
348				root1st;
349			
350			if (targets && targets.length) {
351				if (targets.length > 1 && fm.searchStatus.state === 2) {
352					root1st = fm.file(fm.root(targets[0])).volumeid;
353					if (!jQuery.grep(targets, function(h) { return h.indexOf(root1st) !== 0? true : false ; }).length) {
354						thash = fm.option('trashHash', targets[0]);
355					}
356				} else {
357					thash = fm.option('trashHash', targets[0]);
358				}
359			}
360			return thash;
361		},
362		getSize = false;
363	
364	// for to be able to overwrite
365	this.confirm = confirm;
366	this.toTrash = toTrash;
367	this.remove = remove;
368
369	this.syncTitleOnChange = true;
370	this.updateOnSelect = false;
371	this.shortcuts = [{
372		pattern     : 'delete ctrl+backspace shift+delete'
373	}];
374	this.value = 'rm';
375	
376	this.init = function() {
377		var update = function(origin) {
378			var targets;
379			delete self.extra;
380			self.title = fm.i18n('cmd' + self.value);
381			self.className = self.value;
382			self.button && self.button.children('span.elfinder-button-icon')[self.value === 'trash'? 'addClass' : 'removeClass']('elfinder-button-icon-trash');
383			if (origin && origin !== 'cwd' && (self.state > -1 || origin === 'navbar')) {
384				if (self.value === 'trash') {
385					self.extra = {
386						icon: 'rm',
387						node: jQuery('<span></span>')
388							.attr({title: fm.i18n('cmdrm')})
389							.on('ready', function(e, data) {
390								targets = data.targets;
391							})
392							.on('click touchstart', function(e){
393								if (e.type === 'touchstart' && e.originalEvent.touches.length > 1) {
394									return;
395								}
396								e.stopPropagation();
397								e.preventDefault();
398								fm.getUI().trigger('click'); // to close the context menu immediately
399								fm.exec('rm', targets, {_userAction: true, forceRm : true});
400							})
401					};
402				}
403			}
404		};
405		// re-assign for extended command
406		self = this;
407		fm = this.fm;
408		// bind function of change
409		self.change(function() {
410			update();
411		});
412		fm.bind('contextmenucreate', function(e) {
413			update(e.data.type);
414		});
415	};
416	
417	this.getstate = function(select) {
418		var sel   = this.hashes(select),
419			filter = function(files) {
420				var fres = true;
421				return jQuery.grep(files, function(h) {
422					var f;
423					fres = fres && (f = fm.file(h)) && ! f.locked && ! fm.isRoot(f)? true : false;
424					return fres;
425				});
426			};
427		
428		return sel.length && filter(sel).length == sel.length ? 0 : -1;
429	};
430	
431	this.exec = function(hashes, cOpts) {
432		var opts   = cOpts || {},
433			dfrd   = jQuery.Deferred()
434				.always(function() {
435					if (getSize && getSize.state && getSize.state() === 'pending') {
436						getSize.reject();
437					}
438				})
439				.fail(function(error) {
440					error && fm.error(error);
441				}).done(function(data) {
442					!opts.quiet && !data._noSound && data.removed && data.removed.length && fm.trigger('playsound', {soundFile : 'rm.wav'});
443				}),
444			files  = self.files(hashes),
445			cnt    = files.length,
446			tHash  = null,
447			addTexts = opts.addTexts? opts.addTexts : null,
448			forceRm = opts.forceRm,
449			quiet = opts.quiet,
450			targets;
451
452		if (! cnt) {
453			return dfrd.reject();
454		}
455		
456		jQuery.each(files, function(i, file) {
457			if (fm.isRoot(file)) {
458				return !dfrd.reject(['errRm', file.name, 'errPerm']);
459			}
460			if (file.locked) {
461				return !dfrd.reject(['errLocked', file.name]);
462			}
463		});
464
465		if (dfrd.state() === 'pending') {
466			targets = self.hashes(hashes);
467			cnt     = files.length;
468			
469			if (forceRm || (self.event && self.event.originalEvent && self.event.originalEvent.shiftKey)) {
470				tHash = '';
471				self.title = fm.i18n('cmdrm');
472			}
473			
474			if (tHash === null) {
475				tHash = getTHash(targets);
476			}
477			
478			fm.lockfiles({files : targets});
479			
480			if (tHash && self.options.quickTrash) {
481				self.toTrash(dfrd, targets, tHash);
482			} else {
483				if (quiet) {
484					remove(dfrd, targets, quiet);
485				} else {
486					self.confirm(dfrd, targets, files, tHash, addTexts);
487				}
488			}
489		}
490			
491		return dfrd;
492	};
493
494	fm.bind('select contextmenucreate closecontextmenu', function(e) {
495		var targets = (e.data? (e.data.selected || e.data.targets) : null) || fm.selected();
496		if (targets && targets.length) {
497			self.update(void(0), (targets? getTHash(targets) : fm.option('trashHash'))? 'trash' : 'rm');
498		}
499	});
500
501};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.