AlkantarClanX12
Current Path : /home/thanudqk/siamfreetour.com/wp-content/plugins/wp-file-manager/lib/js/ui/ |
Current File : /home/thanudqk/siamfreetour.com/wp-content/plugins/wp-file-manager/lib/js/ui/cwd.js |
/** * elFinder current working directory ui. * * @author Dmitry (dio) Levashov **/ jQuery.fn.elfindercwd = function(fm, options) { "use strict"; this.not('.elfinder-cwd').each(function() { // fm.time('cwdLoad'); var mobile = fm.UA.Mobile, list = fm.viewType == 'list', undef = 'undefined', /** * Select event full name * * @type String **/ evtSelect = 'select.'+fm.namespace, /** * Unselect event full name * * @type String **/ evtUnselect = 'unselect.'+fm.namespace, /** * Disable event full name * * @type String **/ evtDisable = 'disable.'+fm.namespace, /** * Disable event full name * * @type String **/ evtEnable = 'enable.'+fm.namespace, c = 'class', /** * File css class * * @type String **/ clFile = fm.res(c, 'cwdfile'), /** * Selected css class * * @type String **/ fileSelector = '.'+clFile, /** * Selected css class * * @type String **/ clSelected = 'ui-selected', /** * Disabled css class * * @type String **/ clDisabled = fm.res(c, 'disabled'), /** * Draggable css class * * @type String **/ clDraggable = fm.res(c, 'draggable'), /** * Droppable css class * * @type String **/ clDroppable = fm.res(c, 'droppable'), /** * Hover css class * * @type String **/ clHover = fm.res(c, 'hover'), /** * Active css class * * @type String **/ clActive = fm.res(c, 'active'), /** * Hover css class * * @type String **/ clDropActive = fm.res(c, 'adroppable'), /** * Css class for temporary nodes (for mkdir/mkfile) commands * * @type String **/ clTmp = clFile+'-tmp', /** * Select checkbox css class * * @type String */ clSelChk = 'elfinder-cwd-selectchk', /** * Number of thumbnails to load in one request (new api only) * * @type Number **/ tmbNum = fm.options.loadTmbs > 0 ? fm.options.loadTmbs : 5, /** * Current search query. * * @type String */ query = '', /** * Currect clipboard(cut) hashes as object key * * @type Object */ clipCuts = {}, /** * Parents hashes of cwd * * @type Array */ cwdParents = [], /** * cwd current hashes * * @type Array */ cwdHashes = [], /** * incsearch current hashes * * @type Array */ incHashes = void 0, /** * Custom columns name and order * * @type Array */ customCols = [], /** * Current clicked element id of first time for dblclick * * @type String */ curClickId = '', /** * Custom columns builder * * @type Function */ customColsBuild = function() { var cols = ''; for (var i = 0; i < customCols.length; i++) { cols += '<td class="elfinder-col-'+customCols[i]+'">{' + customCols[i] + '}</td>'; } return cols; }, /** * Make template.row from customCols * * @type Function */ makeTemplateRow = function() { return '<tr id="{id}" class="'+clFile+' {permsclass} {dirclass}" title="{tooltip}"{css}><td class="elfinder-col-name"><div class="elfinder-cwd-file-wrapper"><span class="elfinder-cwd-icon {mime}"{style}></span>{marker}<span class="elfinder-cwd-filename">{name}</span></div>'+selectCheckbox+'</td>'+customColsBuild()+'</tr>'; }, selectCheckbox = (jQuery.map(options.showSelectCheckboxUA, function(t) {return (fm.UA[t] || t.match(/^all$/i))? true : null;}).length)? '<div class="elfinder-cwd-select"><input type="checkbox" class="'+clSelChk+'"></div>' : '', colResizing = false, colWidth = null, /** * Table header height */ thHeight, /** * File templates * * @type Object **/ templates = { icon : '<div id="{id}" class="'+clFile+' {permsclass} {dirclass} ui-corner-all" title="{tooltip}"><div class="elfinder-cwd-file-wrapper ui-corner-all"><div class="elfinder-cwd-icon {mime} ui-corner-all" unselectable="on"{style}></div>{marker}</div><div class="elfinder-cwd-filename" title="{nametitle}">{name}</div>'+selectCheckbox+'</div>', row : '' }, permsTpl = fm.res('tpl', 'perms'), lockTpl = fm.res('tpl', 'lock'), symlinkTpl = fm.res('tpl', 'symlink'), /** * Template placeholders replacement rules * * @type Object **/ replacement = { id : function(f) { return fm.cwdHash2Id(f.hash); }, name : function(f) { var name = fm.escape(f.i18 || f.name); !list && (name = name.replace(/([_.])/g, '​$1')); return name; }, nametitle : function(f) { return fm.escape(f.i18 || f.name); }, permsclass : function(f) { return fm.perms2class(f); }, perm : function(f) { return fm.formatPermissions(f); }, dirclass : function(f) { var cName = f.mime == 'directory' ? 'directory' : ''; f.isroot && (cName += ' isroot'); f.csscls && (cName += ' ' + fm.escape(f.csscls)); options.getClass && (cName += ' ' + options.getClass(f)); return cName; }, style : function(f) { return f.icon? fm.getIconStyle(f) : ''; }, mime : function(f) { var cName = fm.mime2class(f.mime); f.icon && (cName += ' elfinder-cwd-bgurl'); return cName; }, size : function(f) { return (f.mime === 'directory' && !f.size)? '-' : fm.formatSize(f.size); }, date : function(f) { return fm.formatDate(f); }, kind : function(f) { return fm.mime2kind(f); }, mode : function(f) { return f.perm? fm.formatFileMode(f.perm) : ''; }, modestr : function(f) { return f.perm? fm.formatFileMode(f.perm, 'string') : ''; }, modeoct : function(f) { return f.perm? fm.formatFileMode(f.perm, 'octal') : ''; }, modeboth : function(f) { return f.perm? fm.formatFileMode(f.perm, 'both') : ''; }, marker : function(f) { return (f.alias || f.mime == 'symlink-broken' ? symlinkTpl : '')+(!f.read || !f.write ? permsTpl : '')+(f.locked ? lockTpl : ''); }, tooltip : function(f) { var title = fm.formatDate(f) + (f.size > 0 ? ' ('+fm.formatSize(f.size)+')' : ''), info = ''; if (query && f.path) { info = fm.escape(f.path.replace(/\/[^\/]*$/, '')); } else { info = f.tooltip? fm.escape(f.tooltip).replace(/\r/g, ' ') : ''; } if (list) { info += (info? ' ' : '') + fm.escape(f.i18 || f.name); } return info? info + ' ' + title : title; } }, /** * Type badge CSS added flag * * @type Object */ addedBadges = {}, /** * Type badge style sheet element * * @type Object */ addBadgeStyleSheet, /** * Add type badge CSS into 'head' * * @type Fundtion */ addBadgeStyle = function(mime, name) { var sel, ext, type; if (mime && ! addedBadges[mime]) { if (typeof addBadgeStyleSheet === 'undefined') { if (jQuery('#elfinderAddBadgeStyle'+fm.namespace).length) { jQuery('#elfinderAddBadgeStyle'+fm.namespace).remove(); } addBadgeStyleSheet = jQuery('<style id="addBadgeStyle'+fm.namespace+'"></style>').insertBefore(jQuery('head').children(':first')).get(0).sheet || null; } if (addBadgeStyleSheet) { mime = mime.toLowerCase(); type = mime.split('/'); ext = fm.escape(fm.mimeTypes[mime] || (name.replace(/.bac?k$/i, '').match(/\.([^.]+)$/) || ['',''])[1]); if (ext) { sel = '.elfinder-cwd-icon-' + type[0].replace(/(\.|\+)/g, '-'); if (typeof type[1] !== 'undefined') { sel += '.elfinder-cwd-icon-' + type[1].replace(/(\.|\+)/g, '-'); } try { addBadgeStyleSheet.insertRule(sel + ':before{content:"' + ext.toLowerCase() + '"}', 0); } catch(e) {} } addedBadges[mime] = true; } } }, /** * Return file html * * @param Object file info * @return String **/ itemhtml = function(f) { f.mime && f.mime !== 'directory' && !addedBadges[f.mime] && addBadgeStyle(f.mime, f.name); return templates[list ? 'row' : 'icon'] .replace(/\{([a-z0-9_]+)\}/g, function(s, e) { return replacement[e] ? replacement[e](f, fm) : (f[e] ? f[e] : ''); }); }, /** * jQueery node that will be selected next * * @type Object jQuery node */ selectedNext = jQuery(), /** * Flag. Required for msie to avoid unselect files on dragstart * * @type Boolean **/ selectLock = false, /** * Move selection to prev/next file * * @param String move direction * @param Boolean append to current selection * @return void * @rise select */ select = function(keyCode, append) { var code = jQuery.ui.keyCode, prev = keyCode == code.LEFT || keyCode == code.UP, sel = cwd.find('[id].'+clSelected), selector = prev ? 'first:' : 'last', s, n, sib, top, left; function sibling(n, direction) { return n[direction+'All']('[id]:not(.'+clDisabled+'):not(.elfinder-cwd-parent):first'); } if (sel.length) { s = sel.filter(prev ? ':first' : ':last'); sib = sibling(s, prev ? 'prev' : 'next'); if (!sib.length) { // there is no sibling on required side - do not move selection n = s; } else if (list || keyCode == code.LEFT || keyCode == code.RIGHT) { // find real prevoius file n = sib; } else { // find up/down side file in icons view top = s.position().top; left = s.position().left; n = s; if (prev) { do { n = n.prev('[id]'); } while (n.length && !(n.position().top < top && n.position().left <= left)); if (n.hasClass(clDisabled)) { n = sibling(n, 'next'); } } else { do { n = n.next('[id]'); } while (n.length && !(n.position().top > top && n.position().left >= left)); if (n.hasClass(clDisabled)) { n = sibling(n, 'prev'); } // there is row before last one - select last file if (!n.length) { sib = cwd.find('[id]:not(.'+clDisabled+'):last'); if (sib.position().top > top) { n = sib; } } } } // !append && unselectAll(); } else { if (selectedNext.length) { n = prev? selectedNext.prev() : selectedNext; } else { // there are no selected file - select first/last one n = cwd.find('[id]:not(.'+clDisabled+'):not(.elfinder-cwd-parent):'+(prev ? 'last' : 'first')); } } if (n && n.length && !n.hasClass('elfinder-cwd-parent')) { if (s && append) { // append new files to selected n = s.add(s[prev ? 'prevUntil' : 'nextUntil']('#'+n.attr('id'))).add(n); } else { // unselect selected files sel.trigger(evtUnselect); } // select file(s) n.trigger(evtSelect); // set its visible scrollToView(n.filter(prev ? ':first' : ':last')); // update cache/view trigger(); } }, selectedFiles = {}, selectFile = function(hash) { fm.cwdHash2Elm(hash).trigger(evtSelect); }, allSelected = false, selectAll = function() { var phash = fm.cwd().hash; selectCheckbox && selectAllCheckbox.find('input').prop('checked', true); fm.lazy(function() { var files; if (fm.maxTargets && (incHashes || cwdHashes).length > fm.maxTargets) { unselectAll({ notrigger: true }); files = jQuery.map(incHashes || cwdHashes, function(hash) { return fm.file(hash) || null; }); files = files.slice(0, fm.maxTargets); selectedFiles = {}; jQuery.each(files, function(i, v) { selectedFiles[v.hash] = true; fm.cwdHash2Elm(v.hash).trigger(evtSelect); }); fm.toast({mode: 'warning', msg: fm.i18n(['errMaxTargets', fm.maxTargets])}); } else { cwd.find('[id]:not(.'+clSelected+'):not(.elfinder-cwd-parent)').trigger(evtSelect); selectedFiles = fm.arrayFlip(incHashes || cwdHashes, true); } trigger(); selectCheckbox && selectAllCheckbox.data('pending', false); }, 0, {repaint: true}); }, /** * Unselect all files * * @param Object options * @return void */ unselectAll = function(opts) { var o = opts || {}; selectCheckbox && selectAllCheckbox.find('input').prop('checked', false); if (Object.keys(selectedFiles).length) { selectLock = false; selectedFiles = {}; cwd.find('[id].'+clSelected).trigger(evtUnselect); selectCheckbox && cwd.find('input:checkbox.'+clSelChk).prop('checked', false); } !o.notrigger && trigger(); selectCheckbox && selectAllCheckbox.data('pending', false); cwd.removeClass('elfinder-cwd-allselected'); }, selectInvert = function() { var invHashes = {}; if (allSelected) { unselectAll(); } else if (! Object.keys(selectedFiles).length) { selectAll(); } else { jQuery.each((incHashes || cwdHashes), function(i, h) { var itemNode = fm.cwdHash2Elm(h); if (! selectedFiles[h]) { invHashes[h] = true; itemNode.length && itemNode.trigger(evtSelect); } else { itemNode.length && itemNode.trigger(evtUnselect); } }); selectedFiles = invHashes; trigger(); } }, /** * Return selected files hashes list * * @return Array */ selected = function() { return Object.keys(selectedFiles); }, /** * Last selected node id * * @type String|Void */ lastSelect = void 0, /** * Fire elfinder "select" event and pass selected files to it * * @return void */ trigger = function() { var selected = Object.keys(selectedFiles), opts = { selected : selected, origin : 'cwd' }; if (oldSchoolItem && (selected.length > 1 || selected[0] !== fm.cwdId2Hash( oldSchoolItem.attr('id'))) && oldSchoolItem.hasClass(clSelected)) { oldSchoolItem.trigger(evtUnselect); } allSelected = selected.length && (selected.length === (incHashes || cwdHashes).length) && (!fm.maxTargets || selected.length <= fm.maxTargets); if (selectCheckbox) { selectAllCheckbox.find('input').prop('checked', allSelected); cwd[allSelected? 'addClass' : 'removeClass']('elfinder-cwd-allselected'); } if (allSelected) { opts.selectall = true; } else if (! selected.length) { opts.unselectall = true; } fm.trigger('select', opts); }, /** * Scroll file to set it visible * * @param DOMElement file/dir node * @return void */ scrollToView = function(o, blink) { if (! o.length) { return; } var ftop = o.position().top, fheight = o.outerHeight(true), wtop = wrapper.scrollTop(), wheight = wrapper.get(0).clientHeight, thheight = tableHeader? tableHeader.outerHeight(true) : 0; if (ftop + thheight + fheight > wtop + wheight) { wrapper.scrollTop(parseInt(ftop + thheight + fheight - wheight)); } else if (ftop < wtop) { wrapper.scrollTop(ftop); } list && wrapper.scrollLeft(0); !!blink && fm.resources.blink(o, 'lookme'); }, /** * Files we get from server but not show yet * * @type Array **/ buffer = [], /** * Extra data of buffer * * @type Object **/ bufferExt = {}, /** * Return index of elements with required hash in buffer * * @param String file hash * @return Number */ index = function(hash) { var l = buffer.length; while (l--) { if (buffer[l].hash == hash) { return l; } } return -1; }, /** * Scroll start event name * * @type String **/ scrollStartEvent = 'elfscrstart', /** * Scroll stop event name * * @type String **/ scrollEvent = 'elfscrstop', scrolling = false, /** * jQuery UI selectable option * * @type Object */ selectableOption = { disabled : true, filter : '[id]:first', stop : trigger, delay : 250, appendTo : 'body', autoRefresh: false, selected : function(e, ui) { jQuery(ui.selected).trigger(evtSelect); }, unselected : function(e, ui) { jQuery(ui.unselected).trigger(evtUnselect); } }, /** * hashes of items displayed in current view * * @type Object ItemHash => DomId */ inViewHashes = {}, /** * Processing when the current view is changed (On open, search, scroll, resize etc.) * * @return void */ wrapperRepaint = function(init, recnt) { if (!bufferExt.renderd) { return; } var firstNode = (list? cwd.find('tbody:first') : cwd).children('[id]'+(options.oldSchool? ':not(.elfinder-cwd-parent)' : '')+':first'); if (!firstNode.length) { return; } var selectable = cwd.data('selectable'), rec = (function() { var wos = wrapper.offset(), ww = wrapper.width(), w = jQuery(window), x = firstNode.width() / 2, l = Math.min(wos.left - w.scrollLeft() + (fm.direction === 'ltr'? x : ww - x), wos.left + ww - 10), t = wos.top - w.scrollTop() + 10 + (list? thHeight : 0); return {left: Math.max(0, Math.round(l)), top: Math.max(0, Math.round(t))}; })(), tgt = init? firstNode : jQuery(document.elementFromPoint(rec.left , rec.top)), ids = {}, tmbs = {}, multi = 5, cnt = Math.ceil((bufferExt.hpi? Math.ceil((wz.data('rectangle').height / bufferExt.hpi) * 1.5) : showFiles) / multi), chk = function() { var id, hash, file, i; for (i = 0; i < multi; i++) { id = tgt.attr('id'); if (id) { bufferExt.getTmbs = []; hash = fm.cwdId2Hash(id); inViewHashes[hash] = id; // for tmbs if (bufferExt.attachTmbs[hash]) { tmbs[hash] = bufferExt.attachTmbs[hash]; } // for selectable selectable && (ids[id] = true); } // next node tgt = tgt.next(); if (!tgt.length) { break; } } }, done = function() { var idsArr; if (cwd.data('selectable')) { Object.assign(ids, selectedFiles); idsArr = Object.keys(ids); if (idsArr.length) { selectableOption.filter = '#'+idsArr.join(', #'); cwd.selectable('enable').selectable('option', {filter : selectableOption.filter}).selectable('refresh'); } } if (Object.keys(tmbs).length) { bufferExt.getTmbs = []; attachThumbnails(tmbs); } }, setTarget = function() { if (!tgt.hasClass(clFile)) { tgt = tgt.closest(fileSelector); } }, arr, widget; inViewHashes = {}; selectable && cwd.selectable('option', 'disabled'); if (tgt.length) { if (!tgt.hasClass(clFile) && !tgt.closest(fileSelector).length) { // dialog, serach button etc. widget = fm.getUI().find('.ui-dialog:visible,.ui-widget:visible'); if (widget.length) { widget.hide(); tgt = jQuery(document.elementFromPoint(rec.left , rec.top)); widget.show(); } else { widget = null; } } setTarget(); if (!tgt.length) { // try search 5px down widget && widget.hide(); tgt = jQuery(document.elementFromPoint(rec.left , rec.top + 5)); widget && widget.show(); setTarget(); } } if (tgt.length) { if (tgt.attr('id')) { if (init) { for (var i = 0; i < cnt; i++) { chk(); if (! tgt.length) { break; } } done(); } else { bufferExt.repaintJob && bufferExt.repaintJob.state() === 'pending' && bufferExt.repaintJob.reject(); arr = new Array(cnt); bufferExt.repaintJob = fm.asyncJob(function() { chk(); if (! tgt.length) { done(); bufferExt.repaintJob && bufferExt.repaintJob.state() === 'pending' && bufferExt.repaintJob.reject(); } }, arr).done(done); } } } else if (init && bufferExt.renderd) { // In initial request, cwd DOM not renderd so doing lazy check recnt = recnt || 0; if (recnt < 10) { // Prevent infinite loop requestAnimationFrame(function() { wrapperRepaint(init, ++recnt); }); } } }, /** * Item node of oldScholl ".." */ oldSchoolItem = null, /** * display parent folder with ".." name * * @param String phash * @return void */ oldSchool = function(p) { var phash = fm.cwd().phash, pdir = fm.file(phash) || null, set = function(pdir) { if (pdir) { oldSchoolItem = jQuery(itemhtml(jQuery.extend(true, {}, pdir, {name : '..', i18 : '..', mime : 'directory'}))) .addClass('elfinder-cwd-parent') .on('dblclick', function() { fm.trigger('select', {selected : [phash]}).exec('open', phash); }); (list ? oldSchoolItem.children('td:first') : oldSchoolItem).children('.elfinder-cwd-select').remove(); if (fm.cwdHash2Elm(phash).length) { fm.cwdHash2Elm(phash).replaceWith(oldSchoolItem); } else { (list ? cwd.find('tbody') : cwd).prepend(oldSchoolItem); } fm.draggingUiHelper && fm.draggingUiHelper.data('refreshPositions', 1); } }; if (pdir) { set(pdir); } else { set({hash: phash, read: true, write: true}); if (fm.getUI('tree').length) { fm.one('parents', function() { set(fm.file(phash) || null); wrapper.trigger(scrollEvent); }); } else { fm.request({ data : {cmd : 'parents', target : fm.cwd().hash}, preventFail : true }) .done(function(data) { set(fm.file(phash) || null); wrapper.trigger(scrollEvent); }); } } }, showFiles = fm.options.showFiles, /** * Cwd scroll event handler. * Lazy load - append to cwd not shown files * * @return void */ render = function() { if (bufferExt.rendering || (bufferExt.renderd && ! buffer.length)) { return; } var place = (list ? cwd.children('table').children('tbody') : cwd), phash, chk, // created document fragment for jQuery >= 1.12, 2.2, 3.0 // see Studio-42/elFinder#1544 @ github docFlag = jQuery.htmlPrefilter? true : false, tempDom = docFlag? jQuery(document.createDocumentFragment()) : jQuery('<div></div>'), go = function(o){ var over = o || null, html = [], dirs = false, atmb = {}, stmb = (fm.option('tmbUrl') === 'self'), init = bufferExt.renderd? false : true, files, locks, selected; files = buffer.splice(0, showFiles + (over || 0) / (bufferExt.hpi || 1)); bufferExt.renderd += files.length; if (! buffer.length) { bottomMarker.hide(); wrapper.off(scrollEvent, render); } locks = []; html = jQuery.map(files, function(f) { if (f.hash && f.name) { if (f.mime == 'directory') { dirs = true; } if ((f.tmb && (f.tmb != 1 || f.size > 0)) || (stmb && f.mime.indexOf('image/') === 0)) { atmb[f.hash] = f.tmb || 'self'; } clipCuts[f.hash] && locks.push(f.hash); return itemhtml(f); } return null; }); // html into temp node tempDom.empty().append(html.join('')); // make directory droppable dirs && !mobile && makeDroppable(tempDom); // check selected items selected = []; if (Object.keys(selectedFiles).length) { tempDom.find('[id]:not(.'+clSelected+'):not(.elfinder-cwd-parent)').each(function() { selectedFiles[fm.cwdId2Hash(this.id)] && selected.push(jQuery(this)); }); } // append to cwd place.append(docFlag? tempDom : tempDom.children()); // trigger select if (selected.length) { jQuery.each(selected, function(i, n) { n.trigger(evtSelect); }); trigger(); } locks.length && fm.trigger('lockfiles', {files: locks}); !bufferExt.hpi && bottomMarkerShow(place, files.length); if (list) { // show thead cwd.find('thead').show(); // fixed table header fixTableHeader({fitWidth: ! colWidth}); } if (Object.keys(atmb).length) { Object.assign(bufferExt.attachTmbs, atmb); } if (init) { if (! mobile && ! cwd.data('selectable')) { // make files selectable cwd.selectable(selectableOption).data('selectable', true); } } ! scrolling && wrapper.trigger(scrollEvent); }; if (! bufferExt.renderd) { // first time to go() bufferExt.rendering = true; // scroll top on dir load to avoid scroll after page reload wrapper.scrollTop(0); phash = fm.cwd().phash; go(); if (options.oldSchool) { if (phash && !query) { oldSchool(phash); } else { oldSchoolItem = jQuery(); } } if (list) { colWidth && setColwidth(); fixTableHeader({fitWidth: true}); } bufferExt.itemH = (list? place.find('tr:first') : place.find('[id]:first')).outerHeight(true); fm.trigger('cwdrender'); bufferExt.rendering = false; wrapperRepaint(true); } if (! bufferExt.rendering && buffer.length) { // next go() if ((chk = (wrapper.height() + wrapper.scrollTop() + fm.options.showThreshold + bufferExt.row) - (bufferExt.renderd * bufferExt.hpi)) > 0) { bufferExt.rendering = true; fm.lazy(function() { go(chk); bufferExt.rendering = false; }); } else { !fm.enabled() && resize(); } } else { resize(); } }, // fixed table header jQuery object tableHeader = null, // Is UA support CSS sticky cssSticky = fm.UA.CSS.positionSticky && fm.UA.CSS.widthMaxContent, // To fixed table header colmun fixTableHeader = function(optsArg) { thHeight = 0; if (! options.listView.fixedHeader) { return; } var setPos = function() { var val, pos; pos = (fm.direction === 'ltr')? 'left' : 'right'; val = ((fm.direction === 'ltr')? wrapper.scrollLeft() : table.outerWidth(true) - wrapper.width() - wrapper.scrollLeft()) * -1; if (base.css(pos) !== val) { base.css(pos, val); } }, opts = optsArg || {}, cnt, base, table, htable, thead, tbody, hheight, htr, btr, htd, btd, htw, btw, init; tbody = cwd.find('tbody'); btr = tbody.children('tr:first'); if (btr.length && btr.is(':visible')) { table = tbody.parent(); if (! tableHeader) { init = true; tbody.addClass('elfinder-cwd-fixheader'); thead = cwd.find('thead').attr('id', fm.namespace+'-cwd-thead'); htr = thead.children('tr:first'); hheight = htr.outerHeight(true); cwd.css('margin-top', hheight - parseInt(table.css('padding-top'))); if (cssSticky) { tableHeader = jQuery('<div class="elfinder-table-header-sticky"></div>').addClass(cwd.attr('class')).append(jQuery('<table></table>').append(thead)); cwd.after(tableHeader); wrapper.on('resize.fixheader', function(e) { e.stopPropagation(); fixTableHeader({fitWidth: true}); }); } else { base = jQuery('<div></div>').addClass(cwd.attr('class')).append(jQuery('<table></table>').append(thead)); tableHeader = jQuery('<div></div>').addClass(wrapper.attr('class') + ' elfinder-cwd-fixheader') .removeClass('ui-droppable native-droppable') .css(wrapper.position()) .css({ height: hheight, width: cwd.outerWidth() }) .append(base); if (fm.direction === 'rtl') { tableHeader.css('left', (wrapper.data('width') - wrapper.width()) + 'px'); } setPos(); wrapper.after(tableHeader) .on('scroll.fixheader resize.fixheader', function(e) { setPos(); if (e.type === 'resize') { e.stopPropagation(); tableHeader.css(wrapper.position()); wrapper.data('width', wrapper.css('overflow', 'hidden').width()); wrapper.css('overflow', 'auto'); fixTableHeader(); } }); } } else { thead = jQuery('#'+fm.namespace+'-cwd-thead'); htr = thead.children('tr:first'); } if (init || opts.fitWidth || Math.abs(btr.outerWidth() - htr.outerWidth()) > 2) { cnt = customCols.length + 1; for (var i = 0; i < cnt; i++) { htd = htr.children('td:eq('+i+')'); btd = btr.children('td:eq('+i+')'); htw = htd.width(); btw = btd.width(); if (typeof htd.data('delta') === 'undefined') { htd.data('delta', (htd.outerWidth() - htw) - (btd.outerWidth() - btw)); } btw -= htd.data('delta'); if (! init && ! opts.fitWidth && htw === btw) { break; } htd.css('width', btw + 'px'); } } if (!cssSticky) { tableHeader.data('widthTimer') && cancelAnimationFrame(tableHeader.data('widthTimer')); tableHeader.data('widthTimer', requestAnimationFrame(function() { if (tableHeader) { tableHeader.css('width', mBoard.width() + 'px'); if (fm.direction === 'rtl') { tableHeader.css('left', (wrapper.data('width') - wrapper.width()) + 'px'); } } })); } thHeight = thead.height(); } }, // Set colmun width setColwidth = function() { if (list && colWidth) { var cl = 'elfinder-cwd-colwidth', first = cwd.find('tr[id]:first'), former; if (! first.hasClass(cl)) { former = cwd.find('tr.'+cl); former.removeClass(cl).find('td').css('width', ''); first.addClass(cl); cwd.find('table:first').css('table-layout', 'fixed'); jQuery.each(jQuery.merge(['name'], customCols), function(i, k) { var w = colWidth[k] || first.find('td.elfinder-col-'+k).width(); first.find('td.elfinder-col-'+k).width(w); }); } } }, /** * Droppable options for cwd. * Drop target is `wrapper` * Do not add class on childs file over * * @type Object */ droppable = Object.assign({}, fm.droppable, { over : function(e, ui) { var dst = jQuery(this), helper = ui.helper, ctr = fm._commands.copy && (e.shiftKey || e.ctrlKey || e.metaKey), hash, status, inParent; e.stopPropagation(); helper.data('dropover', helper.data('dropover') + 1); dst.data('dropover', true); helper.removeClass('elfinder-drag-helper-move elfinder-drag-helper-plus'); if (helper.data('namespace') !== fm.namespace || ! fm.insideWorkzone(e.pageX, e.pageY)) { dst.removeClass(clDropActive); //helper.removeClass('elfinder-drag-helper-move elfinder-drag-helper-plus'); return; } if (dst.hasClass(fm.res(c, 'cwdfile'))) { hash = fm.cwdId2Hash(dst.attr('id')); dst.data('dropover', hash); } else { hash = fm.cwd().hash; fm.cwd().write && dst.data('dropover', hash); } inParent = (fm.file(helper.data('files')[0]).phash === hash); if (dst.data('dropover') === hash) { jQuery.each(helper.data('files'), function(i, h) { if (h === hash || (inParent && !ctr && !helper.hasClass('elfinder-drag-helper-plus'))) { dst.removeClass(clDropActive); return false; // break jQuery.each } }); } else { dst.removeClass(clDropActive); } if (helper.data('locked') || inParent) { status = 'elfinder-drag-helper-plus'; } else { status = 'elfinder-drag-helper-move'; if (ctr) { status += ' elfinder-drag-helper-plus'; } } dst.hasClass(clDropActive) && helper.addClass(status); requestAnimationFrame(function(){ dst.hasClass(clDropActive) && helper.addClass(status); }); }, out : function(e, ui) { var helper = ui.helper; e.stopPropagation(); helper.removeClass('elfinder-drag-helper-move elfinder-drag-helper-plus').data('dropover', Math.max(helper.data('dropover') - 1, 0)); jQuery(this).removeData('dropover') .removeClass(clDropActive); }, deactivate : function() { jQuery(this).removeData('dropover') .removeClass(clDropActive); }, drop : function(e, ui) { unselectAll({ notrigger: true }); fm.droppable.drop.call(this, e, ui); } }), /** * Make directory droppable * * @return void */ makeDroppable = function(place) { place = place? place : (list ? cwd.find('tbody') : cwd); var targets = place.children('.directory:not(.'+clDroppable+',.elfinder-na,.elfinder-ro)'); if (fm.isCommandEnabled('paste')) { targets.droppable(droppable); } if (fm.isCommandEnabled('upload')) { targets.addClass('native-droppable'); } place.children('.isroot').each(function(i, n) { var $n = jQuery(n), hash = fm.cwdId2Hash(n.id); if (fm.isCommandEnabled('paste', hash)) { if (! $n.hasClass(clDroppable+',elfinder-na,elfinder-ro')) { $n.droppable(droppable); } } else { if ($n.hasClass(clDroppable)) { $n.droppable('destroy'); } } if (fm.isCommandEnabled('upload', hash)) { if (! $n.hasClass('native-droppable,elfinder-na,elfinder-ro')) { $n.addClass('native-droppable'); } } else { if ($n.hasClass('native-droppable')) { $n.removeClass('native-droppable'); } } }); }, /** * Preload required thumbnails and on load add css to files. * Return false if required file is not visible yet (in buffer) - * required for old api to stop loading thumbnails. * * @param Object file hash -> thumbnail map * @param Bool reload * @return void */ attachThumbnails = function(tmbs, reload) { var attach = function(node, tmb) { jQuery('<img/>') .on('load', function() { node.find('.elfinder-cwd-icon').addClass(tmb.className).css('background-image', "url('"+tmb.url+"')"); }) .attr('src', tmb.url); }, chk = function(hash, tmb) { var node = fm.cwdHash2Elm(hash), file, tmbObj, reloads = []; if (node.length) { if (tmb != '1') { file = fm.file(hash); if (file.tmb !== tmb) { file.tmb = tmb; } tmbObj = fm.tmb(file); if (reload) { node.find('.elfinder-cwd-icon').addClass(tmbObj.className).css('background-image', "url('"+tmbObj.url+"')"); } else { attach(node, tmbObj); } delete bufferExt.attachTmbs[hash]; } else { if (reload) { loadThumbnails([hash]); } else if (! bufferExt.tmbLoading[hash]) { bufferExt.getTmbs.push(hash); } } } }; if (jQuery.isPlainObject(tmbs) && Object.keys(tmbs).length) { Object.assign(bufferExt.attachTmbs, tmbs); jQuery.each(tmbs, chk); if (! reload && bufferExt.getTmbs.length && ! Object.keys(bufferExt.tmbLoading).length) { loadThumbnails(); } } }, /** * Load thumbnails from backend. * * @param Array|void reloads hashes list for reload thumbnail items * @return void */ loadThumbnails = function(reloads) { var tmbs = [], reload = false; if (fm.oldAPI) { fm.request({ data : {cmd : 'tmb', current : fm.cwd().hash}, preventFail : true }) .done(function(data) { if (data.images && Object.keys(data.images).length) { attachThumbnails(data.images); } if (data.tmb) { loadThumbnails(); } }); return; } if (reloads) { reload = true; tmbs = reloads.splice(0, tmbNum); } else { tmbs = bufferExt.getTmbs.splice(0, tmbNum); } if (tmbs.length) { if (reload || inViewHashes[tmbs[0]] || inViewHashes[tmbs[tmbs.length-1]]) { jQuery.each(tmbs, function(i, h) { bufferExt.tmbLoading[h] = true; }); fm.request({ data : {cmd : 'tmb', targets : tmbs}, preventFail : true }) .done(function(data) { var errs = [], resLen; if (data.images) { if (resLen = Object.keys(data.images).length) { if (resLen < tmbs.length) { jQuery.each(tmbs, function(i, h) { if (! data.images[h]) { errs.push(h); } }); } attachThumbnails(data.images, reload); } else { errs = tmbs; } // unset error items from bufferExt.attachTmbs if (errs.length) { jQuery.each(errs, function(i, h) { delete bufferExt.attachTmbs[h]; }); } } if (reload) { if (reloads.length) { loadThumbnails(reloads); } } }) .always(function() { bufferExt.tmbLoading = {}; if (! reload && bufferExt.getTmbs.length) { loadThumbnails(); } }); } } }, /** * Add new files to cwd/buffer * * @param Array new files * @return void */ add = function(files, mode) { var place = list ? cwd.find('tbody') : cwd, l = files.length, atmb = {}, findNode = function(file) { var pointer = cwd.find('[id]:first'), file2; while (pointer.length) { file2 = fm.file(fm.cwdId2Hash(pointer.attr('id'))); if (!pointer.hasClass('elfinder-cwd-parent') && file2 && fm.compare(file, file2) < 0) { return pointer; } pointer = pointer.next('[id]'); } }, findIndex = function(file) { var l = buffer.length, i; for (i =0; i < l; i++) { if (fm.compare(file, buffer[i]) < 0) { return i; } } return l || -1; }, // created document fragment for jQuery >= 1.12, 2.2, 3.0 // see Studio-42/elFinder#1544 @ github docFlag = jQuery.htmlPrefilter? true : false, tempDom = docFlag? jQuery(document.createDocumentFragment()) : jQuery('<div></div>'), file, hash, node, nodes, ndx, stmb; if (l > showFiles) { // re-render for performance tune content(); selectedFiles = fm.arrayFlip(jQuery.map(files, function(f) { return f.hash; }), true); trigger(); } else { // add the item immediately l && wz.removeClass('elfinder-cwd-wrapper-empty'); // Self thumbnail stmb = (fm.option('tmbUrl') === 'self'); while (l--) { file = files[l]; hash = file.hash; if (fm.cwdHash2Elm(hash).length) { continue; } if ((node = findNode(file)) && ! node.length) { node = null; } if (! node && (ndx = findIndex(file)) >= 0) { buffer.splice(ndx, 0, file); } else { tempDom.empty().append(itemhtml(file)); (file.mime === 'directory') && !mobile && makeDroppable(tempDom); nodes = docFlag? tempDom : tempDom.children(); if (node) { node.before(nodes); } else { place.append(nodes); } ++bufferExt.renderd; } if (fm.cwdHash2Elm(hash).length) { if ((file.tmb && (file.tmb != 1 || file.size > 0)) || (stmb && file.mime.indexOf('image/') === 0)) { atmb[hash] = file.tmb || 'self'; } } } if (list) { setColwidth(); fixTableHeader({fitWidth: ! colWidth}); } bottomMarkerShow(place); if (Object.keys(atmb).length) { Object.assign(bufferExt.attachTmbs, atmb); if (buffer.length < 1) { loadThumbnails(); } } } }, /** * Remove files from cwd/buffer * * @param Array files hashes * @return void */ remove = function(files) { var l = files.length, inSearch = fm.searchStatus.state > 1, curCmd = fm.getCommand(fm.currentReqCmd) || {}, hash, n, ndx, found; // removed cwd if (!fm.cwd().hash && !curCmd.noChangeDirOnRemovedCwd) { jQuery.each(cwdParents.reverse(), function(i, h) { if (fm.file(h)) { found = true; fm.one(fm.currentReqCmd + 'done', function() { !fm.cwd().hash && fm.exec('open', h); }); return false; } }); // fallback to fm.roots[0] !found && !fm.cwd().hash && fm.exec('open', fm.roots[Object.keys(fm.roots)[0]]); return; } while (l--) { hash = files[l]; if ((n = fm.cwdHash2Elm(hash)).length) { try { n.remove(); --bufferExt.renderd; } catch(e) { fm.debug('error', e); } } else if ((ndx = index(hash)) !== -1) { buffer.splice(ndx, 1); } selectedFiles[hash] && delete selectedFiles[hash]; if (inSearch) { if ((ndx = jQuery.inArray(hash, cwdHashes)) !== -1) { cwdHashes.splice(ndx, 1); } } } inSearch && fm.trigger('cwdhasheschange', cwdHashes); if (list) { setColwidth(); fixTableHeader({fitWidth: ! colWidth}); } }, customColsNameBuild = function() { var name = '', customColsName = ''; for (var i = 0; i < customCols.length; i++) { name = fm.getColumnName(customCols[i]); customColsName +='<td class="elfinder-cwd-view-th-'+customCols[i]+' sortable-item">'+name+'</td>'; } return customColsName; }, setItemBoxSize = function(boxSize) { var place, elm; if (!boxSize.height) { place = (list ? cwd.find('tbody') : cwd); elm = place.find(list? 'tr:first' : '[id]:first'); boxSize.height = elm.outerHeight(true); if (!list) { boxSize.width = elm.outerWidth(true); } } }, bottomMarkerShow = function(cur, cnt) { var place = cur || (list ? cwd.find('tbody') : cwd), boxSize = itemBoxSize[fm.viewType], col = 1, row; if (buffer.length > 0) { if (!bufferExt.hpi) { setItemBoxSize(boxSize); if (! list) { col = Math.floor(place.width() / boxSize.width); bufferExt.row = boxSize.height; bufferExt.hpi = bufferExt.row / col; } else { bufferExt.row = bufferExt.hpi = boxSize.height; } } else if (!list) { col = Math.floor(place.width() / boxSize.width); } row = Math.ceil((buffer.length + (cnt || 0)) / col); if (list && tableHeader) { ++row; } bottomMarker.css({top: (bufferExt.row * row) + 'px'}).show(); } }, wrapperContextMenu = { contextmenu : function(e) { e.preventDefault(); if (cwd.data('longtap') !== void(0)) { e.stopPropagation(); return; } fm.trigger('contextmenu', { 'type' : 'cwd', 'targets' : [fm.cwd().hash], 'x' : e.pageX, 'y' : e.pageY }); }, touchstart : function(e) { if (e.originalEvent.touches.length > 1) { return; } if (cwd.data('longtap') !== false) { wrapper.data('touching', {x: e.originalEvent.touches[0].pageX, y: e.originalEvent.touches[0].pageY}); cwd.data('tmlongtap', setTimeout(function(){ // long tap cwd.data('longtap', true); fm.trigger('contextmenu', { 'type' : 'cwd', 'targets' : [fm.cwd().hash], 'x' : wrapper.data('touching').x, 'y' : wrapper.data('touching').y }); }, 500)); } cwd.data('longtap', null); }, touchend : function(e) { if (e.type === 'touchmove') { if (! wrapper.data('touching') || ( Math.abs(wrapper.data('touching').x - e.originalEvent.touches[0].pageX) + Math.abs(wrapper.data('touching').y - e.originalEvent.touches[0].pageY)) > 4) { wrapper.data('touching', null); } } else { setTimeout(function() { cwd.removeData('longtap'); }, 80); } clearTimeout(cwd.data('tmlongtap')); }, click : function(e) { if (cwd.data('longtap')) { e.preventDefault(); e.stopPropagation(); } } }, /** * Update directory content * * @return void */ content = function() { fm.lazy(function() { var phash, emptyMethod, thtr; wz.append(selectAllCheckbox).removeClass('elfinder-cwd-wrapper-empty elfinder-search-result elfinder-incsearch-result elfinder-letsearch-result'); if (fm.searchStatus.state > 1 || fm.searchStatus.ininc) { wz.addClass('elfinder-search-result' + (fm.searchStatus.ininc? ' elfinder-'+(query.substr(0,1) === '/' ? 'let':'inc')+'search-result' : '')); } // abort attachThumbJob bufferExt.attachThumbJob && bufferExt.attachThumbJob._abort(); // destroy selectable for GC cwd.data('selectable') && cwd.selectable('disable').selectable('destroy').removeData('selectable'); // notify cwd init fm.trigger('cwdinit'); selectedNext = jQuery(); try { // to avoid problem with draggable cwd.empty(); } catch (e) { cwd.html(''); } if (tableHeader) { wrapper.off('scroll.fixheader resize.fixheader'); tableHeader.remove(); tableHeader = null; } cwd.removeClass('elfinder-cwd-view-icons elfinder-cwd-view-list') .addClass('elfinder-cwd-view-'+(list ? 'list' :'icons')) .attr('style', '') .css('height', 'auto'); bottomMarker.hide(); wrapper[list ? 'addClass' : 'removeClass']('elfinder-cwd-wrapper-list')._padding = parseInt(wrapper.css('padding-top')) + parseInt(wrapper.css('padding-bottom')); if (fm.UA.iOS) { wrapper.removeClass('overflow-scrolling-touch').addClass('overflow-scrolling-touch'); } if (list) { cwd.html('<table><thead></thead><tbody></tbody></table>'); thtr = jQuery('<tr class="ui-state-default"><td class="elfinder-cwd-view-th-name">'+fm.getColumnName('name')+'</td>'+customColsNameBuild()+'</tr>'); cwd.find('thead').hide().append(thtr).find('td:first').append(selectAllCheckbox); if (jQuery.fn.sortable) { thtr.addClass('touch-punch touch-punch-keep-default') .sortable({ axis: 'x', distance: 8, items: '> .sortable-item', start: function(e, ui) { jQuery(ui.item[0]).data('dragging', true); ui.placeholder .width(ui.helper.removeClass('ui-state-hover').width()) .removeClass('ui-state-active') .addClass('ui-state-hover') .css('visibility', 'visible'); }, update: function(e, ui){ var target = jQuery(ui.item[0]).attr('class').split(' ')[0].replace('elfinder-cwd-view-th-', ''), prev, done; customCols = jQuery.map(jQuery(this).children(), function(n) { var name = jQuery(n).attr('class').split(' ')[0].replace('elfinder-cwd-view-th-', ''); if (! done) { if (target === name) { done = true; } else { prev = name; } } return (name === 'name')? null : name; }); templates.row = makeTemplateRow(); fm.storage('cwdCols', customCols); prev = '.elfinder-col-'+prev+':first'; target = '.elfinder-col-'+target+':first'; fm.lazy(function() { cwd.find('tbody tr').each(function() { var $this = jQuery(this); $this.children(prev).after($this.children(target)); }); }); }, stop: function(e, ui) { setTimeout(function() { jQuery(ui.item[0]).removeData('dragging'); }, 100); } }); } thtr.find('td').addClass('touch-punch').resizable({ handles: fm.direction === 'ltr'? 'e' : 'w', start: function(e, ui) { var target = cwd.find('td.elfinder-col-' + ui.element.attr('class').split(' ')[0].replace('elfinder-cwd-view-th-', '') + ':first'); ui.element .data('dragging', true) .data('resizeTarget', target) .data('targetWidth', target.width()); colResizing = true; if (cwd.find('table').css('table-layout') !== 'fixed') { cwd.find('tbody tr:first td').each(function() { jQuery(this).width(jQuery(this).width()); }); cwd.find('table').css('table-layout', 'fixed'); } }, resize: function(e, ui) { ui.element.data('resizeTarget').width(ui.element.data('targetWidth') - (ui.originalSize.width - ui.size.width)); }, stop : function(e, ui) { colResizing = false; fixTableHeader({fitWidth: true}); colWidth = {}; cwd.find('tbody tr:first td').each(function() { var name = jQuery(this).attr('class').split(' ')[0].replace('elfinder-col-', ''); colWidth[name] = jQuery(this).width(); }); fm.storage('cwdColWidth', colWidth); setTimeout(function() { ui.element.removeData('dragging'); }, 100); } }) .find('.ui-resizable-handle').addClass('ui-icon ui-icon-grip-dotted-vertical'); } buffer = jQuery.map(incHashes || cwdHashes, function(hash) { return fm.file(hash) || null; }); buffer = fm.sortFiles(buffer); if (incHashes) { incHashes = jQuery.map(buffer, function(f) { return f.hash; }); } else { cwdHashes = jQuery.map(buffer, function(f) { return f.hash; }); } bufferExt = { renderd: 0, attachTmbs: {}, getTmbs: [], tmbLoading: {}, lazyOpts: { tm : 0 } }; wz[(buffer.length < 1) ? 'addClass' : 'removeClass']('elfinder-cwd-wrapper-empty'); wrapper.off(scrollEvent, render).on(scrollEvent, render).trigger(scrollEvent); // set droppable if (!fm.cwd().write) { wrapper.removeClass('native-droppable') .droppable('disable') .removeClass('ui-state-disabled'); // for old jQueryUI see https://bugs.jqueryui.com/ticket/5974 } else { wrapper[fm.isCommandEnabled('upload')? 'addClass' : 'removeClass']('native-droppable'); wrapper.droppable(fm.isCommandEnabled('paste')? 'enable' : 'disable'); } }); }, /** * CWD node itself * * @type JQuery **/ cwd = jQuery(this) .addClass('ui-helper-clearfix elfinder-cwd') .attr('unselectable', 'on') // fix ui.selectable bugs and add shift+click support .on('click.'+fm.namespace, fileSelector, function(e) { var p = this.id ? jQuery(this) : jQuery(this).parents('[id]:first'), tgt = jQuery(e.target), prev, next, pl, nl, sib; if (selectCheckbox && (tgt.is('input:checkbox.'+clSelChk) || tgt.hasClass('elfinder-cwd-select'))) { e.stopPropagation(); e.preventDefault(); p.trigger(p.hasClass(clSelected) ? evtUnselect : evtSelect); trigger(); requestAnimationFrame(function() { tgt.prop('checked', p.hasClass(clSelected)); }); return; } if (cwd.data('longtap') || tgt.hasClass('elfinder-cwd-nonselect')) { e.stopPropagation(); return; } if (!curClickId) { curClickId = p.attr('id'); setTimeout(function() { curClickId = ''; }, 500); } if (e.shiftKey) { prev = p.prevAll(lastSelect || '.'+clSelected+':first'); next = p.nextAll(lastSelect || '.'+clSelected+':first'); pl = prev.length; nl = next.length; } if (e.shiftKey && (pl || nl)) { sib = pl ? p.prevUntil('#'+prev.attr('id')) : p.nextUntil('#'+next.attr('id')); sib = sib.add(p); if (!pl) { sib = jQuery(sib.get().reverse()); } sib.trigger(evtSelect); } else if (e.ctrlKey || e.metaKey) { p.trigger(p.hasClass(clSelected) ? evtUnselect : evtSelect); } else { if (wrapper.data('touching') && p.hasClass(clSelected)) { wrapper.data('touching', null); fm.dblclick({file : fm.cwdId2Hash(this.id)}); return; } else { unselectAll({ notrigger: true }); p.trigger(evtSelect); } } trigger(); }) // call fm.open() .on('dblclick.'+fm.namespace, fileSelector, function(e) { if (curClickId) { var hash = fm.cwdId2Hash(curClickId); e.stopPropagation(); if (this.id !== curClickId) { jQuery(this).trigger(evtUnselect); jQuery('#'+curClickId).trigger(evtSelect); trigger(); } fm.dblclick({file : hash}); } }) // for touch device .on('touchstart.'+fm.namespace, fileSelector, function(e) { if (e.originalEvent.touches.length > 1) { return; } var p = this.id ? jQuery(this) : jQuery(this).parents('[id]:first'), tgt = jQuery(e.target), nodeName = e.target.nodeName, sel; if ((nodeName === 'INPUT' && e.target.type === 'text') || nodeName === 'TEXTAREA' || tgt.hasClass('elfinder-cwd-nonselect')) { e.stopPropagation(); return; } // now name editing if (p.find('input:text,textarea').length) { e.stopPropagation(); e.preventDefault(); return; } wrapper.data('touching', {x: e.originalEvent.touches[0].pageX, y: e.originalEvent.touches[0].pageY}); if (selectCheckbox && (tgt.is('input:checkbox.'+clSelChk) || tgt.hasClass('elfinder-cwd-select'))) { return; } sel = p.prevAll('.'+clSelected+':first').length + p.nextAll('.'+clSelected+':first').length; cwd.data('longtap', null); if (Object.keys(selectedFiles).length || (list && e.target.nodeName !== 'TD') || (!list && this !== e.target) ) { cwd.data('longtap', false); p.addClass(clHover); p.data('tmlongtap', setTimeout(function(){ // long tap cwd.data('longtap', true); p.trigger(evtSelect); trigger(); fm.trigger('contextmenu', { 'type' : 'files', 'targets' : fm.selected(), 'x' : e.originalEvent.touches[0].pageX, 'y' : e.originalEvent.touches[0].pageY }); }, 500)); } }) .on('touchmove.'+fm.namespace+' touchend.'+fm.namespace, fileSelector, function(e) { var tgt = jQuery(e.target), p; if (selectCheckbox && (tgt.is('input:checkbox.'+clSelChk) || tgt.hasClass('elfinder-cwd-select'))) { return; } if (e.target.nodeName == 'INPUT' || e.target.nodeName == 'TEXTAREA') { e.stopPropagation(); return; } p = this.id ? jQuery(this) : jQuery(this).parents('[id]:first'); clearTimeout(p.data('tmlongtap')); if (e.type === 'touchmove') { wrapper.data('touching', null); p.removeClass(clHover); } else { if (wrapper.data('touching') && !cwd.data('longtap') && p.hasClass(clSelected)) { e.preventDefault(); wrapper.data('touching', null); fm.dblclick({file : fm.cwdId2Hash(this.id)}); } setTimeout(function() { cwd.removeData('longtap'); }, 80); } }) // attach draggable .on('mouseenter.'+fm.namespace, fileSelector, function(e) { if (scrolling) { return; } var $this = jQuery(this), helper = null; if (!mobile && !$this.data('dragRegisted') && !$this.hasClass(clTmp) && !$this.hasClass(clDraggable) && !$this.hasClass(clDisabled)) { $this.data('dragRegisted', true); if (!fm.isCommandEnabled('copy', fm.searchStatus.state > 1 || $this.hasClass('isroot')? fm.cwdId2Hash($this.attr('id')) : void 0) && !fm.isCommandEnabled('cut', fm.searchStatus.state > 1 || $this.hasClass('isroot')? fm.cwdId2Hash($this.attr('id')) : void 0)) { return; } $this.on('mousedown', function(e) { // shiftKey or altKey + drag start for HTML5 native drag function // Note: can no use shiftKey with the Google Chrome var metaKey = options.metakeyDragout && !fm.UA.IE && (e.shiftKey || e.altKey), disable = false; if (metaKey && cwd.data('selectable')) { // destroy jQuery-ui selectable while trigger native drag cwd.selectable('disable').selectable('destroy').removeData('selectable'); requestAnimationFrame(function(){ cwd.selectable(selectableOption).selectable('option', {disabled: false}).selectable('refresh').data('selectable', true); }); } $this.removeClass('ui-state-disabled'); if (metaKey) { $this.draggable('option', 'disabled', true).attr('draggable', 'true'); } else { if (!$this.hasClass(clSelected)) { if (list) { disable = jQuery(e.target).closest('span,tr').is('tr'); } else { disable = jQuery(e.target).hasClass('elfinder-cwd-file'); } } if (disable) { // removeClass('ui-state-disabled') for old version of jQueryUI $this.draggable('option', 'disabled', true).removeClass('ui-state-disabled'); } else { $this.draggable('option', 'disabled', false) .removeAttr('draggable') .draggable('option', 'cursorAt', {left: 50 - parseInt(jQuery(e.currentTarget).css('margin-left')), top: 47}); } } }) .on('dragstart', function(e) { var dt = e.dataTransfer || e.originalEvent.dataTransfer || null; helper = null; if (dt && !fm.UA.IE) { var p = this.id ? jQuery(this) : jQuery(this).parents('[id]:first'), elm = jQuery('<span>'), url = '', durl = null, murl = null, files = [], icon = function(f) { var mime = f.mime, i, tmb = fm.tmb(f); i = '<div class="elfinder-cwd-icon elfinder-cwd-icon-drag '+fm.mime2class(mime)+' ui-corner-all"></div>'; if (tmb) { i = jQuery(i).addClass(tmb.className).css('background-image', "url('"+tmb.url+"')").get(0).outerHTML; } return i; }, l, geturl = []; p.trigger(evtSelect); trigger(); jQuery.each(selectedFiles, function(v){ var file = fm.file(v), furl = file.url; if (file && file.mime !== 'directory') { if (!furl) { furl = fm.url(file.hash); } else if (furl == '1') { geturl.push(v); return true; } if (furl) { furl = fm.convAbsUrl(furl); files.push(v); jQuery('<a>').attr('href', furl).text(furl).appendTo(elm); url += furl + "\n"; if (!durl) { durl = file.mime + ':' + file.name + ':' + furl; } if (!murl) { murl = furl + "\n" + file.name; } } } }); if (geturl.length) { jQuery.each(geturl, function(i, v){ var rfile = fm.file(v); rfile.url = ''; fm.request({ data : {cmd : 'url', target : v}, notify : {type : 'url', cnt : 1}, preventDefault : true }) .always(function(data) { rfile.url = data.url? data.url : '1'; }); }); return false; } else if (url) { if (dt.setDragImage) { helper = jQuery('<div class="elfinder-drag-helper html5-native"></div>').append(icon(fm.file(files[0]))).appendTo(jQuery(document.body)); if ((l = files.length) > 1) { helper.append(icon(fm.file(files[l-1])) + '<span class="elfinder-drag-num">'+l+'</span>'); } dt.setDragImage(helper.get(0), 50, 47); } dt.effectAllowed = 'copyLink'; dt.setData('DownloadURL', durl); dt.setData('text/x-moz-url', murl); dt.setData('text/uri-list', url); dt.setData('text/plain', url); dt.setData('text/html', elm.html()); dt.setData('elfinderfrom', window.location.href + fm.cwd().hash); dt.setData('elfinderfrom:' + dt.getData('elfinderfrom'), ''); } else { return false; } } }) .on('dragend', function(e){ unselectAll({ notrigger: true }); helper && helper.remove(); }) .draggable(fm.draggable); } }) // add hover class to selected file .on(evtSelect, fileSelector, function(e) { var $this = jQuery(this), id = fm.cwdId2Hash($this.attr('id')); if (!selectLock && !$this.hasClass(clDisabled)) { lastSelect = '#'+ this.id; $this.addClass(clSelected).children().addClass(clHover).find('input:checkbox.'+clSelChk).prop('checked', true); if (! selectedFiles[id]) { selectedFiles[id] = true; } // will be selected next selectedNext = cwd.find('[id].'+clSelected+':last').next(); } }) // remove hover class from unselected file .on(evtUnselect, fileSelector, function(e) { var $this = jQuery(this), id = fm.cwdId2Hash($this.attr('id')); if (!selectLock) { $this.removeClass(clSelected).children().removeClass(clHover).find('input:checkbox.'+clSelChk).prop('checked', false); if (cwd.hasClass('elfinder-cwd-allselected')) { selectCheckbox && selectAllCheckbox.children('input').prop('checked', false); cwd.removeClass('elfinder-cwd-allselected'); } selectedFiles[id] && delete selectedFiles[id]; } }) // disable files wich removing or moving .on(evtDisable, fileSelector, function() { var $this = jQuery(this).removeClass(clHover+' '+clSelected).addClass(clDisabled), child = $this.children(), target = (list ? $this : child.find('div.elfinder-cwd-file-wrapper,div.elfinder-cwd-filename')); child.removeClass(clHover+' '+clSelected); $this.hasClass(clDroppable) && $this.droppable('disable'); target.hasClass(clDraggable) && target.draggable('disable'); }) // if any files was not removed/moved - unlock its .on(evtEnable, fileSelector, function() { var $this = jQuery(this).removeClass(clDisabled), target = list ? $this : $this.children('div.elfinder-cwd-file-wrapper,div.elfinder-cwd-filename'); $this.hasClass(clDroppable) && $this.droppable('enable'); target.hasClass(clDraggable) && target.draggable('enable'); }) .on('scrolltoview', fileSelector, function(e, data) { scrollToView(jQuery(this), (data && typeof data.blink !== 'undefined')? data.blink : true); }) .on('mouseenter.'+fm.namespace+' mouseleave.'+fm.namespace, fileSelector, function(e) { var enter = (e.type === 'mouseenter'); if (enter && (scrolling || fm.UA.Mobile)) { return; } fm.trigger('hover', {hash : fm.cwdId2Hash(jQuery(this).attr('id')), type : e.type}); jQuery(this).toggleClass(clHover, (e.type == 'mouseenter')); }) // for file contextmenu .on('mouseenter.'+fm.namespace+' mouseleave.'+fm.namespace, '.elfinder-cwd-file-wrapper,.elfinder-cwd-filename', function(e) { var enter = (e.type === 'mouseenter'); if (enter && scrolling) { return; } jQuery(this).closest(fileSelector).children('.elfinder-cwd-file-wrapper,.elfinder-cwd-filename').toggleClass(clActive, (e.type == 'mouseenter')); }) .on('contextmenu.'+fm.namespace, function(e) { var file = jQuery(e.target).closest(fileSelector); if (file.get(0) === e.target && !selectedFiles[fm.cwdId2Hash(file.get(0).id)]) { return; } // now filename editing if (file.find('input:text,textarea').length) { e.stopPropagation(); return; } if (file.length && (e.target.nodeName != 'TD' || selectedFiles[fm.cwdId2Hash(file.get(0).id)])) { e.stopPropagation(); e.preventDefault(); if (!file.hasClass(clDisabled) && !wrapper.data('touching')) { if (!file.hasClass(clSelected)) { unselectAll({ notrigger: true }); file.trigger(evtSelect); trigger(); } fm.trigger('contextmenu', { 'type' : 'files', 'targets' : fm.selected(), 'x' : e.pageX, 'y' : e.pageY }); } } }) // unselect all on cwd click .on('click.'+fm.namespace, function(e) { if (e.target === this && ! cwd.data('longtap')) { !e.shiftKey && !e.ctrlKey && !e.metaKey && unselectAll(); } }) // prepend fake file/dir .on('create.'+fm.namespace, function(e, f) { var parent = list ? cwd.find('tbody') : cwd, p = parent.find('.elfinder-cwd-parent'), lock = f.move || false, file = jQuery(itemhtml(f)).addClass(clTmp), selected = fm.selected(); if (selected.length) { lock && fm.trigger('lockfiles', {files: selected}); } else { unselectAll(); } if (p.length) { p.after(file); } else { parent.prepend(file); } setColwidth(); wrapper.scrollTop(0).scrollLeft(0); }) // unselect all selected files .on('unselectall', unselectAll) .on('selectfile', function(e, id) { fm.cwdHash2Elm(id).trigger(evtSelect); trigger(); }) .on('colwidth', function() { if (list) { cwd.find('table').css('table-layout', '') .find('td').css('width', ''); fixTableHeader({fitWidth: true}); fm.storage('cwdColWidth', colWidth = null); } }) .on('iconpref', function(e, data) { cwd.removeClass(function(i, cName) { return (cName.match(/\belfinder-cwd-size\S+/g) || []).join(' '); }); iconSize = data? (parseInt(data.size) || 0) : 0; if (!list) { if (iconSize > 0) { cwd.addClass('elfinder-cwd-size' + iconSize); } if (bufferExt.renderd) { requestAnimationFrame(function() { itemBoxSize.icons = {}; bufferExt.hpi = null; bottomMarkerShow(cwd, bufferExt.renderd); wrapperRepaint(); }); } } }) // Change icon size with mouse wheel event .on('onwheel' in document ? 'wheel' : 'mousewheel', function(e) { var tm, size, delta; if (!list && ((e.ctrlKey && !e.metaKey) || (!e.ctrlKey && e.metaKey))) { e.stopPropagation(); e.preventDefault(); tm = cwd.data('wheelTm'); if (typeof tm !== 'undefined') { clearTimeout(tm); cwd.data('wheelTm', setTimeout(function() { cwd.removeData('wheelTm'); }, 200)); } else { cwd.data('wheelTm', false); size = iconSize || 0; delta = e.originalEvent.deltaY ? e.originalEvent.deltaY : -(e.originalEvent.wheelDelta); if (delta > 0) { if (iconSize > 0) { size = iconSize - 1; } } else { if (iconSize < options.iconsView.sizeMax) { size = iconSize + 1; } } if (size !== iconSize) { fm.storage('iconsize', size); cwd.trigger('iconpref', {size: size}); } } } }), wrapper = jQuery('<div class="elfinder-cwd-wrapper"></div>') // make cwd itself droppable for folders from nav panel .droppable(Object.assign({}, droppable, {autoDisable: false})) .on('contextmenu.'+fm.namespace, wrapperContextMenu.contextmenu) .on('touchstart.'+fm.namespace, wrapperContextMenu.touchstart) .on('touchmove.'+fm.namespace+' touchend.'+fm.namespace, wrapperContextMenu.touchend) .on('click.'+fm.namespace, wrapperContextMenu.click) .on('scroll.'+fm.namespace, function() { if (! scrolling) { cwd.data('selectable') && cwd.selectable('disable'); wrapper.trigger(scrollStartEvent); } scrolling = true; bufferExt.scrtm && cancelAnimationFrame(bufferExt.scrtm); if (bufferExt.scrtm && Math.abs((bufferExt.scrolltop || 0) - (bufferExt.scrolltop = (this.scrollTop || jQuery(this).scrollTop()))) < 5) { bufferExt.scrtm = 0; wrapper.trigger(scrollEvent); } bufferExt.scrtm = requestAnimationFrame(function() { bufferExt.scrtm = 0; wrapper.trigger(scrollEvent); }); }) .on(scrollEvent, function() { scrolling = false; wrapperRepaint(); }), bottomMarker = jQuery('<div> </div>') .css({position: 'absolute', width: '1px', height: '1px'}) .hide(), selectAllCheckbox = selectCheckbox? jQuery('<div class="elfinder-cwd-selectall"><input type="checkbox"/></div>') .attr('title', fm.i18n('selectall')) .on('click', function(e) { e.stopPropagation(); e.preventDefault(); if (jQuery(this).data('pending')) { return false; } selectAllCheckbox.data('pending', true); if (cwd.hasClass('elfinder-cwd-allselected')) { selectAllCheckbox.find('input').prop('checked', false); requestAnimationFrame(function() { unselectAll(); }); } else { selectAll(); } }) : jQuery(), restm = null, resize = function(init) { var initHeight = function() { if (typeof bufferExt.renderd !== 'undefined') { var h = 0; wrapper.siblings('div.elfinder-panel:visible').each(function() { h += jQuery(this).outerHeight(true); }); wrapper.height(wz.height() - h - wrapper._padding); } }; init && initHeight(); restm && cancelAnimationFrame(restm); restm = requestAnimationFrame(function(){ !init && initHeight(); var wph, cwdoh; // fix cwd height if it less then wrapper cwd.css('height', 'auto'); wph = wrapper[0].clientHeight - parseInt(wrapper.css('padding-top')) - parseInt(wrapper.css('padding-bottom')) - parseInt(cwd.css('margin-top')), cwdoh = cwd.outerHeight(true); if (cwdoh < wph) { cwd.height(wph); } }); list && ! colResizing && (init? wrapper.trigger('resize.fixheader') : fixTableHeader()); wrapperRepaint(); }, // elfinder node parent = jQuery(this).parent().on('resize', resize), // workzone node wz = parent.children('.elfinder-workzone').append(wrapper.append(this).append(bottomMarker)), // message board mBoard = jQuery('<div class="elfinder-cwd-message-board"></div>').insertAfter(cwd), // Volume expires vExpires = jQuery('<div class="elfinder-cwd-expires" ></div>'), vExpiresTm, showVolumeExpires = function() { var remain, sec, int; vExpiresTm && clearTimeout(vExpiresTm); if (curVolId && fm.volumeExpires[curVolId]) { sec = fm.volumeExpires[curVolId] - ((+new Date()) / 1000); int = (sec % 60) + 0.1; remain = Math.floor(sec / 60); vExpires.html(fm.i18n(['minsLeft', remain])).show(); if (remain) { vExpiresTm = setTimeout(showVolumeExpires, int * 1000); } } }, // each item box size itemBoxSize = { icons : {}, list : {} }, // has UI tree hasUiTree, // Icon size of icons view iconSize, // Current volume id curVolId, winScrTm; // IE < 11 not support CSS `pointer-events: none` if (!fm.UA.ltIE10) { mBoard.append(jQuery('<div class="elfinder-cwd-trash" ></div>').html(fm.i18n('volume_Trash'))) .append(vExpires); } // setup by options replacement = Object.assign(replacement, options.replacement || {}); try { colWidth = fm.storage('cwdColWidth')? fm.storage('cwdColWidth') : null; } catch(e) { colWidth = null; } // setup costomCols fm.bind('columnpref', function(e) { var opts = e.data || {}; if (customCols = fm.storage('cwdCols')) { customCols = jQuery.grep(customCols, function(n) { return (options.listView.columns.indexOf(n) !== -1)? true : false; }); if (options.listView.columns.length > customCols.length) { jQuery.each(options.listView.columns, function(i, n) { if (customCols.indexOf(n) === -1) { customCols.push(n); } }); } } else { customCols = options.listView.columns; } // column names array that hidden var columnhides = fm.storage('columnhides') || null; if (columnhides && Object.keys(columnhides).length) customCols = jQuery.grep(customCols, function(n) { return columnhides[n]? false : true; }); // make template with customCols templates.row = makeTemplateRow(); // repaint if need it list && opts.repaint && content(); }).trigger('columnpref'); if (mobile) { // for iOS5 bug jQuery('body').on('touchstart touchmove touchend', function(e){}); } selectCheckbox && cwd.addClass('elfinder-has-checkbox'); jQuery(window).on('scroll.'+fm.namespace, function() { winScrTm && cancelAnimationFrame(winScrTm); winScrTm = requestAnimationFrame(function() { wrapper.trigger(scrollEvent); }); }); jQuery(document).on('keydown.'+fm.namespace, function(e) { if (e.keyCode == jQuery.ui.keyCode.ESCAPE) { if (! fm.getUI().find('.ui-widget:visible').length) { unselectAll(); } } }); fm .one('init', function(){ var style = document.createElement('style'), sheet, node, base, resizeTm, iconSize, i = 0; if (document.head) { document.head.appendChild(style); sheet = style.sheet; sheet.insertRule('.elfinder-cwd-wrapper-empty .elfinder-cwd:not(.elfinder-table-header-sticky):after{ content:"'+fm.i18n('emptyFolder')+'" }', i++); sheet.insertRule('.elfinder-cwd-wrapper-empty .native-droppable .elfinder-cwd:not(.elfinder-table-header-sticky):after{ content:"'+fm.i18n('emptyFolder'+(mobile? 'LTap' : 'Drop'))+'" }', i++); sheet.insertRule('.elfinder-cwd-wrapper-empty .ui-droppable-disabled .elfinder-cwd:not(.elfinder-table-header-sticky):after{ content:"'+fm.i18n('emptyFolder')+'" }', i++); sheet.insertRule('.elfinder-cwd-wrapper-empty.elfinder-search-result .elfinder-cwd:not(.elfinder-table-header-sticky):after{ content:"'+fm.i18n('emptySearch')+'" }', i++); sheet.insertRule('.elfinder-cwd-wrapper-empty.elfinder-search-result.elfinder-incsearch-result .elfinder-cwd:not(.elfinder-table-header-sticky):after{ content:"'+fm.i18n('emptyIncSearch')+'" }', i++); sheet.insertRule('.elfinder-cwd-wrapper-empty.elfinder-search-result.elfinder-letsearch-result .elfinder-cwd:not(.elfinder-table-header-sticky):after{ content:"'+fm.i18n('emptyLetSearch')+'" }', i++); } if (iconSize = (fm.storage('iconsize') || options.iconsView.size || 0)) { iconSize = Math.min(iconSize, options.iconsView.sizeMax); cwd.trigger('iconpref', {size: iconSize}); } if (! mobile) { fm.one('open', function() { sheet && fm.zIndex && sheet.insertRule('.ui-selectable-helper{z-index:'+fm.zIndex+';}', i++); }); base = jQuery('<div style="position:absolute"></div>'); node = fm.getUI(); node.on('resize', function(e, data) { var offset; e.preventDefault(); e.stopPropagation(); if (data && data.fullscreen) { offset = node.offset(); if (data.fullscreen === 'on') { base.css({top:offset.top * -1 , left:offset.left * -1 }).appendTo(node); selectableOption.appendTo = base; } else { base.detach(); selectableOption.appendTo = 'body'; } cwd.data('selectable') && cwd.selectable('option', {appendTo : selectableOption.appendTo}); } }); } hasUiTree = fm.getUI('tree').length; }) .bind('enable', function() { resize(); }) .bind('request.open', function() { bufferExt.getTmbs = []; }) .one('open', function() { if (fm.maxTargets) { tmbNum = Math.min(fm.maxTargets, tmbNum); } }) .bind('open add remove searchend', function() { var phash = fm.cwd().hash, type = this.type; if (type === 'open' || type === 'searchend' || fm.searchStatus.state < 2) { cwdHashes = jQuery.map(fm.files(phash), function(f) { return f.hash; }); fm.trigger('cwdhasheschange', cwdHashes); } if (type === 'open') { var inTrash = function() { var isIn = false; jQuery.each(cwdParents, function(i, h) { if (fm.trashes[h]) { isIn = true; return false; } }); return isIn; }, req = phash? (! fm.file(phash) || hasUiTree? (! hasUiTree? fm.request({ data: { cmd : 'parents', target : fm.cwd().hash }, preventFail : true }) : (function() { var dfd = jQuery.Deferred(); fm.one('treesync', function(e) { e.data.always(function() { dfd.resolve(); }); }); return dfd; })() ) : null ) : null, cwdObj = fm.cwd(); // add/remove volume id class if (cwdObj.volumeid !== curVolId) { vExpires.empty().hide(); if (curVolId) { wrapper.removeClass('elfinder-cwd-wrapper-' + curVolId); } curVolId = cwdObj.volumeid; showVolumeExpires(); wrapper.addClass('elfinder-cwd-wrapper-' + curVolId); } // add/remove trash class jQuery.when(req).done(function() { cwdParents = fm.parents(cwdObj.hash); wrapper[inTrash()? 'addClass':'removeClass']('elfinder-cwd-wrapper-trash'); }); incHashes = void 0; unselectAll({ notrigger: true }); content(); } }) .bind('search', function(e) { cwdHashes = jQuery.map(e.data.files, function(f) { return f.hash; }); fm.trigger('cwdhasheschange', cwdHashes); incHashes = void 0; fm.searchStatus.ininc = false; content(); fm.autoSync('stop'); }) .bind('searchend', function(e) { if (query || incHashes) { query = ''; if (incHashes) { fm.trigger('incsearchend', e.data); } else { if (!e.data || !e.data.noupdate) { content(); } } } fm.autoSync(); }) .bind('searchstart', function(e) { unselectAll(); query = e.data.query; }) .bind('incsearchstart', function(e) { var q = e.data.query || '', type = e.data.type || 'SearchName', searchTypes = fm.options.commandsOptions.search.searchTypes || {}; if ((searchTypes[type] && searchTypes[type].incsearch) || type === 'SearchName') { selectedFiles = {}; fm.lazy(function() { // incremental search var regex, incSearch, fst = ''; query = q; if (q) { if (q.substr(0,1) === '/') { q = q.substr(1); fst = '^'; } regex = new RegExp(fst + q.replace(/([\\*\;\.\?\[\]\{\}\(\)\^\$\-\|])/g, '\\$1'), 'i'); if (type === 'SearchName') { incHashes = jQuery.grep(cwdHashes, function(hash) { var file = fm.file(hash); return (file && (file.name.match(regex) || (file.i18 && file.i18.match(regex))))? true : false; }); } else { incSearch = searchTypes[type].incsearch; if (typeof incSearch === 'string') { incHashes = jQuery.grep(cwdHashes, function(hash) { var file = fm.file(hash); return (file && file[incSearch] && (file[incSearch] + '').match(regex))? true : false; }); } else if (typeof incSearch === 'function') { try { incHashes = jQuery.grep(incSearch({val: q, regex: regex}, cwdHashes, fm), function(hash) { return fm.file(hash)? true : false; }); } catch(e) { incHashes = []; } } } fm.trigger('incsearch', { hashes: incHashes, query: q }) .searchStatus.ininc = true; content(); fm.autoSync('stop'); } else { fm.trigger('incsearchend'); } }); } }) .bind('incsearchend', function(e) { query = ''; fm.searchStatus.ininc = false; incHashes = void 0; if (!e.data || !e.data.noupdate) { content(); } fm.autoSync(); }) .bind('sortchange', function() { var lastScrollLeft = wrapper.scrollLeft(), allsel = cwd.hasClass('elfinder-cwd-allselected'); content(); fm.one('cwdrender', function() { wrapper.scrollLeft(lastScrollLeft); if (allsel) { selectedFiles = fm.arrayFlip(incHashes || cwdHashes, true); } (allsel || Object.keys(selectedFiles).length) && trigger(); }); }) .bind('viewchange', function() { var l = fm.viewType != 'list', allsel = cwd.hasClass('elfinder-cwd-allselected'); if (l != list) { list = l; fm.viewType = list? 'list' : 'icons'; if (iconSize) { fm.one('cwdinit', function() { cwd.trigger('iconpref', {size: iconSize}); }); } content(); resize(); if (allsel) { cwd.addClass('elfinder-cwd-allselected'); selectAllCheckbox.find('input').prop('checked', true); } Object.keys(selectedFiles).length && trigger(); } }) .bind('wzresize', function() { var place = list ? cwd.find('tbody') : cwd, cwdOffset; resize(true); if (bufferExt.hpi) { bottomMarkerShow(place, place.find('[id]').length); } cwdOffset = cwd.offset(); wz.data('rectangle', Object.assign( { width: wz.width(), height: wz.height(), cwdEdge: (fm.direction === 'ltr')? cwdOffset.left : cwdOffset.left + cwd.width() }, wz.offset()) ); bufferExt.itemH = (list? place.find('tr:first') : place.find('[id]:first')).outerHeight(true); }) .bind('changeclipboard', function(e) { clipCuts = {}; if (e.data && e.data.clipboard && e.data.clipboard.length) { jQuery.each(e.data.clipboard, function(i, f) { if (f.cut) { clipCuts[f.hash] = true; } }); } }) .bind('resMixinMake', function() { setColwidth(); }) .bind('tmbreload', function(e) { var imgs = {}, files = (e.data && e.data.files)? e.data.files : null; jQuery.each(files, function(i, f) { if (f.tmb && f.tmb != '1') { imgs[f.hash] = f.tmb; } }); if (Object.keys(imgs).length) { attachThumbnails(imgs, true); } }) .add(function(e) { var regex = query? new RegExp(query.replace(/([\\*\;\.\?\[\]\{\}\(\)\^\$\-\|])/g, '\\$1'), 'i') : null, mime = fm.searchStatus.mime, inSearch = fm.searchStatus.state > 1, phash = inSearch && fm.searchStatus.target? fm.searchStatus.target : fm.cwd().hash, curPath = fm.path(phash), inTarget = function(f) { var res, parents, path; res = (f.phash === phash); if (!res && inSearch) { path = f.path || fm.path(f.hash); res = (curPath && path.indexOf(curPath) === 0); if (! res && fm.searchStatus.mixed) { res = jQuery.grep(fm.searchStatus.mixed, function(vid) { return f.hash.indexOf(vid) === 0? true : false; }).length? true : false; } } if (res && inSearch) { if (mime) { res = (f.mime.indexOf(mime) === 0); } else { res = (f.name.match(regex) || (f.i18 && f.i18.match(regex)))? true : false; } } return res; }, files = jQuery.grep(e.data.added || [], function(f) { return inTarget(f)? true : false ;}); add(files); if (fm.searchStatus.state === 2) { jQuery.each(files, function(i, f) { if (jQuery.inArray(f.hash, cwdHashes) === -1) { cwdHashes.push(f.hash); } }); fm.trigger('cwdhasheschange', cwdHashes); } list && resize(); wrapper.trigger(scrollEvent); }) .change(function(e) { var phash = fm.cwd().hash, sel = fm.selected(), files, added; if (query) { jQuery.each(e.data.changed || [], function(i, file) { if (fm.cwdHash2Elm(file.hash).length) { remove([file.hash]); add([file], 'change'); jQuery.inArray(file.hash, sel) !== -1 && selectFile(file.hash); added = true; } }); } else { jQuery.each(jQuery.grep(e.data.changed || [], function(f) { return f.phash == phash ? true : false; }), function(i, file) { if (fm.cwdHash2Elm(file.hash).length) { remove([file.hash]); add([file], 'change'); jQuery.inArray(file.hash, sel) !== -1 && selectFile(file.hash); added = true; } }); } if (added) { fm.trigger('cwdhasheschange', cwdHashes); list && resize(); wrapper.trigger(scrollEvent); } trigger(); }) .remove(function(e) { var place = list ? cwd.find('tbody') : cwd; remove(e.data.removed || []); trigger(); if (buffer.length < 1 && place.children(fileSelector + (options.oldSchool? ':not(.elfinder-cwd-parent)' : '')).length < 1) { wz.addClass('elfinder-cwd-wrapper-empty'); selectCheckbox && selectAllCheckbox.find('input').prop('checked', false); bottomMarker.hide(); wrapper.off(scrollEvent, render); resize(); } else { bottomMarkerShow(place); wrapper.trigger(scrollEvent); } }) // select dragged file if no selected, disable selectable .dragstart(function(e) { var target = jQuery(e.data.target), oe = e.data.originalEvent; if (target.hasClass(clFile)) { if (!target.hasClass(clSelected)) { !(oe.ctrlKey || oe.metaKey || oe.shiftKey) && unselectAll({ notrigger: true }); target.trigger(evtSelect); trigger(); } } cwd.removeClass(clDisabled).data('selectable') && cwd.selectable('disable'); selectLock = true; }) // enable selectable .dragstop(function() { cwd.data('selectable') && cwd.selectable('enable'); selectLock = false; }) .bind('lockfiles unlockfiles selectfiles unselectfiles', function(e) { var events = { lockfiles : evtDisable , unlockfiles : evtEnable , selectfiles : evtSelect, unselectfiles : evtUnselect }, event = events[e.type], files = e.data.files || [], l = files.length, helper = e.data.helper || jQuery(), parents, ctr, add; if (l > 0) { parents = fm.parents(files[0]); } if (event === evtSelect || event === evtUnselect) { add = (event === evtSelect), jQuery.each(files, function(i, hash) { var all = cwd.hasClass('elfinder-cwd-allselected'); if (! selectedFiles[hash]) { add && (selectedFiles[hash] = true); } else { if (all) { selectCheckbox && selectAllCheckbox.children('input').prop('checked', false); cwd.removeClass('elfinder-cwd-allselected'); all = false; } ! add && delete selectedFiles[hash]; } }); } if (!helper.data('locked')) { while (l--) { try { fm.cwdHash2Elm(files[l]).trigger(event); } catch(e) {} } ! e.data.inselect && trigger(); } if (wrapper.data('dropover') && parents.indexOf(wrapper.data('dropover')) !== -1) { ctr = e.type !== 'lockfiles'; helper.toggleClass('elfinder-drag-helper-plus', ctr); wrapper.toggleClass(clDropActive, ctr); } }) // select new files after some actions .bind('mkdir mkfile duplicate upload rename archive extract paste multiupload', function(e) { if (e.type == 'upload' && e.data._multiupload) return; var phash = fm.cwd().hash, files; unselectAll({ notrigger: true }); jQuery.each((e.data.added || []).concat(e.data.changed || []), function(i, file) { file && file.phash == phash && selectFile(file.hash); }); trigger(); }) .shortcut({ pattern :'ctrl+a', description : 'selectall', callback : selectAll }) .shortcut({ pattern :'ctrl+shift+i', description : 'selectinvert', callback : selectInvert }) .shortcut({ pattern : 'left right up down shift+left shift+right shift+up shift+down', description : 'selectfiles', type : 'keydown' , //fm.UA.Firefox || fm.UA.Opera ? 'keypress' : 'keydown', callback : function(e) { select(e.keyCode, e.shiftKey); } }) .shortcut({ pattern : 'home', description : 'selectffile', callback : function(e) { unselectAll({ notrigger: true }); scrollToView(cwd.find('[id]:first').trigger(evtSelect)); trigger(); } }) .shortcut({ pattern : 'end', description : 'selectlfile', callback : function(e) { unselectAll({ notrigger: true }); scrollToView(cwd.find('[id]:last').trigger(evtSelect)) ; trigger(); } }) .shortcut({ pattern : 'page_up', description : 'pageTurning', callback : function(e) { if (bufferExt.itemH) { wrapper.scrollTop( Math.round( wrapper.scrollTop() - (Math.floor((wrapper.height() + (list? bufferExt.itemH * -1 : 16)) / bufferExt.itemH)) * bufferExt.itemH ) ); } } }).shortcut({ pattern : 'page_down', description : 'pageTurning', callback : function(e) { if (bufferExt.itemH) { wrapper.scrollTop( Math.round( wrapper.scrollTop() + (Math.floor((wrapper.height() + (list? bufferExt.itemH * -1 : 16)) / bufferExt.itemH)) * bufferExt.itemH ) ); } } }); }); // fm.timeEnd('cwdLoad') return this; };