{"version":3,"sources":["jsdelivr-header.js","/npm/js-fileexplorer@1.0.0/file-explorer/file-explorer.js"],"names":[],"mappings":"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","file":"/npm/js-fileexplorer@1.0.0/file-explorer/file-explorer.js/+esm","sourceRoot":"","sourcesContent":["/**\n * Bundled by jsDelivr using Rollup v2.79.2 and Terser v5.39.0.\n * Original file: /npm/js-fileexplorer@1.0.0/file-explorer/file-explorer.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","// Folder and File Explorer.  A pure, zero-dependencies Javascript widget.\n// (C) 2020 CubicleSoft.  All Rights Reserved.\n\n(function() {\n\t// Prevent multiple instances.\n\tif (window.hasOwnProperty('FileExplorer'))  return;\n\n\tvar EscapeHTML = function(text) {\n\t\tvar map = {\n\t\t\t'&': '&amp;',\n\t\t\t'<': '&lt;',\n\t\t\t'>': '&gt;',\n\t\t\t'\"': '&quot;',\n\t\t\t\"'\": '&#039;'\n\t\t};\n\n\t\treturn text.replace(/[&<>\"']/g, function(m) { return map[m]; });\n\t}\n\n\tvar FormatStr = function(format) {\n\t\tvar args = Array.prototype.slice.call(arguments, 1);\n\n\t\treturn format.replace(/{(\\d+)}/g, function(match, number) {\n\t\t\treturn (typeof args[number] != 'undefined' ? args[number] : match);\n\t\t});\n\t};\n\n\tvar GetDisplayFilesize = function(numbytes, adjustprecision, units) {\n\t\tif (numbytes == 0)  return '0 Bytes';\n\t\tif (numbytes == 1)  return '1 Byte';\n\n\t\tnumbytes = Math.abs(numbytes);\n\t\tvar magnitude, abbreviations;\n\t\tif (units && units.toLowerCase() === 'iec_formal')\n\t\t{\n\t\t\tmagnitude = Math.pow(2, 10);\n\t\t\tabbreviations = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];\n\t\t}\n\t\telse if (units && units.toLowerCase() === 'si')\n\t\t{\n\t\t\tmagnitude = Math.pow(10, 3);\n\t\t\tabbreviations = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tmagnitude = Math.pow(2, 10);\n\t\t\tabbreviations = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n\t\t}\n\n\t\tvar pos = Math.floor(Math.log(numbytes) / Math.log(magnitude));\n\t\tvar result = (numbytes / Math.pow(magnitude, pos));\n\n\t\treturn (pos == 0 || (adjustprecision && result >= 99.995) ? result.toFixed(0) : result.toFixed(2)) + ' ' + abbreviations[pos];\n\t};\n\n\tvar CreateNode = function(tag, classes, attrs, styles) {\n\t\tvar elem = document.createElement(tag);\n\n\t\tif (classes)\n\t\t{\n\t\t\tif (typeof classes === 'string')  elem.className = classes;\n\t\t\telse  elem.className = classes.join(' ');\n\t\t}\n\n\t\tif (attrs)  Object.assign(elem, attrs);\n\n\t\tif (styles)  Object.assign(elem.style, styles);\n\n\t\treturn elem;\n\t};\n\n\tvar DebounceAttributes = function(options) {\n\t\tif (!(this instanceof DebounceAttributes))  return new DebounceAttributes(options);\n\n\t\tvar intervaltimer = null, numsame;\n\t\tvar $this = this;\n\n\t\tvar defaults = {\n\t\t\twatchers: [],\n\t\t\tinterval: 50,\n\t\t\tstopsame: 1,\n\n\t\t\tcallback: null,\n\t\t\tintervalcallback: null\n\t\t};\n\n\t\t$this.settings = Object.assign({}, defaults, options);\n\n\t\tvar MainIntervalHandler = function() {\n\t\t\tvar nummatches = 0;\n\n\t\t\tfor (var x = 0; x < $this.settings.watchers.length; x++)\n\t\t\t{\n\t\t\t\tvar watcher = $this.settings.watchers[x];\n\n\t\t\t\tif (watcher.val === watcher.elem[watcher.attr])  nummatches++;\n\t\t\t\telse  watcher.val = watcher.elem[watcher.attr];\n\t\t\t}\n\n\t\t\tif (nummatches < $this.settings.watchers.length)\n\t\t\t{\n\t\t\t\tnumsame = 0;\n\n\t\t\t\tif ($this.settings.intervalcallback)  $this.settings.intervalcallback.call($this);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tnumsame++;\n\n\t\t\t\tif (numsame >= $this.settings.stopsame)\n\t\t\t\t{\n\t\t\t\t\t$this.Stop();\n\n\t\t\t\t\tif ($this.settings.intervalcallback)  $this.settings.intervalcallback.call($this);\n\n\t\t\t\t\tif ($this.settings.callback)  $this.settings.callback.call($this);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\n\t\t// Public functions.\n\n\t\t$this.Start = function() {\n\t\t\tif (!intervaltimer)\n\t\t\t{\n\t\t\t\tnumsame = 0;\n\n\t\t\t\tintervaltimer = setInterval(MainIntervalHandler, $this.settings.interval);\n\t\t\t}\n\t\t};\n\n\t\t$this.Stop = function() {\n\t\t\tif (intervaltimer)\n\t\t\t{\n\t\t\t\tclearInterval(intervaltimer);\n\n\t\t\t\tintervaltimer = null;\n\t\t\t}\n\t\t};\n\n\t\t$this.Destroy = function() {\n\t\t\t$this.Stop();\n\n\t\t\t$this = null;\n\t\t}\n\t};\n\n\tfunction GetScrollLineHeight() {\n\t\tvar iframe = document.createElement('iframe');\n\t\tiframe.src = '#';\n\t\tdocument.body.appendChild(iframe);\n\t\tvar iwin = iframe.contentWindow;\n\t\tvar idoc = iwin.document;\n\t\tidoc.open();\n\t\tidoc.write('<!DOCTYPE html><html><head></head><body><span>a</span></body></html>');\n\t\tidoc.close();\n\t\tvar span = idoc.body.firstElementChild;\n\t\tvar r = span.offsetHeight;\n\t\tdocument.body.removeChild(iframe);\n\n\t\treturn r;\n\t}\n\n\tvar scrolllineheight = GetScrollLineHeight();\n\n\t// Clean up history stack.\n\tvar capturingrefs = 0, prevscrollrestore;\n\tfunction HistoryPopStateHandler(e) {\n\t\tif (!capturingrefs)\n\t\t{\n\t\t\tif (e.state && e.state._fileexplorer)\n\t\t\t{\n\t\t\t\tvar prevscrollstatecopy = e.state._fileexplorerprevscroll;\n\n\t\t\t\twindow.history.back();\n\n\t\t\t\tif (prevscrollstatecopy)  prevscrollrestore = prevscrollstatecopy;\n\t\t\t}\n\t\t\telse if (prevscrollrestore)\n\t\t\t{\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\twindow.history.scrollRestoration = prevscrollrestore;\n\n\t\t\t\t\tprevscrollrestore = null;\n\t\t\t\t}, 20);\n\t\t\t}\n\t\t}\n\t}\n\n\twindow.addEventListener('popstate', HistoryPopStateHandler, true);\n\n\tif (window.history.state && window.history.state._fileexplorer)\n\t{\n\t\tvar prevscrollstatecopy = window.history.state._fileexplorerprevscroll;\n\n\t\twindow.history.back();\n\n\t\tif (prevscrollstatecopy)  prevscrollrestore = prevscrollstatecopy;\n\t}\n\n\t// Extracts and returns global drag group icon data for drag-and-drop operations.\n\tfunction GetFileExplorerDragIconData(e, group) {\n\t\tif (!e.dataTransfer)  return false;\n\n\t\tfor (var x = 0; x < e.dataTransfer.types.length; x++)\n\t\t{\n\t\t\tif (e.dataTransfer.types[x].startsWith('application/file-explorer-icon;'))\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tvar icondata = JSON.parse(e.dataTransfer.types[x].substring(31));\n\n\t\t\t\t\treturn (!group || group === icondata.group ? icondata : false);\n\t\t\t\t}\n\t\t\t\tcatch (e)\n\t\t\t\t{\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t// Creates a custom overlay that tracks with the position when entering the window.\n\tvar fe_numdragenters = 0, fe_dragiconoverlay, fe_dragiconoverlaypos = {};\n\tfunction OverlayDragEnterHandler(e) {\n\t\tif (!fe_numdragenters)\n\t\t{\n\t\t\tvar icondata = GetFileExplorerDragIconData(e);\n\n\t\t\tif (icondata !== false)\n\t\t\t{\n\t\t\t\t// Create the floating icon tracking overlay.\n\t\t\t\tfe_dragiconoverlay = CreateNode('div', ['fe_fileexplorer_floating_drag_icon_wrap']);\n\t\t\t\tvar innernode = CreateNode('div', ['fe_fileexplorer_floating_drag_icon_wrap_inner']);\n\t\t\t\tvar iconnode = CreateNode('div', ['fe_fileexplorer_item_icon']);\n\n\t\t\t\tif (icondata.numitems > 1)  innernode.dataset.numitems = icondata.numitems;\n\n\t\t\t\ticonnode.classList.add('fe_fileexplorer_item_icon_' + icondata.type);\n\n\t\t\t\tinnernode.appendChild(iconnode);\n\t\t\t\tfe_dragiconoverlay.appendChild(innernode);\n\t\t\t\tdocument.body.appendChild(fe_dragiconoverlay);\n\n\t\t\t\tfe_dragiconoverlaypos = {\n\t\t\t\t\tlastx: -9999,\n\t\t\t\t\tlasty: 0,\n\t\t\t\t\txdiff: Math.floor(fe_dragiconoverlay.offsetWidth / 2),\n\t\t\t\t\tydiff: Math.floor(fe_dragiconoverlay.offsetHeight - 8)\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tfe_numdragenters++;\n\t}\n\n\t// Moves the overlay to the drag position.\n\tfunction OverlayDragOverHandler(e) {\n\t\tif (fe_dragiconoverlay && (fe_dragiconoverlaypos.lastx !== e.clientX || fe_dragiconoverlaypos.lasty !== e.clientY))\n\t\t{\n\t\t\tfe_dragiconoverlaypos.lastx = e.clientX;\n\t\t\tfe_dragiconoverlaypos.lasty = e.clientY;\n\n\t\t\t// Update the overlay position.\n\t\t\tfe_dragiconoverlay.style.left = (e.clientX - fe_dragiconoverlaypos.xdiff) + 'px';\n\t\t\tfe_dragiconoverlay.style.top = (e.clientY - fe_dragiconoverlaypos.ydiff) + 'px';\n\t\t}\n\t}\n\n\t// Removes the custom overlay when leaving the window.\n\tfunction OverlayDragLeaveHandler(e) {\n\t\tfe_numdragenters--;\n\n\t\tif (fe_numdragenters < 1)\n\t\t{\n\t\t\tfe_numdragenters = 0;\n\n\t\t\tif (fe_dragiconoverlay)\n\t\t\t{\n\t\t\t\tfe_dragiconoverlay.parentNode.removeChild(fe_dragiconoverlay);\n\t\t\t\tfe_dragiconoverlay = null;\n\t\t\t}\n\n\t\t\tfe_dragiconoverlaypos = {};\n\t\t}\n\t}\n\n\twindow.addEventListener('dragenter', OverlayDragEnterHandler, true);\n\twindow.addEventListener('dragover', OverlayDragOverHandler, true);\n\twindow.addEventListener('dragleave', OverlayDragLeaveHandler, true);\n\twindow.addEventListener('drop', OverlayDragLeaveHandler, true);\n\n\n\t// Basic XMLHttpRequest (XHR) wrapper.\n\tvar PrepareXHR = function(options) {\n\t\tif (!(this instanceof PrepareXHR))  return new PrepareXHR(options);\n\n\t\tvar sent = false;\n\t\tvar $this = this;\n\n\t\t$this.xhr = new XMLHttpRequest();\n\n\t\tvar RequestEndedHandler = function(e) {\n\t\t\tif ($this)  $this.xhr = null;\n\t\t};\n\n\t\t$this.xhr.addEventListener('loadend', RequestEndedHandler);\n\n\t\tif (options.onsuccess || options.onload)  $this.xhr.addEventListener('load', options.onsuccess || options.onload);\n\t\tif (options.onerror)\n\t\t{\n\t\t\t$this.xhr.addEventListener('error', options.onerror);\n\n\t\t\tif (!options.onabort)  $this.xhr.addEventListener('abort', options.onerror);\n\t\t\tif (!options.ontimeout)  $this.xhr.addEventListener('timeout', options.onerror);\n\t\t}\n\t\tif (options.onabort)  $this.xhr.addEventListener('abort', options.onabort);\n\t\tif (options.onloadstart)  $this.xhr.addEventListener('loadstart', options.onloadstart);\n\t\tif (options.onprogress)  $this.xhr.addEventListener('progress', options.onprogress);\n\t\tif (options.ontimeout)  $this.xhr.addEventListener('timeout', options.ontimeout);\n\t\tif (options.onloadend)  $this.xhr.addEventListener('loadend', options.onloadend);\n\n\n\t\t// Public functions.\n\n\t\t// Transparently route event listener registration/removals.\n\t\t$this.upload = {};\n\t\t$this.upload.addEventListener = function(type, listener, options) {\n\t\t\tif (!sent && $this && $this.xhr)  $this.xhr.upload.addEventListener(type, listener, options);\n\t\t};\n\n\t\t$this.upload.removeEventListener = function(type, listener, options) {\n\t\t\tif ($this && $this.xhr)  $this.xhr.upload.removeEventListener(type, listener, options);\n\t\t};\n\n\t\t$this.addEventListener = function(type, listener, options) {\n\t\t\tif (!sent && $this && $this.xhr)  $this.xhr.addEventListener(type, listener, options);\n\t\t};\n\n\t\t$this.removeEventListener = function(type, listener, options) {\n\t\t\tif ($this && $this.xhr)  $this.xhr.removeEventListener(type, listener, options);\n\t\t};\n\n\t\t// Returns the calculated method.\n\t\t$this.GetMethod = function() {\n\t\t\treturn (options.method || (options.params || options.body ? 'POST' : 'GET'));\n\t\t};\n\n\t\t$this.PrepareBody = function() {\n\t\t\tif (options.body)  return options.body;\n\n\t\t\tvar method = $this.GetMethod();\n\n\t\t\t// Build a FormData object.\n\t\t\tvar xhrbody = (options.params || method === 'POST' ? new FormData() : null);\n\n\t\t\tif (options.params)\n\t\t\t{\n\t\t\t\tif (options.params instanceof FormData)\n\t\t\t\t{\n\t\t\t\t\txhrbody = options.params;\n\t\t\t\t}\n\t\t\t\telse if (Array.isArray(options.params))\n\t\t\t\t{\n\t\t\t\t\tfor (var x = 0; x < options.params.length; x++)  xhrbody.append(options.params[x].name, options.params[x].value);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfor (var x in options.params)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (options.params.hasOwnProperty(x))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (typeof options.params[x] === 'string' || typeof options.params[x] === 'number')  xhrbody.append(x, options.params[x]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn xhrbody;\n\t\t};\n\n\t\t$this.Send = function(xhrbody) {\n\t\t\tif (sent || !$this || !$this.xhr)  return;\n\n\t\t\tsent = true;\n\n\t\t\t$this.xhr.open($this.GetMethod(), options.url);\n\n\t\t\t// Set request headers.\n\t\t\tif (options.headers)\n\t\t\t{\n\t\t\t\tfor (var x in options.headers)\n\t\t\t\t{\n\t\t\t\t\tif (options.headers.hasOwnProperty(x) && typeof options.headers[x] === 'string')  $this.xhr.setRequestHeader(x, options.headers[x]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!xhrbody)  xhrbody = $this.PrepareBody();\n\n\t\t\t// Send the XHR request.\n\t\t\t$this.xhr.send(xhrbody);\n\t\t};\n\n\t\t$this.Abort = function() {\n\t\t\tif (!$this || !$this.xhr)  return;\n\n\t\t\tvar tempxhr = $this.xhr;\n\n\t\t\t$this.xhr = null;\n\n\t\t\tif (sent)  tempxhr.abort();\n\t\t};\n\n\t\t$this.Destroy = function() {\n\t\t\t$this.Abort();\n\n\t\t\t$this = null;\n\t\t};\n\t};\n\n\n\t// Image loader.  Items can be cancelled.\n\tvar ImageLoader = function(options) {\n\t\tif (!(this instanceof ImageLoader))  return new ImageLoader(options);\n\n\t\tvar activequeue = {}, numactive = 0, queue = {}, numqueued = 0, minqueueid = 1, nextid = 1;\n\t\tvar $this = this;\n\n\t\tvar defaults = {\n\t\t\tmaxactive: 10\n\t\t};\n\n\t\t$this.settings = Object.assign({}, defaults, options);\n\n\t\tvar ImgLoadHandler = function(e) {\n\t\t\tvar id = e.target._ilid;\n\n\t\t\tvar opts = activequeue[id];\n\n\t\t\tdelete activequeue[id];\n\n\t\t\tnumactive--;\n\n\t\t\topts.img.onload = null;\n\t\t\topts.img.onerror = null;\n\n\t\t\tif (opts.callback)  opts.callback.call($this, opts, true, e);\n\n\t\t\t$this.ProcessQueue();\n\t\t};\n\n\t\tvar ImgErrorHandler = function(e) {\n\t\t\tvar id = e.target._ilid;\n\n\t\t\tvar opts = activequeue[id];\n\n\t\t\tdelete activequeue[id];\n\n\t\t\tnumactive--;\n\n\t\t\topts.img.onload = null;\n\t\t\topts.img.onerror = null;\n\n\t\t\tif (opts.callback)  opts.callback.call($this, opts, false, e);\n\n\t\t\t$this.ProcessQueue();\n\t\t};\n\n\t\t// Public functions.\n\n\t\t// Adds an image request to the queue.\n\t\t// Required opts keys:  src (image URL).\n\t\t// Optional opts keys:  width, height, callback.\n\t\t// Reserved opts keys:  id, started, img.\n\t\t$this.AddToQueue = function(opts) {\n\t\t\t// Ignore if an existing ID is already in a queue.\n\t\t\tif (opts.id && ((opts.id in activequeue) || (opts.id in queue)))  return;\n\n\t\t\topts.id = nextid;\n\n\t\t\tqueue[nextid] = opts;\n\t\t\tnumqueued++;\n\n\t\t\tnextid++;\n\t\t};\n\n\t\t// Starts the next images in the queue up to maxactive.\n\t\t$this.ProcessQueue = function() {\n\t\t\twhile (numactive < $this.settings.maxactive && numqueued)\n\t\t\t{\n\t\t\t\twhile (minqueueid < nextid && !queue.hasOwnProperty(minqueueid))  minqueueid++;\n\n\t\t\t\t// Move an item from the waiting queue to the active queue.\n\t\t\t\tvar opts = queue[minqueueid];\n\t\t\t\tdelete queue[minqueueid];\n\t\t\t\tnumqueued--;\n\n\t\t\t\tactivequeue[opts.id] = opts;\n\t\t\t\tnumactive++;\n\n\t\t\t\t// Create the image.\n\t\t\t\tvar imgnode = (opts.width && opts.height ? new Image(opts.width, opts.height) : new Image());\n\n\t\t\t\timgnode._ilid = opts.id;\n\n\t\t\t\topts.started = Date.now();\n\t\t\t\topts.img = imgnode;\n\n\t\t\t\timgnode.onload = ImgLoadHandler;\n\t\t\t\timgnode.onerror = ImgErrorHandler;\n\t\t\t\timgnode.src = opts.src;\n\t\t\t}\n\t\t};\n\n\t\t// Checks to see if the supplied ID is in the active queue.\n\t\t$this.IsActive = function(id) {\n\t\t\treturn (id in activequeue);\n\t\t};\n\n\t\t// Remove an item from the queue it is in.\n\t\t$this.RemoveFromQueue = function(id) {\n\t\t\tif (id in queue)\n\t\t\t{\n\t\t\t\tdelete queue[id];\n\n\t\t\t\tnumqueued--;\n\t\t\t}\n\t\t\telse if (id in activequeue)\n\t\t\t{\n\t\t\t\tvar opts = activequeue[id];\n\n\t\t\t\t// Cancel an active image download.\n\t\t\t\topts.img.onload = null;\n\t\t\t\topts.img.onerror = null;\n\t\t\t\topts.img.src = '';\n\n\t\t\t\tdelete opts.img;\n\n\t\t\t\tdelete activequeue[id];\n\n\t\t\t\tnumactive--;\n\t\t\t}\n\t\t};\n\n\t\t$this.Destroy = function() {\n\t\t\tfor (var x in activequeue)\n\t\t\t{\n\t\t\t\tif (activequeue.hasOwnProperty(x))\n\t\t\t\t{\n\t\t\t\t\tactivequeue[x].img.onload = null;\n\t\t\t\t\tactivequeue[x].img.onerror = null;\n\t\t\t\t\tactivequeue[x].img.src = '';\n\n\t\t\t\t\tdelete activequeue[x].img;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tactivequeue = {};\n\t\t\tnumactive = 0;\n\t\t\tqueue = {};\n\t\t\tnumqueued = 0;\n\n\t\t\t$this = null;\n\t\t};\n\t};\n\n\t// Single instance of ImageLoader for loading thumbnails.\n\tvar fe_thumbnailloader = new ImageLoader();\n\n\n\t// Folder tracking.  Manages information related to folders and files in the defined folder.\n\t// Pass in an array of path segments to define the path.  Each path segment is an array consisting of [id, value, attrs].\n\tvar Folder = function(path) {\n\t\tif (!(this instanceof Folder))  return new Folder(path);\n\n\t\tvar triggers = {}, entries = [], entryidmap = {}, busyref = 0, busyqueue = [], autosort = true;\n\t\tvar $this = this;\n\n\t\tif (!path[path.length - 1][2])  path[path.length - 1][2] = {};\n\n\t\t// Internal functions.\n\t\tvar DispatchEvent = function(eventname, params) {\n\t\t\tif (!triggers[eventname])  return;\n\n\t\t\ttriggers[eventname].forEach(function(callback) {\n\t\t\t\tif (Array.isArray(params))  callback.apply($this, params);\n\t\t\t\telse  callback.call($this, params);\n\t\t\t});\n\t\t};\n\n\t\t// Public DOM-style functions.\n\t\t$this.addEventListener = function(eventname, callback) {\n\t\t\tif (!triggers[eventname])  triggers[eventname] = [];\n\n\t\t\tfor (var x in triggers[eventname])\n\t\t\t{\n\t\t\t\tif (triggers[eventname][x] === callback)  return;\n\t\t\t}\n\n\t\t\ttriggers[eventname].push(callback);\n\t\t};\n\n\t\t$this.removeEventListener = function(eventname, callback) {\n\t\t\tif (!triggers[eventname])  return;\n\n\t\t\tfor (var x in triggers[eventname])\n\t\t\t{\n\t\t\t\tif (triggers[eventname][x] === callback)\n\t\t\t\t{\n\t\t\t\t\ttriggers[eventname].splice(x, 1);\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t$this.hasEventListener = function(eventname) {\n\t\t\treturn (triggers[eventname] && triggers[eventname].length);\n\t\t};\n\n\t\t// Internal variables.\n\t\t$this.lastrefresh = 0;\n\t\t$this.waiting = true;\n\t\t$this.refs = 0;\n\n\t\t// Public functions.\n\n\t\t// Add the value of newval to the folder busy state.  Any queued changes will be applied when cleared.\n\t\t$this.SetBusyRef = function(newval) {\n\t\t\tbusyref += newval;\n\t\t\tif (busyref < 0)  busyref = 0;\n\n\t\t\twhile (!busyref && busyqueue.length)\n\t\t\t{\n\t\t\t\tvar item = busyqueue.shift();\n\n\t\t\t\titem.callback.apply($this, item.callbackopts);\n\t\t\t}\n\t\t};\n\n\t\t$this.IsBusy = function() {\n\t\t\treturn (busyref > 0);\n\t\t};\n\n\t\t$this.AddBusyQueueCallback = function(callback, callbackopts) {\n\t\t\tbusyqueue.push({ callback: callback, callbackopts: callbackopts });\n\n\t\t\t$this.SetBusyRef(0);\n\t\t};\n\n\t\t// Internal function to only be used by FileExplorer.\n\t\t$this.ClearBusyQueueCallbacks = function() {\n\t\t\tbusyqueue = [];\n\t\t};\n\n\t\t$this.GetPath = function() {\n\t\t\treturn path;\n\t\t};\n\n\t\t$this.GetPathIDs = function() {\n\t\t\tvar result = [];\n\n\t\t\tfor (var x = 0; x < path.length; x++)  result.push(path[x][0]);\n\n\t\t\treturn result;\n\t\t};\n\n\t\t// Sets an object containing optional attributes for the path.\n\t\t// Used primarily to disable some/all tools from functioning for specific folders.\n\t\t$this.SetAttributes = function(newattrs) {\n\t\t\tpath[path.length - 1][2] = newattrs;\n\n\t\t\tDispatchEvent('set_attributes');\n\t\t};\n\n\t\t$this.SetAttribute = function(key, value) {\n\t\t\tpath[path.length - 1][2][key] = value;\n\n\t\t\tDispatchEvent('set_attributes', key);\n\t\t};\n\n\t\t$this.GetAttributes = function() {\n\t\t\treturn path[path.length - 1][2];\n\t\t};\n\n\t\t$this.SetAutoSort = function(newautosort) {\n\t\t\tautosort = (newautosort ? true : false);\n\t\t};\n\n\t\t$this.SortEntries = function() {\n\t\t\tif ($this.busy)\n\t\t\t{\n\t\t\t\t$this.busyqueue.push({ callback: $this.SortEntries, callbackopts: [] });\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar localeopts = { numeric: true, sensitivity: 'base' };\n\n\t\t\tentries.sort(function(a, b) {\n\t\t\t\tif (a.type !== b.type)  return (a.type === 'folder' ? -1 : 1);\n\n\t\t\t\treturn a.name.localeCompare(b.name, undefined, localeopts);\n\t\t\t});\n\t\t};\n\n\t\t// Sets an array of objects containing the folder entries.\n\t\t// Required per-item object keys:  id (unique string), name, type ('folder' or 'file'), hash (unique string).\n\t\t// Optional per-item object keys:  attrs, size, tooltip (tooltip string), thumb (thumbnail image URL), overlay (class name).\n\t\t$this.SetEntries = function(newentries) {\n\t\t\tif ($this.busy)\n\t\t\t{\n\t\t\t\t$this.busyqueue.push({ callback: $this.SetEntries, callbackopts: [newentries] });\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tentries = newentries;\n\n\t\t\tif (autosort)  $this.SortEntries();\n\n\t\t\tentryidmap = {};\n\t\t\tfor (var x = 0; x < entries.length; x++)\n\t\t\t{\n\t\t\t\tentryidmap[entries[x].id] = x;\n\t\t\t}\n\n\t\t\t$this.waiting = false;\n\n\t\t\tDispatchEvent('set_entries');\n\t\t};\n\n\t\t// Creates/Updates multiple entries.\n\t\t$this.UpdateEntries = function(updatedentries) {\n\t\t\tif ($this.busy)\n\t\t\t{\n\t\t\t\t$this.busyqueue.push({ callback: $this.UpdateEntries, callbackopts: [updatedentries] });\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfor (var x = 0; x < updatedentries.length; x++)\n\t\t\t{\n\t\t\t\tvar entry = updatedentries[x];\n\n\t\t\t\tif (!(entry.id in entryidmap))  entries.push(entry);\n\t\t\t\telse  entries[entryidmap[entry.id]] = entry;\n\t\t\t}\n\n\t\t\tif (autosort)  $this.SortEntries();\n\n\t\t\tentryidmap = {};\n\t\t\tfor (var x = 0; x < entries.length; x++)\n\t\t\t{\n\t\t\t\tentryidmap[entries[x].id] = x;\n\t\t\t}\n\n\t\t\t$this.waiting = false;\n\n\t\t\tDispatchEvent('set_entries');\n\t\t};\n\n\t\t// Sets a single entry and triggers a full refresh.\n\t\t$this.SetEntry = function(entry) {\n\t\t\tif ($this.busy)\n\t\t\t{\n\t\t\t\t$this.busyqueue.push({ callback: $this.SetEntry, callbackopts: [entry] });\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!(entry.id in entryidmap))  entries.push(entry);\n\t\t\telse  entries[entryidmap[entry.id]] = entry;\n\n\t\t\tif (autosort)  $this.SortEntries();\n\n\t\t\tentryidmap = {};\n\t\t\tfor (var x = 0; x < entries.length; x++)\n\t\t\t{\n\t\t\t\tentryidmap[entries[x].id] = x;\n\t\t\t}\n\n\t\t\t$this.waiting = false;\n\n\t\t\tDispatchEvent('set_entries');\n\t\t};\n\n\t\t$this.RemoveEntry = function(id) {\n\t\t\tif ($this.busy)\n\t\t\t{\n\t\t\t\t$this.busyqueue.push({ callback: $this.RemoveEntry, callbackopts: [id] });\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!(id in entryidmap))  return;\n\n\t\t\tvar pos = entryidmap[id];\n\n\t\t\tdelete entryidmap[id];\n\n\t\t\tentries.splice(pos, 1);\n\n\t\t\tfor (var x = pos; x < entries.length; x++)\n\t\t\t{\n\t\t\t\tentryidmap[entries[x].id] = x;\n\t\t\t}\n\n\t\t\tDispatchEvent('remove_entry', pos);\n\t\t};\n\n\t\t$this.GetEntries = function() {\n\t\t\treturn entries;\n\t\t};\n\n\t\t$this.GetEntryIDMap = function() {\n\t\t\treturn entryidmap;\n\t\t};\n\n\t\t$this.Destroy = function() {\n\t\t\tDispatchEvent('destroy');\n\n\t\t\ttriggers = {};\n\t\t\tentries = [];\n\t\t\tentryidmap = {};\n\t\t\tbusyref = 0\n\t\t\tbusyqueue = [];\n\n\t\t\t$this.lastrefresh = 0;\n\t\t\t$this.waiting = true;\n\t\t\t$this.refs = 0;\n\n\t\t\t$this = null;\n\t\t\tpath = null;\n\t\t};\n\t};\n\n\n\t// Attaches a popup menu to the DOM.\n\tvar PopupMenu = function(parentelem, options) {\n\t\tif (!(this instanceof PopupMenu))  return new PopupMenu(parentelem, options);\n\n\t\tvar triggers = {};\n\t\tvar $this = this;\n\n\t\tvar defaults = {\n\t\t\titems: [],\n\n\t\t\tresizewatchers: null,\n\n\t\t\tonposition: null,\n\t\t\tonselchanged: null,\n\t\t\tonselected: null,\n\t\t\toncancel: null,\n\n\t\t\tonleft: null,\n\t\t\tonright: null,\n\n\t\t\tondestroy: null\n\t\t};\n\n\t\t$this.settings = Object.assign({}, defaults, options);\n\n\t\t// Initialize the UI elements.\n\t\tvar elems = {\n\t\t\tpopupwrap: CreateNode('div', ['fe_fileexplorer_popup_wrap'], { tabIndex: 0 }),\n\t\t\tinnerwrap: CreateNode('div', ['fe_fileexplorer_popup_inner_wrap'])\n\t\t};\n\n\t\t// Track the last hovered/focused item.\n\t\tvar lastitem = false, itemidmap = {};\n\n\t\t// Attach elements to DOM.\n\t\tfor (var x = 0; x < $this.settings.items.length; x++)\n\t\t{\n\t\t\tvar item = $this.settings.items[x];\n\n\t\t\tif (item === 'split')\n\t\t\t{\n\t\t\t\tvar itemnode = CreateNode('div', ['fe_fileexplorer_popup_item_split']);\n\n\t\t\t\telems.innerwrap.appendChild(itemnode);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tvar itemnode = CreateNode('div', ['fe_fileexplorer_popup_item_wrap'], { tabIndex: -1 });\n\t\t\t\tvar itemicon = CreateNode('div', ['fe_fileexplorer_popup_item_icon']);\n\t\t\t\tvar itemiconinner = CreateNode('div', ['fe_fileexplorer_popup_item_icon_inner']);\n\t\t\t\tvar itemtext = CreateNode('div', ['fe_fileexplorer_popup_item_text']);\n\t\t\t\tvar enabled = (!('enabled' in item) || item.enabled);\n\n\t\t\t\tif (!enabled)  itemnode.classList.add('fe_fileexplorer_popup_item_disabled');\n\n\t\t\t\tif ('icon' in item)  itemiconinner.classList.add(item.icon);\n\n\t\t\t\titemtext.innerHTML = item.name;\n\n\t\t\t\titemicon.appendChild(itemiconinner);\n\t\t\t\titemnode.appendChild(itemicon);\n\t\t\t\titemnode.appendChild(itemtext);\n\n\t\t\t\titemnode.dataset.itemid = item.id;\n\t\t\t\titemidmap[item.id] = item;\n\n\t\t\t\telems.innerwrap.appendChild(itemnode);\n\t\t\t}\n\t\t}\n\n\t\telems.popupwrap.appendChild(elems.innerwrap);\n\n\t\tparentelem.appendChild(elems.popupwrap);\n\n\t\t// Internal functions.\n\t\tvar DispatchEvent = function(eventname, params) {\n\t\t\tif (!triggers[eventname])  return;\n\n\t\t\ttriggers[eventname].forEach(function(callback) {\n\t\t\t\tif (Array.isArray(params))  callback.apply($this, params);\n\t\t\t\telse  callback.call($this, params);\n\t\t\t});\n\t\t};\n\n\t\t// Public DOM-style functions.\n\t\t$this.addEventListener = function(eventname, callback) {\n\t\t\tif (!triggers[eventname])  triggers[eventname] = [];\n\n\t\t\tfor (var x in triggers[eventname])\n\t\t\t{\n\t\t\t\tif (triggers[eventname][x] === callback)  return;\n\t\t\t}\n\n\t\t\ttriggers[eventname].push(callback);\n\t\t};\n\n\t\t$this.removeEventListener = function(eventname, callback) {\n\t\t\tif (!triggers[eventname])  return;\n\n\t\t\tfor (var x in triggers[eventname])\n\t\t\t{\n\t\t\t\tif (triggers[eventname][x] === callback)\n\t\t\t\t{\n\t\t\t\t\ttriggers[eventname].splice(x, 1);\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t$this.hasEventListener = function(eventname) {\n\t\t\treturn (triggers[eventname] && triggers[eventname].length);\n\t\t};\n\n\t\t// Register settings callbacks.\n\t\tif ($this.settings.onposition)  $this.addEventListener('position', $this.settings.onposition);\n\t\tif ($this.settings.onselchanged)  $this.addEventListener('selection_changed', $this.settings.onselchanged);\n\t\tif ($this.settings.onselected)  $this.addEventListener('selected', $this.settings.onselected);\n\t\tif ($this.settings.oncancel)  $this.addEventListener('cancelled', $this.settings.oncancel);\n\t\tif ($this.settings.onleft)  $this.addEventListener('left', $this.settings.onleft);\n\t\tif ($this.settings.onright)  $this.addEventListener('right', $this.settings.onright);\n\t\tif ($this.settings.ondestroy)  $this.addEventListener('destroy', $this.settings.ondestroy);\n\n\t\t// Set up focus changing closing rules.\n\t\tvar MainFocusHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tvar node = e.target;\n\t\t\twhile (node && node !== elems.popupwrap)  node = node.parentNode;\n\n\t\t\tif (node !== elems.popupwrap && allowcancel)\n\t\t\t{\n\t\t\t\tlastactiveelem = e.target;\n\n\t\t\t\t$this.Cancel(e.type === 'focus' ? 'focus' : 'mouse');\n\t\t\t}\n\t\t};\n\n\t\twindow.addEventListener('mousedown', MainFocusHandler, true);\n\t\twindow.addEventListener('focus', MainFocusHandler, true);\n\n\t\tvar MainWindowBlurHander = function(e) {\n\t\t\tif (e.target === window || e.target === document)  $this.Cancel('blur');\n\t\t};\n\n\t\twindow.addEventListener('blur', MainWindowBlurHander, true);\n\n\t\t// Track mouse movement to update the last hovered/focused item.\n\t\tvar InnerWrapMoveHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\te.preventDefault();\n\n\t\t\tvar node = e.target;\n\t\t\twhile (node && node.parentNode !== elems.innerwrap)  node = node.parentNode;\n\n\t\t\tif (node && (lastitem !== node || lastitem !== document.activeElement))\n\t\t\t{\n\t\t\t\tif (node.classList.contains('fe_fileexplorer_popup_item_wrap'))\n\t\t\t\t{\n\t\t\t\t\tnode.tabIndex = 0;\n\t\t\t\t\tnode.focus();\n\n\t\t\t\t\tif (lastitem !== false)  lastitem.tabIndex = -1;\n\n\t\t\t\t\tif (lastitem !== node)  DispatchEvent('selection_changed', [node.dataset.itemid, itemidmap[node.dataset.itemid]]);\n\n\t\t\t\t\tlastitem = node;\n\t\t\t\t}\n\t\t\t\telse if (elems.popupwrap !== document.activeElement)\n\t\t\t\t{\n\t\t\t\t\telems.popupwrap.focus();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\telems.innerwrap.addEventListener('mousemove', InnerWrapMoveHandler);\n\n\t\tvar InnerWrapLeaveHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\telems.popupwrap.focus();\n\t\t};\n\n\t\telems.innerwrap.addEventListener('mouseleave', InnerWrapLeaveHandler);\n\n\t\t// Notify listeners that the last item was selected.\n\t\tvar lastactiveelem = document.activeElement;\n\t\tvar NotifySelected = function(etype) {\n\t\t\tallowcancel = false;\n\n\t\t\tDispatchEvent('selected', [itemidmap[lastitem.dataset.itemid].id, itemidmap[lastitem.dataset.itemid], lastactiveelem, etype]);\n\t\t};\n\n\t\t// Handle clicks.\n\t\tvar MainClickHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\te.preventDefault();\n\n\t\t\tif (e.button == 0 && lastitem !== false && lastitem === document.activeElement && !lastitem.classList.contains('fe_fileexplorer_popup_item_disabled'))  NotifySelected('mouse');\n\t\t};\n\n\t\telems.innerwrap.addEventListener('mouseup', MainClickHandler);\n\n\t\tvar StopContextMenu = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\te.preventDefault();\n\t\t};\n\n\t\telems.innerwrap.addEventListener('contextmenu', StopContextMenu);\n\n\t\t// Handle keyboard navigation.\n\t\tvar MainKeyHandler = function(e) {\n\t\t\t// The keyboard is modal while the mouse is not.  Stop propagation of all keyboard actions.\n\t\t\te.stopPropagation();\n\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (e.keyCode == 37)\n\t\t\t{\n\t\t\t\t// Left Arrow.  Send event to registered caller (if any).\n\t\t\t\te.preventDefault();\n\n\t\t\t\tDispatchEvent('left', lastactiveelem);\n\t\t\t}\n\t\t\telse if (e.keyCode == 39)\n\t\t\t{\n\t\t\t\t// Right Arrow.  Send event to registered caller (if any).\n\t\t\t\te.preventDefault();\n\n\t\t\t\tDispatchEvent('right', lastactiveelem);\n\t\t\t}\n\t\t\telse if (e.keyCode == 38)\n\t\t\t{\n\t\t\t\t// Up Arrow.  Move to previous or last item.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tvar node = (lastitem === false ? elems.innerwrap.lastChild : lastitem.previousSibling);\n\n\t\t\t\twhile (node && !node.classList.contains('fe_fileexplorer_popup_item_wrap'))  node = node.previousSibling;\n\n\t\t\t\tif (!node)  node = elems.innerwrap.lastChild;\n\n\t\t\t\tif (node)\n\t\t\t\t{\n\t\t\t\t\tnode.tabIndex = 0;\n\t\t\t\t\tnode.focus();\n\n\t\t\t\t\tif (lastitem !== false)  lastitem.tabIndex = -1;\n\n\t\t\t\t\tif (lastitem !== node)  DispatchEvent('selection_changed', [node.dataset.itemid, itemidmap[node.dataset.itemid]]);\n\n\t\t\t\t\tlastitem = node;\n\t\t\t\t}\n\n\t\t\t\tif (lastitem !== false)  lastitem.focus();\n\t\t\t}\n\t\t\telse if (e.keyCode == 40)\n\t\t\t{\n\t\t\t\t// Down Arrow.  Move to next or first item.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tvar node = (lastitem === false ? elems.innerwrap.firstChild : lastitem.nextSibling);\n\n\t\t\t\twhile (node && !node.classList.contains('fe_fileexplorer_popup_item_wrap'))  node = node.nextSibling;\n\n\t\t\t\tif (!node)  node = elems.innerwrap.firstChild;\n\n\t\t\t\tif (node)\n\t\t\t\t{\n\t\t\t\t\tnode.tabIndex = 0;\n\t\t\t\t\tnode.focus();\n\n\t\t\t\t\tif (lastitem !== false)  lastitem.tabIndex = -1;\n\n\t\t\t\t\tif (lastitem !== node)  DispatchEvent('selection_changed', [node.dataset.itemid, itemidmap[node.dataset.itemid]]);\n\n\t\t\t\t\tlastitem = node;\n\t\t\t\t}\n\n\t\t\t\tif (lastitem !== false)  lastitem.focus();\n\t\t\t}\n\t\t\telse if (e.keyCode == 13)\n\t\t\t{\n\t\t\t\t// Enter.  Select item or cancel the popup if the item is disabled.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tif (lastitem === false || lastitem !== document.activeElement || lastitem.classList.contains('fe_fileexplorer_popup_item_disabled'))  $this.Cancel('key');\n\t\t\t\telse  NotifySelected('key');\n\t\t\t}\n\t\t\telse if (e.keyCode == 27 || e.keyCode == 9 || e.altKey)\n\t\t\t{\n\t\t\t\t// Escape, Tab, or Alt.  Cancel the popup.\n\t\t\t\te.preventDefault();\n\n\t\t\t\t$this.Cancel('key');\n\t\t\t}\n\t\t};\n\n\t\telems.popupwrap.addEventListener('keydown', MainKeyHandler);\n\n\t\tvar IgnoreKeyHandler = function(e) {\n\t\t\te.stopPropagation();\n\n\t\t\tif (!e.isTrusted)  return;\n\t\t};\n\n\t\telems.popupwrap.addEventListener('keyup', IgnoreKeyHandler);\n\t\telems.popupwrap.addEventListener('keypress', IgnoreKeyHandler);\n\n\n\t\t// Public functions.\n\n\t\t// Updates the position of the popup menu.\n\t\t$this.UpdatePosition = function() {\n\t\t\telems.popupwrap.style.left = '-9999px';\n\n\t\t\tDispatchEvent('position', elems.popupwrap);\n\t\t};\n\n\t\t$this.UpdatePosition();\n\n\t\t// Set up a debounced element attribute watcher on window resize.\n\t\tvar updatepositionwatcher;\n\t\tif (Array.isArray($this.settings.resizewatchers) && $this.settings.resizewatchers.length)\n\t\t{\n\t\t\tupdatepositionwatcher = new DebounceAttributes({\n\t\t\t\twatchers: $this.settings.resizewatchers,\n\t\t\t\tinterval: 100,\n\t\t\t\tstopsame: 5,\n\t\t\t\tcallback: $this.UpdatePosition,\n\t\t\t\tintervalcallback: $this.UpdatePosition\n\t\t\t});\n\n\t\t\twindow.addEventListener('resize', updatepositionwatcher.Start, true);\n\t\t}\n\n\t\t// Dispatches the cancelled event.\n\t\tvar allowcancel = false;\n\t\t$this.Cancel = function(etype) {\n\t\t\tif (allowcancel)\n\t\t\t{\n\t\t\t\tallowcancel = false;\n\n\t\t\t\tDispatchEvent('cancelled', [lastactiveelem, etype]);\n\t\t\t}\n\t\t};\n\n\t\t// Prevents Cancel() from having any effect.\n\t\t$this.PreventCancel = function() {\n\t\t\tallowcancel = false;\n\t\t};\n\n\t\t// Destroys the popup menu.\n\t\t$this.Destroy = function() {\n\t\t\tDispatchEvent('destroy');\n\n\t\t\twindow.removeEventListener('mousedown', MainFocusHandler, true);\n\t\t\twindow.removeEventListener('focus', MainFocusHandler, true);\n\t\t\twindow.removeEventListener('blur', MainWindowBlurHander, true);\n\n\t\t\telems.innerwrap.removeEventListener('mousemove', InnerWrapMoveHandler);\n\t\t\telems.innerwrap.removeEventListener('mouseleave', InnerWrapLeaveHandler);\n\t\t\telems.innerwrap.removeEventListener('mouseup', MainClickHandler);\n\t\t\telems.innerwrap.removeEventListener('contextmenu', StopContextMenu);\n\n\t\t\telems.popupwrap.removeEventListener('keydown', MainKeyHandler);\n\t\t\telems.popupwrap.removeEventListener('keyup', IgnoreKeyHandler);\n\t\t\telems.popupwrap.removeEventListener('keypress', IgnoreKeyHandler);\n\n\t\t\tif (Array.isArray($this.settings.resizewatchers) && $this.settings.resizewatchers.length)\n\t\t\t{\n\t\t\t\twindow.removeEventListener('resize', updatepositionwatcher.Start, true);\n\n\t\t\t\tupdatepositionwatcher.Destroy();\n\t\t\t}\n\n\t\t\tfor (var node in elems)\n\t\t\t{\n\t\t\t\tif (elems[node].parentNode)  elems[node].parentNode.removeChild(elems[node]);\n\t\t\t}\n\n\t\t\t// Remaining cleanup.\n\t\t\telems = null;\n\t\t\tlastactiveelem = null;\n\n\t\t\t$this.settings = Object.assign({}, defaults);\n\n\t\t\t$this = null;\n\t\t\tparentelem = null;\n\t\t\toptions = null;\n\t\t};\n\n\t\t// Focus on the popup menu but do not select anything.\n\t\telems.popupwrap.focus();\n\t\tallowcancel = true;\n\t};\n\n\n\t// Overlays a textarea placed into a parent element.\n\tvar TextareaOverlay = function(parentelem, options) {\n\t\tif (!(this instanceof TextareaOverlay))  return new TextareaOverlay(parentelem, options);\n\n\t\tvar triggers = {};\n\t\tvar $this = this;\n\n\t\tvar defaults = {\n\t\t\tcapturetab: false,\n\t\t\tmultiline: false,\n\n\t\t\tinitvalue: '',\n\t\t\tinitselstart: -1,\n\t\t\tinitselend: -1,\n\n\t\t\tresizewatchers: null,\n\n\t\t\tonposition: null,\n\t\t\tondone: null,\n\t\t\toncancel: null,\n\n\t\t\tondestroy: null\n\t\t};\n\n\t\t$this.settings = Object.assign({}, defaults, options);\n\n\t\t// Initialize the UI elements.\n\t\tvar elems = {\n\t\t\tmaintext: CreateNode('textarea', ['fe_fileexplorer_textarea'])\n\t\t};\n\n\t\t// Attach elements to DOM.\n\t\telems.maintext.value = $this.settings.initvalue;\n\n\t\tparentelem.appendChild(elems.maintext);\n\n\t\t// Internal functions.\n\t\tvar DispatchEvent = function(eventname, params) {\n\t\t\tif (!triggers[eventname])  return;\n\n\t\t\ttriggers[eventname].forEach(function(callback) {\n\t\t\t\tif (Array.isArray(params))  callback.apply($this, params);\n\t\t\t\telse  callback.call($this, params);\n\t\t\t});\n\t\t};\n\n\t\t// Public DOM-style functions.\n\t\t$this.addEventListener = function(eventname, callback) {\n\t\t\tif (!triggers[eventname])  triggers[eventname] = [];\n\n\t\t\tfor (var x in triggers[eventname])\n\t\t\t{\n\t\t\t\tif (triggers[eventname][x] === callback)  return;\n\t\t\t}\n\n\t\t\ttriggers[eventname].push(callback);\n\t\t};\n\n\t\t$this.removeEventListener = function(eventname, callback) {\n\t\t\tif (!triggers[eventname])  return;\n\n\t\t\tfor (var x in triggers[eventname])\n\t\t\t{\n\t\t\t\tif (triggers[eventname][x] === callback)\n\t\t\t\t{\n\t\t\t\t\ttriggers[eventname].splice(x, 1);\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t$this.hasEventListener = function(eventname) {\n\t\t\treturn (triggers[eventname] && triggers[eventname].length);\n\t\t};\n\n\t\t// Register settings callbacks.\n\t\tif ($this.settings.onposition)  $this.addEventListener('position', $this.settings.onposition);\n\t\tif ($this.settings.ondone)  $this.addEventListener('done', $this.settings.ondone);\n\t\tif ($this.settings.oncancel)  $this.addEventListener('cancelled', $this.settings.oncancel);\n\t\tif ($this.settings.ondestroy)  $this.addEventListener('destroy', $this.settings.ondestroy);\n\n\t\t// Set up focus changing closing rules.\n\t\tvar MainFocusHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tvar node = e.target;\n\t\t\twhile (node && node !== elems.maintext)  node = node.parentNode;\n\n\t\t\tif (node !== elems.maintext && allowcanceldone)\n\t\t\t{\n\t\t\t\tlastactiveelem = e.target;\n\n\t\t\t\t$this.Done(e.type === 'focus' ? 'focus' : 'mouse');\n\t\t\t}\n\t\t};\n\n\t\twindow.addEventListener('mousedown', MainFocusHandler, true);\n\t\twindow.addEventListener('focus', MainFocusHandler, true);\n\n\t\tvar MainWindowBlurHander = function(e) {\n\t\t\tif (e.target === window || e.target === document)  $this.Done('blur');\n\t\t};\n\n\t\twindow.addEventListener('blur', MainWindowBlurHander, true);\n\n\t\tvar lastactiveelem = document.activeElement;\n\n\t\t// Handle keyboard navigation.\n\t\tvar MainKeyHandler = function(e) {\n\t\t\t// The keyboard is modal while the mouse is not.  Stop propagation of all keyboard actions.\n\t\t\te.stopPropagation();\n\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (e.keyCode == 8)\n\t\t\t{\n\t\t\t\t// Backspace.\n\t\t\t\t$this.UpdatePosition();\n\t\t\t\tsetTimeout($this.UpdatePosition, 0);\n\t\t\t}\n\t\t\tif (e.keyCode == 46)\n\t\t\t{\n\t\t\t\t// Delete.\n\t\t\t\t$this.UpdatePosition();\n\t\t\t\tsetTimeout($this.UpdatePosition, 0);\n\t\t\t}\n\t\t\telse if (e.keyCode == 9)\n\t\t\t{\n\t\t\t\t// Tab.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tif (!$this.settings.capturetab || e.shiftKey)  $this.Done('key');\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tvar pos = elems.maintext.selectionStart;\n\t\t\t\t\telems.maintext.value = elems.maintext.value.substring(0, pos) + '\\t' + elems.maintext.value.substring(elems.maintext.selectionEnd);\n\t\t\t\t\telems.maintext.selectionEnd = pos + 1;\n\n\t\t\t\t\t$this.UpdatePosition();\n\t\t\t\t\tsetTimeout($this.UpdatePosition, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (e.keyCode == 13)\n\t\t\t{\n\t\t\t\t// Enter.  Complete the entry if not multiline.\n\t\t\t\tif (!$this.settings.multiline)\n\t\t\t\t{\n\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t$this.Done('key');\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (e.keyCode == 27)\n\t\t\t{\n\t\t\t\t// Escape.  Cancel the textarea.\n\t\t\t\te.preventDefault();\n\n\t\t\t\t$this.Cancel('key');\n\t\t\t}\n\t\t};\n\n\t\telems.maintext.addEventListener('keydown', MainKeyHandler);\n\n\t\tvar MainKeypressHandler = function(e) {\n\t\t\te.stopPropagation();\n\n\t\t\t$this.UpdatePosition();\n\t\t};\n\n\t\telems.maintext.addEventListener('keyup', MainKeypressHandler);\n\t\telems.maintext.addEventListener('keypress', MainKeypressHandler);\n\n\n\t\t// Public functions.\n\n\t\t// Updates the position of the textarea.\n\t\t$this.UpdatePosition = function() {\n\t\t\telems.maintext.style.height = '1px';\n\n\t\t\tDispatchEvent('position', elems.maintext);\n\t\t};\n\n\t\t$this.UpdatePosition();\n\n\t\t// Set up a debounced element attribute watcher on window resize.\n\t\tvar updatepositionwatcher;\n\t\tif (Array.isArray($this.settings.resizewatchers) && $this.settings.resizewatchers.length)\n\t\t{\n\t\t\tupdatepositionwatcher = new DebounceAttributes({\n\t\t\t\twatchers: $this.settings.resizewatchers,\n\t\t\t\tinterval: 100,\n\t\t\t\tstopsame: 5,\n\t\t\t\tcallback: $this.UpdatePosition,\n\t\t\t\tintervalcallback: $this.UpdatePosition\n\t\t\t});\n\n\t\t\twindow.addEventListener('resize', updatepositionwatcher.Start, true);\n\t\t}\n\n\t\t// Dispatches the done event if the content has changed.\n\t\tvar allowcanceldone = false;\n\t\t$this.Done = function(etype) {\n\t\t\tif ($this.settings.initvalue === elems.maintext.value)  $this.Cancel(etype);\n\t\t\telse if (allowcanceldone)\n\t\t\t{\n\t\t\t\tallowcanceldone = false;\n\t\t\t\telems.maintext.readOnly = true;\n\n\t\t\t\tDispatchEvent('done', [elems.maintext.value, lastactiveelem, etype]);\n\t\t\t}\n\t\t};\n\n\t\t// Dispatches the cancelled event.\n\t\t$this.Cancel = function(etype) {\n\t\t\tif (allowcanceldone)\n\t\t\t{\n\t\t\t\tallowcanceldone = false;\n\t\t\t\telems.maintext.readOnly = true;\n\n\t\t\t\tDispatchEvent('cancelled', [lastactiveelem, etype]);\n\t\t\t}\n\t\t};\n\n\t\t// Resets the cancel/done status to true so another event can be dispatched.\n\t\t$this.ResetAllowCancelDone = function() {\n\t\t\tsetTimeout(function() {\n\t\t\t\telems.maintext.readOnly = false;\n\t\t\t\telems.maintext.focus();\n\n\t\t\t\tallowcanceldone = true;\n\t\t\t}, 0);\n\t\t};\n\n\t\t// Destroys the textarea.\n\t\t$this.Destroy = function() {\n\t\t\tDispatchEvent('destroy');\n\n\t\t\twindow.removeEventListener('mousedown', MainFocusHandler, true);\n\t\t\twindow.removeEventListener('focus', MainFocusHandler, true);\n\t\t\twindow.removeEventListener('blur', MainWindowBlurHander, true);\n\n\t\t\telems.maintext.removeEventListener('keydown', MainKeyHandler);\n\t\t\telems.maintext.removeEventListener('keyup', MainKeypressHandler);\n\t\t\telems.maintext.removeEventListener('keypress', MainKeypressHandler);\n\n\t\t\tif (Array.isArray($this.settings.resizewatchers) && $this.settings.resizewatchers.length)\n\t\t\t{\n\t\t\t\twindow.removeEventListener('resize', updatepositionwatcher.Start, true);\n\n\t\t\t\tupdatepositionwatcher.Destroy();\n\t\t\t}\n\n\t\t\tfor (var node in elems)\n\t\t\t{\n\t\t\t\tif (elems[node].parentNode)  elems[node].parentNode.removeChild(elems[node]);\n\t\t\t}\n\n\t\t\t// Remaining cleanup.\n\t\t\telems = null;\n\t\t\tlastactiveelem = null;\n\n\t\t\t$this.settings = Object.assign({}, defaults);\n\n\t\t\t$this = null;\n\t\t\tparentelem = null;\n\t\t\toptions = null;\n\t\t};\n\n\t\t// Focus on the textarea.\n\t\telems.maintext.focus();\n\t\telems.maintext.setSelectionRange(($this.settings.initselstart > -1 ? $this.settings.initselstart : elems.maintext.value.length), ($this.settings.initselend > -1 ? $this.settings.initselend : elems.maintext.value.length));\n\t\tallowcanceldone = true;\n\t};\n\n\n\t// File Explorer.\n\tvar nextmain_id = 1, coretools = [];\n\twindow.FileExplorer = function(parentelem, options) {\n\t\tif (!(this instanceof FileExplorer))  return new FileExplorer(parentelem, options);\n\n\t\tvar triggers = {}, historystack = [], currhistory = -1, foldermap = {}, currfolder = false, destroyinprogress = false;\n\t\tvar $this = this;\n\n\t\t// The internal ID needs to be fairly unique to identify source for clipboard paste and drag/drop targets.\n\t\tvar main_id = nextmain_id + '_fileexplorer_js_' + Date.now() + '_' + (window.crypto && window.crypto.getRandomValues ? window.crypto.getRandomValues(new Uint32Array(1))[0] : Math.random());\n\t\tnextmain_id++;\n\n\t\tvar defaults = {\n\t\t\tgroup: null,\n\n\t\t\talwaysfocused: false,\n\t\t\tcapturebrowser: false,\n\n\t\t\tmessagetimeout: 2000,\n\n\t\t\tdisplayunits: 'iec_windows',\n\t\t\tadjustprecision: true,\n\n\t\t\tinitpath: null,\n\n\t\t\tonfocus: null,\n\t\t\tonblur: null,\n\n\t\t\tonrefresh: null,\n\t\t\tonselchanged: null,\n\n\t\t\tonrename: null,\n\t\t\tonopenfile: null,\n\t\t\toninitupload: null,\n\t\t\tonfinishedupload: null,\n\t\t\tonuploaderror: null,\n\t\t\tconcurrentuploads: 4,\n\n\t\t\ttools: {},\n\n\t\t\tonnewfolder: null,\n\t\t\tonnewfile: null,\n\t\t\toninitdownload: null,\n\t\t\tondownloadstarted: null,\n\t\t\tondownloaderror: null,\n\n\t\t\tondownloadurl: null,\n\n\t\t\toncopy: null,\n\t\t\tonmove: null,\n\t\t\tondelete: null,\n\n\t\t\tlangmap: {}\n\t\t};\n\n\t\t$this.settings = Object.assign({}, defaults, options);\n\n\t\t// If the group is not specified, set it to the unique main ID + the current time.\n\t\tvar main_group = (typeof $this.settings.group === 'string' ? $this.settings.group : main_id);\n\n\t\t// Multilingual translation.\n\t\t$this.Translate = function(str) {\n\t\t\treturn ($this.settings.langmap[str] ? $this.settings.langmap[str] : str);\n\t\t};\n\n\t\t// Initialize the UI elements.\n\t\tvar elems = {\n\t\t\tmainwrap: CreateNode('div', ['fe_fileexplorer_wrap']),\n\t\t\tdropzonewrap: CreateNode('div', ['fe_fileexplorer_dropzone_wrap']),\n\t\t\tinnerwrap: CreateNode('div', ['fe_fileexplorer_inner_wrap']),\n\n\t\t\ttoolbar: CreateNode('div', ['fe_fileexplorer_toolbar']),\n\t\t\tnavtools: CreateNode('div', ['fe_fileexplorer_navtools']),\n\t\t\tnavtool_back: CreateNode('button', ['fe_fileexplorer_navtool_back', 'fe_fileexplorer_disabled'], { title: $this.Translate('Back (Alt + Left Arrow)'), tabIndex: -1 }),\n\t\t\tnavtool_forward: CreateNode('button', ['fe_fileexplorer_navtool_forward', 'fe_fileexplorer_disabled'], { title: $this.Translate('Forward (Alt + Right Arrow)'), tabIndex: -1 }),\n\t\t\tnavtool_history: CreateNode('button', ['fe_fileexplorer_navtool_history'], { title: $this.Translate('Recent locations') }),\n\t\t\tnavtool_up: CreateNode('button', ['fe_fileexplorer_navtool_up', 'fe_fileexplorer_disabled'], { title: $this.Translate('Up (Alt + Up Arrow)'), tabIndex: -1 }),\n\n\t\t\tpathwrap: CreateNode('div', ['fe_fileexplorer_path_wrap']),\n\t\t\tpathicon: CreateNode('div', ['fe_fileexplorer_path_icon']),\n\t\t\tpathiconinner: CreateNode('div', ['fe_fileexplorer_path_icon_inner']),\n\t\t\tpathsegmentsscrollwrap: CreateNode('div', ['fe_fileexplorer_path_segments_scroll_wrap']),\n\t\t\tpathsegmentswrap: CreateNode('div', ['fe_fileexplorer_path_segments_wrap']),\n\n\t\t\tbodywrapouter: CreateNode('div', ['fe_fileexplorer_body_wrap_outer']),\n\t\t\tbodywrap: CreateNode('div', ['fe_fileexplorer_body_wrap']),\n\n\t\t\tbodytoolsscrollwrap: CreateNode('div', ['fe_fileexplorer_folder_tools_scroll_wrap', 'fe_fileexplorer_hidden']),\n\t\t\tbodytoolbar: CreateNode('div', ['fe_fileexplorer_folder_tools']),\n\t\t\tbodytools: [],\n\n\t\t\titemsscrollwrap: CreateNode('div', ['fe_fileexplorer_items_scroll_wrap'], { tabIndex: 0 }),\n\t\t\titemsscrollwrapinner: CreateNode('div', ['fe_fileexplorer_items_scroll_wrap_inner']),\n\t\t\titemsmessagewrap: CreateNode('div', ['fe_fileexplorer_items_message_wrap']),\n\t\t\titemswrap: CreateNode('div', ['fe_fileexplorer_items_wrap', 'fe_fileexplorer_hidden']),\n\n\t\t\titemsclipboardoverlaypastewrap: CreateNode('div', ['fe_fileexplorer_items_clipboard_overlay_paste_wrap', 'fe_fileexplorer_hidden']),\n\t\t\titemsclipboardoverlaypasteinnerwrap: CreateNode('div', ['fe_fileexplorer_items_clipboard_overlay_paste_inner_wrap']),\n\t\t\titemsclipboardoverlaypastetextwrap: CreateNode('div', ['fe_fileexplorer_items_clipboard_overlay_paste_text_wrap']),\n\t\t\titemsclipboardoverlaypastetext: CreateNode('div', ['fe_fileexplorer_items_clipboard_overlay_paste_text']),\n\t\t\titemsclipboardoverlaypastetextline: CreateNode('div', ['fe_fileexplorer_items_clipboard_overlay_paste_text_big'], { innerHTML: $this.Translate('Paste here') }),\n\t\t\titemsclipboardoverlaypastetexthint: CreateNode('div', ['fe_fileexplorer_items_clipboard_overlay_paste_text_small']),\n\t\t\titemsclipboardoverlay: CreateNode('textarea', ['fe_fileexplorer_items_clipboard_overlay'], { tabIndex: -1, inputMode: 'none', autocomplete: 'off', autocorrect: 'off', autocapitalize: 'off', spellcheck: false }),\n\n\t\t\tstatusbar: CreateNode('div', ['fe_fileexplorer_statusbar_wrap']),\n\t\t\tstatusbarmeasuresize: CreateNode('div', ['fe_fileexplorer_statusbar_measure_em_size']),\n\t\t\tstatusbartextwrap: CreateNode('div', ['fe_fileexplorer_statusbar_text_wrap']),\n\t\t\tstatusbartextsegments: [],\n\t\t\tstatusbartextsegmentmap: {},\n\t\t\tstatusbaractionwrap: CreateNode('div', ['fe_fileexplorer_action_wrap']),\n\t\t\tstatusbaractionprogresswrap: CreateNode('div', ['fe_fileexplorer_action_progress_wrap', 'fe_fileexplorer_hidden']),\n\t\t\tstatusbaractionprogressmessagewrap: CreateNode('div', ['fe_fileexplorer_action_progress_msg_wrap']),\n\t\t\tstatusbaractionprogressmessagewrap2: CreateNode('div', ['fe_fileexplorer_action_progress_msg_wrap', 'fe_fileexplorer_action_progress_msg_wrap_last']),\n\t\t\tstatusbaractionprogresscancelwrap: CreateNode('div', ['fe_fileexplorer_action_progress_cancel_wrap'], { title: $this.Translate('Cancel all'), tabIndex: 0 }),\n\t\t};\n\n\t\t// Sets a text segment's displayed text in the status bar.\n\t\t$this.SetNamedStatusBarText = function(name, text, timeout) {\n\t\t\tif (destroyinprogress)  return;\n\n\t\t\tif (!(name in elems.statusbartextsegmentmap))\n\t\t\t{\n\t\t\t\telems.statusbartextsegmentmap[name] = { pos: elems.statusbartextsegments.length, timeout: null };\n\n\t\t\t\tvar node = CreateNode('div', ['fe_fileexplorer_statusbar_text_segment_wrap']);\n\n\t\t\t\telems.statusbartextsegments.push(node);\n\t\t\t\telems.statusbartextwrap.appendChild(node);\n\t\t\t}\n\n\t\t\tvar currsegment = elems.statusbartextsegmentmap[name];\n\n\t\t\tif (currsegment.timeout)\n\t\t\t{\n\t\t\t\tclearTimeout(currsegment.timeout);\n\n\t\t\t\tcurrsegment.timeout = null;\n\t\t\t}\n\n\t\t\tvar elem = elems.statusbartextsegments[currsegment.pos];\n\n\t\t\tif (text === '')\n\t\t\t{\n\t\t\t\telem.innerHTML = '';\n\t\t\t\telem.classList.add('fe_fileexplorer_hidden');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\telem.innerHTML = text;\n\t\t\t\telem.classList.remove('fe_fileexplorer_hidden');\n\n\t\t\t\tif (timeout)\n\t\t\t\t{\n\t\t\t\t\telems.statusbartextsegmentmap[name].timeout = setTimeout(function() {\n\t\t\t\t\t\t$this.SetNamedStatusBarText(name, '');\n\t\t\t\t\t}, timeout);\n\n\t\t\t\t\t// Recalculate widths.\n\t\t\t\t\tvar widthmap = [], totalwidth = 1.5 * elems.statusbarmeasuresize.offsetWidth;\n\t\t\t\t\tfor (var x = 0; x < elems.statusbartextsegments.length; x++)\n\t\t\t\t\t{\n\t\t\t\t\t\tvar elem2 = elems.statusbartextsegments[x];\n\n\t\t\t\t\t\tif (elem2.classList.contains('fe_fileexplorer_hidden'))  widthmap.push(0);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvar currstyle = elem2.currentStyle || window.getComputedStyle(elem2);\n\t\t\t\t\t\t\tvar elemwidth = elem2.offsetWidth + parseFloat(currstyle.marginLeft) + parseFloat(currstyle.marginRight);\n\n\t\t\t\t\t\t\twidthmap.push(elemwidth);\n\n\t\t\t\t\t\t\ttotalwidth += elemwidth;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (var x = elems.statusbartextsegments.length; totalwidth >= elems.statusbartextwrap.offsetWidth && x; x--)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (widthmap[x - 1] && elem !== elems.statusbartextsegments[x - 1])\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\telems.statusbartextsegments[x - 1].classList.add('fe_fileexplorer_hidden');\n\n\t\t\t\t\t\t\ttotalwidth -= widthmap[x - 1];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Adjust the last visible class.\n\t\t\telem = null;\n\t\t\telems.statusbartextsegments.forEach(function(elem2) {\n\t\t\t\tif (!timeout && elem2.innerHTML !== '')  elem2.classList.remove('fe_fileexplorer_hidden');\n\n\t\t\t\tif (!elem2.classList.contains('fe_fileexplorer_hidden'))\n\t\t\t\t{\n\t\t\t\t\telem2.classList.remove('fe_fileexplorer_statusbar_text_segment_wrap_last');\n\n\t\t\t\t\telem = elem2;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (elem)  elem.classList.add('fe_fileexplorer_statusbar_text_segment_wrap_last');\n\t\t};\n\n\t\t$this.SetNamedStatusBarText('folder', '');\n\t\t$this.SetNamedStatusBarText('selected', '');\n\t\t$this.SetNamedStatusBarText('message', '');\n\n\t\telems.itemsmessagewrap.innerHTML = EscapeHTML($this.Translate('Loading...'));\n\n\t\t// Determine what text should show to the user when displaying the paste box.\n\t\tif (matchMedia('(pointer: coarse)').matches)  elems.itemsclipboardoverlaypastetexthint.innerHTML = EscapeHTML($this.Translate('Long-press + paste'));\n\t\telse if (navigator.platform.indexOf('Mac') > -1)  elems.itemsclipboardoverlaypastetexthint.innerHTML = EscapeHTML($this.Translate('\\u2318 + V\\u00A0\\u00A0\\u00A0/\\u00A0\\u00A0\\u00A0Right-click + Paste'));\n\t\telse  elems.itemsclipboardoverlaypastetexthint.innerHTML = EscapeHTML($this.Translate('Ctrl + V\\u00A0\\u00A0\\u00A0/\\u00A0\\u00A0\\u00A0Right-click + Paste'));\n\n\t\t// Attach elements to DOM.\n\t\telems.navtools.appendChild(elems.navtool_back);\n\t\telems.navtools.appendChild(elems.navtool_forward);\n\t\telems.navtools.appendChild(elems.navtool_history);\n\t\telems.navtools.appendChild(elems.navtool_up);\n\n\t\telems.pathicon.appendChild(elems.pathiconinner);\n\t\telems.pathwrap.appendChild(elems.pathicon);\n\n\t\telems.pathsegmentsscrollwrap.appendChild(elems.pathsegmentswrap);\n\t\telems.pathwrap.appendChild(elems.pathsegmentsscrollwrap);\n\n\t\telems.toolbar.appendChild(elems.navtools);\n\t\telems.toolbar.appendChild(elems.pathwrap);\n\n\t\telems.bodytoolsscrollwrap.appendChild(elems.bodytoolbar);\n\t\telems.itemsscrollwrapinner.appendChild(elems.itemsmessagewrap);\n\t\telems.itemsscrollwrapinner.appendChild(elems.itemswrap);\n\t\telems.itemsscrollwrap.appendChild(elems.itemsscrollwrapinner);\n\n\t\telems.itemsclipboardoverlaypastetext.appendChild(elems.itemsclipboardoverlaypastetextline);\n\t\telems.itemsclipboardoverlaypastetext.appendChild(elems.itemsclipboardoverlaypastetexthint);\n\t\telems.itemsclipboardoverlaypastetextwrap.appendChild(elems.itemsclipboardoverlaypastetext);\n\t\telems.itemsclipboardoverlaypasteinnerwrap.appendChild(elems.itemsclipboardoverlaypastetextwrap);\n\t\telems.itemsclipboardoverlaypasteinnerwrap.appendChild(elems.itemsclipboardoverlay);\n\t\telems.itemsclipboardoverlaypastewrap.appendChild(elems.itemsclipboardoverlaypasteinnerwrap);\n\n\t\telems.bodywrap.appendChild(elems.bodytoolsscrollwrap);\n\t\telems.bodywrap.appendChild(elems.itemsscrollwrap);\n\t\telems.bodywrapouter.appendChild(elems.bodywrap);\n\t\telems.bodywrapouter.appendChild(elems.itemsclipboardoverlaypastewrap);\n\n\t\telems.statusbaractionprogresswrap.appendChild(elems.statusbaractionprogressmessagewrap);\n\t\telems.statusbaractionprogresswrap.appendChild(elems.statusbaractionprogressmessagewrap2);\n\t\telems.statusbaractionprogresswrap.appendChild(elems.statusbaractionprogresscancelwrap);\n\t\telems.statusbaractionwrap.appendChild(elems.statusbaractionprogresswrap);\n\n\t\telems.statusbar.appendChild(elems.statusbarmeasuresize);\n\t\telems.statusbar.appendChild(elems.statusbartextwrap);\n\t\telems.statusbar.appendChild(elems.statusbaractionwrap);\n\n\t\telems.innerwrap.appendChild(elems.toolbar);\n\t\telems.innerwrap.appendChild(elems.bodywrapouter);\n\t\telems.innerwrap.appendChild(elems.statusbar);\n\t\telems.dropzonewrap.appendChild(elems.innerwrap);\n\t\telems.mainwrap.appendChild(elems.dropzonewrap);\n\n\t\tparentelem.appendChild(elems.mainwrap);\n\n\t\t$this.SetNamedStatusBarText('folder', EscapeHTML($this.Translate('Loading...')));\n\n\t\t// Adjusts the status bar based on how large/small the mainwrap element is.\n\t\tvar CalculateUpdateMultilineStatus = function() {\n\t\t\tif (elems.mainwrap.offsetWidth / elems.statusbarmeasuresize.offsetWidth < 58)  elems.statusbar.classList.add('fe_fileexplorer_statusbar_wrap_multiline');\n\t\t\telse  elems.statusbar.classList.remove('fe_fileexplorer_statusbar_wrap_multiline');\n\t\t};\n\n\t\tCalculateUpdateMultilineStatus();\n\n\t\t// Set up an offsetWidth attribute watcher that calls CalculateUpdateMultilineStatus.\n\t\tvar statusbarresizewatch = new DebounceAttributes({\n\t\t\twatchers: [\n\t\t\t\t{ elem: elems.mainwrap, attr: 'offsetWidth', val: -1 }\n\t\t\t],\n\t\t\tinterval: 50,\n\t\t\tstopsame: 5,\n\t\t\tcallback: CalculateUpdateMultilineStatus,\n\t\t\tintervalcallback: CalculateUpdateMultilineStatus\n\t\t});\n\n\t\twindow.addEventListener('resize', statusbarresizewatch.Start, true);\n\n\t\t// Internal DOM-style function.\n\t\tvar DispatchEvent = function(eventname, params) {\n\t\t\tif (!triggers[eventname])  return;\n\n\t\t\ttriggers[eventname].forEach(function(callback) {\n\t\t\t\tif (Array.isArray(params))  callback.apply($this, params);\n\t\t\t\telse  callback.call($this, params);\n\t\t\t});\n\t\t};\n\n\t\t// Public DOM-style functions.\n\t\t$this.addEventListener = function(eventname, callback) {\n\t\t\tif (!triggers[eventname])  triggers[eventname] = [];\n\n\t\t\tfor (var x in triggers[eventname])\n\t\t\t{\n\t\t\t\tif (triggers[eventname][x] === callback)  return;\n\t\t\t}\n\n\t\t\ttriggers[eventname].push(callback);\n\t\t};\n\n\t\t$this.removeEventListener = function(eventname, callback) {\n\t\t\tif (!triggers[eventname])  return;\n\n\t\t\tfor (var x in triggers[eventname])\n\t\t\t{\n\t\t\t\tif (triggers[eventname][x] === callback)\n\t\t\t\t{\n\t\t\t\t\ttriggers[eventname].splice(x, 1);\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t$this.hasEventListener = function(eventname) {\n\t\t\treturn (triggers[eventname] && triggers[eventname].length);\n\t\t};\n\n\t\t// Dispatches a tool-specific event to listeners.\n\t\t$this.DispatchToolEvent = function(eventname, params) {\n\t\t\tDispatchEvent('tool_' + eventname, params);\n\t\t};\n\n\t\t// Public DOM-style functions for tools.\n\t\t$this.addToolEventListener = function(eventname, callback) {\n\t\t\t$this.addEventListener('tool_' + eventname, callback);\n\t\t};\n\n\t\t$this.removeToolEventListener = function(eventname, callback) {\n\t\t\t$this.removeEventListener('tool_' + eventname, callback);\n\t\t};\n\n\t\t$this.hasToolEventListener = function(eventname, callback) {\n\t\t\treturn $this.hasEventListener('tool_' + eventname);\n\t\t};\n\n\t\t// Register settings callbacks.\n\t\tif ($this.settings.onfocus)  $this.addEventListener('focus', $this.settings.onfocus);\n\t\tif ($this.settings.onblur)  $this.addEventListener('blur', $this.settings.onblur);\n\t\tif ($this.settings.onrefresh)  $this.addEventListener('refresh_folder', $this.settings.onrefresh);\n\t\tif ($this.settings.onselchanged)  $this.addEventListener('selections_changed', $this.settings.onselchanged);\n\t\tif ($this.settings.onrename)  $this.addEventListener('rename', $this.settings.onrename);\n\t\tif ($this.settings.onopenfile)  $this.addEventListener('open_file', $this.settings.onopenfile);\n\t\tif ($this.settings.oninitupload)  $this.addEventListener('init_upload', $this.settings.oninitupload);\n\t\tif ($this.settings.onuploaderror)  $this.addEventListener('upload_error', $this.settings.onuploaderror);\n\t\tif ($this.settings.onfinishedupload)  $this.addEventListener('upload_done', $this.settings.onfinishedupload);\n\t\tif ($this.settings.ondownloadurl)  $this.addEventListener('get_download_url', $this.settings.ondownloadurl);\n\t\tif ($this.settings.oncopy)  $this.addEventListener('copy', $this.settings.oncopy);\n\t\tif ($this.settings.onmove)  $this.addEventListener('move', $this.settings.onmove);\n\t\tif ($this.settings.ondelete)  $this.addEventListener('delete', $this.settings.ondelete);\n\n\t\t// Capture browser-level back/forward buttons.  Alters browser history.\n\t\tvar CapturePopStateHandler = function(e) {\n\t\t\tif (e.state && e.state._fileexplorer)\n\t\t\t{\n\t\t\t\tif (e.state._fileexplorer === 'back')\n\t\t\t\t{\n\t\t\t\t\twindow.history.forward();\n\n\t\t\t\t\t$this.HistoryBack();\n\t\t\t\t\t$this.Focus(true);\n\t\t\t\t}\n\t\t\t\telse if (e.state._fileexplorer === 'forward')\n\t\t\t\t{\n\t\t\t\t\twindow.history.back();\n\n\t\t\t\t\t$this.HistoryForward();\n\t\t\t\t\t$this.Focus(true);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Sets up three history items and places the user in the middle of those three.\n\t\tvar internalcapturerefs = 0;\n\t\tvar CaptureMouseEnterHandler = function(e) {\n\t\t\tif (!capturingrefs)  prevscrollrestore = window.history.scrollRestoration;\n\n\t\t\tcapturingrefs++;\n\t\t\tinternalcapturerefs++;\n\n\t\t\tif (internalcapturerefs === 1)\n\t\t\t{\n\t\t\t\twindow.history.scrollRestoration = 'manual';\n\t\t\t\twindow.history.pushState({ _fileexplorer: 'back', _fileexplorerprevscroll: prevscrollrestore }, document.title);\n\t\t\t\twindow.history.scrollRestoration = 'manual';\n\t\t\t\twindow.history.pushState({ _fileexplorer: 'main' }, document.title);\n\t\t\t\twindow.history.scrollRestoration = 'manual';\n\t\t\t\twindow.history.pushState({ _fileexplorer: 'forward' }, document.title);\n\t\t\t\twindow.history.scrollRestoration = 'manual';\n\t\t\t\twindow.history.back();\n\n\t\t\t\twindow.addEventListener('popstate', CapturePopStateHandler, true);\n\t\t\t}\n\t\t};\n\n\t\t// Restores the browser history as best as possible.\n\t\tvar CaptureMouseLeaveHandler = function(e) {\n\t\t\tcapturingrefs--;\n\t\t\tinternalcapturerefs--;\n\n\t\t\tif (!internalcapturerefs)\n\t\t\t{\n\t\t\t\twindow.removeEventListener('popstate', CapturePopStateHandler, true);\n\n\t\t\t\tif (window.history.state && window.history.state._fileexplorer)  window.history.back();\n\t\t\t}\n\t\t};\n\n\t\tif ($this.settings.capturebrowser)\n\t\t{\n\t\t\telems.mainwrap.addEventListener('mouseenter', CaptureMouseEnterHandler);\n\t\t\telems.mainwrap.addEventListener('mouseleave', CaptureMouseLeaveHandler);\n\t\t}\n\n\t\t// Handle main wrap focus.\n\t\tvar MainWrapFocusMouseHandler = function(e) {\n\t\t\telems.innerwrap.classList.add('fe_fileexplorer_inner_wrap_focused');\n\n\t\t\tvar node = document.activeElement;\n\t\t\twhile (node && node !== elems.mainwrap)  node = node.parentNode;\n\n\t\t\tif (node !== elems.mainwrap)  elems.itemsscrollwrap.focus();\n\t\t};\n\n\t\telems.mainwrap.addEventListener('mousedown', MainWrapFocusMouseHandler);\n\t\telems.mainwrap.addEventListener('mouseup', MainWrapFocusMouseHandler);\n\t\telems.mainwrap.addEventListener('click', MainWrapFocusMouseHandler);\n\n\t\t// Set up focusing rules.\n\t\tif ($this.settings.alwaysfocused)  elems.innerwrap.classList.add('fe_fileexplorer_inner_wrap_focused');\n\n\t\tvar hasfocus = false;\n\t\tvar InnerWrapBlurHandler = function(e) {\n\t\t\tvar node = e.target;\n\t\t\twhile (node && node !== elems.mainwrap)  node = node.parentNode;\n\n\t\t\tif (node !== elems.mainwrap)\n\t\t\t{\n\t\t\t\tif (!$this.settings.alwaysfocused)  elems.innerwrap.classList.remove('fe_fileexplorer_inner_wrap_focused');\n\n\t\t\t\tif (hasfocus)  DispatchEvent('blur', e);\n\n\t\t\t\thasfocus = false;\n\t\t\t}\n\t\t};\n\n\t\twindow.addEventListener('mousedown', InnerWrapBlurHandler, true);\n\n\t\t// Trigger window blur visual appearance changes.\n\t\tvar InnerWrapWindowBlurHandler = function(e) {\n\t\t\tif (e.target === window || e.target === document)\n\t\t\t{\n\t\t\t\tif (!$this.settings.alwaysfocused)  elems.innerwrap.classList.remove('fe_fileexplorer_inner_wrap_focused');\n\t\t\t}\n\t\t};\n\n\t\twindow.addEventListener('blur', InnerWrapWindowBlurHandler, true);\n\n\t\t// When the tab key is pressed, adjust the focus.\n\t\tvar FocusKeyHandler = function(e) {\n\t\t\t// Handle window-level focus events specially.  There will be another focus event if actually focused.\n\t\t\tif (e.target === window || e.target === document)\n\t\t\t{\n\t\t\t\tvar node = document.activeElement;\n\t\t\t\twhile (node && node !== elems.mainwrap)  node = node.parentNode;\n\n\t\t\t\tif (node === elems.mainwrap)  elems.innerwrap.classList.add('fe_fileexplorer_inner_wrap_focused');\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar node = e.target;\n\t\t\twhile (node && node !== elems.itemsscrollwrap && node !== elems.mainwrap)  node = node.parentNode;\n\n\t\t\tif (node === elems.itemsscrollwrap || e.target === elems.itemsclipboardoverlay)  elems.itemswrap.classList.add('fe_fileexplorer_items_focus');\n\t\t\telse  elems.itemswrap.classList.remove('fe_fileexplorer_items_focus');\n\n\t\t\twhile (node && node !== elems.mainwrap)  node = node.parentNode;\n\n\t\t\tif (node === elems.mainwrap)\n\t\t\t{\n\t\t\t\telems.innerwrap.classList.add('fe_fileexplorer_inner_wrap_focused');\n\n\t\t\t\tDispatchEvent('focus', e);\n\n\t\t\t\thasfocus = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (!$this.settings.alwaysfocused)  elems.innerwrap.classList.remove('fe_fileexplorer_inner_wrap_focused');\n\n\t\t\t\tif (hasfocus)  DispatchEvent('blur', e);\n\n\t\t\t\thasfocus = false;\n\t\t\t}\n\t\t};\n\n\t\twindow.addEventListener('focus', FocusKeyHandler, true);\n\n\t\t// If the device has a coarse pointer (e.g. touch), show checkboxes.\n\t\tif (matchMedia('(pointer: coarse)').matches)  elems.innerwrap.classList.add('fe_fileexplorer_show_item_checkboxes');\n\n\t\t// Toolbar button keyboard navigation.\n\t\tvar ToolbarKeyHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (e.target.tagName === 'BUTTON')\n\t\t\t{\n\t\t\t\tif (e.keyCode == 38)\n\t\t\t\t{\n\t\t\t\t\t// Up arrow.\n\t\t\t\t\tvar lastelem = null;\n\t\t\t\t\tfor (var x = 0; x < elems.bodytools.length; x++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (elems.bodytools[x].tabIndex == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!lastelem)  elems.bodytools[x].focus();\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\t\t\tlastelem.tabIndex = 0;\n\t\t\t\t\t\t\t\tlastelem.focus();\n\t\t\t\t\t\t\t\telems.bodytools[x].tabIndex = -1;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!elems.bodytools[x].classList.contains('fe_fileexplorer_disabled'))  lastelem = elems.bodytools[x];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (e.keyCode == 40)\n\t\t\t\t{\n\t\t\t\t\t// Down arrow.\n\t\t\t\t\tfor (var x = elems.bodytools.length; x; x--)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (elems.bodytools[x - 1].tabIndex == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!lastelem)  elems.bodytools[x - 1].focus();\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\t\t\tlastelem.tabIndex = 0;\n\t\t\t\t\t\t\t\tlastelem.focus();\n\t\t\t\t\t\t\t\telems.bodytools[x - 1].tabIndex = -1;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!elems.bodytools[x - 1].classList.contains('fe_fileexplorer_disabled'))  lastelem = elems.bodytools[x - 1];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\telems.bodytoolbar.addEventListener('keydown', ToolbarKeyHandler);\n\n\t\tvar ToolbarToolFocusHandler = function(e) {\n\t\t\tvar node = e.target;\n\n\t\t\tif (node.parentNode === elems.bodytoolbar)\n\t\t\t{\n\t\t\t\tif (node.offsetTop - 1 < elems.bodytoolsscrollwrap.scrollTop)  elems.bodytoolsscrollwrap.scrollTop = node.offsetTop - 1;\n\t\t\t\telse if (node.offsetTop + node.offsetHeight + 1 > elems.bodytoolsscrollwrap.scrollTop + elems.bodytoolsscrollwrap.clientHeight)  elems.bodytoolsscrollwrap.scrollTop = (node.offsetTop + node.offsetHeight + 1) - elems.bodytoolsscrollwrap.clientHeight;\n\t\t\t}\n\t\t};\n\n\t\telems.bodytoolsscrollwrap.addEventListener('focus', ToolbarToolFocusHandler, true);\n\n\t\tvar toolupdated = false;\n\t\t$this.ToolStateUpdated = function() {\n\t\t\ttoolupdated = true;\n\t\t};\n\n\t\tvar UpdateToolbarIcons = function() {\n\t\t\ttoolupdated = false;\n\n\t\t\tDispatchEvent('update_tool', [currfolder, currfolder.GetAttributes()]);\n\n\t\t\tif (toolupdated)\n\t\t\t{\n\t\t\t\t// Find the tab-focus element.\n\t\t\t\tvar found = false;\n\t\t\t\tfor (var x = 0; x < elems.bodytools.length; x++)\n\t\t\t\t{\n\t\t\t\t\tif (elems.bodytools[x].tabIndex == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// If the tool is disabled, attempt to find a nearby tool that isn't disabled and update the tab index.\n\t\t\t\t\t\tif (!elems.bodytools[x].classList.contains('fe_fileexplorer_disabled'))  found = true;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (var x2 = x; x2; x2--)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (!elems.bodytools[x2 - 1].classList.contains('fe_fileexplorer_disabled'))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\telems.bodytools[x2 - 1].tabIndex = 0;\n\t\t\t\t\t\t\t\t\tif (document.activeElement === elems.bodytools[x])  elems.bodytools[x2 - 1].focus();\n\n\t\t\t\t\t\t\t\t\tfound = true;\n\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (!found)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfor (var x2 = x + 1; x2 < elems.bodytools.length; x2++)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (!elems.bodytools[x2].classList.contains('fe_fileexplorer_disabled'))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tfound = true;\n\n\t\t\t\t\t\t\t\t\t\telems.bodytools[x2].tabIndex = 0;\n\t\t\t\t\t\t\t\t\t\tif (document.activeElement === elems.bodytools[x])  elems.bodytools[x2].focus();\n\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (!found && document.activeElement === elems.bodytools[x])  $this.Focus(true);\n\t\t\t\t\t\t\telems.bodytools[x].tabIndex = -1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!found)\n\t\t\t\t{\n\t\t\t\t\tfor (var x = 0; x < elems.bodytools.length; x++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!elems.bodytools[x].classList.contains('fe_fileexplorer_disabled'))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\telems.bodytools[x].tabIndex = 0;\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\n\t\tvar selecteditemsmap = {}, numselecteditems = 0, focuseditem = false, lastanchorpos = 0, popupmenu = null;\n\n\t\t// Clear selected items.\n\t\t$this.ClearSelectedItems = function(ignorebusy, skipuiupdate) {\n\t\t\t// If the current folder is busy, then queue the change for later.\n\t\t\tif (currfolder && currfolder.IsBusy() && !ignorebusy)\n\t\t\t{\n\t\t\t\tcurrfolder.AddBusyQueueCallback($this.ClearSelectedItems, [ignorebusy, skipuiupdate]);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!currfolder || currfolder.waiting)  return;\n\n\t\t\t// Clear selected.\n\t\t\tvar node;\n\t\t\tfor (var x in selecteditemsmap)\n\t\t\t{\n\t\t\t\tif (selecteditemsmap.hasOwnProperty(x))\n\t\t\t\t{\n\t\t\t\t\tnode = elems.itemswrap.children[selecteditemsmap[x]];\n\n\t\t\t\t\tif (node)\n\t\t\t\t\t{\n\t\t\t\t\t\tnode.classList.remove('fe_fileexplorer_item_selected');\n\t\t\t\t\t\tnode.firstChild.firstChild.checked = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tselecteditemsmap = {};\n\t\t\tnumselecteditems = 0;\n\n\t\t\tif (!skipuiupdate)\n\t\t\t{\n\t\t\t\t// Update toolbar icons.\n\t\t\t\tUpdateToolbarIcons();\n\n\t\t\t\t// Update the status bar and notify listeners.\n\t\t\t\tUpdateSelectionsChanged();\n\t\t\t}\n\t\t};\n\n\t\t// Select all items.  Does not dispatch selection change events.\n\t\t$this.SelectAllItems = function(skipuiupdate) {\n\t\t\t// If the current folder is busy, then queue the change for later.\n\t\t\tif (currfolder && currfolder.IsBusy())\n\t\t\t{\n\t\t\t\tcurrfolder.AddBusyQueueCallback($this.SelectAllItems, [skipuiupdate]);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!currfolder || currfolder.waiting)  return;\n\n\t\t\tfor (var x = 0; x < elems.itemswrap.children.length; x++)\n\t\t\t{\n\t\t\t\tvar node = elems.itemswrap.children[x];\n\n\t\t\t\tif (!(node.dataset.feid in selecteditemsmap))\n\t\t\t\t{\n\t\t\t\t\tnode.classList.add('fe_fileexplorer_item_selected');\n\t\t\t\t\tnode.firstChild.firstChild.checked = true;\n\n\t\t\t\t\tselecteditemsmap[node.dataset.feid] = x;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tnumselecteditems = elems.itemswrap.children.length;\n\n\t\t\tif (!skipuiupdate)\n\t\t\t{\n\t\t\t\t// Update toolbar icons.\n\t\t\t\tUpdateToolbarIcons();\n\n\t\t\t\t// Update the status bar and notify listeners.\n\t\t\t\tUpdateSelectionsChanged();\n\t\t\t}\n\t\t};\n\n\t\t// Toggles selection of a specific item.\n\t\t$this.ToggleItemSelection = function(elem, ignorebusy, skipuiupdate) {\n\t\t\tif (!currfolder || currfolder.waiting || (!ignorebusy && currfolder.IsBusy()))  return;\n\n\t\t\tif (typeof elem === 'string')\n\t\t\t{\n\t\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\n\t\t\t\tif (!(elem in entryidmap))  return;\n\n\t\t\t\telem = elems.itemswrap.children[entryidmap[elem]];\n\t\t\t}\n\n\t\t\tif (elem.dataset.feid in selecteditemsmap)\n\t\t\t{\n\t\t\t\telem.classList.remove('fe_fileexplorer_item_selected');\n\t\t\t\telem.firstChild.firstChild.checked = false;\n\n\t\t\t\tdelete selecteditemsmap[elem.dataset.feid];\n\n\t\t\t\tnumselecteditems--;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\t\t\t\tif (elem.dataset.feid in entryidmap)\n\t\t\t\t{\n\t\t\t\t\tvar entrynum = entryidmap[elem.dataset.feid];\n\n\t\t\t\t\telem.classList.add('fe_fileexplorer_item_selected');\n\t\t\t\t\telem.firstChild.firstChild.checked = true;\n\n\t\t\t\t\tselecteditemsmap[elem.dataset.feid] = entrynum;\n\t\t\t\t\tnumselecteditems++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!skipuiupdate)\n\t\t\t{\n\t\t\t\t// Update toolbar icons.\n\t\t\t\tUpdateToolbarIcons();\n\n\t\t\t\t// Update the status bar and notify listeners.\n\t\t\t\tUpdateSelectionsChanged();\n\t\t\t}\n\t\t};\n\n\t\t// Selects all items from the last anchor to the focused item.\n\t\t$this.SelectItemsFromLastAnchor = function(ignorebusy, skipuiupdate) {\n\t\t\tif (!currfolder || currfolder.waiting || (!ignorebusy && currfolder.IsBusy()))  return;\n\n\t\t\tif (focuseditem === false)  return;\n\n\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\t\t\tvar entrynum = entryidmap[focuseditem.dataset.feid];\n\n\t\t\t$this.ClearSelectedItems(ignorebusy, true);\n\n\t\t\tvar pos = lastanchorpos;\n\t\t\tvar pos2 = entrynum;\n\n\t\t\tif (pos > pos2)\n\t\t\t{\n\t\t\t\tvar pos3 = pos;\n\t\t\t\tpos = pos2;\n\t\t\t\tpos2 = pos3;\n\t\t\t}\n\n\t\t\tfor (; pos <= pos2; pos++)\n\t\t\t{\n\t\t\t\tvar elem = elems.itemswrap.children[pos];\n\n\t\t\t\telem.classList.add('fe_fileexplorer_item_selected');\n\t\t\t\telem.firstChild.firstChild.checked = true;\n\n\t\t\t\tselecteditemsmap[elem.dataset.feid] = pos;\n\t\t\t\tnumselecteditems++;\n\t\t\t}\n\n\t\t\tif (!skipuiupdate)\n\t\t\t{\n\t\t\t\t// Update toolbar icons.\n\t\t\t\tUpdateToolbarIcons();\n\n\t\t\t\t// Update the status bar and notify listeners.\n\t\t\t\tUpdateSelectionsChanged();\n\t\t\t}\n\t\t};\n\n\t\t// Sets the item that has focus.\n\t\t$this.SetFocusItem = function(id, updateanchor) {\n\t\t\tif (!currfolder || currfolder.waiting)  return;\n\n\t\t\tvar node = null;\n\t\t\tif (typeof id === 'string')\n\t\t\t{\n\t\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\n\t\t\t\tif (id in entryidmap)\n\t\t\t\t{\n\t\t\t\t\tnode = elems.itemswrap.children[entryidmap[id]];\n\n\t\t\t\t\tif (node)\n\t\t\t\t\t{\n\t\t\t\t\t\tnode.classList.add('fe_fileexplorer_item_focused');\n\t\t\t\t\t\tnode.firstChild.tabIndex = 0;\n\t\t\t\t\t\tnode.firstChild.focus();\n\n\t\t\t\t\t\tif (updateanchor)  lastanchorpos = entryidmap[id];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (focuseditem !== false && focuseditem !== node)\n\t\t\t{\n\t\t\t\tfocuseditem.classList.remove('fe_fileexplorer_item_focused');\n\t\t\t\tfocuseditem.firstChild.tabIndex = -1;\n\n\t\t\t\tfocuseditem = false;\n\t\t\t}\n\n\t\t\tif (node)  focuseditem = node;\n\t\t};\n\n\t\t// Scrolls the view so the focused item is fully viewable.\n\t\t$this.ScrollToFocusedItem = function() {\n\t\t\tif (focuseditem !== false)\n\t\t\t{\n\t\t\t\tif (focuseditem.offsetTop - 1 < elems.itemsscrollwrap.scrollTop)  elems.itemsscrollwrap.scrollTop = focuseditem.offsetTop - 1;\n\t\t\t\telse if (focuseditem.offsetTop + focuseditem.offsetHeight + 1 > elems.itemsscrollwrap.scrollTop + elems.itemsscrollwrap.clientHeight)  elems.itemsscrollwrap.scrollTop = (focuseditem.offsetTop + focuseditem.offsetHeight + 1) - elems.itemsscrollwrap.clientHeight;\n\t\t\t}\n\t\t};\n\n\t\t// Opens selected items.\n\t\t$this.OpenSelectedItems = function() {\n\t\t\tif (!currfolder || currfolder.waiting || currfolder.IsBusy())  return;\n\n\t\t\tvar entries = currfolder.GetEntries();\n\t\t\tvar selnums = [];\n\t\t\tvar numfolders = 0, folderentry = null;\n\n\t\t\tfor (var x in selecteditemsmap)\n\t\t\t{\n\t\t\t\tif (selecteditemsmap.hasOwnProperty(x))  selnums.push(selecteditemsmap[x]);\n\t\t\t}\n\n\t\t\tselnums.sort(function(a, b) { return (a < b ? -1 : 1); });\n\n\t\t\tfor (var x = 0; x < selnums.length; x++)\n\t\t\t{\n\t\t\t\tvar entry = entries[selnums[x]];\n\n\t\t\t\tif (entry.type === 'folder')\n\t\t\t\t{\n\t\t\t\t\tfolderentry = entry;\n\n\t\t\t\t\tnumfolders++;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tDispatchEvent('open_file', [currfolder, entry]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (numfolders === 1)\n\t\t\t{\n\t\t\t\t$this.Focus(true);\n\n\t\t\t\tvar newpath = currfolder.GetPath().slice();\n\n\t\t\t\t// Append the new path segment.\n\t\t\t\tvar pathitem = [folderentry.id, folderentry.name];\n\t\t\t\tif ('attrs' in folderentry)  pathitem.push(folderentry.attrs);\n\n\t\t\t\tnewpath.push(pathitem);\n\n\t\t\t\t$this.SetPath(newpath);\n\t\t\t}\n\t\t};\n\n\t\t// Adjusts images in the thumbnail loading queue.\n\t\tvar queuedthumbs = {}, queuedthumbfailed = {}, queuedthumbfolder, queuedthumbstartrow, queuedthumbendrow;\n\n\t\tvar ThumbnailDisplayHandler = function(opts, success) {\n\t\t\tif (queuedthumbfolder !== currfolder)  return;\n\n\t\t\tif (!success)  queuedthumbfailed[opts.src] = true;\n\t\t\telse\n\t\t\t{\n\t\t\t\tvar entries = currfolder.GetEntries();\n\t\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\n\t\t\t\tif ((opts.id in queuedthumbs) && (queuedthumbs[opts.id] in entryidmap))\n\t\t\t\t{\n\t\t\t\t\tvar pos = entryidmap[queuedthumbs[opts.id]];\n\t\t\t\t\tvar node = elems.itemswrap.children[pos].firstChild.firstChild.nextSibling;\n\n\t\t\t\t\tnode.className = 'fe_fileexplorer_item_icon fe_fileexplorer_item_icon_img';\n\t\t\t\t\tnode.appendChild(opts.img);\n\n\t\t\t\t\tentries[pos].thumb = false;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tvar ThumbnailQueueUpdate = function() {\n\t\t\tUpdateCurrFolderItemCache(false);\n\n\t\t\t// Clear the thumbnail queue if the folder changed since the last call.\n\t\t\tif (queuedthumbfolder !== currfolder)\n\t\t\t{\n\t\t\t\tif (queuedthumbfolder)  DecrementMappedFolderRefCount(queuedthumbfolder);\n\n\t\t\t\tfor (var x in queuedthumbs)\n\t\t\t\t{\n\t\t\t\t\tif (queuedthumbs.hasOwnProperty(x))\n\t\t\t\t\t{\n\t\t\t\t\t\tfe_thumbnailloader.RemoveFromQueue(x);\n\n\t\t\t\t\t\tdelete queuedthumbs[x];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tqueuedthumbfailed = {};\n\n\t\t\t\tqueuedthumbfolder = currfolder;\n\t\t\t\tqueuedthumbfolder.refs++;\n\n\t\t\t\tqueuedthumbstartrow = 0;\n\t\t\t\tqueuedthumbendrow = (folderitemcache.rows.length ? folderitemcache.rows.length - 1 : 0);\n\t\t\t}\n\n\t\t\t// Remove non-active items and removed folder entries from the thumbnail queue.\n\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\t\t\tfor (var x in queuedthumbs)\n\t\t\t{\n\t\t\t\tif (!fe_thumbnailloader.IsActive(x) || !(queuedthumbs[x] in entryidmap))\n\t\t\t\t{\n\t\t\t\t\tfe_thumbnailloader.RemoveFromQueue(x);\n\n\t\t\t\t\tdelete queuedthumbs[x];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!folderitemcache.size)  return;\n\n\t\t\t// Calculate the new start and end row item cache positions.\n\t\t\tvar miny = elems.itemsscrollwrap.scrollTop;\n\t\t\tvar maxy = miny + elems.itemsscrollwrap.offsetHeight;\n\n\t\t\t// Adjust start and end row until they fall within two tops.\n\t\t\twhile (queuedthumbstartrow && (queuedthumbstartrow > folderitemcache.rows.length - 1 || miny < folderitemcache.rows[queuedthumbstartrow].top))  queuedthumbstartrow--;\n\t\t\twhile (queuedthumbstartrow < folderitemcache.rows.length - 1 && miny >= folderitemcache.rows[queuedthumbstartrow + 1].top)  queuedthumbstartrow++;\n\n\t\t\twhile (queuedthumbendrow && (queuedthumbendrow > folderitemcache.rows.length - 1 || maxy < folderitemcache.rows[queuedthumbendrow].top))  queuedthumbendrow--;\n\t\t\tif (queuedthumbendrow < queuedthumbstartrow)  queuedthumbendrow = queuedthumbstartrow;\n\t\t\twhile (queuedthumbendrow < folderitemcache.rows.length - 1 && maxy >= folderitemcache.rows[queuedthumbendrow + 1].top)  queuedthumbendrow++;\n\n\t\t\t// Add items to the thumbnail queue.\n\t\t\tvar entries = currfolder.GetEntries();\n\t\t\tvar y = (queuedthumbendrow + 1) * folderitemcache.cols.length;\n\t\t\tif (y > entries.length)  y = entries.length;\n\t\t\tfor (var x = queuedthumbstartrow * folderitemcache.cols.length; x < y; x++)\n\t\t\t{\n\t\t\t\tif (entries[x].thumb && (typeof entries[x].thumb !== 'string' || !queuedthumbfailed[entries[x].thumb]))\n\t\t\t\t{\n\t\t\t\t\t// Build the thumbnail queue options.\n\t\t\t\t\tif (typeof entries[x].thumb === 'string')\n\t\t\t\t\t{\n\t\t\t\t\t\tentries[x].thumb = {\n\t\t\t\t\t\t\tsrc: entries[x].thumb,\n\t\t\t\t\t\t\tcallback: ThumbnailDisplayHandler\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\tfe_thumbnailloader.AddToQueue(entries[x].thumb);\n\n\t\t\t\t\tqueuedthumbs[entries[x].thumb.id] = entries[x].id;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfe_thumbnailloader.ProcessQueue();\n\t\t};\n\n\t\t// Set up a scrollTop/clientWidth attribute watcher that calls ThumbnailQueueUpdate after 10 identical scrollTop and clientWidth values over a period of 500ms.\n\t\tvar thumbnailscrollwatch = new DebounceAttributes({\n\t\t\twatchers: [\n\t\t\t\t{ elem: elems.itemsscrollwrap, attr: 'scrollTop', val: -1 },\n\t\t\t\t{ elem: elems.itemsscrollwrapinner, attr: 'clientWidth', val: -1 }\n\t\t\t],\n\t\t\tinterval: 50,\n\t\t\tstopsame: 10,\n\t\t\tcallback: ThumbnailQueueUpdate\n\t\t});\n\n\t\telems.itemsscrollwrap.addEventListener('scroll', thumbnailscrollwatch.Start);\n\t\twindow.addEventListener('resize', thumbnailscrollwatch.Start, true);\n\n\t\t// Track the position information of each item in the current folder.\n\t\tvar folderitemcache;\n\t\tvar UpdateCurrFolderItemCache = function(forcerefresh) {\n\t\t\tif (!forcerefresh && folderitemcache && folderitemcache.lastinnerwidth === elems.itemsscrollwrapinner.clientWidth && folderitemcache.size === elems.itemswrap.children.length)  return;\n\n\t\t\tfolderitemcache = {\n\t\t\t\tlastinnerwidth: elems.itemsscrollwrapinner.clientWidth,\n\t\t\t\tsize: elems.itemswrap.children.length,\n\t\t\t\tcols: [],\n\t\t\t\trows: []\n\t\t\t};\n\n\t\t\tif (!folderitemcache.size)  return;\n\n\t\t\tvar node = elems.itemswrap.firstChild;\n\t\t\tvar basey = node.firstChild.offsetTop;\n\t\t\tvar currrow = { top: basey, bottoms: [] };\n\t\t\twhile (node)\n\t\t\t{\n\t\t\t\tvar childnode = node.firstChild;\n\n\t\t\t\t// Calculate column boundaries of the items in the first row.\n\t\t\t\tif (childnode.offsetTop === basey)  folderitemcache.cols.push({ left: childnode.offsetLeft, right: childnode.offsetLeft + childnode.offsetWidth });\n\n\t\t\t\t// Calculate row boundaries of each item.\n\t\t\t\tif (childnode.offsetTop !== currrow.top)\n\t\t\t\t{\n\t\t\t\t\tfolderitemcache.rows.push(currrow);\n\n\t\t\t\t\tcurrrow = { top: childnode.offsetTop, bottoms: [] };\n\t\t\t\t}\n\n\t\t\t\tcurrrow.bottoms.push(currrow.top + childnode.offsetHeight);\n\n\t\t\t\tnode = node.nextSibling;\n\t\t\t}\n\n\t\t\tif (currrow.bottoms.length)  folderitemcache.rows.push(currrow);\n\t\t};\n\n\t\t// Update the selected items status bar and notify selection change listeners.\n\t\tvar UpdateSelectionsChanged = function() {\n\t\t\t// Calculate the total size for all selected items.  Set the last selected item as well.\n\t\t\tvar totalsize = 0, numfound = 0, sizestr, entries = currfolder.GetEntries();\n\t\t\thistorystack[currhistory].lastselected = false;\n\t\t\tfor (var x in selecteditemsmap)\n\t\t\t{\n\t\t\t\tif (selecteditemsmap.hasOwnProperty(x))\n\t\t\t\t{\n\t\t\t\t\tif (numselecteditems == 1)  historystack[currhistory].lastselected = x;\n\n\t\t\t\t\tif ('size' in entries[selecteditemsmap[x]])\n\t\t\t\t\t{\n\t\t\t\t\t\ttotalsize += entries[selecteditemsmap[x]].size;\n\t\t\t\t\t\tnumfound++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (numfound)  sizestr = GetDisplayFilesize(totalsize, $this.settings.adjustprecision, $this.settings.displayunits);\n\n\t\t\t// Update the status bar.\n\t\t\tif (numselecteditems == 0)  $this.SetNamedStatusBarText('selected', '');\n\t\t\telse if (numselecteditems > 1)\n\t\t\t{\n\t\t\t\tif (numfound)  $this.SetNamedStatusBarText('selected', EscapeHTML(FormatStr($this.Translate('{0} items selected {1}'), numselecteditems, sizestr)));\n\t\t\t\telse  $this.SetNamedStatusBarText('selected', EscapeHTML(FormatStr($this.Translate('{0} items selected'), numselecteditems)));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (numfound)  $this.SetNamedStatusBarText('selected', EscapeHTML(FormatStr($this.Translate('1 item selected {0}'), sizestr)));\n\t\t\t\telse  $this.SetNamedStatusBarText('selected', EscapeHTML($this.Translate('1 item selected')));\n\t\t\t}\n\n\t\t\t// Notify selection change listeners.\n\t\t\tDispatchEvent('selections_changed', [currfolder, selecteditemsmap, numselecteditems]);\n\t\t};\n\n\t\t// Rare update attributes callback.  Just updates tools for now.\n\t\tvar SetFolderAttributesHandler = function() {\n\t\t\t// Update toolbar icons.\n\t\t\tUpdateToolbarIcons();\n\t\t};\n\n\t\t// Efficiently synchronizes the current folder entries to the DOM.\n\t\tvar SyncCurrFolderToDOM = function() {\n\t\t\tvar entries = currfolder.GetEntries();\n\n\t\t\t// Create a mapping from ids to existing DOM nodes.\n\t\t\tvar x, elemmap = {};\n\t\t\tvar nodes = elems.itemswrap.children;\n\t\t\tfor (x = 0; x < nodes.length; x++)\n\t\t\t{\n\t\t\t\telemmap[nodes[x].dataset.feid] = [x, nodes[x].dataset.fehash, nodes[x], false];\n\t\t\t}\n\n\t\t\t// If moved forward to an earlier folder, select the subfolder item ID.\n\t\t\tif (currhistory > 0 && currhistory === historystack.length - 1 && historystack[currhistory].lastselected === true)\n\t\t\t{\n\t\t\t\tvar currkey = historystack[currhistory].folderkeys[historystack[currhistory].folderkeys.length - 1];\n\n\t\t\t\tfor (x = 0; x < historystack[currhistory - 1].folderkeys.length - 1; x++)\n\t\t\t\t{\n\t\t\t\t\tif (currkey === historystack[currhistory - 1].folderkeys[x])\n\t\t\t\t\t{\n\t\t\t\t\t\tvar temppath = foldermap[historystack[currhistory - 1].folderkeys[x + 1]].GetPath();\n\n\t\t\t\t\t\thistorystack[currhistory].lastselected = temppath[temppath.length - 1][0];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Skip any starting matching nodes.\n\t\t\tvar node, historyselected = false, selchanged = false;\n\t\t\tfor (x = 0; x < entries.length && elemmap[entries[x].id] && entries[x].hash === elemmap[entries[x].id][1]; x++)\n\t\t\t{\n\t\t\t\tnode = elemmap[entries[x].id][2];\n\n\t\t\t\telemmap[entries[x].id][3] = true;\n\n\t\t\t\t// Select item if it matches last selection.\n\t\t\t\tif (!selchanged && historystack[currhistory].lastselected === node.dataset.feid && !(node.dataset.feid in selecteditemsmap))\n\t\t\t\t{\n\t\t\t\t\tnode.classList.add('fe_fileexplorer_item_selected');\n\t\t\t\t\tnode.firstChild.firstChild.checked = true;\n\n\t\t\t\t\tselecteditemsmap[node.dataset.feid] = x;\n\t\t\t\t\tnumselecteditems++;\n\n\t\t\t\t\thistoryselected = true;\n\t\t\t\t\tselchanged = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar tempscroll = elems.itemsscrollwrap.scrollTop;\n\n\t\t\t// Append new nodes and update existing nodes that have changed.\n\t\t\tfor (; x < entries.length; x++)\n\t\t\t{\n\t\t\t\tvar itemicon, itemtext;\n\n\t\t\t\tif (entries[x].id in elemmap)\n\t\t\t\t{\n\t\t\t\t\t// Found an existing item.\n\t\t\t\t\tnode = elemmap[entries[x].id][2];\n\t\t\t\t\telemmap[entries[x].id][3] = true;\n\n\t\t\t\t\titemicon = node.firstChild.children[1];\n\t\t\t\t\titemtext = node.firstChild.lastChild;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Create a new item.\n\t\t\t\t\tnode = CreateNode('div', ['fe_fileexplorer_item_wrap']);\n\t\t\t\t\tvar iteminner = CreateNode('div', ['fe_fileexplorer_item_wrap_inner'], { tabIndex: -1, draggable: true });\n\t\t\t\t\tvar itemcheckbox = CreateNode('input', ['fe_fileexplorer_item_checkbox'], { type: 'checkbox', tabIndex: -1 });\n\n\t\t\t\t\titemicon = CreateNode('div', ['fe_fileexplorer_item_icon']);\n\t\t\t\t\titemtext = CreateNode('div', ['fe_fileexplorer_item_text']);\n\n\t\t\t\t\titeminner.appendChild(itemcheckbox);\n\t\t\t\t\titeminner.appendChild(itemicon);\n\t\t\t\t\titeminner.appendChild(itemtext);\n\n\t\t\t\t\tnode.appendChild(iteminner);\n\n\t\t\t\t\tnode.dataset.feid = entries[x].id;\n\t\t\t\t\tnode.dataset.fehash = '';\n\t\t\t\t}\n\n\t\t\t\t// Select item if it matches last selection.\n\t\t\t\tif (!selchanged && historystack[currhistory].lastselected === node.dataset.feid && !(node.dataset.feid in selecteditemsmap))\n\t\t\t\t{\n\t\t\t\t\tnode.classList.add('fe_fileexplorer_item_selected');\n\t\t\t\t\tnode.firstChild.firstChild.checked = true;\n\n\t\t\t\t\tselecteditemsmap[node.dataset.feid] = x;\n\t\t\t\t\tnumselecteditems++;\n\n\t\t\t\t\thistoryselected = true;\n\t\t\t\t\tselchanged = true;\n\t\t\t\t}\n\n\t\t\t\t// Update the node.\n\t\t\t\tif (entries[x].hash !== node.dataset.fehash)\n\t\t\t\t{\n\t\t\t\t\titemicon.className = 'fe_fileexplorer_item_icon';\n\t\t\t\t\tdelete itemicon.dataset.ext;\n\n\t\t\t\t\tif (entries[x].type === 'folder')\n\t\t\t\t\t{\n\t\t\t\t\t\tnode.classList.add('fe_fileexplorer_item_folder');\n\n\t\t\t\t\t\titemicon.classList.add('fe_fileexplorer_item_icon_folder');\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\titemicon.classList.add('fe_fileexplorer_item_icon_file');\n\n\t\t\t\t\t\tvar ext = entries[x].name;\n\t\t\t\t\t\tvar pos = ext.lastIndexOf('.');\n\t\t\t\t\t\tif (pos < 0)  itemicon.classList.add('fe_fileexplorer_item_icon_file_no_ext');\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\text = ext.substring(pos + 1).toUpperCase();\n\n\t\t\t\t\t\t\titemicon.dataset.ext = ext.substring(0, 4);\n\n\t\t\t\t\t\t\tif (ext === '')  itemicon.classList.add('fe_fileexplorer_item_icon_file_no_ext');\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvar cc = ext.charCodeAt(0);\n\n\t\t\t\t\t\t\t\tif ((cc >= 48 && cc < 58) || (cc >= 64 && cc < 91))  itemicon.classList.add('fe_fileexplorer_item_icon_ext_' + ext.substring(0, 1).toLowerCase());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tnode.firstChild.className = 'fe_fileexplorer_item_wrap_inner';\n\n\t\t\t\t\tif ('overlay' in entries[x])\n\t\t\t\t\t{\n\t\t\t\t\t\tif (typeof entries[x].overlay === 'string')  entries[x].overlay = [entries[x].overlay];\n\n\t\t\t\t\t\tfor (var x2 = 0; x2 < entries[x].overlay.length; x2++)  node.firstChild.classList.add(entries[x].overlay[x2]);\n\t\t\t\t\t}\n\n\t\t\t\t\tif ('tooltip' in entries[x])  node.firstChild.title = entries[x].tooltip;\n\t\t\t\t\telse  node.firstChild.title = '';\n\n\t\t\t\t\titemtext.innerHTML = EscapeHTML(entries[x].name);\n\n\t\t\t\t\tnode.dataset.fehash = entries[x].hash;\n\t\t\t\t}\n\n\t\t\t\t// Move node to the end of the list so it ends up in the correct order.\n\t\t\t\telems.itemswrap.appendChild(node);\n\t\t\t}\n\n\t\t\t// Remove deleted nodes.\n\t\t\tfor (var id in elemmap)\n\t\t\t{\n\t\t\t\tif (elemmap.hasOwnProperty(id) && !elemmap[id][3])\n\t\t\t\t{\n\t\t\t\t\tif (elemmap[id][2].dataset.feid in selecteditemsmap)\n\t\t\t\t\t{\n\t\t\t\t\t\tdelete selecteditemsmap[elemmap[id][2].dataset.feid];\n\n\t\t\t\t\t\tnumselecteditems--;\n\t\t\t\t\t\tselchanged = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (focuseditem === elemmap[id][2])\n\t\t\t\t\t{\n\t\t\t\t\t\tif ($this.HasFocus(true))  elems.itemsscrollwrap.focus();\n\n\t\t\t\t\t\tfocuseditem.classList.remove('fe_fileexplorer_item_focused');\n\t\t\t\t\t\tfocuseditem.firstChild.tabIndex = -1;\n\n\t\t\t\t\t\tfocuseditem = false;\n\t\t\t\t\t}\n\n\t\t\t\t\telemmap[id][2].parentNode.removeChild(elemmap[id][2]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\telems.itemsscrollwrap.scrollTop = tempscroll;\n\n\t\t\t// Finalize the synchronization operation.\n\t\t\tFinalizeSyncCurrFolderToDOM(historyselected, selchanged);\n\t\t};\n\n\t\tvar FinalizeSyncCurrFolderToDOM = function(historyselected, selchanged) {\n\t\t\tvar entries = currfolder.GetEntries();\n\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\n\t\t\t// Fix selection items map.\n\t\t\tfor (var x in selecteditemsmap)\n\t\t\t{\n\t\t\t\tif (selecteditemsmap.hasOwnProperty(x) && (x in entryidmap))  selecteditemsmap[x] = entryidmap[x];\n\t\t\t}\n\n\t\t\t// Update the main area.\n\t\t\tif (entries.length)\n\t\t\t{\n\t\t\t\telems.itemsmessagewrap.classList.add('fe_fileexplorer_hidden');\n\t\t\t\telems.itemswrap.classList.remove('fe_fileexplorer_hidden');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (currfolder.waiting)  elems.itemsmessagewrap.innerHTML = EscapeHTML($this.Translate('Loading...'));\n\t\t\t\telse  elems.itemsmessagewrap.innerHTML = EscapeHTML($this.Translate('This folder is empty.'));\n\n\t\t\t\telems.itemsmessagewrap.classList.remove('fe_fileexplorer_hidden');\n\t\t\t\telems.itemswrap.classList.add('fe_fileexplorer_hidden');\n\t\t\t}\n\n\t\t\t// Update the folder item position cache.\n\t\t\tUpdateCurrFolderItemCache(true);\n\n\t\t\t// Set the focus item and scroll to it.\n\t\t\tif (historyselected)\n\t\t\t{\n\t\t\t\t$this.SetFocusItem(historystack[currhistory].lastselected, true);\n\t\t\t\t$this.ScrollToFocusedItem();\n\t\t\t}\n\t\t\telse if (focuseditem !== false)\n\t\t\t{\n\t\t\t\t$this.SetFocusItem(focuseditem.dataset.feid, false);\n\t\t\t}\n\n\t\t\t// Trigger thumbnail queue update.\n\t\t\tThumbnailQueueUpdate();\n\n\t\t\t// Update the status bar.\n\t\t\tif (currfolder.waiting)  $this.SetNamedStatusBarText('folder', EscapeHTML($this.Translate('Loading...')));\n\t\t\telse  $this.SetNamedStatusBarText('folder', EscapeHTML(FormatStr($this.Translate('{0} items'), entries.length)));\n\n\t\t\t// Update toolbar icons.\n\t\t\tUpdateToolbarIcons();\n\n\t\t\t// If selections changed, update the status bar and notify listeners.\n\t\t\tif (selchanged)  UpdateSelectionsChanged();\n\t\t};\n\n\t\t// Set up handlers for current folder entry changes.\n\t\tvar SetFolderEntriesHandler = function() {\n\t\t\tif (this === currfolder)  SyncCurrFolderToDOM();\n\t\t};\n\n\t\tvar RemoveFolderEntryHandler = function(pos) {\n\t\t\tvar node = elems.itemswrap.children[pos];\n\t\t\tvar selchanged = false;\n\n\t\t\tif (node.dataset.feid in selecteditemsmap)\n\t\t\t{\n\t\t\t\tdelete selecteditemsmap[node.dataset.feid];\n\n\t\t\t\tnumselecteditems--;\n\t\t\t\tselchanged = true;\n\t\t\t}\n\n\t\t\tif (focuseditem === node)\n\t\t\t{\n\t\t\t\tif ($this.HasFocus(true))  elems.itemsscrollwrap.focus();\n\n\t\t\t\tfocuseditem.classList.remove('fe_fileexplorer_item_focused');\n\t\t\t\tfocuseditem.firstChild.tabIndex = -1;\n\n\t\t\t\tfocuseditem = false;\n\t\t\t}\n\n\t\t\tvar tempscroll = elems.itemsscrollwrap.scrollTop;\n\n\t\t\tnode.parentNode.removeChild(node);\n\n\t\t\telems.itemsscrollwrap.scrollTop = tempscroll;\n\n\t\t\t// Finalize the synchronization operation.\n\t\t\tFinalizeSyncCurrFolderToDOM(false, selchanged);\n\t\t};\n\n\t\tvar ConvertVertToHorzScroll = function(e) {\n\t\t\tvar mult = (e.deltaMode == 1 ? scrolllineheight * 2 : (e.deltaMode == 2 ? document.documentElement.clientHeight - (2 * scrolllineheight) : 1));\n\t\t\tif (e.deltaY)  e.currentTarget.scrollLeft += e.deltaY * mult;\n\n\t\t\t// Only viable option is to completely prevent scrolling.  Very strange behavior occurs otherwise in all browsers.\n\t\t\tif (e.currentTarget.scrollWidth > e.currentTarget.clientWidth)  e.preventDefault();\n\t\t};\n\n\t\telems.pathsegmentsscrollwrap.addEventListener('wheel', ConvertVertToHorzScroll);\n\n\t\t// Set the current path.\n\t\t$this.IsValidPath = function(path) {\n\t\t\tif (!path || !Array.isArray(path) || !path.length)  return false;\n\n\t\t\tfor (var x = 0; x < path.length; x++)\n\t\t\t{\n\t\t\t\tif (!Array.isArray(path[x]) || path[x].length < 2 || typeof path[x][0] !== 'string' || typeof path[x][1] !== 'string')  return false;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t};\n\n\t\t$this.RefreshFolders = function(forcecurrfolder) {\n\t\t\tif (forcecurrfolder)  currfolder.lastrefresh = 0;\n\n\t\t\tvar historyentry = historystack[currhistory];\n\t\t\tvar ts = Date.now();\n\t\t\tvar ts2 = ts - 300 * 1000;\n\n\t\t\tfor (var x = historyentry.folderkeys.length; x; x--)\n\t\t\t{\n\t\t\t\tif (foldermap[historyentry.folderkeys[x - 1]].lastrefresh < ts2)\n\t\t\t\t{\n\t\t\t\t\tDispatchEvent('refresh_folder', [foldermap[historyentry.folderkeys[x - 1]], !foldermap[historyentry.folderkeys[x - 1]].lastrefresh]);\n\n\t\t\t\t\tfoldermap[historyentry.folderkeys[x - 1]].lastrefresh = ts;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Update navigation and toolabar icons.\n\t\tvar NavigationChanged = function() {\n\t\t\t// Back button.\n\t\t\tif (currhistory <= 0)\n\t\t\t{\n\t\t\t\tif (document.activeElement === elems.navtool_back)\n\t\t\t\t{\n\t\t\t\t\tif (currhistory >= historystack.length - 1)  elems.navtool_history.focus();\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\telems.navtool_forward.tabIndex = 0;\n\t\t\t\t\t\telems.navtool_forward.focus();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telems.navtool_back.classList.add('fe_fileexplorer_disabled');\n\t\t\t\telems.navtool_back.tabIndex = -1;\n\n\t\t\t\telems.navtool_back.title = $this.Translate('Back (Alt + Left Arrow)');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\telems.navtool_back.classList.remove('fe_fileexplorer_disabled');\n\t\t\t\telems.navtool_back.tabIndex = 0;\n\n\t\t\t\tvar prevpath = foldermap[historystack[currhistory - 1].folderkeys[historystack[currhistory - 1].folderkeys.length - 1]].GetPath();\n\n\t\t\t\telems.navtool_back.title = FormatStr($this.Translate('Back to \"{0}\" (Alt + Left Arrow)'), prevpath[prevpath.length - 1][1]);\n\t\t\t}\n\n\t\t\t// Forward button.\n\t\t\tif (currhistory >= historystack.length - 1)\n\t\t\t{\n\t\t\t\tif (document.activeElement === elems.navtool_forward)\n\t\t\t\t{\n\t\t\t\t\tif (currhistory <= 0)  elems.navtool_history.focus();\n\t\t\t\t\telse  elems.navtool_back.focus();\n\t\t\t\t}\n\n\t\t\t\telems.navtool_forward.classList.add('fe_fileexplorer_disabled');\n\t\t\t\telems.navtool_forward.tabIndex = -1;\n\n\t\t\t\telems.navtool_forward.title = $this.Translate('Forward (Alt + Right Arrow)');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\telems.navtool_forward.classList.remove('fe_fileexplorer_disabled');\n\t\t\t\telems.navtool_forward.tabIndex = 0;\n\n\t\t\t\tvar nextpath = foldermap[historystack[currhistory + 1].folderkeys[historystack[currhistory + 1].folderkeys.length - 1]].GetPath();\n\n\t\t\t\telems.navtool_forward.title = FormatStr($this.Translate('Forward to \"{0}\" (Alt + Right Arrow)'), nextpath[nextpath.length - 1][1]);\n\t\t\t}\n\n\t\t\t// Up button.\n\t\t\tvar currpath = currfolder.GetPath();\n\n\t\t\tif (currpath.length <= 1)\n\t\t\t{\n\t\t\t\tif (document.activeElement === elems.navtool_up)  elems.navtool_history.focus();\n\n\t\t\t\telems.navtool_up.classList.add('fe_fileexplorer_disabled');\n\t\t\t\telems.navtool_up.tabIndex = -1;\n\n\t\t\t\telems.navtool_up.title = $this.Translate('Up (Alt + Up Arrow)');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\telems.navtool_up.classList.remove('fe_fileexplorer_disabled');\n\t\t\t\telems.navtool_up.tabIndex = 0;\n\n\t\t\t\telems.navtool_up.title = FormatStr($this.Translate('Up to \"{0}\" (Alt + Up Arrow)'), currpath[currpath.length - 2][1]);\n\t\t\t}\n\n\t\t\tDispatchEvent('navigated');\n\n\t\t\t// Update toolbar icons.\n\t\t\tUpdateToolbarIcons();\n\t\t};\n\n\t\tvar NavToolsKeyHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (e.keyCode == 37)\n\t\t\t{\n\t\t\t\t// Left Arrow.  Move to previous nav tool.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tif (document.activeElement && document.activeElement.parentNode === elems.navtools)\n\t\t\t\t{\n\t\t\t\t\tvar node = document.activeElement.previousSibling;\n\t\t\t\t\twhile (node && node.classList.contains('fe_fileexplorer_disabled'))  node = node.previousSibling;\n\n\t\t\t\t\tif (node)  node.focus();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (e.keyCode == 39)\n\t\t\t{\n\t\t\t\t// Right Arrow.  Move to next nav tool.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tif (document.activeElement && document.activeElement.parentNode === elems.navtools)\n\t\t\t\t{\n\t\t\t\t\tvar node = document.activeElement.nextSibling;\n\t\t\t\t\twhile (node && node.classList.contains('fe_fileexplorer_disabled'))  node = node.nextSibling;\n\n\t\t\t\t\tif (node)  node.focus();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (e.keyCode == 40)\n\t\t\t{\n\t\t\t\t// Down Arrow.  Focus on the history tool and open it.\n\t\t\t\te.preventDefault();\n\n\t\t\t\telems.navtool_history.focus();\n\n\t\t\t\tRecentLocationsHandler(e);\n\t\t\t}\n\t\t};\n\n\t\telems.navtools.addEventListener('keydown', NavToolsKeyHandler);\n\n\t\t// Returns a path key for the folder map.\n\t\tvar GetMappedPathKey = function(path) {\n\t\t\t// Build the path key.\n\t\t\tvar pathkey = '';\n\n\t\t\tfor (var x = 0; x < path.length; x++)\n\t\t\t{\n\t\t\t\tpathkey += '/' + path[x][0];\n\t\t\t}\n\n\t\t\treturn pathkey;\n\t\t};\n\n\t\t// Attempts to return a mapped folder from a calculated path.\n\t\t$this.GetMappedFolderFromPath = function(path) {\n\t\t\treturn foldermap[GetMappedPathKey(path)];\n\t\t};\n\n\t\tvar DecrementMappedFolderRefCount = function(folder) {\n\t\t\tfolder.refs--;\n\n\t\t\tif (!folder.refs)\n\t\t\t{\n\t\t\t\tvar pathkey = GetMappedPathKey(folder.GetPath());\n\n\t\t\t\tfolder.Destroy();\n\n\t\t\t\tdelete foldermap[pathkey];\n\t\t\t}\n\t\t};\n\n\t\t$this.GetPathIDs = function(path) {\n\t\t\tvar result = [];\n\n\t\t\tfor (var x = 0; x < path.length; x++)  result.push(path[x][0]);\n\n\t\t\treturn result;\n\t\t};\n\n\t\t$this.SetPath = function(newpath) {\n\t\t\t// If the current folder is busy, then queue the change for later.\n\t\t\tif (currfolder && currfolder.IsBusy())\n\t\t\t{\n\t\t\t\tcurrfolder.AddBusyQueueCallback($this.SetPath, [newpath]);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!$this.IsValidPath(newpath))  return;\n\n\t\t\t// Cancel any active popup menu.\n\t\t\tif (popupmenu)  popupmenu.Cancel();\n\n\t\t\t// Unregister events for the current folder.\n\t\t\tif (currfolder)\n\t\t\t{\n\t\t\t\tcurrfolder.removeEventListener('set_attributes', SetFolderAttributesHandler);\n\t\t\t\tcurrfolder.removeEventListener('set_entries', SetFolderEntriesHandler);\n\t\t\t\tcurrfolder.removeEventListener('remove_entry', RemoveFolderEntryHandler);\n\t\t\t}\n\n\t\t\t// Clear existing DOM path segments.\n\t\t\twhile (elems.pathsegmentswrap.firstChild)  elems.pathsegmentswrap.removeChild(elems.pathsegmentswrap.lastChild);\n\n\t\t\t// Calculate path keys for a new history stack entry.\n\t\t\tvar historyentry = { folderkeys: [], lastselected: true };\n\t\t\tvar pathkey = '';\n\n\t\t\tfor (var x = 0; x < newpath.length; x++)\n\t\t\t{\n\t\t\t\t// Create/Update folder cache entries.\n\t\t\t\tpathkey += '/' + newpath[x][0];\n\n\t\t\t\tif (!foldermap[pathkey])  foldermap[pathkey] = new Folder(newpath.slice(0, x + 1));\n\n\t\t\t\tfoldermap[pathkey].refs++;\n\n\t\t\t\thistoryentry.folderkeys.push(pathkey);\n\n\t\t\t\t// Create new DOM path segment.\n\t\t\t\tvar segmentwrap = CreateNode('div', ['fe_fileexplorer_path_segment_wrap'], { tabIndex: (x < newpath.length - 1 ? -1 : 0) });\n\t\t\t\tvar segmentpathname = CreateNode('button', ['fe_fileexplorer_path_name'], { tabIndex: -1 });\n\t\t\t\tvar segmentpathopts = CreateNode('button', ['fe_fileexplorer_path_opts'], { tabIndex: -1 });\n\n\t\t\t\tsegmentwrap._fepos = x;\n\n\t\t\t\tsegmentpathname.innerHTML = EscapeHTML(newpath[x][1]);\n\n\t\t\t\tsegmentwrap.appendChild(segmentpathname);\n\t\t\t\tsegmentwrap.appendChild(segmentpathopts);\n\n\t\t\t\telems.pathsegmentswrap.appendChild(segmentwrap);\n\t\t\t}\n\n\t\t\t// Scroll the path segment scroll view to the end.\n\t\t\telems.pathsegmentsscrollwrap.scrollLeft = elems.pathsegmentsscrollwrap.scrollWidth;\n\t\t\telems.pathsegmentswrap._fepos = newpath.length - 1;\n\n\t\t\t// Register events for the new current folder.\n\t\t\tvar prevfolder = currfolder;\n\t\t\tcurrfolder = foldermap[pathkey];\n\t\t\tcurrfolder.addEventListener('set_attributes', SetFolderAttributesHandler);\n\t\t\tcurrfolder.addEventListener('set_entries', SetFolderEntriesHandler);\n\t\t\tcurrfolder.addEventListener('remove_entry', RemoveFolderEntryHandler);\n\n\t\t\t// Clear selected and focused items if the folder is the same.\n\t\t\tif (prevfolder === currfolder)\n\t\t\t{\n\t\t\t\t$this.ClearSelectedItems(false, true);\n\t\t\t\t$this.SetFocusItem(false, false);\n\t\t\t}\n\n\t\t\t// Scroll view to top.\n\t\t\telems.itemsscrollwrap.scrollTop = 0;\n\n\t\t\t// Force a refresh and clear selections and focus.\n\t\t\tcurrfolder.lastrefresh = 0;\n\t\t\tselecteditemsmap = {};\n\t\t\tnumselecteditems = 0;\n\t\t\tfocuseditem = false;\n\t\t\tlastanchorpos = 0;\n\n\t\t\t// Clear DOM items if the folder changed.\n\t\t\tif (prevfolder !== currfolder)\n\t\t\t{\n\t\t\t\twhile (elems.itemswrap.firstChild)\n\t\t\t\t{\n\t\t\t\t\tif (document.activeElement === elems.itemswrap.lastChild.firstChild)  elems.itemsscrollwrap.focus();\n\n\t\t\t\t\telems.itemswrap.removeChild(elems.itemswrap.lastChild);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Adjust history stack.\n\t\t\tif (currhistory < 0 || pathkey !== historystack[currhistory].folderkeys[historystack[currhistory].folderkeys.length - 1])\n\t\t\t{\n\t\t\t\t// Clear any subsequent history stack entries.\n\t\t\t\tcurrhistory++;\n\t\t\t\tfor (var x = currhistory; x < historystack.length; x++)\n\t\t\t\t{\n\t\t\t\t\tfor (var x2 = 0; x2 < historystack[x].folderkeys.length; x2++)\n\t\t\t\t\t{\n\t\t\t\t\t\tDecrementMappedFolderRefCount(foldermap[historystack[x].folderkeys[x2]]);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\thistorystack = historystack.slice(0, currhistory);\n\n\t\t\t\t// Create a new history stack entry.\n\t\t\t\thistorystack.push(historyentry);\n\n\t\t\t\tDispatchEvent('history_changed');\n\t\t\t}\n\t\t\telse if (currhistory > -1)\n\t\t\t{\n\t\t\t\t// Decrement folder references for the current path.\n\t\t\t\tfor (var x = 0; x < historystack[currhistory].folderkeys.length; x++)\n\t\t\t\t{\n\t\t\t\t\tDecrementMappedFolderRefCount(foldermap[historystack[currhistory].folderkeys[x]]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Save last selected item.\n\t\t\tvar lastselected = historystack[currhistory].lastselected;\n\n\t\t\t// Create/Update DOM items.\n\t\t\tSyncCurrFolderToDOM();\n\n\t\t\t// Update the status bar and notify listeners.\n\t\t\tif (!numselecteditems)  UpdateSelectionsChanged();\n\n\t\t\t// Restore last selected item.\n\t\t\thistorystack[currhistory].lastselected = lastselected;\n\n\t\t\t// Update folders that haven't been refreshed in the last 5 minutes.\n\t\t\t$this.RefreshFolders(true);\n\n\t\t\t// Notify navigation completed.\n\t\t\tNavigationChanged();\n\t\t};\n\n\n\t\t// Handle mouse and touch selections for the current folder.\n\t\tvar selectanchorpos = null, prevselectrect = null, selectbox = null, selectchangeinvert = false, autoscrolltimer = null, lastmouseevent = null;\n\t\tvar lastselecttouch = null, lastmousedownevent = null, selectmodemulti = false;\n\n\t\t// Updates the specified rectangle with start/end row/column numbers from the folder item cache.  The hint start/end row/column info is optional.\n\t\tvar UpdateCalculatedSelectedItemsRect = function(rect, hintrect) {\n\t\t\trect.startrow = (hintrect ? hintrect.startrow : 0);\n\t\t\trect.startcol = (hintrect ? hintrect.startcol : 0);\n\t\t\trect.endrow = (hintrect ? hintrect.endrow : (folderitemcache.rows.length ? folderitemcache.rows.length - 1 : 0));\n\t\t\trect.endcol = (hintrect ? hintrect.endcol : (folderitemcache.rows.length ? folderitemcache.cols.length - 1 : 0));\n\n\t\t\t// Adjust startrow and endrow until they fall within two tops.\n\t\t\twhile (rect.startrow && rect.top < folderitemcache.rows[rect.startrow].top)  rect.startrow--;\n\t\t\twhile (rect.startrow < folderitemcache.rows.length - 1 && rect.top >= folderitemcache.rows[rect.startrow + 1].top)  rect.startrow++;\n\n\t\t\twhile (rect.endrow && rect.bottom < folderitemcache.rows[rect.endrow].top)  rect.endrow--;\n\t\t\tif (rect.endrow < rect.startrow)  rect.endrow = rect.startrow;\n\t\t\twhile (rect.endrow < folderitemcache.rows.length - 1 && rect.bottom >= folderitemcache.rows[rect.endrow + 1].top)  rect.endrow++;\n\n\t\t\t// Adjust startcol and endcol until they fall within two lefts.\n\t\t\twhile (rect.startcol && rect.left < folderitemcache.cols[rect.startcol].left)  rect.startcol--;\n\t\t\twhile (rect.startcol < folderitemcache.cols.length - 1 && rect.left >= folderitemcache.cols[rect.startcol + 1].left)  rect.startcol++;\n\n\t\t\twhile (rect.endcol && rect.right < folderitemcache.cols[rect.endcol].left)  rect.endcol--;\n\t\t\tif (rect.endcol < rect.startcol)  rect.endcol = rect.startcol;\n\t\t\twhile (rect.endcol < folderitemcache.cols.length - 1 && rect.right >= folderitemcache.cols[rect.endcol + 1].left)  rect.endcol++;\n\t\t};\n\n\t\tvar DoesRectOverlapItemRect = function(rect, x, y) {\n\t\t\treturn (folderitemcache.size && rect.left < folderitemcache.cols[x].right && rect.right >= folderitemcache.cols[x].left && rect.bottom >= folderitemcache.rows[y].top && rect.top < folderitemcache.rows[y].bottoms[x]);\n\t\t};\n\n\t\t// Updates information and selected items for SelectBoxDragHandler().\n\t\tvar UpdateSelectBoxDragInfoItems = function(currselectrect, newpos, newwidth, newheight, scrolling) {\n\t\t\tif (!scrolling)  currselectrect.left = (newpos.x < selectanchorpos.x ? newpos.x : selectanchorpos.x);\n\t\t\tcurrselectrect.top = (newpos.y < selectanchorpos.y ? newpos.y : selectanchorpos.y);\n\t\t\tif (!scrolling)  currselectrect.right = currselectrect.left + newwidth;\n\t\t\tcurrselectrect.bottom = currselectrect.top + newheight;\n\n\t\t\t// Calculate rough position info.\n\t\t\tUpdateCalculatedSelectedItemsRect(currselectrect, prevselectrect);\n\n\t\t\tif (!scrolling)  selectbox.style.left = currselectrect.left + 'px';\n\t\t\tselectbox.style.top = currselectrect.top + 'px';\n\t\t\tif (!scrolling)  selectbox.style.width = newwidth + 'px';\n\t\t\tselectbox.style.height = newheight + 'px';\n\n\t\t\t// Apply item selection changes.\n\t\t\tvar updateitems = {}, selchanged = false;\n\t\t\tif (!scrolling)\n\t\t\t{\n\t\t\t\tvar minrow = (currselectrect.startrow < prevselectrect.startrow ? currselectrect.startrow : prevselectrect.startrow);\n\t\t\t\tvar maxrow = (currselectrect.endrow > prevselectrect.endrow ? currselectrect.endrow : prevselectrect.endrow);\n\n\t\t\t\tif (currselectrect.left < prevselectrect.left)\n\t\t\t\t{\n\t\t\t\t\tfor (var y = minrow; y <= maxrow; y++)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (var x = currselectrect.startcol; x <= prevselectrect.startcol; x++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!DoesRectOverlapItemRect(prevselectrect, x, y) && DoesRectOverlapItemRect(currselectrect, x, y))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tupdateitems[y * folderitemcache.cols.length + x] = true;\n\n\t\t\t\t\t\t\t\tselchanged = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (currselectrect.left > prevselectrect.left)\n\t\t\t\t{\n\t\t\t\t\tfor (var y = minrow; y <= maxrow; y++)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (var x = prevselectrect.startcol; x <= currselectrect.startcol; x++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (DoesRectOverlapItemRect(prevselectrect, x, y) && !DoesRectOverlapItemRect(currselectrect, x, y))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tupdateitems[y * folderitemcache.cols.length + x] = false;\n\n\t\t\t\t\t\t\t\tselchanged = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (currselectrect.right > prevselectrect.right)\n\t\t\t\t{\n\t\t\t\t\tfor (var y = minrow; y <= maxrow; y++)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (var x = prevselectrect.endcol; x <= currselectrect.endcol; x++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!DoesRectOverlapItemRect(prevselectrect, x, y) && DoesRectOverlapItemRect(currselectrect, x, y))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tupdateitems[y * folderitemcache.cols.length + x] = true;\n\n\t\t\t\t\t\t\t\tselchanged = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (currselectrect.right < prevselectrect.right)\n\t\t\t\t{\n\t\t\t\t\tfor (var y = minrow; y <= maxrow; y++)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (var x = currselectrect.endcol; x <= prevselectrect.endcol; x++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (DoesRectOverlapItemRect(prevselectrect, x, y) && !DoesRectOverlapItemRect(currselectrect, x, y))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tupdateitems[y * folderitemcache.cols.length + x] = false;\n\n\t\t\t\t\t\t\t\tselchanged = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar mincol = (currselectrect.startcol < prevselectrect.startcol ? currselectrect.startcol : prevselectrect.startcol);\n\t\t\tvar maxcol = (currselectrect.endcol > prevselectrect.endcol ? currselectrect.endcol : prevselectrect.endcol);\n\n\t\t\tif (currselectrect.top < prevselectrect.top)\n\t\t\t{\n\t\t\t\tfor (var y = currselectrect.startrow; y <= prevselectrect.startrow; y++)\n\t\t\t\t{\n\t\t\t\t\tfor (var x = mincol; x <= maxcol; x++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!DoesRectOverlapItemRect(prevselectrect, x, y) && DoesRectOverlapItemRect(currselectrect, x, y))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tupdateitems[y * folderitemcache.cols.length + x] = true;\n\n\t\t\t\t\t\t\tselchanged = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (currselectrect.top > prevselectrect.top)\n\t\t\t{\n\t\t\t\tfor (var y = prevselectrect.startrow; y <= currselectrect.startrow; y++)\n\t\t\t\t{\n\t\t\t\t\tfor (var x = mincol; x <= maxcol; x++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (DoesRectOverlapItemRect(prevselectrect, x, y) && !DoesRectOverlapItemRect(currselectrect, x, y))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tupdateitems[y * folderitemcache.cols.length + x] = false;\n\n\t\t\t\t\t\t\tselchanged = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currselectrect.bottom > prevselectrect.bottom)\n\t\t\t{\n\t\t\t\tfor (var y = prevselectrect.endrow; y <= currselectrect.endrow; y++)\n\t\t\t\t{\n\t\t\t\t\tfor (var x = mincol; x <= maxcol; x++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (!DoesRectOverlapItemRect(prevselectrect, x, y) && DoesRectOverlapItemRect(currselectrect, x, y))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tupdateitems[y * folderitemcache.cols.length + x] = true;\n\n\t\t\t\t\t\t\tselchanged = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (currselectrect.bottom < prevselectrect.bottom)\n\t\t\t{\n\t\t\t\tfor (var y = currselectrect.endrow; y <= prevselectrect.endrow; y++)\n\t\t\t\t{\n\t\t\t\t\tfor (var x = mincol; x <= maxcol; x++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (DoesRectOverlapItemRect(prevselectrect, x, y) && !DoesRectOverlapItemRect(currselectrect, x, y))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tupdateitems[y * folderitemcache.cols.length + x] = false;\n\n\t\t\t\t\t\t\tselchanged = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Update items.\n\t\t\tif (selchanged)\n\t\t\t{\n\t\t\t\tfor (var x in updateitems)\n\t\t\t\t{\n\t\t\t\t\tif (updateitems.hasOwnProperty(x))\n\t\t\t\t\t{\n\t\t\t\t\t\tvar elem = elems.itemswrap.children[x];\n\n\t\t\t\t\t\tif (selectchangeinvert)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Invert the selection.\n\t\t\t\t\t\t\tif (elem.dataset.feid in selecteditemsmap)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\telem.classList.remove('fe_fileexplorer_item_selected');\n\t\t\t\t\t\t\t\telem.firstChild.firstChild.checked = false;\n\n\t\t\t\t\t\t\t\tdelete selecteditemsmap[elem.dataset.feid];\n\n\t\t\t\t\t\t\t\tnumselecteditems--;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\telem.classList.add('fe_fileexplorer_item_selected');\n\t\t\t\t\t\t\t\telem.firstChild.firstChild.checked = true;\n\n\t\t\t\t\t\t\t\tselecteditemsmap[elem.dataset.feid] = x;\n\t\t\t\t\t\t\t\tnumselecteditems++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (updateitems[x])\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Add the selection.\n\t\t\t\t\t\t\telem.classList.add('fe_fileexplorer_item_selected');\n\t\t\t\t\t\t\telem.firstChild.firstChild.checked = true;\n\n\t\t\t\t\t\t\tselecteditemsmap[elem.dataset.feid] = x;\n\t\t\t\t\t\t\tnumselecteditems++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Remove the selection.\n\t\t\t\t\t\t\telem.classList.remove('fe_fileexplorer_item_selected');\n\t\t\t\t\t\t\telem.firstChild.firstChild.checked = false;\n\n\t\t\t\t\t\t\tdelete selecteditemsmap[elem.dataset.feid];\n\n\t\t\t\t\t\t\tnumselecteditems--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Update toolbar icons.\n\t\t\t\tUpdateToolbarIcons();\n\n\t\t\t\t// Update the status bar and notify listeners.\n\t\t\t\tUpdateSelectionsChanged();\n\t\t\t}\n\n\t\t\tObject.assign(prevselectrect, currselectrect);\n\t\t};\n\n\t\t// Resize, autoscroll, and select highlighted items using a selection box.\n\t\tvar SelectBoxDragHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\t// Perform our own much smoother scrolling and avoid item selections.\n\t\t\te.preventDefault();\n\n\t\t\tlastmouseevent = e;\n\n\t\t\tvar rect = elems.itemsscrollwrapinner.getBoundingClientRect();\n\n\t\t\tvar newpos = {\n\t\t\t\tx: e.clientX - rect.left,\n\t\t\t\ty: e.clientY - rect.top\n\t\t\t};\n\n\t\t\tif (newpos.x < 0)  newpos.x = 0;\n\t\t\tif (newpos.x > rect.width)  newpos.x = rect.width;\n\t\t\tif (newpos.y < 0)  newpos.y = 0;\n\t\t\tif (newpos.y > rect.height)  newpos.y = rect.height;\n\n\t\t\tvar newwidth = Math.abs(newpos.x - selectanchorpos.x);\n\t\t\tvar newheight = Math.abs(newpos.y - selectanchorpos.y);\n\n\t\t\tif (!selectbox && (newwidth > 8 || newheight > 8))\n\t\t\t{\n\t\t\t\tselectbox = CreateNode('div', ['fe_fileexplorer_select_box']);\n\t\t\t\telems.itemsscrollwrapinner.appendChild(selectbox);\n\t\t\t}\n\n\t\t\tif (selectbox)\n\t\t\t{\n\t\t\t\tif (e.ctrlKey)  selectchangeinvert = true;\n\t\t\t\telse if (e.shiftKey)  selectchangeinvert = false;\n\n\t\t\t\tvar currselectrect = {};\n\n\t\t\t\t// Update information and selected items.\n\t\t\t\tUpdateSelectBoxDragInfoItems(currselectrect, newpos, newwidth, newheight, false);\n\n\t\t\t\t// Handle scrolling of the view.\n\t\t\t\tvar rect2 = elems.itemsscrollwrap.getBoundingClientRect();\n\n\t\t\t\tif (autoscrolltimer)\n\t\t\t\t{\n\t\t\t\t\tclearInterval(autoscrolltimer);\n\n\t\t\t\t\tautoscrolltimer = null;\n\t\t\t\t}\n\n\t\t\t\tif (e.clientY < rect2.top)\n\t\t\t\t{\n\t\t\t\t\t// Scroll up.\n\t\t\t\t\tvar scrollspeed = Math.floor((rect2.top - e.clientY) / 10) + 1;\n\n\t\t\t\t\tvar TempScrollUp = function(e) {\n\t\t\t\t\t\telems.itemsscrollwrap.scrollTop -= scrollspeed;\n\n\t\t\t\t\t\tnewpos.y -= scrollspeed;\n\t\t\t\t\t\tif (newpos.y < 0)  newpos.y = 0;\n\n\t\t\t\t\t\tnewheight = Math.abs(newpos.y - selectanchorpos.y);\n\n\t\t\t\t\t\t// Update information and selected items.\n\t\t\t\t\t\tUpdateSelectBoxDragInfoItems(currselectrect, newpos, newwidth, newheight, true);\n\n\t\t\t\t\t\tif (elems.itemsscrollwrap.scrollTop <= 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tclearInterval(autoscrolltimer);\n\n\t\t\t\t\t\t\tautoscrolltimer = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tautoscrolltimer = setInterval(TempScrollUp, 10);\n\n\t\t\t\t\tTempScrollUp();\n\t\t\t\t}\n\t\t\t\telse if (e.clientY > rect2.bottom)\n\t\t\t\t{\n\t\t\t\t\t// Scroll down.\n\t\t\t\t\tvar scrollspeed = (Math.floor((e.clientY - rect2.bottom) / 10) + 1);\n\n\t\t\t\t\tvar TempScrollDown = function(e) {\n\t\t\t\t\t\telems.itemsscrollwrap.scrollTop += scrollspeed;\n\n\t\t\t\t\t\tnewpos.y += scrollspeed;\n\t\t\t\t\t\tif (newpos.y > rect.height)  newpos.y = rect.height;\n\n\t\t\t\t\t\tnewheight = Math.abs(newpos.y - selectanchorpos.y);\n\n\t\t\t\t\t\t// Update information and selected items.\n\t\t\t\t\t\tUpdateSelectBoxDragInfoItems(currselectrect, newpos, newwidth, newheight, true);\n\n\t\t\t\t\t\tif (elems.itemsscrollwrap.scrollTop >= elems.itemsscrollwrap.scrollHeight - elems.itemsscrollwrap.clientHeight)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tclearInterval(autoscrolltimer);\n\n\t\t\t\t\t\t\tautoscrolltimer = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tautoscrolltimer = setInterval(TempScrollDown, 10);\n\n\t\t\t\t\tTempScrollDown();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Handle scrolling using the wheel while selecting items.\n\t\tvar SelectBoxScrollWheelHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tvar lastscrolltop = -1;\n\t\t\tvar numsame = 0;\n\n\t\t\tvar TempWheelScrollHandler = function() {\n\t\t\t\tSelectBoxDragHandler(lastmouseevent);\n\n\t\t\t\tif (autoscrolltimer)  clearInterval(autoscrolltimer);\n\n\t\t\t\tautoscrolltimer = setInterval(TempWheelScrollHandler, 10);\n\n\t\t\t\tif (lastscrolltop !== elems.itemsscrollwrap.scrollTop)  numsame = 0;\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tnumsame++;\n\n\t\t\t\t\tif (numsame >= 5)\n\t\t\t\t\t{\n\t\t\t\t\t\tclearInterval(autoscrolltimer);\n\n\t\t\t\t\t\tautoscrolltimer = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlastscrolltop = elems.itemsscrollwrap.scrollTop;\n\t\t\t};\n\n\t\t\tTempWheelScrollHandler();\n\t\t};\n\n\t\t// Handle starting a clipboard operation.\n\t\tvar clipboardmenutimout, clipboardcontextmenu;\n\t\tvar ClipboardOverlayKeyHandler = function(e) {\n\t\t\t// If the context menu key was pressed, don't change focus until the menu has appeared, otherwise change focus now.\n\t\t\tif (!e.ctrlKey && !e.metaKey && e.keyCode != 93)\n\t\t\t{\n\t\t\t\tClipboardOverlayExitContextMenuHandler(e);\n\t\t\t}\n\t\t};\n\n\t\tvar ClipboardOverlayExitContextMenuHandler = function(e) {\n\t\t\t// Clean up event handlers.\n\t\t\twindow.removeEventListener('focus', ClipboardOverlayExitContextMenuHandler, true);\n\t\t\telems.itemsclipboardoverlay.removeEventListener('keyup', ClipboardOverlayKeyHandler);\n\t\t\twindow.removeEventListener('mousedown', ClipboardOverlayExitContextMenuHandler, true);\n\t\t\telems.itemsclipboardoverlay.removeEventListener('input', ClipboardOverlayExitContextMenuHandler, true);\n\t\t\telems.itemsclipboardoverlay.removeEventListener('select', ClipboardOverlayExitContextMenuHandler, true);\n\t\t\twindow.removeEventListener('keydown', ClipboardPasteBoxKeyHandler, true);\n\t\t\twindow.removeEventListener('mousedown', ClipboardPasteBoxMouseHandler, true);\n\n\t\t\tif (clipboardmenutimout)\n\t\t\t{\n\t\t\t\tclearTimeout(clipboardmenutimout);\n\t\t\t\tclipboardmenutimout = null;\n\t\t\t}\n\n\t\t\t// Move the focus back to the main area if the target is the clipboard overlay.\n\t\t\tif (e && e.target === elems.itemsclipboardoverlay)  $this.Focus(true, true);\n\n\t\t\telems.itemsclipboardoverlaypastewrap.classList.add('fe_fileexplorer_hidden');\n\t\t\telems.itemsclipboardoverlaypastewrap.classList.remove('fe_fileexplorer_items_show_clipboard_overlay_paste');\n\t\t\telems.itemsclipboardoverlay.tabIndex = -1;\n\n\t\t\tclipboardcontextmenu = false;\n\t\t};\n\n\t\tvar ClipboardOverlayContextMenuHandler = function(e) {\n\t\t\t// Remove the pointer events class after the context menu shows BUT there is no standard event available for it after this one.\n\t\t\tif (clipboardmenutimout)  clearTimeout(clipboardmenutimout);\n\n\t\t\tclipboardmenutimout = setTimeout(function() {\n\t\t\t\tclipboardmenutimout = null;\n\n\t\t\t\telems.itemsclipboardoverlaypastewrap.classList.remove('fe_fileexplorer_items_clipboard_contextmenu');\n\n\t\t\t\telems.itemsclipboardoverlay.addEventListener('input', ClipboardOverlayExitContextMenuHandler, true);\n\t\t\t\telems.itemsclipboardoverlay.addEventListener('select', ClipboardOverlayExitContextMenuHandler, true);\n\t\t\t}, 0);\n\n\t\t\t// Track when the context menu exits.\n\t\t\twindow.addEventListener('focus', ClipboardOverlayExitContextMenuHandler, true);\n\t\t\telems.itemsclipboardoverlay.addEventListener('keyup', ClipboardOverlayKeyHandler);\n\t\t\twindow.addEventListener('mousedown', ClipboardOverlayExitContextMenuHandler, true);\n\n\t\t\t// Remove the event handler for the context menu.\n\t\t\twindow.removeEventListener('contextmenu', ClipboardOverlayContextMenuHandler, true);\n\n\t\t\tclipboardcontextmenu = true;\n\t\t};\n\n\t\tvar StartClipboardOverlayMenu = function() {\n\t\t\tif (elems.itemsclipboardoverlaypastewrap.classList.contains('fe_fileexplorer_items_clipboard_contextmenu'))\n\t\t\t{\n\t\t\t\t// Temporarily enable an event handler for opening a context menu.\n\t\t\t\twindow.addEventListener('contextmenu', ClipboardOverlayContextMenuHandler, true);\n\n\t\t\t\telems.itemsclipboardoverlay.focus();\n\t\t\t\telems.itemsclipboardoverlay.setSelectionRange((numselecteditems ? 1 : 2), 2);\n\t\t\t}\n\t\t};\n\n\t\tvar ClipboardPasteBoxKeyHandler = function(e) {\n\t\t\telems.itemsclipboardoverlay.value = '   ';\n\t\t\telems.itemsclipboardoverlay.setSelectionRange(2, 2);\n\n\t\t\tif (e.keyCode == 27)  ClipboardOverlayExitContextMenuHandler(e);\n\t\t};\n\n\t\tvar ClipboardPasteBoxMouseHandler = function(e) {\n\t\t\tif (e.target !== elems.itemsclipboardoverlay)  ClipboardOverlayExitContextMenuHandler(e);\n\t\t};\n\n\t\t$this.ShowClipboardPasteBox = function() {\n\t\t\telems.itemsclipboardoverlaypastewrap.classList.add('fe_fileexplorer_items_show_clipboard_overlay_paste');\n\t\t\telems.itemsclipboardoverlaypastewrap.classList.remove('fe_fileexplorer_hidden');\n\t\t\telems.itemsclipboardoverlay.tabIndex = 0;\n\n\t\t\twindow.addEventListener('keydown', ClipboardPasteBoxKeyHandler, true);\n\t\t\twindow.addEventListener('mousedown', ClipboardPasteBoxMouseHandler, true);\n\t\t};\n\n\t\t$this.HideClipboardPasteBox = function(e) {\n\t\t\tClipboardOverlayExitContextMenuHandler(e);\n\t\t};\n\n\t\t// Stop selecting items, clears event handlers, and decrements busy state.\n\t\tvar SelectBoxEndHandler = function(e) {\n\t\t\tif (selectbox)\n\t\t\t{\n\t\t\t\tselectbox.parentNode.removeChild(selectbox);\n\t\t\t\tselectbox = null;\n\n\t\t\t\tclearInterval(autoscrolltimer);\n\t\t\t\tautoscrolltimer = null;\n\t\t\t}\n\n\t\t\telems.itemswrap.classList.remove('fe_fileexplorer_items_selecting');\n\n\t\t\t// Disable clipboard overlay.\n\t\t\tStartClipboardOverlayMenu();\n\n\t\t\twindow.removeEventListener('mousemove', SelectBoxDragHandler, true);\n\t\t\twindow.removeEventListener('mouseup', SelectBoxEndHandler, true);\n\t\t\twindow.removeEventListener('blur', SelectBoxEndHandler, true);\n\t\t\telems.itemsscrollwrap.removeEventListener('wheel', SelectBoxScrollWheelHandler);\n\n\t\t\tcurrfolder.SetBusyRef(-1);\n\t\t};\n\n\t\t// Handle rename start from click.\n\t\tvar startrename = false, startrenamefolder, startrenameid, startrenametimeout;\n\t\tvar StartRenameHandler = function() {\n\t\t\tstartrenametimeout = null;\n\n\t\t\tCancelRenameHandler();\n\n\t\t\tif (startrenamefolder === currfolder && !currfolder.IsBusy() && numselecteditems === 1 && (startrenameid in selecteditemsmap))  $this.RenameSelectedItem();\n\t\t};\n\n\t\tvar CancelRenameHandler = function(e) {\n\t\t\twindow.removeEventListener('touchstart', CancelRenameHandler, true);\n\t\t\twindow.removeEventListener('mousedown', CancelRenameHandler, true);\n\t\t\twindow.removeEventListener('keydown', CancelRenameHandler, true);\n\n\t\t\tif (startrenametimeout)\n\t\t\t{\n\t\t\t\tclearTimeout(startrenametimeout);\n\t\t\t\tstartrenametimeout = null;\n\t\t\t}\n\t\t};\n\n\t\t// Scrolls the main view if the focused item is released before a move/copy operation starts.\n\t\tvar scrollnomoveinfo = null;\n\t\tvar ScrollNoMoveHandler = function(e) {\n\t\t\te.preventDefault();\n\n\t\t\tif (scrollnomoveinfo)\n\t\t\t{\n\t\t\t\tif (scrollnomoveinfo.origevent.button == 2)\n\t\t\t\t{\n\t\t\t\t\t// Ignore selection changes since the right-click context menu will be showing in a moment.\n\t\t\t\t}\n\t\t\t\telse if (scrollnomoveinfo.origevent.ctrlKey || scrollnomoveinfo.origevent.target.tagName === 'INPUT' || selectmodemulti)\n\t\t\t\t{\n\t\t\t\t\t// Toggle item selection.\n\t\t\t\t\t$this.ToggleItemSelection(scrollnomoveinfo.origelem, true);\n\t\t\t\t}\n\t\t\t\telse if (!scrollnomoveinfo.origevent.shiftKey)\n\t\t\t\t{\n\t\t\t\t\t// Select items starting at the last anchor position.\n\t\t\t\t\t$this.SelectItemsFromLastAnchor(true);\n\t\t\t\t}\n\n\t\t\t\tif (!numselecteditems)  selectmodemulti = false;\n\t\t\t\telse if (lastselecttouch && scrollnomoveinfo.origevent.target.tagName === 'INPUT')  selectmodemulti = true;\n\n\t\t\t\tscrollnomoveinfo = null;\n\t\t\t}\n\n\t\t\t$this.ScrollToFocusedItem();\n\n\t\t\twindow.removeEventListener('mouseup', ScrollNoMoveHandler, true);\n\n\t\t\tStartClipboardOverlayMenu();\n\n\t\t\t// Rename the selected item if the user started the selection on the text but didn't actually move the item.\n\t\t\tif (startrename)\n\t\t\t{\n\t\t\t\tstartrenametimeout = setTimeout(StartRenameHandler, 500);\n\n\t\t\t\twindow.addEventListener('touchstart', CancelRenameHandler, true);\n\t\t\t\twindow.addEventListener('mousedown', CancelRenameHandler, true);\n\t\t\t\twindow.addEventListener('keydown', CancelRenameHandler, true);\n\t\t\t}\n\t\t};\n\n\t\t// Start a drag operation.\n\t\tvar MoveCopyDragStartHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\t// Stop the no move/copy handler since a move/copy operation has started.\n\t\t\tif (scrollnomoveinfo)\n\t\t\t{\n\t\t\t\tif (scrollnomoveinfo.origevent.ctrlKey || scrollnomoveinfo.origevent.target.tagName === 'INPUT' || scrollnomoveinfo.origevent.button == 2 || selectmodemulti)\n\t\t\t\t{\n\t\t\t\t\t$this.SetSelectedItems([scrollnomoveinfo.origelem.dataset.feid], true);\n\t\t\t\t}\n\n\t\t\t\tscrollnomoveinfo = null;\n\t\t\t}\n\n\t\t\twindow.removeEventListener('mouseup', ScrollNoMoveHandler, true);\n\n\t\t\t// Disable clipboard overlay.\n\t\t\telems.itemsclipboardoverlaypastewrap.classList.remove('fe_fileexplorer_items_clipboard_contextmenu');\n\t\t\telems.itemsclipboardoverlaypastewrap.classList.add('fe_fileexplorer_hidden');\n\n\t\t\tif (!numselecteditems)\n\t\t\t{\n\t\t\t\te.preventDefault();\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Allow for same-instance drop target detection.\n\t\t\telems.innerwrap.classList.add('fe_fileexplorer_drag_source');\n\n\t\t\tvar icontype, ids = [];\n\n\t\t\tif (focuseditem === false)  icontype = 'file';\n\t\t\telse\n\t\t\t{\n\t\t\t\tvar entries = currfolder.GetEntries();\n\t\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\t\t\t\tvar entry = entries[entryidmap[focuseditem.dataset.feid]];\n\n\t\t\t\ticontype = entry.type;\n\t\t\t}\n\n\t\t\tfor (var x in selecteditemsmap)\n\t\t\t{\n\t\t\t\tif (selecteditemsmap.hasOwnProperty(x))  ids.push(x);\n\t\t\t}\n\n\t\t\te.dataTransfer.setDragImage(new Image(), 9999, 0);\n\n\t\t\te.dataTransfer.setData('application/file-explorer-icon;' + JSON.stringify({ group: main_group, numitems: numselecteditems, type: icontype }), '');\n\t\t\te.dataTransfer.setData('application/file-explorer-folder', JSON.stringify({ source: main_id, path: currfolder.GetPath(), ids: ids }));\n\n\t\t\t// Chromium DownloadURL support.\n\t\t\tif ($this.hasEventListener('get_download_url'))\n\t\t\t{\n\t\t\t\t// Synchronous call only.\n\t\t\t\tvar entries = currfolder.GetEntries();\n\t\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\t\t\t\tvar entry = entries[entryidmap[ids[0]]];\n\t\t\t\tvar result = {};\n\n\t\t\t\tDispatchEvent('get_download_url', [result, currfolder, ids, entry]);\n\n\t\t\t\tif (result && result.name && result.url)  e.dataTransfer.setData('DownloadURL', 'application/octet-stream:' + result.name + ':' + result.url);\n\t\t\t}\n\t\t};\n\n\t\tvar MoveCopyDragEndHandler = function(e) {\n\t\t\telems.innerwrap.classList.remove('fe_fileexplorer_drag_source');\n\t\t};\n\n\t\telems.itemswrap.addEventListener('dragstart', MoveCopyDragStartHandler);\n\t\telems.itemswrap.addEventListener('dragend', MoveCopyDragEndHandler);\n\n\t\t// Handle drop target operations.  When the drag source is the same as the drop target (i.e. the same instance), treat selected items a bit differently.\n\t\tvar movecopyenters = 0, movecopydata = false;\n\t\tvar GetMoveCopyDragNodeInfo = function(e) {\n\t\t\tvar node = e.target;\n\t\t\twhile (node && node.parentNode && node.parentNode !== elems.pathsegmentswrap && node.parentNode.parentNode !== elems.itemswrap && node !== elems.innerwrap)  node = node.parentNode;\n\n\t\t\tif (!node)  return { node: null, type: 'error' };\n\n\t\t\tif (node === elems.innerwrap)  return { node: null, type: 'currfolder' };\n\n\t\t\tif (!node.parentNode)  return { node: null, type: 'error' };\n\n\t\t\tif (node.parentNode.parentNode === elems.itemswrap)\n\t\t\t{\n\t\t\t\tif (node.parentNode.classList.contains('fe_fileexplorer_item_folder'))  return { node: node.parentNode, type: 'item' };\n\t\t\t\telse  return { node: null, type: 'currfolder' };\n\t\t\t}\n\n\t\t\tif (node.parentNode === elems.pathsegmentswrap)  return { node: node, type: 'path' };\n\t\t};\n\n\t\tvar MoveCopyDragUpdateStatusText = function(e, final) {\n\t\t\tif (movecopydata.dropeffect === 'none')  return;\n\n\t\t\tvar str = (e.ctrlKey || movecopydata.dropeffect === 'copy' ? (final ? 'Copying' : 'Copy') : (final ? 'Moving' : 'Move'));\n\n\t\t\tstr += (movecopydata.numitems === 1 ? ' 1 item' : ' {0} items');\n\n\t\t\tif (!movecopydata.dropallowed)  $this.SetNamedStatusBarText('selected', EscapeHTML(FormatStr($this.Translate(str + '...'), movecopydata.numitems)));\n\t\t\telse if (movecopydata.lasttype === 'currfolder')\n\t\t\t{\n\t\t\t\tvar path = currfolder.GetPath();\n\n\t\t\t\t$this.SetNamedStatusBarText('selected', EscapeHTML(FormatStr($this.Translate(str + ' to \"{1}\"...'), movecopydata.numitems, path[path.length - 1][1])));\n\t\t\t}\n\t\t\telse if (movecopydata.lasttype === 'path')\n\t\t\t{\n\t\t\t\tvar path = currfolder.GetPath();\n\n\t\t\t\t$this.SetNamedStatusBarText('selected', EscapeHTML(FormatStr($this.Translate(str + ' to \"{1}\"...'), movecopydata.numitems, path[movecopydata.lastnode._fepos][1])));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tvar entries = currfolder.GetEntries();\n\t\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\t\t\t\tvar entry = entries[entryidmap[movecopydata.lastnode.dataset.feid]];\n\n\t\t\t\t$this.SetNamedStatusBarText('selected', EscapeHTML(FormatStr($this.Translate(str + ' to \"{1}\"...'), movecopydata.numitems, entry.name)));\n\t\t\t}\n\t\t};\n\n\t\tvar MoveCopyDragEnterHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (!movecopyenters)\n\t\t\t{\n\t\t\t\t// See if the source is from File Explorer.\n\t\t\t\tmovecopydata = GetFileExplorerDragIconData(e, main_group);\n\n\t\t\t\tif (movecopydata !== false)\n\t\t\t\t{\n\t\t\t\t\tmovecopydata.issource = elems.innerwrap.classList.contains('fe_fileexplorer_drag_source');\n\t\t\t\t\tmovecopydata.lastnode = null;\n\t\t\t\t\tmovecopydata.lasttype = 'error';\n\t\t\t\t\tmovecopydata.dropallowed = false;\n\t\t\t\t\tmovecopydata.dropeffect = 'auto';\n\n\t\t\t\t\tMoveCopyDragUpdateStatusText(e);\n\n\t\t\t\t\t// Deny folder changes.\n\t\t\t\t\tcurrfolder.SetBusyRef(1);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// See if the dataTransfer contains files (from the desktop).\n\t\t\t\t\tfor (var x = 0; x < e.dataTransfer.types.length; x++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (e.dataTransfer.types[x] === 'Files')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Create a fake move/copy structure.\n\t\t\t\t\t\t\tmovecopydata = {\n\t\t\t\t\t\t\t\tgroup: main_group,\n\t\t\t\t\t\t\t\tnumitems: '',\n\t\t\t\t\t\t\t\ttype: 'file',\n\t\t\t\t\t\t\t\tissource: false,\n\t\t\t\t\t\t\t\tlastnode: null,\n\t\t\t\t\t\t\t\tlasttype: 'error',\n\t\t\t\t\t\t\t\tdropallowed: false,\n\t\t\t\t\t\t\t\tdropeffect: ($this.hasEventListener('init_upload') ? 'copy' : 'none')\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\tMoveCopyDragUpdateStatusText(e);\n\n\t\t\t\t\t\t\t// Deny folder changes.\n\t\t\t\t\t\t\tcurrfolder.SetBusyRef(1);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (movecopydata !== false)\n\t\t\t{\n\t\t\t\te.preventDefault();\n\n\t\t\t\t// Apply hover effect if the node changed.\n\t\t\t\tif (movecopydata.dropeffect !== 'none')\n\t\t\t\t{\n\t\t\t\t\tvar nodeinfo = GetMoveCopyDragNodeInfo(e);\n\n\t\t\t\t\tif (nodeinfo.node !== movecopydata.lastnode || nodeinfo.type !== movecopydata.lasttype)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (movecopydata.lastnode)  movecopydata.lastnode.classList.remove('fe_fileexplorer_drag_hover');\n\n\t\t\t\t\t\tmovecopydata.lastnode = nodeinfo.node;\n\t\t\t\t\t\tmovecopydata.lasttype = nodeinfo.type;\n\n\t\t\t\t\t\tif (!movecopydata.lastnode)  movecopydata.dropallowed = (!movecopydata.issource && movecopydata.lasttype === 'currfolder');\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmovecopydata.lastnode.classList.add('fe_fileexplorer_drag_hover');\n\n\t\t\t\t\t\t\tmovecopydata.dropallowed = (!movecopydata.issource || movecopydata.lasttype != 'item' || !(movecopydata.lastnode.dataset.feid in selecteditemsmap));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tMoveCopyDragUpdateStatusText(e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmovecopyenters++;\n\t\t};\n\n\t\tvar MoveCopyDragOverHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (movecopydata !== false)\n\t\t\t{\n\t\t\t\te.preventDefault();\n\n\t\t\t\tvar origeffect = e.dataTransfer.dropEffect;\n\n\t\t\t\tif (movecopydata.dropeffect !== 'auto')  e.dataTransfer.dropEffect = movecopydata.dropeffect;\n\t\t\t\telse if (e.ctrlKey)  e.dataTransfer.dropEffect = ($this.hasEventListener('copy') ? 'copy' : 'none');\n\t\t\t\telse  e.dataTransfer.dropEffect = ($this.hasEventListener('move') ? 'move' : 'none');\n\n\t\t\t\tif (origeffect !== e.dataTransfer.dropEffect)  MoveCopyDragUpdateStatusText(e);\n\t\t\t}\n\t\t};\n\n\t\tvar MoveCopyDragLeaveHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tmovecopyenters--;\n\n\t\t\tif (movecopyenters < 1)\n\t\t\t{\n\t\t\t\tmovecopyenters = 0;\n\n\t\t\t\tif (movecopydata.lastnode)  movecopydata.lastnode.classList.remove('fe_fileexplorer_drag_hover');\n\n\t\t\t\t// Restore the status bar.\n\t\t\t\tUpdateSelectionsChanged();\n\n\t\t\t\t// Allow folder changes.\n\t\t\t\tcurrfolder.SetBusyRef(-1);\n\n\t\t\t\tmovecopydata = false;\n\t\t\t}\n\t\t};\n\n\t\t// Semi-reusable code for both drag-and-drop and clipboard paste.\n\t\tvar PerformFinalMoveCopy = function(issource, lasttype, lastnode, optype, dropdata) {\n\t\t\t// Copy existing information for later use.\n\t\t\tvar origcurrfolder = currfolder;\n\t\t\tvar targetfolder;\n\t\t\tvar selecteditemsmap2 = Object.assign({}, selecteditemsmap);\n\t\t\tvar numselecteditems2 = numselecteditems;\n\n\t\t\t// Determine the target folder, creating it if necessary.  Path is only used for drag-and-drop.\n\t\t\tif (lasttype === 'currfolder')  targetfolder = currfolder;\n\t\t\telse if (lasttype === 'path')  targetfolder = $this.GetMappedFolderFromPath(currfolder.GetPath().slice(0, lastnode._fepos + 1));\n\t\t\telse if (lasttype === 'item')\n\t\t\t{\n\t\t\t\tvar entries = currfolder.GetEntries();\n\t\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\t\t\t\tvar entry = entries[entryidmap[lastnode.dataset.feid]];\n\t\t\t\tvar path = currfolder.GetPath().slice();\n\n\t\t\t\t// Append the selected path segment.\n\t\t\t\tvar pathitem = [entry.id, entry.name];\n\t\t\t\tif ('attrs' in entry)  pathitem.push(entry.attrs);\n\n\t\t\t\tpath.push(pathitem);\n\n\t\t\t\t// Create/Update the target folder.\n\t\t\t\tvar pathkey = GetMappedPathKey(path);\n\n\t\t\t\tif (!foldermap[pathkey])  foldermap[pathkey] = new Folder(path);\n\n\t\t\t\ttargetfolder = foldermap[pathkey];\n\t\t\t}\n\n\t\t\ttargetfolder.refs++;\n\n\t\t\tvar calledback = false;\n\t\t\tvar movecopycallback = function(success, selectentries) {\n\t\t\t\tif (calledback || destroyinprogress)  return;\n\n\t\t\t\tcalledback = true;\n\n\t\t\t\t$this.StopOperationIndicator();\n\n\t\t\t\tDecrementMappedFolderRefCount(targetfolder);\n\n\t\t\t\t// Restore the status bar.\n\t\t\t\tUpdateSelectionsChanged();\n\n\t\t\t\tif (optype === 'move')  currfolder.SetBusyRef(-1);\n\n\t\t\t\tif (success === true)\n\t\t\t\t{\n\t\t\t\t\t// If the target folder was also the source folder and the same folder is being viewed and performing a move operation, remove the previously selected item(s).\n\t\t\t\t\tif (issource && currfolder === origcurrfolder && targetfolder !== currfolder && optype === 'move')\n\t\t\t\t\t{\n\t\t\t\t\t\tvar entries = currfolder.GetEntries();\n\t\t\t\t\t\tvar entries2 = [];\n\t\t\t\t\t\tfor (var x = 0; x < entries.length; x++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!(entries[x].id in selecteditemsmap2))  entries2.push(entries[x]);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Adjust the focused item.\n\t\t\t\t\t\tif (focuseditem !== false && (focuseditem.dataset.feid in selecteditemsmap2))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvar node = focuseditem.nextSibling;\n\t\t\t\t\t\t\twhile (node && (node.dataset.feid in selecteditemsmap2))  node = node.nextSibling;\n\n\t\t\t\t\t\t\tif (!node)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tnode = focuseditem.previousSibling;\n\t\t\t\t\t\t\t\twhile (node && (node.dataset.feid in selecteditemsmap2))  node = node.previousSibling;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (node)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$this.SetFocusItem(node.dataset.feid, true);\n\t\t\t\t\t\t\t\t$this.ScrollToFocusedItem();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcurrfolder.SetEntries(entries2);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this.SetNamedStatusBarText('message', EscapeHTML(FormatStr($this.Translate((optype === 'copy' ? 'Copying' : 'Moving') + ' items failed.' + (typeof success === 'string' ? '  {0}' : '')), success)), $this.settings.messagetimeout);\n\t\t\t\t}\n\n\t\t\t\t// Handle entries.\n\t\t\t\tif ($this.IsMappedFolder(targetfolder) && selectentries && Array.isArray(selectentries))\n\t\t\t\t{\n\t\t\t\t\t// Merge items into the target folder.\n\t\t\t\t\tvar entries = targetfolder.GetEntries();\n\t\t\t\t\tvar entryidmap = targetfolder.GetEntryIDMap();\n\n\t\t\t\t\tfor (var x = 0; x < selectentries.length; x++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (selectentries[x].id in entryidmap)  entries[entryidmap[selectentries[x].id]] = selectentries[x];\n\t\t\t\t\t\telse  entries.push(selectentries[x]);\n\t\t\t\t\t}\n\n\t\t\t\t\ttargetfolder.SetEntries(entries);\n\n\t\t\t\t\t// If the target folder is visible, set selections to the IDs moved/copied.\n\t\t\t\t\tif (targetfolder === currfolder)\n\t\t\t\t\t{\n\t\t\t\t\t\tvar selectids = [];\n\n\t\t\t\t\t\tfor (var x = 0; x < selectentries.length; x++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tselectids.push(selectentries[x].id);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$this.SetSelectedItems(selectids);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Handle all scenarios with a forced refresh.\n\t\t\t\t$this.RefreshFolders(true);\n\t\t\t};\n\n\t\t\t// Release busy status for copy operations.\n\t\t\tif (optype === 'copy')  currfolder.SetBusyRef(-1);\n\n\t\t\t$this.StartOperationIndicator();\n\n\t\t\tDispatchEvent(optype, [movecopycallback, dropdata.path, dropdata.ids, targetfolder]);\n\t\t};\n\n\n\t\t// Reusable progress tracker.\n\t\tvar progresstrackers = [], progresstrackerinterval;\n\n\t\tvar InitProgressTracker = function() {\n\t\t\tvar tracker = {\n\t\t\t\tstarted: Date.now(),\n\t\t\t\ttotalbytes: 0,\n\t\t\t\tshowbyterate: false,\n\t\t\t\tuploading: false,\n\t\t\t\tqueueditems: 0,\n\t\t\t\tqueuesizeunknown: false,\n\t\t\t\titemsdone: 0,\n\t\t\t\tfaileditems: 0,\n\t\t\t\tcancelcallback: null\n\t\t\t};\n\n\t\t\treturn tracker;\n\t\t};\n\n\t\t$this.UpdateProgressText = function() {\n\t\t\tif (!progresstrackers || !progresstrackers.length)  return;\n\n\t\t\t// Combine all progress tracker info.\n\t\t\tvar tracker = InitProgressTracker();\n\n\t\t\tvar currts = tracker.started;\n\n\t\t\tfor (var x = 0; x < progresstrackers.length; x++)\n\t\t\t{\n\t\t\t\ttracker.totalbytes += progresstrackers[x].totalbytes;\n\n\t\t\t\tif (progresstrackers[x].showbyterate !== false)\n\t\t\t\t{\n\t\t\t\t\ttracker.showbyterate = true;\n\n\t\t\t\t\tif (tracker.started > progresstrackers[x].started)  tracker.started = progresstrackers[x].started;\n\t\t\t\t}\n\n\t\t\t\tif (progresstrackers[x].uploading !== false)\n\t\t\t\t{\n\t\t\t\t\tif (tracker.uploading === false)  tracker.uploading = 0;\n\n\t\t\t\t\ttracker.uploading += progresstrackers[x].uploading;\n\t\t\t\t}\n\n\t\t\t\ttracker.queueditems += progresstrackers[x].queueditems;\n\n\t\t\t\tif (progresstrackers[x].queuesizeunknown !== false)  tracker.queuesizeunknown = true;\n\n\t\t\t\ttracker.itemsdone += progresstrackers[x].itemsdone;\n\t\t\t\ttracker.faileditems += progresstrackers[x].faileditems;\n\t\t\t}\n\n\t\t\tvar totalbytesstr = GetDisplayFilesize(tracker.totalbytes, $this.settings.adjustprecision, $this.settings.displayunits);\n\n\t\t\t// Wait a few seconds before calculating the byte rate.\n\t\t\tif (tracker.showbyterate && currts > tracker.started + 3000)\n\t\t\t{\n\t\t\t\tvar byterate = tracker.totalbytes / ((currts - tracker.started) / 1000);\n\n\t\t\t\tvar byteratestr = FormatStr($this.Translate('{0}/s'), GetDisplayFilesize(byterate, $this.settings.adjustprecision, $this.settings.displayunits));\n\n\t\t\t\telems.statusbaractionprogressmessagewrap.innerHTML = EscapeHTML(FormatStr('{0}\\u00A0\\u00A0\\u00A0{1}', byteratestr, totalbytesstr));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\telems.statusbaractionprogressmessagewrap.innerHTML = EscapeHTML(FormatStr('{0}', totalbytesstr));\n\t\t\t}\n\n\t\t\tvar stropts = [];\n\t\t\tvar titleopts = [];\n\n\t\t\tif (tracker.uploading !== false)\n\t\t\t{\n\t\t\t\tstropts.push($this.Translate('{0} <span class=\"fe_fileexplorer_action_progress_msg_icon fe_fileexplorer_action_progress_msg_icon_uploads_in_progress\"></span>'));\n\t\t\t\ttitleopts.push($this.Translate('{0} uploading'));\n\t\t\t}\n\n\t\t\tif (tracker.queueditems)\n\t\t\t{\n\t\t\t\tstropts.push($this.Translate((tracker.queuesizeunknown ? '{1}+ ' : '{1} ') + '<span class=\"fe_fileexplorer_action_progress_msg_icon fe_fileexplorer_action_progress_msg_icon_queued\"></span>'));\n\t\t\t\ttitleopts.push($this.Translate(tracker.queuesizeunknown ? '{1}+ queued' : '{1} queued'));\n\t\t\t}\n\n\t\t\tif (tracker.itemsdone)\n\t\t\t{\n\t\t\t\tstropts.push($this.Translate('{2} <span class=\"fe_fileexplorer_action_progress_msg_icon fe_fileexplorer_action_progress_msg_icon_done\"></span>'));\n\t\t\t\ttitleopts.push($this.Translate('{2} done'));\n\t\t\t}\n\n\t\t\tif (tracker.faileditems)\n\t\t\t{\n\t\t\t\tstropts.push($this.Translate('{3} <span class=\"fe_fileexplorer_action_progress_msg_icon fe_fileexplorer_action_progress_msg_icon_errors\"></span>'));\n\t\t\t\ttitleopts.push($this.Translate('{3} failed'));\n\t\t\t}\n\n\t\t\telems.statusbaractionprogressmessagewrap2.innerHTML = FormatStr(stropts.join('\\u00A0\\u00A0\\u00A0'), tracker.uploading, tracker.queueditems, tracker.itemsdone, tracker.faileditems);\n\t\t\telems.statusbaractionprogressmessagewrap2.title = EscapeHTML(FormatStr(titleopts.join(', '), tracker.uploading, tracker.queueditems, tracker.itemsdone, tracker.faileditems));\n\t\t};\n\n\t\t// Stop all progress callbacks.\n\t\tvar ProgressCancelAllHandler = function(e) {\n\t\t\tif (e)\n\t\t\t{\n\t\t\t\tif (!e.isTrusted)  return;\n\n\t\t\t\te.preventDefault();\n\t\t\t}\n\n\t\t\t$this.SetNamedStatusBarText('message', EscapeHTML($this.Translate('Stopping...')), $this.settings.messagetimeout);\n\n\t\t\tfor (var x = 0; x < progresstrackers.length; x++)\n\t\t\t{\n\t\t\t\tif (progresstrackers[x].cancelcallback)  progresstrackers[x].cancelcallback.call($this, e);\n\t\t\t}\n\n\t\t\t$this.Focus(true, true);\n\n\t\t\telems.statusbaractionprogresscancelwrap.classList.add('fe_fileexplorer_hidden');\n\t\t};\n\n\t\telems.statusbaractionprogresscancelwrap.addEventListener('click', ProgressCancelAllHandler);\n\n\t\tvar ProgressCancelKeydownHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (e.keyCode == 13 || e.keyCode == 32)  ProgressCancelAllHandler(e);\n\t\t};\n\n\t\telems.statusbaractionprogresscancelwrap.addEventListener('keydown', ProgressCancelKeydownHandler);\n\n\t\tvar FinishProgressDisplay = function() {\n\t\t\telems.statusbaractionprogresswrap.classList.add('fe_fileexplorer_hidden');\n\n\t\t\telems.statusbaractionprogressmessagewrap.innerHTML = '';\n\n\t\t\t$this.SetNamedStatusBarText('message', '');\n\n\t\t\tclearInterval(progresstrackerinterval);\n\t\t\tprogresstrackerinterval = null;\n\t\t};\n\n\t\t// When a touch, mouse, or keyboard event happens after the last tracker is finished, start a short timeout to clean up the remaining bits.\n\t\tvar PreFinishProgressDisplay = function(e) {\n\t\t\twindow.removeEventListener('touchstart', PreFinishProgressDisplay, true);\n\t\t\twindow.removeEventListener('mousemove', PreFinishProgressDisplay, true);\n\t\t\twindow.removeEventListener('mousedown', PreFinishProgressDisplay, true);\n\t\t\twindow.removeEventListener('keydown', PreFinishProgressDisplay, true);\n\n\t\t\tif (e)  progresstrackerinterval = setInterval(FinishProgressDisplay, 1000);\n\t\t};\n\n\t\t$this.CreateProgressTracker = function(cancelcallback) {\n\t\t\tvar tracker = InitProgressTracker();\n\n\t\t\ttracker.cancelcallback = cancelcallback;\n\n\t\t\tprogresstrackers.push(tracker);\n\n\t\t\tif (progresstrackerinterval)  clearInterval(progresstrackerinterval);\n\n\t\t\tprogresstrackerinterval = setInterval($this.UpdateProgressText, 1000);\n\n\t\t\tPreFinishProgressDisplay();\n\n\t\t\t$this.UpdateProgressText();\n\n\t\t\tif (cancelcallback)  elems.statusbaractionprogresscancelwrap.classList.remove('fe_fileexplorer_hidden');\n\t\t\telems.statusbaractionprogresswrap.classList.remove('fe_fileexplorer_hidden');\n\n\t\t\treturn tracker;\n\t\t};\n\n\t\t$this.RemoveProgressTracker = function(tracker, finishmessage) {\n\t\t\t$this.UpdateProgressText();\n\n\t\t\tfor (var x = 0; x < progresstrackers.length; x++)\n\t\t\t{\n\t\t\t\tif (progresstrackers[x] === tracker)\n\t\t\t\t{\n\t\t\t\t\tprogresstrackers.splice(x, 1);\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar found = false;\n\t\t\tfor (var x = 0; x < progresstrackers.length; x++)\n\t\t\t{\n\t\t\t\tif (progresstrackers[x].cancelcallback)  found = true;\n\t\t\t}\n\n\t\t\tif (!found)  elems.statusbaractionprogresscancelwrap.classList.add('fe_fileexplorer_hidden');\n\n\t\t\tif (!progresstrackers.length)\n\t\t\t{\n\t\t\t\tif (progresstrackerinterval)\n\t\t\t\t{\n\t\t\t\t\tclearInterval(progresstrackerinterval);\n\t\t\t\t\tprogresstrackerinterval = null;\n\t\t\t\t}\n\n\t\t\t\twindow.addEventListener('touchstart', PreFinishProgressDisplay, true);\n\t\t\t\twindow.addEventListener('mousemove', PreFinishProgressDisplay, true);\n\t\t\t\twindow.addEventListener('mousedown', PreFinishProgressDisplay, true);\n\t\t\t\twindow.addEventListener('keydown', PreFinishProgressDisplay, true);\n\n\t\t\t\tif (finishmessage)  $this.SetNamedStatusBarText('message', $this.Translate(finishmessage));\n\t\t\t}\n\t\t};\n\n\n\t\t// Manages active uploads.\n\t\tvar uploadactivequeue = [], uploadqueue = [], uploaddirentries = [], uploadqueuestarted = false, uploadprogresstracker = false, uploadfolderinterval, uploadcancel = false;\n\n\t\tvar BlobSlice = function() {\n\t\t\tvar tempslice = this.slice || this.webkitSlice || this.mozSlice;\n\n\t\t\treturn tempslice.apply(this, arguments);\n\t\t};\n\n\t\t// Forcefully stop all uploads and clear out the queue.\n\t\tvar UploadCancelAllHandler = function(e) {\n\t\t\tif (e)\n\t\t\t{\n\t\t\t\tif (!e.isTrusted)  return;\n\n\t\t\t\te.preventDefault();\n\t\t\t}\n\n\t\t\tuploadcancel = true;\n\n\t\t\tfor (var x = uploadactivequeue.length; x; x--)\n\t\t\t{\n\t\t\t\tif (uploadactivequeue[x - 1].xhr)  uploadactivequeue[x - 1].xhr.Abort();\n\t\t\t}\n\n\t\t\tif (uploadfolderinterval)\n\t\t\t{\n\t\t\t\tclearInterval(uploadfolderinterval);\n\t\t\t\tuploadfolderinterval = null;\n\t\t\t}\n\t\t};\n\n\t\t// Refreshes the current folder every 30 seconds while uploading.\n\t\tvar UpdateUploadRefreshFolder = function() {\n\t\t\t$this.RefreshFolders(true);\n\t\t};\n\n\t\tvar UpdateUploadProgressInfo = function() {\n\t\t\tif (!uploadprogresstracker)  return;\n\n\t\t\tuploadprogresstracker.uploading = uploadactivequeue.length;\n\t\t\tuploadprogresstracker.queueditems = uploadqueue.length;\n\t\t\tuploadprogresstracker.queuesizeunknown = (uploaddirentries.length > 0);\n\t\t};\n\n\t\t// Remove the item from the active queue and start the next upload item.\n\t\tvar RemoveUploadActiveQueueItem = function(fileinfo) {\n\t\t\tfor (var x = 0; x < uploadactivequeue.length; x++)\n\t\t\t{\n\t\t\t\tif (uploadactivequeue[x] === fileinfo)\n\t\t\t\t{\n\t\t\t\t\tDecrementMappedFolderRefCount(fileinfo.folder);\n\n\t\t\t\t\tuploadactivequeue.splice(x, 1);\n\n\t\t\t\t\tif (fileinfo.xhr)\n\t\t\t\t\t{\n\t\t\t\t\t\tfileinfo.xhr.Destroy();\n\n\t\t\t\t\t\tdelete fileinfo.xhr;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tUpdateUploadProgressInfo();\n\n\t\t\tStartNextUpload();\n\t\t};\n\n\t\tvar FailUpload = function(fileinfo, newstatus, e) {\n\t\t\tfileinfo.status = newstatus;\n\n\t\t\tuploadprogresstracker.faileditems++;\n\n\t\t\tDispatchEvent('upload_error', [fileinfo, e]);\n\n\t\t\tRemoveUploadActiveQueueItem(fileinfo);\n\t\t};\n\n\t\t// Builds a chunk and an upload request object and starts the upload.\n\t\tvar StartUploadChunk = function(fileinfo) {\n\t\t\tif (uploadcancel)\n\t\t\t{\n\t\t\t\tFailUpload(fileinfo, 'request_aborted');\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Calculate the chunk size.\n\t\t\tvar chunksize = (fileinfo.chunksize ? (typeof fileinfo.chunksize === 'function' ? fileinfo.chunksize(fileinfo) : fileinfo.chunksize) : fileinfo.sizebytes - fileinfo.currchunkstart);\n\n\t\t\tif (fileinfo.currchunkstart + chunksize > fileinfo.sizebytes)  chunksize = fileinfo.sizebytes - fileinfo.currchunkstart;\n\n\t\t\t// When sending chunked data, make the first chunk fairly small so if the the upload is going to fail for whatever reason (e.g. an invalid file extension), it will fail quickly.\n\t\t\tif (!fileinfo.currchunkstart && chunksize < fileinfo.sizebytes && chunksize > 4096)  chunksize = 4096;\n\n\t\t\tif (fileinfo.type === 'file')\n\t\t\t{\n\t\t\t\tfileinfo.currblob = BlobSlice.call(fileinfo.file, fileinfo.currchunkstart, fileinfo.currchunkstart + chunksize, fileinfo.file.type);\n\n\t\t\t\tchunksize = fileinfo.currblob.size;\n\t\t\t}\n\n\t\t\tfileinfo.currchunksize = chunksize;\n\n\t\t\t// Set up various callbacks.\n\t\t\tvar uploadstarthandler = function(e) {\n\t\t\t\tfileinfo.status = 'upload_started';\n\t\t\t\tfileinfo.progress.uploadedchunkbytes = 0;\n\t\t\t};\n\n\t\t\tvar uploadprogresshandler = function(e) {\n\t\t\t\tfileinfo.status = 'upload_in_progress';\n\n\t\t\t\tvar diffsize = (e.loaded - fileinfo.progress.uploadedchunkbytes);\n\n\t\t\t\tuploadprogresstracker.totalbytes += diffsize;\n\t\t\t\tfileinfo.progress.uploadedbytes += diffsize;\n\n\t\t\t\tfileinfo.progress.uploadedchunkbytes = e.loaded;\n\n\t\t\t\tvar currts = Date.now();\n\n\t\t\t\t// Wait a few seconds before calculating the byterate.\n\t\t\t\tif (currts > fileinfo.progress.started + 3000)  fileinfo.progress.byterate = fileinfo.progress.uploadedbytes / (currts - fileinfo.progress.started);\n\n\t\t\t\tfileinfo.progress.percent = (e.lengthComputable ? e.loaded / e.total * 100 : (fileinfo.currchunksize ? e.loaded / fileinfo.currchunksize : 0));\n\t\t\t};\n\n\t\t\tvar uploadcompletehandler = function(e) {\n\t\t\t\tfileinfo.status = 'upload_complete';\n\n\t\t\t\tif (fileinfo.progress.uploadedbytes < fileinfo.currchunksize)  uploadprogresstracker.trackerbytes += (fileinfo.currchunksize - fileinfo.progress.uploadedbytes);\n\t\t\t};\n\n\t\t\tvar origcurrfolder = currfolder;\n\t\t\tvar requestcompletehandler = function(e) {\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tvar response = JSON.parse(e.target.responseText);\n\n\t\t\t\t\tfileinfo.currchunkstart += fileinfo.currchunksize;\n\n\t\t\t\t\tif (!response.success)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this.SetNamedStatusBarText('message', EscapeHTML(FormatStr($this.Translate('Error uploading \"{0}\" ({1})'), fileinfo.fullPath, response.errorcode)), $this.settings.messagetimeout * 5);\n\n\t\t\t\t\t\tFailUpload(fileinfo, 'request_error', e);\n\t\t\t\t\t}\n\t\t\t\t\telse if (fileinfo.currchunkstart < fileinfo.sizebytes)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Start the next upload chunk.\n\t\t\t\t\t\tfileinfo.retriesleft = fileinfo.retries;\n\n\t\t\t\t\t\tStartUploadChunk(fileinfo);\n\t\t\t\t\t}\n\t\t\t\t\telse if (!$this.hasEventListener('upload_done'))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (response.entry && $this.IsMappedFolder(origcurrfolder))  origcurrfolder.SetEntry(response.entry);\n\n\t\t\t\t\t\tuploadprogresstracker.itemsdone++;\n\n\t\t\t\t\t\tRemoveUploadActiveQueueItem(fileinfo);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// Finalize the upload.\n\t\t\t\t\t\tif (response.entry && $this.IsMappedFolder(origcurrfolder))  origcurrfolder.SetEntry(response.entry);\n\n\t\t\t\t\t\torigcurrfolder = currfolder;\n\n\t\t\t\t\t\tvar calledback = false;\n\t\t\t\t\t\tvar finalizecallback = function(success, entry) {\n\t\t\t\t\t\t\tif (calledback)  return;\n\n\t\t\t\t\t\t\tcalledback = true;\n\n\t\t\t\t\t\t\tif (entry && $this.IsMappedFolder(origcurrfolder))  origcurrfolder.SetEntry(entry);\n\n\t\t\t\t\t\t\tif (success === true)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tuploadprogresstracker.itemsdone++;\n\n\t\t\t\t\t\t\t\tRemoveUploadActiveQueueItem(fileinfo);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$this.SetNamedStatusBarText('message', EscapeHTML(FormatStr($this.Translate('Finalizing \"{0}\" failed.' + (typeof success === 'string' ? '  {1}' : '')), fileinfo.fullPath, success)), $this.settings.messagetimeout);\n\n\t\t\t\t\t\t\t\tFailUpload(fileinfo, 'finalize_failed');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tDispatchEvent('upload_done', [finalizecallback, fileinfo]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch(e)\n\t\t\t\t{\n\t\t\t\t\trequesterrorhandler(e);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tvar requesterrorhandler = function(e) {\n\t\t\t\tif (!fileinfo.retriesleft)  FailUpload(fileinfo, 'request_failed', e);\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Retry.\n\t\t\t\t\tfileinfo.retriesleft--;\n\n\t\t\t\t\tStartUploadChunk(fileinfo);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tvar requestabortedhandler = function(e) {\n\t\t\t\tFailUpload(fileinfo, 'request_aborted', e);\n\t\t\t};\n\n\t\t\tfileinfo.xhr = new PrepareXHR(fileinfo);\n\n\t\t\t// Allow headers/params to be modified for the current chunk and/or add listeners to the xhr object.\n\t\t\tDispatchEvent('update_upload_fileinfo', fileinfo);\n\n\t\t\tfileinfo.xhr.upload.addEventListener('loadstart', uploadstarthandler);\n\t\t\tfileinfo.xhr.upload.addEventListener('progress', uploadprogresshandler);\n\t\t\tfileinfo.xhr.upload.addEventListener('load', uploadcompletehandler);\n\n\t\t\tfileinfo.xhr.addEventListener('load', requestcompletehandler);\n\t\t\tfileinfo.xhr.addEventListener('error', requesterrorhandler);\n\t\t\tfileinfo.xhr.addEventListener('timeout', requesterrorhandler);\n\t\t\tfileinfo.xhr.addEventListener('abort', requestabortedhandler);\n\n\t\t\tfileinfo.method = 'POST';\n\t\t\tfileinfo.headers = fileinfo.headers || {};\n\n\t\t\t// Set the Content-Range request header for chunked file transfers.\n\t\t\tif (fileinfo.type === 'file' && (fileinfo.currchunkstart || fileinfo.currchunksize < fileinfo.sizebytes))\n\t\t\t{\n\t\t\t\t// Handle zero byte chunks gracefully (0 - 1 + 1 = 0).\n\t\t\t\tif (!fileinfo.currchunksize)  fileinfo.headers['Content-Range'] = 'bytes 1-0/' + fileinfo.sizebytes;\n\t\t\t\telse  fileinfo.headers['Content-Range'] = 'bytes ' + fileinfo.currchunkstart + '-' + (fileinfo.currchunkstart + fileinfo.currchunksize - 1) + '/' + fileinfo.sizebytes;\n\n\t\t\t\t// Enable FileUploadHelper compatibility.  Only really needs to exist.\n\t\t\t\tfileinfo.headers['Content-Disposition'] = 'attachment; filename=\"' + encodeURI(fileinfo.name || fileinfo.file.name) + '\"';\n\t\t\t}\n\n\t\t\tfileinfo.headers['Accept'] = 'application/json';\n\n\t\t\t// When using FormData for params, the FormData object has to be rebuilt with each request.\n\t\t\tvar formdata = fileinfo.xhr.PrepareBody();\n\n\t\t\t// Append current path.  Useful for returning an entry from the server.\n\t\t\tif (fileinfo.currpathparam)\n\t\t\t{\n\t\t\t\tformdata.append(fileinfo.currpathparam, JSON.stringify(currfolder.GetPathIDs()));\n\t\t\t}\n\n\t\t\t// Append the file data.\n\t\t\tif (fileinfo.type === 'file')\n\t\t\t{\n\t\t\t\tformdata.append(fileinfo.fileparam, fileinfo.currblob, fileinfo.name || fileinfo.file.name);\n\t\t\t}\n\n\t\t\t// Start the upload.\n\t\t\tfileinfo.xhr.Send(formdata);\n\t\t};\n\n\t\tvar InitializeUpload = function(fileinfo) {\n\t\t\tvar calledback = false;\n\t\t\tvar startuploadcallback = function(process) {\n\t\t\t\tif (calledback)  return;\n\n\t\t\t\tcalledback = true;\n\n\t\t\t\tif (process === true && !destroyinprogress)\n\t\t\t\t{\n\t\t\t\t\t// Initialize the fileinfo data.\n\t\t\t\t\tfileinfo.status = 'upload_start';\n\n\t\t\t\t\tfileinfo.progress = {\n\t\t\t\t\t\tstarted: Date.now(),\n\t\t\t\t\t\tuploadedbytes: 0,\n\t\t\t\t\t\tbyterate: 0,\n\t\t\t\t\t\tpercent: 0\n\t\t\t\t\t};\n\n\t\t\t\t\tfileinfo.sizebytes = (fileinfo.type === 'file' ? fileinfo.file.size : 0);\n\t\t\t\t\tfileinfo.currchunkstart = 0;\n\t\t\t\t\tif (!fileinfo.retries)  fileinfo.retries = 0;\n\t\t\t\t\tfileinfo.retriesleft = fileinfo.retries;\n\n\t\t\t\t\tif (!uploadcancel)  $this.SetNamedStatusBarText('message', EscapeHTML(FormatStr($this.Translate('Uploading \"{0}\"...'), fileinfo.fullPath)), $this.settings.messagetimeout * 5);\n\n\t\t\t\t\t// Set up initial progress tracker info.\n\t\t\t\t\tif (!uploadprogresstracker)\n\t\t\t\t\t{\n\t\t\t\t\t\tuploadprogresstracker = $this.CreateProgressTracker(UploadCancelAllHandler);\n\t\t\t\t\t\tuploadprogresstracker.showbyterate = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!uploadfolderinterval)  uploadfolderinterval = setInterval(UpdateUploadRefreshFolder, 30000);\n\n\t\t\t\t\tUpdateUploadProgressInfo();\n\n\t\t\t\t\t$this.UpdateProgressText();\n\n\t\t\t\t\t// Start the first chunk.\n\t\t\t\t\tStartUploadChunk(fileinfo);\n\t\t\t\t}\n\t\t\t\telse if (typeof process === 'string')\n\t\t\t\t{\n\t\t\t\t\t$this.SetNamedStatusBarText('message', EscapeHTML(FormatStr($this.Translate('Starting \"{0}\" failed.  {1}'), fileinfo.fullPath, process)), $this.settings.messagetimeout);\n\n\t\t\t\t\t// Set up initial progress tracker info.\n\t\t\t\t\tif (!uploadprogresstracker)\n\t\t\t\t\t{\n\t\t\t\t\t\tuploadprogresstracker = $this.CreateProgressTracker(UploadCancelAllHandler);\n\t\t\t\t\t\tuploadprogresstracker.showbyterate = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tFailUpload(fileinfo, 'start_failed');\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tRemoveUploadActiveQueueItem(fileinfo);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tUpdateUploadProgressInfo();\n\n\t\t\t$this.UpdateProgressText();\n\n\t\t\tif (!uploadqueuestarted)  uploadqueuestarted = Date.now();\n\n\t\t\tDispatchEvent('init_upload', [startuploadcallback, fileinfo, uploadqueuestarted]);\n\t\t};\n\n\t\t// Uses a FileReader object to determine if a File blob is readable or not.\n\t\tvar TestUnknownTypeUpload = function(fileinfo) {\n\t\t\tfileinfo.status = 'waiting';\n\n\t\t\tvar fr = new FileReader();\n\n\t\t\t// Early terminate reading files.\n\t\t\tfr.addEventListener('progress', function(e) {\n\t\t\t\tfr.abort();\n\n\t\t\t\tfileinfo.status = 'init';\n\t\t\t\tfileinfo.type = 'file';\n\n\t\t\t\tStartNextUpload();\n\t\t\t});\n\n\t\t\t// The whole file loaded.\n\t\t\tfr.addEventListener('load', function(e) {\n\t\t\t\tfileinfo.status = 'init';\n\t\t\t\tfileinfo.type = 'file';\n\n\t\t\t\tStartNextUpload();\n\t\t\t});\n\n\t\t\t// Not a usable file.  Possibly a directory.\n\t\t\tfr.addEventListener('error', function(e) {\n\t\t\t\tfileinfo.status = 'invalid_item';\n\n\t\t\t\tDispatchEvent('upload_error', [fileinfo, e]);\n\n\t\t\t\tStartNextUpload();\n\t\t\t});\n\n\t\t\tfr.readAsArrayBuffer(fileinfo.file);\n\t\t};\n\n\t\tvar QueueUploadEntry = function(targetfolder, entry) {\n\t\t\tif (entry.isDirectory)\n\t\t\t{\n\t\t\t\tvar reader = entry.createReader();\n\n\t\t\t\tvar dirinfo = {\n\t\t\t\t\tentry: entry,\n\t\t\t\t\treader: reader,\n\t\t\t\t\tfolder: targetfolder,\n\t\t\t\t\ttype: 'direntry',\n\t\t\t\t\tsize: 0,\n\t\t\t\t\tfullPath: entry.fullPath,\n\t\t\t\t\tbusy: false\n\t\t\t\t};\n\n\t\t\t\ttargetfolder.refs++;\n\n\t\t\t\tuploaddirentries.push(dirinfo);\n\t\t\t}\n\t\t\telse if (entry.isFile)\n\t\t\t{\n\t\t\t\tvar fileinfo = {\n\t\t\t\t\tstatus: 'init',\n\t\t\t\t\tfolder: targetfolder,\n\t\t\t\t\ttype: 'file',\n\t\t\t\t\tfile: null,\n\t\t\t\t\tfullPath: entry.fullPath\n\t\t\t\t};\n\n\t\t\t\ttargetfolder.refs++;\n\n\t\t\t\tentry.file(function(file) {\n\t\t\t\t\tfileinfo.file = file;\n\n\t\t\t\t\tuploadqueue.push(fileinfo);\n\n\t\t\t\t\tStartNextUpload();\n\t\t\t\t}, function(e) {\n\t\t\t\t\tfileinfo.status = 'invalid_file';\n\n\t\t\t\t\tDispatchEvent('upload_error', [fileinfo, e]);\n\n\t\t\t\t\tDecrementMappedFolderRefCount(targetfolder);\n\n\t\t\t\t\tStartNextUpload();\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tvar StartNextUpload = function() {\n\t\t\tif (!$this.hasEventListener('init_upload'))  uploadcancel = true;\n\n\t\t\tif (uploadcancel && uploaddirentries.length && !uploaddirentries[0].busy)  uploaddirentries = [];\n\n\t\t\t// Queue up some items from directory entries.\n\t\t\tif (!uploadcancel && uploadqueue.length < 100 && uploaddirentries.length && !uploaddirentries[0].busy)\n\t\t\t{\n\t\t\t\tvar targetfolder = uploaddirentries[0].folder;\n\n\t\t\t\tuploaddirentries[0].busy = true;\n\n\t\t\t\t// May only read up to 100 entries on some browsers (e.g. Chromium-based).\n\t\t\t\tuploaddirentries[0].reader.readEntries(function(entries) {\n\t\t\t\t\tuploaddirentries[0].busy = false;\n\n\t\t\t\t\tif (uploadcancel)\n\t\t\t\t\t{\n\t\t\t\t\t\tuploaddirentries.shift();\n\n\t\t\t\t\t\tUpdateUploadProgressInfo();\n\t\t\t\t\t}\n\t\t\t\t\telse if (!entries.length)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Add empty directory to the queue.\n\t\t\t\t\t\tif (!uploaddirentries[0].size)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvar fileinfo = {\n\t\t\t\t\t\t\t\tstatus: 'init',\n\t\t\t\t\t\t\t\tfolder: targetfolder,\n\t\t\t\t\t\t\t\ttype: 'dir',\n\t\t\t\t\t\t\t\tfullPath: uploaddirentries[0].fullPath\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\ttargetfolder.refs++;\n\n\t\t\t\t\t\t\tuploadqueue.push(fileinfo);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// No more entries.\n\t\t\t\t\t\tDecrementMappedFolderRefCount(targetfolder);\n\n\t\t\t\t\t\tuploaddirentries.shift();\n\n\t\t\t\t\t\tUpdateUploadProgressInfo();\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tuploaddirentries[0].size += entries.length;\n\n\t\t\t\t\t\tentries.forEach(function(entry) {\n\t\t\t\t\t\t\tQueueUploadEntry(targetfolder, entry);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tStartNextUpload();\n\t\t\t\t}, function(e) {\n\t\t\t\t\t// An error occurred.  Remove the directory.\n\t\t\t\t\tDispatchEvent('upload_error', [uploaddirentries[0], e]);\n\n\t\t\t\t\tDecrementMappedFolderRefCount(targetfolder);\n\n\t\t\t\t\tuploaddirentries.shift();\n\n\t\t\t\t\tUpdateUploadProgressInfo();\n\n\t\t\t\t\tStartNextUpload();\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Trigger concurrent upload start.\n\t\t\tif (uploadactivequeue.length < $this.settings.concurrentuploads && uploadqueue.length)\n\t\t\t{\n\t\t\t\t// Find something to do.\n\t\t\t\tvar waiting = 0, found = false;\n\t\t\t\tfor (var x = 0; x < uploadqueue.length; x++)\n\t\t\t\t{\n\t\t\t\t\tif (uploadqueue[x].status === 'waiting')  waiting++;\n\t\t\t\t\telse if (uploadcancel || uploadqueue[x].status === 'invalid_item')\n\t\t\t\t\t{\n\t\t\t\t\t\tif (uploadqueue[x].status === 'invalid_item')  console.error('Removed \\'' + uploadqueue[x].fullPath + '\\' from the upload queue due to an error - it is probably a directory.');\n\n\t\t\t\t\t\tDecrementMappedFolderRefCount(uploadqueue[x].folder);\n\n\t\t\t\t\t\tuploadqueue.splice(x, 1);\n\n\t\t\t\t\t\tx--;\n\n\t\t\t\t\t\tUpdateUploadProgressInfo();\n\n\t\t\t\t\t\tfound = true;\n\t\t\t\t\t}\n\t\t\t\t\telse if (uploadqueue[x].status === 'init')\n\t\t\t\t\t{\n\t\t\t\t\t\tif (uploadqueue[x].type === 'file' || uploadqueue[x].type === 'dir')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (uploadactivequeue.length < $this.settings.concurrentuploads)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvar fileinfo = uploadqueue[x];\n\n\t\t\t\t\t\t\t\tuploadactivequeue.push(fileinfo);\n\n\t\t\t\t\t\t\t\tuploadqueue.splice(x, 1);\n\n\t\t\t\t\t\t\t\tx--;\n\n\t\t\t\t\t\t\t\tInitializeUpload(fileinfo);\n\n\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (uploadqueue[x].type === '' && waiting < 10)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tTestUnknownTypeUpload(uploadqueue[x]);\n\n\t\t\t\t\t\t\twaiting++;\n\n\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (found)  StartNextUpload();\n\t\t\t}\n\n\t\t\t// Nothing left to do in any queue.  Clean up.\n\t\t\tif (uploadprogresstracker && !uploadactivequeue.length && !uploadqueue.length && !uploaddirentries.length && !destroyinprogress)\n\t\t\t{\n\t\t\t\t$this.RemoveProgressTracker(uploadprogresstracker, (uploadcancel || destroyinprogress ? 'Uploading stopped' : 'Uploading done'));\n\n\t\t\t\tif (uploadfolderinterval)\n\t\t\t\t{\n\t\t\t\t\tclearInterval(uploadfolderinterval);\n\t\t\t\t\tuploadfolderinterval = null;\n\t\t\t\t}\n\n\t\t\t\t$this.RefreshFolders(true);\n\n\t\t\t\tuploadqueuestarted = false;\n\t\t\t\tuploadprogresstracker = false;\n\t\t\t\tuploadcancel = false;\n\n\t\t\t\t// May trigger garbage collection.\n\t\t\t\tuploadactivequeue = [];\n\t\t\t\tuploadqueue = [];\n\t\t\t\tuploaddirentries = [];\n\t\t\t}\n\t\t};\n\n\t\t// Upload files specified by dataTransfer or clipboardData.\n\t\t$this.ProcessFilesAndUpload = function(targettype, targetnode, dt) {\n\t\t\tvar targetfolder;\n\n\t\t\t// Determine the target folder, creating it if necessary.  Path is only used for drag-and-drop.\n\t\t\tif (targettype === 'currfolder')  targetfolder = currfolder;\n\t\t\telse if (targettype === 'path')  targetfolder = $this.GetMappedFolderFromPath(currfolder.GetPath().slice(0, targetnode._fepos + 1));\n\t\t\telse if (targettype === 'item')\n\t\t\t{\n\t\t\t\tvar entries = currfolder.GetEntries();\n\t\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\t\t\t\tvar entry = entries[entryidmap[targetnode.dataset.feid]];\n\t\t\t\tvar path = currfolder.GetPath().slice();\n\n\t\t\t\t// Append the selected path segment.\n\t\t\t\tvar pathitem = [entry.id, entry.name];\n\t\t\t\tif ('attrs' in entry)  pathitem.push(entry.attrs);\n\n\t\t\t\tpath.push(pathitem);\n\n\t\t\t\t// Create/Update the target folder.\n\t\t\t\tvar pathkey = GetMappedPathKey(path);\n\n\t\t\t\tif (!foldermap[pathkey])  foldermap[pathkey] = new Folder(path);\n\n\t\t\t\ttargetfolder = foldermap[pathkey];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (dt.items && dt.items.length)\n\t\t\t{\n\t\t\t\t// Browser has 'items' support.\n\t\t\t\tvar entry;\n\n\t\t\t\tfor (var x = 0; x < dt.items.length; x++)\n\t\t\t\t{\n\t\t\t\t\tif (typeof dt.items[x].getAsEntry === 'function' && (entry = dt.items[x].getAsEntry()))  QueueUploadEntry(targetfolder, entry);\n\t\t\t\t\telse if (typeof dt.items[x].webkitGetAsEntry === 'function' && (entry = dt.items[x].webkitGetAsEntry()))  QueueUploadEntry(targetfolder, entry);\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// The item may be File-compatible.\n\t\t\t\t\t\tvar file = dt.items[x].getAsFile();\n\n\t\t\t\t\t\tif (file)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvar fileinfo = {\n\t\t\t\t\t\t\t\tstatus: 'init',\n\t\t\t\t\t\t\t\tfolder: targetfolder,\n\t\t\t\t\t\t\t\ttype: '',\n\t\t\t\t\t\t\t\tfile: file\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\ttargetfolder.refs++;\n\n\t\t\t\t\t\t\tfileinfo.fullPath = '/' + fileinfo.file.name;\n\n\t\t\t\t\t\t\tuploadqueue.push(fileinfo);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (dt.files && dt.files.length)\n\t\t\t{\n\t\t\t\t// Browser has 'files' support.\n\t\t\t\tfor (var x = 0; x < dt.files.length; x++)\n\t\t\t\t{\n\t\t\t\t\tvar file = dt.files[x];\n\n\t\t\t\t\tvar fileinfo = {\n\t\t\t\t\t\tstatus: 'init',\n\t\t\t\t\t\tfolder: targetfolder,\n\t\t\t\t\t\ttype: '',\n\t\t\t\t\t\tfile: file\n\t\t\t\t\t};\n\n\t\t\t\t\ttargetfolder.refs++;\n\n\t\t\t\t\tfileinfo.fullPath = '/' + fileinfo.file.name;\n\n\t\t\t\t\tuploadqueue.push(fileinfo);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tStartNextUpload();\n\t\t};\n\n\t\tvar MoveCopyDropHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (movecopydata !== false)\n\t\t\t{\n\t\t\t\te.preventDefault();\n\n\t\t\t\tif (movecopydata.lasttype !== 'error')\n\t\t\t\t{\n\t\t\t\t\tif (movecopydata.lastnode)  movecopydata.lastnode.classList.remove('fe_fileexplorer_drag_hover');\n\n\t\t\t\t\t// Grab the drop data.\n\t\t\t\t\tvar dropdata;\n\t\t\t\t\ttry\n\t\t\t\t\t{\n\t\t\t\t\t\tdropdata = JSON.parse(e.dataTransfer.getData('application/file-explorer-folder'));\n\t\t\t\t\t}\n\t\t\t\t\tcatch(e)\n\t\t\t\t\t{\n\t\t\t\t\t}\n\n\t\t\t\t\t// Update the drop effect.\n\t\t\t\t\tMoveCopyDragOverHandler(e);\n\n\t\t\t\t\tif (dropdata && movecopydata.dropallowed)\n\t\t\t\t\t{\n\t\t\t\t\t\tMoveCopyDragUpdateStatusText(e, true);\n\n\t\t\t\t\t\t// The current folder is already marked busy when MoveCopyDragEnterHandler() was called.\n\t\t\t\t\t\tPerformFinalMoveCopy(movecopydata.issource, movecopydata.lasttype, movecopydata.lastnode, e.dataTransfer.dropEffect, dropdata);\n\t\t\t\t\t}\n\t\t\t\t\telse if ((e.dataTransfer.files && e.dataTransfer.files.length) && movecopydata.dropallowed)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Restore the status bar.\n\t\t\t\t\t\tUpdateSelectionsChanged();\n\n\t\t\t\t\t\t$this.ProcessFilesAndUpload(movecopydata.lasttype, movecopydata.lastnode, e.dataTransfer);\n\n\t\t\t\t\t\tcurrfolder.SetBusyRef(-1);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// Restore the status bar.\n\t\t\t\t\t\tUpdateSelectionsChanged();\n\n\t\t\t\t\t\tcurrfolder.SetBusyRef(-1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Restore the status bar.\n\t\t\t\t\tUpdateSelectionsChanged();\n\n\t\t\t\t\tcurrfolder.SetBusyRef(-1);\n\t\t\t\t}\n\n\t\t\t\tmovecopydata = false;\n\t\t\t}\n\n\t\t\tmovecopyenters = 0;\n\t\t};\n\n\t\telems.innerwrap.addEventListener('dragenter', MoveCopyDragEnterHandler);\n\t\telems.innerwrap.addEventListener('dragover', MoveCopyDragOverHandler);\n\t\telems.innerwrap.addEventListener('dragleave', MoveCopyDragLeaveHandler);\n\t\telems.innerwrap.addEventListener('drop', MoveCopyDropHandler);\n\n\t\t// Handle moving/copying items and autoscroll.\n// Probably obsolete code but possibly useful for mobile drag-and-drop IF that even makes sense to implement.\n/*\n\t\t// Return the target entry (if any) for the supplied rectangle.\n\t\tvar GetMoveCopyItemTarget = function(rect) {\n\t\t\tvar entries = currfolder.GetEntries();\n\n\t\t\treturn (DoesRectOverlapItemRect(rect, rect.startcol, rect.startrow) ? entries[rect.startrow * folderitemcache.cols.length + rect.startcol] : false);\n\t\t};\n\n\t\tvar movingitems = false, copyitems = false;\n\t\tvar UpdateMoveCopyItemsDisplay = function(newpos, forcemessage, final) {\n\t\t\tif (forcemessage)\n\t\t\t{\n\t\t\t\tif (copyitems)  elems.itemswrap.classList.add('fe_fileexplorer_items_copy');\n\t\t\t\telse  elems.itemswrap.classList.remove('fe_fileexplorer_items_copy');\n\t\t\t}\n\n\t\t\tvar str = (copyitems ? (final ? 'Copying' : 'Copy') : (final ? 'Moving' : 'Move'));\n\n\t\t\tstr += (numselecteditems === 1 ? ' 1 item' : ' {0} items');\n\n\t\t\tvar currselectrect = {\n\t\t\t\tleft: newpos.x,\n\t\t\t\ttop: newpos.y,\n\t\t\t\tright: newpos.x,\n\t\t\t\tbottom: newpos.y\n\t\t\t};\n\n\t\t\t// Calculate rough position info.\n\t\t\tUpdateCalculatedSelectedItemsRect(currselectrect, prevselectrect);\n\n\t\t\t// If the point is inside an item, apply a different message if the message should change.\n\t\t\tvar preventry = (forcemessage ? false : GetMoveCopyItemTarget(prevselectrect));\n\t\t\tvar currentry = GetMoveCopyItemTarget(currselectrect);\n\n\t\t\tif (forcemessage || preventry !== currentry)\n\t\t\t{\n\t\t\t\tif (currentry && currentry.type === 'folder' && (!(currentry.id in selecteditemsmap)))  $this.SetNamedStatusBarText('selected', EscapeHTML(FormatStr($this.Translate(str + ' to \"{1}\"...'), numselecteditems, currentry.name)));\n\t\t\t\telse  $this.SetNamedStatusBarText('selected', EscapeHTML(FormatStr($this.Translate(str + '...'), numselecteditems)));\n\t\t\t}\n\n\t\t\tObject.assign(prevselectrect, currselectrect);\n\n\t\t\tif (final)  return { folder: folder, entry: currentry };\n\t\t};\n\n\t\tvar movenewpos = {}, movecopyoverlay, movecopyoverlaysize = {};\n\t\tvar MoveCopyHandler = function(e) {\n\t\t\te.preventDefault();\n\n\t\t\tlastmouseevent = e;\n\n\t\t\tvar rect = elems.itemsscrollwrapinner.getBoundingClientRect();\n\n\t\t\tmovenewpos = {\n\t\t\t\tx: e.clientX - rect.left,\n\t\t\t\ty: e.clientY - rect.top\n\t\t\t};\n\n\t\t\tif (movenewpos.x < 0)  movenewpos.x = 0;\n\t\t\tif (movenewpos.x > rect.width)  movenewpos.x = rect.width;\n\t\t\tif (movenewpos.y < 0)  movenewpos.y = 0;\n\t\t\tif (movenewpos.y > rect.height)  movenewpos.y = rect.height;\n\n\t\t\tif (!movingitems && (Math.abs(movenewpos.x - selectanchorpos.x) > 8 || Math.abs(movenewpos.y - selectanchorpos.y) > 8))\n\t\t\t{\n\t\t\t\t// Initialize the move/copy operation.\n\t\t\t\tmovingitems = true;\n\t\t\t\tcopyitems = ('_fe_ctrl' in e ? e._fe_ctrl : e.ctrlKey);\n\n\t\t\t\telems.itemswrap.classList.add('fe_fileexplorer_items_move_copy');\n\n\t\t\t\tUpdateMoveCopyItemsDisplay(movenewpos, true);\n\n\t\t\t\t// Stop the no move/copy handler since a move/copy operation has started.\n\t\t\t\tif (scrollnomoveinfo)\n\t\t\t\t{\n\t\t\t\t\tif (scrollnomoveinfo.origevent.ctrlKey || scrollnomoveinfo.origevent.target.tagName === 'INPUT' || scrollnomoveinfo.origevent.button == 2 || selectmodemulti)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this.SetSelectedItems([scrollnomoveinfo.origelem.dataset.feid], true);\n\t\t\t\t\t}\n\n\t\t\t\t\tscrollnomoveinfo = null;\n\t\t\t\t}\n\n\t\t\t\twindow.removeEventListener('mouseup', ScrollNoMoveHandler, true);\n\n\t\t\t\t// Disable clipboard overlay.\n\t\t\t\telems.itemsclipboardoverlaypastewrap.classList.remove('fe_fileexplorer_items_clipboard_contextmenu');\n\t\t\t\telems.itemsclipboardoverlaypastewrap.classList.add('fe_fileexplorer_hidden');\n\n\t\t\t\t// Create the floating icon tracking overlay.\n\t\t\t\tmovecopyoverlay = CreateNode('div', ['fe_fileexplorer_floating_drag_icon_wrap']);\n\t\t\t\tvar innernode = CreateNode('div', ['fe_fileexplorer_floating_drag_icon_wrap_inner']);\n\t\t\t\tvar iconnode = CreateNode('div', ['fe_fileexplorer_item_icon']);\n\n\t\t\t\tif (numselecteditems > 1)  innernode.dataset.numitems = numselecteditems;\n\n\t\t\t\tif (focuseditem === false)  iconnode.classList.add('fe_fileexplorer_item_icon_file');\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tvar entries = currfolder.GetEntries();\n\t\t\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\t\t\t\t\tvar entry = entries[entryidmap[focuseditem.dataset.feid]];\n\n\t\t\t\t\tif (entry.type === 'folder')  iconnode.classList.add('fe_fileexplorer_item_icon_folder');\n\t\t\t\t\telse  iconnode.classList.add('fe_fileexplorer_item_icon_file');\n\t\t\t\t}\n\n\t\t\t\tinnernode.appendChild(iconnode);\n\t\t\t\tmovecopyoverlay.appendChild(innernode);\n\t\t\t\tdocument.body.appendChild(movecopyoverlay);\n\n\t\t\t\tmovecopyoverlaysize = {\n\t\t\t\t\txdiff: Math.floor(movecopyoverlay.offsetWidth / 2),\n\t\t\t\t\tydiff: Math.floor(movecopyoverlay.offsetHeight - 8)\n\t\t\t\t};\n\n\t\t\t\t// Deny folder changes.\n\t\t\t\tcurrfolder.SetBusyRef(1);\n\t\t\t}\n\n\t\t\tif (movingitems)\n\t\t\t{\n\t\t\t\t// Update the status bar.\n\t\t\t\tvar prevcopyitems = copyitems;\n\n\t\t\t\tcopyitems = ('_fe_ctrl' in e ? e._fe_ctrl : e.ctrlKey);\n\n\t\t\t\tUpdateMoveCopyItemsDisplay(movenewpos, (prevcopyitems !== copyitems));\n\n\t\t\t\t// Update the overlay position.\n\t\t\t\tmovecopyoverlay.style.left = (e.clientX - movecopyoverlaysize.xdiff) + 'px';\n\t\t\t\tmovecopyoverlay.style.top = (e.clientY - movecopyoverlaysize.ydiff) + 'px';\n\n\n// Implement similar auto-scroll behavior to selection boxes.\n\t\t\t}\n\t\t};\n\n\t\t// Handle scrolling using the wheel while moving/copying items.\n\t\tvar MoveCopyScrollWheelHandler = function(e) {\n\t\t\tvar lastscrolltop = -1;\n\t\t\tvar numsame = 0;\n\n\t\t\tvar TempWheelScrollHandler = function(e) {\n\t\t\t\tMoveCopyHandler(lastmouseevent);\n\n\t\t\t\tif (autoscrolltimer)  clearInterval(autoscrolltimer);\n\n\t\t\t\tautoscrolltimer = setInterval(TempWheelScrollHandler, 10);\n\n\t\t\t\tif (lastscrolltop !== elems.itemsscrollwrap.scrollTop)  numsame = 0;\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tnumsame++;\n\n\t\t\t\t\tif (numsame >= 5)\n\t\t\t\t\t{\n\t\t\t\t\t\tclearInterval(autoscrolltimer);\n\n\t\t\t\t\t\tautoscrolltimer = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlastscrolltop = elems.itemsscrollwrap.scrollTop;\n\t\t\t};\n\n\t\t\tTempWheelScrollHandler();\n\t\t};\n\n\t\t// Alter the move/copy state on keydown/keyup.\n\t\tvar MoveCopyCtrlKeyHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (movingitems)\n\t\t\t{\n\t\t\t\te.preventDefault();\n\n\t\t\t\tvar prevcopyitems = copyitems;\n\n\t\t\t\tlastmouseevent._fe_ctrl = e.ctrlKey;\n\t\t\t\tcopyitems = e.ctrlKey;\n\n\t\t\t\tUpdateMoveCopyItemsDisplay(movenewpos, (prevcopyitems !== copyitems));\n\t\t\t}\n\t\t};\n\n\t\tvar MoveCopyEndHandler = function(e) {\n\t\t\tif (e)\n\t\t\t{\n\t\t\t\tif (!e.isTrusted)  return;\n\n\t\t\t\te.preventDefault();\n\t\t\t}\nconsole.log('MoveCopyEndHandler');\n\n\t\t\tclearInterval(autoscrolltimer);\n\t\t\tautoscrolltimer = null;\n\n\t\t\twindow.removeEventListener('mousemove', MoveCopyHandler, true);\n\t\t\twindow.removeEventListener('mouseup', MoveCopyEndHandler, true);\n\t\t\twindow.removeEventListener('blur', MoveCopyEndHandler, true);\n\t\t\telems.itemsscrollwrap.removeEventListener('wheel', MoveCopyScrollWheelHandler);\n\t\t\twindow.removeEventListener('keydown', MoveCopyCtrlKeyHandler, true);\n\t\t\twindow.removeEventListener('keyup', MoveCopyCtrlKeyHandler, true);\n\n\t\t\tif (movecopyoverlay)\n\t\t\t{\n\t\t\t\tmovecopyoverlay.parentNode.removeChild(movecopyoverlay);\n\t\t\t\tmovecopyoverlay = null;\n\t\t\t}\n\n\t\t\tif (movingitems)\n\t\t\t{\n\t\t\t\t// Update the status bar with the final message and get the drop location.\n\t\t\t\tvar droptarget = UpdateMoveCopyItemsDisplay(movenewpos, true, true);\n\n\t\t\t\telems.itemswrap.classList.remove('fe_fileexplorer_items_move_copy');\n\t\t\t\telems.itemswrap.classList.remove('fe_fileexplorer_items_copy');\n\n//\t\t\t\t// Restore the status bar to its previous state.\n//\t\t\t\tUpdateSelectionsChanged();\n\n\t\t\t\tcurrfolder.SetBusyRef(-1);\n\t\t\t}\n\t\t};\n*/\n\n\t\tvar StartSelectionHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\t// Ignore when the target does not trace to the items wrapper.\n\t\t\tvar node = e.target;\n\n\t\t\twhile (node && node !== elems.itemsscrollwrap)  node = node.parentNode;\n\n\t\t\tif (!node)  return;\n\n\t\t\t// Don't start a selection operation if the folder is updating or busy.\n\t\t\tif (!currfolder || currfolder.waiting)  return;\n\n\t\t\tif (e.type === 'touchstart')\n\t\t\t{\n\t\t\t\tvar rect = elems.itemsscrollwrapinner.getBoundingClientRect();\n\n\t\t\t\tlastselecttouch = {\n\t\t\t\t\tx: e.touches[0].clientX - rect.left,\n\t\t\t\t\ty: e.touches[0].clientY - rect.top,\n\n\t\t\t\t\tprocessed: false\n\t\t\t\t};\n\n\t\t\t\tselectanchorpos = lastselecttouch;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tUpdateCurrFolderItemCache(false);\n\n\t\t\t\t// If the user has selected an item, focus it.\n\t\t\t\tif (e.target.classList.contains('fe_fileexplorer_item_wrap_inner') || e.target.closest('.fe_fileexplorer_item_wrap_inner'))\n\t\t\t\t{\n\t\t\t\t\tvar elem = e.target.closest('.fe_fileexplorer_item_wrap');\n\t\t\t\t\tvar orignumselected = numselecteditems;\n\t\t\t\t\tvar origselecteditem = (elem.dataset.feid in selecteditemsmap);\n\n\t\t\t\t\tif (e.ctrlKey || e.target.tagName === 'INPUT' || e.button == 2 || selectmodemulti)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Ctrl or checkbox.\n\t\t\t\t\t\tstartrename = false;\n\n\t\t\t\t\t\t$this.SetFocusItem(elem.dataset.feid, true);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tstartrename = (!currfolder.IsBusy() && !e.shiftKey && $this.hasEventListener('rename') && numselecteditems === 1 && (elem.dataset.feid in selecteditemsmap) && e.target.classList.contains('fe_fileexplorer_item_text'));\n\n\t\t\t\t\t\tif (startrename)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstartrenamefolder = currfolder;\n\t\t\t\t\t\t\tstartrenameid = elem.dataset.feid;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$this.SetFocusItem(elem.dataset.feid, !e.shiftKey);\n\n\t\t\t\t\t\t// Select items starting at the last anchor position.\n\t\t\t\t\t\tif (e.shiftKey || !(elem.dataset.feid in selecteditemsmap))  $this.SelectItemsFromLastAnchor(true);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Scroll the view to show the entire row containing the selected item.\n\t\t\t\t\tscrollnomoveinfo = { origelem: elem, origevent: e };\n\t\t\t\t\twindow.addEventListener('mouseup', ScrollNoMoveHandler, true);\n\n\t\t\t\t\t// Enable right-click context menu.\n\t\t\t\t\tif (e.button == 2)\n\t\t\t\t\t{\n\t\t\t\t\t\telems.itemsclipboardoverlay.value = '   ';\n\t\t\t\t\t\telems.itemsclipboardoverlaypastewrap.classList.remove('fe_fileexplorer_hidden');\n\t\t\t\t\t\telems.itemsclipboardoverlaypastewrap.classList.add('fe_fileexplorer_items_clipboard_contextmenu');\n\t\t\t\t\t}\n\n\t\t\t\t\tif (orignumselected && (e.detail > 1 || (lastselecttouch && origselecteditem && lastmousedownevent && e.timeStamp - lastmousedownevent.timeStamp < 500)))\n\t\t\t\t\t{\n\t\t\t\t\t\t// Open selected items on double-click.\n\t\t\t\t\t\t$this.OpenSelectedItems();\n\t\t\t\t\t}\n/*\n\t\t\t\t\telse if ($this.hasEventListener('move') || $this.hasEventListener('copy'))\n\t\t\t\t\t{\n\t\t\t\t\t\t// Start a move/copy operation.\n\t\t\t\t\t\tmovingitems = false;\n\n\t\t\t\t\t\tlastmouseevent = e;\n\n\t\t\t\t\t\tvar rect = elems.itemsscrollwrapinner.getBoundingClientRect();\n\n\t\t\t\t\t\tselectanchorpos = {\n\t\t\t\t\t\t\tx: e.clientX - rect.left,\n\t\t\t\t\t\t\ty: e.clientY - rect.top\n\t\t\t\t\t\t};\nconsole.log(selectanchorpos);\n\n\t\t\t\t\t\tcopyitems = e.ctrlKey;\n\n\t\t\t\t\t\tprevselectrect = {\n\t\t\t\t\t\t\tleft: selectanchorpos.x,\n\t\t\t\t\t\t\ttop: selectanchorpos.y,\n\t\t\t\t\t\t\tright: selectanchorpos.x,\n\t\t\t\t\t\t\tbottom: selectanchorpos.y\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tUpdateCalculatedSelectedItemsRect(prevselectrect);\n\n\t\t\t\t\t\twindow.addEventListener('mousemove', MoveCopyHandler, true);\n\t\t\t\t\t\twindow.addEventListener('mouseup', MoveCopyEndHandler, true);\n\t\t\t\t\t\twindow.addEventListener('blur', MoveCopyEndHandler, true);\n\t\t\t\t\t\telems.itemsscrollwrap.addEventListener('wheel', MoveCopyScrollWheelHandler);\n\t\t\t\t\t\twindow.addEventListener('keydown', MoveCopyCtrlKeyHandler, true);\n\t\t\t\t\t\twindow.addEventListener('keyup', MoveCopyCtrlKeyHandler, true);\n\t\t\t\t\t}\n*/\n\t\t\t\t}\n\t\t\t\telse if (lastselecttouch && !lastselecttouch.processed)\n\t\t\t\t{\n\t\t\t\t\tif (e.detail == 2 || (e.detail < 2 && (!selectmodemulti || numselecteditems === 1)))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this.ClearSelectedItems(true);\n\t\t\t\t\t}\n\t\t\t\t\telse if (e.detail == 3)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this.SelectAllItems();\n\n\t\t\t\t\t\tselectmodemulti = (numselecteditems > 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlastmouseevent = e;\n\n\t\t\t\t\telems.itemsscrollwrap.focus();\n\t\t\t\t\telems.itemswrap.classList.add('fe_fileexplorer_items_selecting');\n\n\t\t\t\t\t// Enable right-click context menu.\n\t\t\t\t\tif (e.button == 2)\n\t\t\t\t\t{\n\t\t\t\t\t\telems.itemsclipboardoverlay.value = '   ';\n\t\t\t\t\t\telems.itemsclipboardoverlaypastewrap.classList.remove('fe_fileexplorer_hidden');\n\t\t\t\t\t\telems.itemsclipboardoverlaypastewrap.classList.add('fe_fileexplorer_items_clipboard_contextmenu');\n\t\t\t\t\t}\n\n\t\t\t\t\tvar rect = elems.itemsscrollwrapinner.getBoundingClientRect();\n\n\t\t\t\t\tselectanchorpos = {\n\t\t\t\t\t\tx: e.clientX - rect.left,\n\t\t\t\t\t\ty: e.clientY - rect.top\n\t\t\t\t\t};\n\n\t\t\t\t\tif (!e.ctrlKey && !e.shiftKey)  $this.ClearSelectedItems(true);\n\n\t\t\t\t\tselectchangeinvert = e.ctrlKey;\n\n\t\t\t\t\tcurrfolder.SetBusyRef(1);\n\n\t\t\t\t\tprevselectrect = {\n\t\t\t\t\t\tleft: selectanchorpos.x,\n\t\t\t\t\t\ttop: selectanchorpos.y,\n\t\t\t\t\t\tright: selectanchorpos.x,\n\t\t\t\t\t\tbottom: selectanchorpos.y\n\t\t\t\t\t};\n\n\t\t\t\t\tUpdateCalculatedSelectedItemsRect(prevselectrect);\n\n\t\t\t\t\twindow.addEventListener('mousemove', SelectBoxDragHandler, true);\n\t\t\t\t\twindow.addEventListener('mouseup', SelectBoxEndHandler, true);\n\t\t\t\t\twindow.addEventListener('blur', SelectBoxEndHandler, true);\n\t\t\t\t\telems.itemsscrollwrap.addEventListener('wheel', SelectBoxScrollWheelHandler);\n\t\t\t\t}\n\n\t\t\t\tlastmousedownevent = e;\n\n\t\t\t\tif (lastselecttouch)\n\t\t\t\t{\n\t\t\t\t\tif (!lastselecttouch.processed)  lastselecttouch.processed = true;\n\t\t\t\t\telse  lastselecttouch = null;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\telems.itemsscrollwrapinner.addEventListener('mousedown', StartSelectionHandler);\n\t\telems.itemsscrollwrapinner.addEventListener('touchstart', StartSelectionHandler);\n\n\t\tvar CheckboxSelectedFixHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (e.target.tagName === 'INPUT')\n\t\t\t{\n\t\t\t\t// Make the checkmark match the selected status.  The browser tends to invert it when the checkbox is clicked.\n\t\t\t\te.target.checked = e.target.parentNode.parentNode.classList.contains('fe_fileexplorer_item_selected');\n\t\t\t}\n\t\t};\n\n\t\telems.itemsscrollwrapinner.addEventListener('click', CheckboxSelectedFixHandler);\n\n\t\t// Recent locations popup menu handler.\n\t\tvar RecentLocationsHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\t// Stop the button from stealing focus.\n\t\t\te.preventDefault();\n\n\t\t\t// Cancel any existing popup menu.\n\t\t\tif (popupmenu)  popupmenu.Cancel();\n\n\t\t\t// Force focus for mousedown to the main area.\n\t\t\tif (e.type === 'mousedown')\n\t\t\t{\n\t\t\t\tvar blockpopup = elems.navtool_history.classList.contains('fe_fileexplorer_block_popup');\n\n\t\t\t\tif (blockpopup)  elems.navtool_history.classList.remove('fe_fileexplorer_block_popup');\n\n\t\t\t\tif (!$this.HasFocus())  $this.Focus(true, true);\n\t\t\t\telse if (document.activeElement === elems.navtool_history)\n\t\t\t\t{\n\t\t\t\t\t// Keep the popup closed if it was open.\n\t\t\t\t\t$this.Focus(true, true);\n\n\t\t\t\t\tif (blockpopup)  return;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Setup popup menu options.\n\t\t\tvar options = {\n\t\t\t\titems: [],\n\n\t\t\t\tonposition: function(popupelem) {\n\t\t\t\t\tpopupelem.style.left = '1px';\n\t\t\t\t\tpopupelem.style.top = (elems.toolbar.offsetTop + elems.toolbar.offsetHeight + 1) + 'px';\n\t\t\t\t},\n\n\t\t\t\tonselected: function(id, item, lastelem, etype) {\n\t\t\t\t\tpopupmenu = null;\n\t\t\t\t\t$this.Focus(true);\n\t\t\t\t\tthis.Destroy();\n\n\t\t\t\t\tcurrhistory = id;\n\n\t\t\t\t\tvar newpath = foldermap[historystack[currhistory].folderkeys[historystack[currhistory].folderkeys.length - 1]].GetPath();\n\n\t\t\t\t\t$this.SetPath(newpath);\n\t\t\t\t},\n\n\t\t\t\toncancel: function(lastelem, etype) {\n\t\t\t\t\tpopupmenu = null;\n\n\t\t\t\t\tif (lastelem)  lastelem.focus();\n\n\t\t\t\t\tif (etype === 'mouse' && lastelem === elems.navtool_history)  elems.navtool_history.classList.add('fe_fileexplorer_block_popup');\n\n\t\t\t\t\tthis.Destroy();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Set up menu items.\n\t\t\tvar minnum = currhistory - 4;\n\t\t\tvar maxnum = currhistory + 4;\n\n\t\t\tif (minnum < 0)\n\t\t\t{\n\t\t\t\tmaxnum += -minnum;\n\t\t\t\tminnum = 0;\n\t\t\t}\n\n\t\t\tif (maxnum > historystack.length - 1)\n\t\t\t{\n\t\t\t\tminnum -= maxnum - (historystack.length - 1);\n\t\t\t\tif (minnum < 0)  minnum = 0;\n\t\t\t\tmaxnum = historystack.length - 1;\n\t\t\t}\n\n\t\t\tfor (var x = minnum; x <= maxnum; x++)\n\t\t\t{\n\t\t\t\tvar temppath = foldermap[historystack[x].folderkeys[historystack[x].folderkeys.length - 1]].GetPath();\n\t\t\t\tvar item = { id: x, name: EscapeHTML(temppath[temppath.length - 1][1]) };\n\n\t\t\t\tif (x < currhistory)  item.icon = 'fe_fileexplorer_popup_item_icon_back';\n\t\t\t\telse if (x > currhistory)  item.icon = 'fe_fileexplorer_popup_item_icon_forward';\n\t\t\t\telse  item.icon = 'fe_fileexplorer_popup_item_icon_check';\n\n\t\t\t\toptions.items.unshift(item);\n\t\t\t}\n\n\t\t\tpopupmenu = new PopupMenu(elems.mainwrap, options);\n\t\t};\n\n\t\telems.navtool_history.addEventListener('mousedown', RecentLocationsHandler);\n\n\t\tvar RecentLocationsKeyHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (e.keyCode == 13 || e.keyCode == 32)  RecentLocationsHandler(e);\n\t\t};\n\n\t\telems.navtool_history.addEventListener('keydown', RecentLocationsKeyHandler);\n\n\t\t// Path segment handlers.\n\t\tvar GetCurrentPathSegmentPos = function() {\n\t\t\treturn elems.pathsegmentswrap._fepos;\n\t\t};\n\n\t\tvar StartPathSegmentFolderSelection = function(node) {\n\t\t\tvar posx = node.lastChild.offsetLeft - elems.pathsegmentsscrollwrap.scrollLeft + elems.pathsegmentsscrollwrap.offsetLeft - 18;\n\t\t\tvar basepath = currfolder.GetPath();\n\n\t\t\t// Adjust basepath.\n\t\t\tbasepath = basepath.slice(0, GetCurrentPathSegmentPos() + 1);\n\n\t\t\t// Apply styles.\n\t\t\tnode.classList.add('fe_fileexplorer_path_segment_wrap_focus');\n\t\t\tnode.classList.add('fe_fileexplorer_path_segment_wrap_down');\n\n\t\t\t// Cancel any existing popup menu.\n\t\t\tif (popupmenu)  popupmenu.Cancel();\n\n\t\t\t// Setup popup menu options.\n\t\t\tvar options = {\n\t\t\t\titems: [],\n\n\t\t\t\tresizewatchers: [\n\t\t\t\t\t{ elem: document.body, attr: 'offsetWidth', val: -1 }\n\t\t\t\t],\n\n\t\t\t\tonposition: function(popupelem) {\n\t\t\t\t\tvar posx2 = (posx + popupelem.offsetWidth < document.body.offsetWidth ? posx : document.body.offsetWidth - popupelem.offsetWidth - 1);\n\n\t\t\t\t\tpopupelem.style.left = posx2 + 'px';\n\t\t\t\t\tpopupelem.style.top = (elems.toolbar.offsetTop + elems.toolbar.offsetHeight) + 'px';\n\t\t\t\t},\n\n\t\t\t\tonselected: function(id, item, lastelem, etype) {\n\t\t\t\t\tpopupmenu = null;\n\t\t\t\t\t$this.Focus(true);\n\t\t\t\t\tthis.Destroy();\n\n\t\t\t\t\t// Append the selected path segment.\n\t\t\t\t\tvar pathitem = [item.info.id, item.name];\n\t\t\t\t\tif ('attrs' in item.info)  pathitem.push(item.info.attrs);\n\n\t\t\t\t\tbasepath.push(pathitem);\n\n\t\t\t\t\t$this.SetPath(basepath);\n\t\t\t\t},\n\n\t\t\t\toncancel: function(lastelem, etype) {\n\t\t\t\t\tpopupmenu = null;\n\n\t\t\t\t\tnode.classList.remove('fe_fileexplorer_path_segment_wrap_focus');\n\t\t\t\t\tnode.classList.remove('fe_fileexplorer_path_segment_wrap_down');\n\n\t\t\t\t\tif (lastelem)  lastelem.focus();\n\n\t\t\t\t\tif (etype === 'mouse' && lastelem.classList.contains('fe_fileexplorer_path_opts'))  node.classList.add('fe_fileexplorer_block_popup');\n\n\t\t\t\t\tthis.Destroy();\n\t\t\t\t},\n\n\t\t\t\tonleft: function(lastelem) {\n\t\t\t\t\tvar pos = GetCurrentPathSegmentPos();\n\n\t\t\t\t\tif (pos)\n\t\t\t\t\t{\n\t\t\t\t\t\tpopupmenu = null;\n\n\t\t\t\t\t\tnode.classList.remove('fe_fileexplorer_path_segment_wrap_focus');\n\t\t\t\t\t\tnode.classList.remove('fe_fileexplorer_path_segment_wrap_down');\n\n\t\t\t\t\t\t// Don't let oncancel be called because it steals focus to the wrong element.\n\t\t\t\t\t\tthis.PreventCancel();\n\n\t\t\t\t\t\telems.pathsegmentswrap.children[pos - 1].focus();\n\n\t\t\t\t\t\tthis.Destroy();\n\n\t\t\t\t\t\tStartPathSegmentFolderSelection(elems.pathsegmentswrap.children[pos - 1]);\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tonright: function(lastelem) {\n\t\t\t\t\tvar pos = GetCurrentPathSegmentPos();\n\n\t\t\t\t\tif (pos < elems.pathsegmentswrap.children.length - 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tpopupmenu = null;\n\n\t\t\t\t\t\tnode.classList.remove('fe_fileexplorer_path_segment_wrap_focus');\n\t\t\t\t\t\tnode.classList.remove('fe_fileexplorer_path_segment_wrap_down');\n\n\t\t\t\t\t\t// Don't let oncancel be called because it steals focus to the wrong element.\n\t\t\t\t\t\tthis.PreventCancel();\n\n\t\t\t\t\t\telems.pathsegmentswrap.children[pos + 1].focus();\n\n\t\t\t\t\t\tthis.Destroy();\n\n\t\t\t\t\t\tStartPathSegmentFolderSelection(elems.pathsegmentswrap.children[pos + 1]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// Set up menu items.\n\t\t\tvar entries = $this.GetMappedFolderFromPath(basepath);\n\n\t\t\tif (entries)\n\t\t\t{\n\t\t\t\tentries = entries.GetEntries();\n\n\t\t\t\tfor (var x = 0; x < entries.length; x++)\n\t\t\t\t{\n\t\t\t\t\tif (entries[x].type === 'folder')\n\t\t\t\t\t{\n\t\t\t\t\t\tvar item = { id: options.items.length, name: EscapeHTML(entries[x].name), icon: 'fe_fileexplorer_popup_item_icon_folder', info: entries[x] };\n\n\t\t\t\t\t\toptions.items.push(item);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tpopupmenu = new PopupMenu(elems.mainwrap, options);\n\t\t\t}\n\t\t};\n\n\t\tvar PathSegmentMouseFocusHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\t// Provide our own focus handling.\n\t\t\te.preventDefault();\n\n\t\t\t// Find the node with a valid tab index.\n\t\t\tvar tabnode = elems.pathsegmentswrap.children[elems.pathsegmentswrap._fepos];\n\n\t\t\tvar node = e.target;\n\t\t\twhile (node && node !== elems.pathsegmentsscrollwrap)\n\t\t\t{\n\t\t\t\tif (node.parentNode === elems.pathsegmentswrap)\n\t\t\t\t{\n\t\t\t\t\tnode.focus();\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tnode = node.parentNode;\n\t\t\t}\n\n\t\t\tif (node && node === elems.pathsegmentsscrollwrap && tabnode)  tabnode.focus();\n\n\t\t\t// Open the menu if the collapse button was not clicked.\n\t\t\tif (node && e.target.classList.contains('fe_fileexplorer_path_opts'))\n\t\t\t{\n\t\t\t\tvar blockpopup = node.classList.contains('fe_fileexplorer_block_popup');\n\n\t\t\t\tif (blockpopup)  node.classList.remove('fe_fileexplorer_block_popup');\n\t\t\t\telse  StartPathSegmentFolderSelection(node);\n\t\t\t}\n\t\t};\n\n\t\telems.pathsegmentsscrollwrap.addEventListener('mousedown', PathSegmentMouseFocusHandler);\n\n\t\tvar PathSegmentFocusScrollHandler = function(e) {\n\t\t\tvar node = e.target;\n\n\t\t\tif (node.parentNode === elems.pathsegmentswrap)\n\t\t\t{\n\t\t\t\tif (elems.pathsegmentswrap._fepos !== node._fepos)\n\t\t\t\t{\n\t\t\t\t\tnode.tabIndex = 0;\n\n\t\t\t\t\telems.pathsegmentswrap.children[elems.pathsegmentswrap._fepos].tabIndex = -1;\n\n\t\t\t\t\telems.pathsegmentswrap._fepos = node._fepos;\n\t\t\t\t}\n\n\t\t\t\tif (node.offsetLeft - 1 < elems.pathsegmentsscrollwrap.scrollLeft)  elems.pathsegmentsscrollwrap.scrollLeft = node.offsetLeft - 1;\n\t\t\t\telse if (node.offsetLeft + node.offsetWidth + 1 > elems.pathsegmentsscrollwrap.scrollLeft + elems.pathsegmentsscrollwrap.clientWidth)  elems.pathsegmentsscrollwrap.scrollLeft = (node.offsetLeft + node.offsetWidth + 1) - elems.pathsegmentsscrollwrap.clientWidth;\n\t\t\t}\n\t\t};\n\n\t\telems.pathsegmentsscrollwrap.addEventListener('focus', PathSegmentFocusScrollHandler, true);\n\n\t\tvar PathSegmentClickHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (e.target.classList.contains('fe_fileexplorer_path_name'))\n\t\t\t{\n\t\t\t\t// Go to the selected folder.\n\t\t\t\tvar currpath = currfolder.GetPath();\n\n\t\t\t\t$this.SetPath(currpath.slice(0, GetCurrentPathSegmentPos() + 1));\n\n\t\t\t\t$this.Focus(true);\n\t\t\t}\n\t\t};\n\n\t\telems.pathsegmentsscrollwrap.addEventListener('click', PathSegmentClickHandler);\n\n\t\tvar PathSegmentKeyHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (e.keyCode == 37)\n\t\t\t{\n\t\t\t\t// Left Arrow.  Move to previous path segment.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tvar pos = GetCurrentPathSegmentPos();\n\n\t\t\t\tif (pos)  elems.pathsegmentswrap.children[pos - 1].focus();\n\t\t\t}\n\t\t\telse if (e.keyCode == 39)\n\t\t\t{\n\t\t\t\t// Right Arrow.  Move to next path segment.\n\t\t\t\tvar pos = GetCurrentPathSegmentPos();\n\n\t\t\t\tif (pos < elems.pathsegmentswrap.children.length - 1)\n\t\t\t\t{\n\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\telems.pathsegmentswrap.children[pos + 1].focus();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (e.keyCode == 13)\n\t\t\t{\n\t\t\t\t// Enter.  Go to path.\n\t\t\t\te.preventDefault();\n\n\t\t\t\t// Go to the selected folder.\n\t\t\t\tvar currpath = currfolder.GetPath();\n\n\t\t\t\t$this.SetPath(currpath.slice(0, GetCurrentPathSegmentPos() + 1));\n\n\t\t\t\t$this.Focus(true);\n\t\t\t}\n\t\t\telse if (e.keyCode == 40)\n\t\t\t{\n\t\t\t\t// Down Arrow.  Show the subfolder selection menu.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tvar node = elems.pathsegmentswrap.children[GetCurrentPathSegmentPos()];\n\n\t\t\t\tnode.focus();\n\n\t\t\t\tStartPathSegmentFolderSelection(node);\n\t\t\t}\n\t\t};\n\n\t\telems.pathsegmentsscrollwrap.addEventListener('keydown', PathSegmentKeyHandler);\n\n\t\t// Clipboard cut/copy handler.\n\t\tvar ClipboardCutCopyHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\t// Do not handle cut/copy when the paste box is showing.\n\t\t\tif (elems.itemsclipboardoverlaypastewrap.classList.contains('fe_fileexplorer_items_show_clipboard_overlay_paste'))  return;\n\n\t\t\te.preventDefault();\n\n\t\t\tif (numselecteditems)\n\t\t\t{\n\t\t\t\tvar ids = [];\n\n\t\t\t\tfor (var x in selecteditemsmap)\n\t\t\t\t{\n\t\t\t\t\tif (selecteditemsmap.hasOwnProperty(x))  ids.push(x);\n\t\t\t\t}\n\n\t\t\t\tvar dropeffect = (e.type === 'copy' ? 'copy' : 'move');\n\n\t\t\t\te.clipboardData.dropEffect = dropeffect;\n\t\t\t\te.clipboardData.setData('application/file-explorer-clipboard', JSON.stringify({ type: dropeffect, source: main_id, group: main_group, path: currfolder.GetPath(), ids: ids }));\n\t\t\t\te.clipboardData.setData('text/plain', JSON.stringify({ 'application/file-explorer-clipboard' : { type: dropeffect, source: main_id, group: main_group, path: currfolder.GetPath(), ids: ids } }));\n\n\t\t\t\t// Chromium DownloadURL support.\n\t\t\t\tif (e.type === 'copy' && $this.hasEventListener('get_download_url'))\n\t\t\t\t{\n\t\t\t\t\t// Synchronous call only.\n\t\t\t\t\tvar entries = currfolder.GetEntries();\n\t\t\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\t\t\t\t\tvar entry = entries[entryidmap[ids[0]]];\n\t\t\t\t\tvar result = {};\n\n\t\t\t\t\tDispatchEvent('get_download_url', [result, currfolder, ids, entry]);\n\n\t\t\t\t\tif (result && result.name && result.url)  e.clipboardData.setData('DownloadURL', 'application/octet-stream:' + result.name + ':' + result.url);\n\t\t\t\t}\n\n\t\t\t\t$this.SetNamedStatusBarText('message', EscapeHTML($this.Translate((e.type === 'copy' ? 'Copy' : 'Cut') + ' to clipboard completed')), $this.settings.messagetimeout);\n\t\t\t}\n\n\t\t\tClipboardOverlayExitContextMenuHandler(e);\n\t\t};\n\n\t\t// Clipboard paste handler.\n\t\tvar ClipboardPasteHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\te.preventDefault();\n\n\t\t\t// Attempt to read the dropped clipboard data.\n\t\t\tvar dropdata;\n\t\t\ttry\n\t\t\t{\n\t\t\t\tdropdata = JSON.parse(e.clipboardData.getData('application/file-explorer-clipboard'));\n\t\t\t}\n\t\t\tcatch(err)\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\t// Attempt to extract a text/plain variant.\n\t\t\t\t\tvar data = JSON.parse(e.clipboardData.getData('text/plain'));\n\n\t\t\t\t\tif (data['application/file-explorer-clipboard'])  dropdata = data['application/file-explorer-clipboard'];\n\t\t\t\t}\n\t\t\t\tcatch(err)\n\t\t\t\t{\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (dropdata && dropdata.group === main_group && Array.isArray(dropdata.path) && Array.isArray(dropdata.ids) && dropdata.ids.length && ((dropdata.type === 'copy' && $this.hasEventListener('copy')) || (dropdata.type === 'move' && $this.hasEventListener('move'))))\n\t\t\t{\n\t\t\t\tvar lasttype = 'currfolder', lastnode = null;\n\n\t\t\t\t// If the clipboard context menu was used and the target focused item is a folder, then copy/move to the folder.\n\t\t\t\tif (clipboardcontextmenu && focuseditem !== false && focuseditem.classList.contains('fe_fileexplorer_item_folder'))\n\t\t\t\t{\n\t\t\t\t\tlasttype = 'item';\n\t\t\t\t\tlastnode = focuseditem;\n\t\t\t\t}\n\n\t\t\t\t// Update the status bar with a description of the operation.\n\t\t\t\tvar str = (dropdata.type === 'copy' ? 'Copying' : 'Moving');\n\n\t\t\t\tstr += (dropdata.ids.length === 1 ? ' 1 item' : ' {0} items');\n\n\t\t\t\tif (lasttype === 'currfolder')\n\t\t\t\t{\n\t\t\t\t\tvar path = currfolder.GetPath();\n\n\t\t\t\t\t$this.SetNamedStatusBarText('selected', EscapeHTML(FormatStr($this.Translate(str + ' to \"{1}\"...'), dropdata.ids.length, path[path.length - 1][1])));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tvar entries = currfolder.GetEntries();\n\t\t\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\t\t\t\t\tvar entry = entries[entryidmap[lastnode.dataset.feid]];\n\n\t\t\t\t\t$this.SetNamedStatusBarText('selected', EscapeHTML(FormatStr($this.Translate(str + ' to \"{1}\"...'), dropdata.ids.length, entry.name)));\n\t\t\t\t}\n\n\t\t\t\tcurrfolder.SetBusyRef(1);\n\n\t\t\t\tPerformFinalMoveCopy((dropdata.source === main_id), lasttype, lastnode, dropdata.type, dropdata);\n\t\t\t}\n\t\t\telse if (!dropdata && e.clipboardData.files && e.clipboardData.files.length)\n\t\t\t{\n\t\t\t\t// Pasted a browser-compatible file blob (e.g. an image).\n\t\t\t\t$this.ProcessFilesAndUpload('currfolder', null, e.clipboardData);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (dropdata && dropdata.group !== main_group)  $this.SetNamedStatusBarText('message', EscapeHTML($this.Translate('Paste operation failed due to mismatched group name')), $this.settings.messagetimeout);\n\t\t\t\telse  $this.SetNamedStatusBarText('message', EscapeHTML($this.Translate('Paste operation failed')), $this.settings.messagetimeout);\n\t\t\t}\n\n\t\t\tClipboardOverlayExitContextMenuHandler(e);\n\t\t};\n\n\t\telems.itemsclipboardoverlay.addEventListener('cut', ClipboardCutCopyHandler);\n\t\telems.itemsclipboardoverlay.addEventListener('copy', ClipboardCutCopyHandler);\n\t\telems.itemsclipboardoverlay.addEventListener('paste', ClipboardPasteHandler);\n\n\t\t// Item selection keyboard handler.\n\t\tvar lasttypingts = 0, lasttypingstr = '';\n\t\tvar ItemsKeyHandler = function(e) {\n\t\t\tif (!e.isTrusted || e.altKey)  return;\n\n\t\t\tvar updatefocus = false;\n\n\t\t\tif (e.keyCode == 37)\n\t\t\t{\n\t\t\t\t// Left Arrow.  Move item selection left.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tUpdateCurrFolderItemCache(false);\n\n\t\t\t\t// Change focus to the previous item.\n\t\t\t\tif (focuseditem !== false)\n\t\t\t\t{\n\t\t\t\t\tif (focuseditem.previousSibling)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this.SetFocusItem(focuseditem.previousSibling.dataset.feid, (!e.ctrlKey && !e.shiftKey));\n\n\t\t\t\t\t\tupdatefocus = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (folderitemcache.size)\n\t\t\t\t{\n\t\t\t\t\t$this.SetFocusItem(elems.itemswrap.firstChild.dataset.feid, (!e.ctrlKey && !e.shiftKey));\n\n\t\t\t\t\tupdatefocus = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (e.keyCode == 39)\n\t\t\t{\n\t\t\t\t// Right Arrow.  Move item selection right.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tUpdateCurrFolderItemCache(false);\n\n\t\t\t\t// Change focus to the next item.\n\t\t\t\tif (focuseditem !== false)\n\t\t\t\t{\n\t\t\t\t\tif (focuseditem.nextSibling)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this.SetFocusItem(focuseditem.nextSibling.dataset.feid, (!e.ctrlKey && !e.shiftKey));\n\n\t\t\t\t\t\tupdatefocus = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (folderitemcache.size)\n\t\t\t\t{\n\t\t\t\t\t$this.SetFocusItem(elems.itemswrap.firstChild.dataset.feid, (!e.ctrlKey && !e.shiftKey));\n\n\t\t\t\t\tupdatefocus = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (e.keyCode == 38)\n\t\t\t{\n\t\t\t\t// Up Arrow.  Move item selection up.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tUpdateCurrFolderItemCache(false);\n\n\t\t\t\t// Change focus to the next row.\n\t\t\t\tif (focuseditem !== false)\n\t\t\t\t{\n\t\t\t\t\tif (focuseditem.offsetTop !== folderitemcache.rows[0].top)\n\t\t\t\t\t{\n\t\t\t\t\t\tvar num = folderitemcache.cols.length;\n\t\t\t\t\t\tvar node = focuseditem;\n\n\t\t\t\t\t\twhile (node.previousSibling && num)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnode = node.previousSibling;\n\n\t\t\t\t\t\t\tnum--;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (node !== focuseditem)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this.SetFocusItem(node.dataset.feid, (!e.ctrlKey && !e.shiftKey));\n\n\t\t\t\t\t\t\tupdatefocus = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (folderitemcache.size)\n\t\t\t\t{\n\t\t\t\t\t$this.SetFocusItem(elems.itemswrap.firstChild.dataset.feid, (!e.ctrlKey && !e.shiftKey));\n\n\t\t\t\t\tupdatefocus = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (e.keyCode == 40)\n\t\t\t{\n\t\t\t\t// Down Arrow.  Move item selection down.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tUpdateCurrFolderItemCache(false);\n\n\t\t\t\t// Change focus to the next row.\n\t\t\t\tif (focuseditem !== false)\n\t\t\t\t{\n\t\t\t\t\tif (focuseditem.offsetTop !== folderitemcache.rows[folderitemcache.rows.length - 1].top)\n\t\t\t\t\t{\n\t\t\t\t\t\tvar num = folderitemcache.cols.length;\n\t\t\t\t\t\tvar node = focuseditem;\n\n\t\t\t\t\t\twhile (node.nextSibling && num)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnode = node.nextSibling;\n\n\t\t\t\t\t\t\tnum--;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (node !== focuseditem)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this.SetFocusItem(node.dataset.feid, (!e.ctrlKey && !e.shiftKey));\n\n\t\t\t\t\t\t\tupdatefocus = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (folderitemcache.size)\n\t\t\t\t{\n\t\t\t\t\t$this.SetFocusItem(elems.itemswrap.firstChild.dataset.feid, (!e.ctrlKey && !e.shiftKey));\n\n\t\t\t\t\tupdatefocus = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (e.keyCode == 36)\n\t\t\t{\n\t\t\t\t// Home.  Move to first item.\n\t\t\t\tUpdateCurrFolderItemCache(false);\n\n\t\t\t\t// Change focus to the first item.\n\t\t\t\tif (folderitemcache.size)\n\t\t\t\t{\n\t\t\t\t\t$this.SetFocusItem(elems.itemswrap.firstChild.dataset.feid, (!e.ctrlKey && !e.shiftKey));\n\n\t\t\t\t\tupdatefocus = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (e.keyCode == 35)\n\t\t\t{\n\t\t\t\t// End.  Move to last item.\n\t\t\t\tUpdateCurrFolderItemCache(false);\n\n\t\t\t\t// Change focus to the first item.\n\t\t\t\tif (folderitemcache.size)\n\t\t\t\t{\n\t\t\t\t\t$this.SetFocusItem(elems.itemswrap.lastChild.dataset.feid, (!e.ctrlKey && !e.shiftKey));\n\n\t\t\t\t\tupdatefocus = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (e.keyCode == 32)\n\t\t\t{\n\t\t\t\t// Space.  Select currently focused item OR find an item if typing.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tUpdateCurrFolderItemCache(false);\n\n\t\t\t\tvar ts = Date.now() - 1000;\n\n\t\t\t\tif (lasttypingts > ts)\n\t\t\t\t{\n\t\t\t\t\t// The preventDefault() stops the keypress event, so fake it.\n\t\t\t\t\te.key = ' ';\n\t\t\t\t\tItemsKeypressHandler(e);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (focuseditem === false && folderitemcache.size)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this.SetFocusItem(elems.itemswrap.firstChild.dataset.feid, (!e.ctrlKey && !e.shiftKey));\n\n\t\t\t\t\t\tupdatefocus = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (focuseditem !== false)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (e.ctrlKey)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this.SetFocusItem(focuseditem.dataset.feid, true);\n\n\t\t\t\t\t\t\t// Toggle item selection.  Skip toolbar and status bar update.\n\t\t\t\t\t\t\t$this.ToggleItemSelection(focuseditem, false, true);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tupdatefocus = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (e.keyCode == 13)\n\t\t\t{\n\t\t\t\t// Enter.\n\t\t\t\te.preventDefault();\n\n\t\t\t\t$this.OpenSelectedItems();\n\t\t\t}\n\t\t\telse if (e.keyCode == 46)\n\t\t\t{\n\t\t\t\t// Delete.\n\t\t\t\te.preventDefault();\n\n\t\t\t\t$this.DeleteSelectedItems(!e.shiftKey);\n\t\t\t}\n\t\t\telse if ((e.ctrlKey || e.metaKey) && (e.keyCode == 88 || e.keyCode == 67))\n\t\t\t{\n\t\t\t\t// Ctrl/Meta + X/C.  Cut/Copy selections onto the clipboard.\n\t\t\t\tif (numselecteditems)\n\t\t\t\t{\n\t\t\t\t\telems.itemsclipboardoverlay.value = '';\n\t\t\t\t\telems.itemsclipboardoverlaypastewrap.classList.remove('fe_fileexplorer_hidden');\n\t\t\t\t\telems.itemsclipboardoverlay.focus();\n\n\t\t\t\t\telems.itemsclipboardoverlay.addEventListener('keyup', ClipboardOverlayKeyHandler);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ((e.ctrlKey || e.metaKey) && e.keyCode == 86)\n\t\t\t{\n\t\t\t\t// Ctrl/Meta + V.  Paste content from the clipboard.\n\t\t\t\telems.itemsclipboardoverlay.value = '';\n\t\t\t\telems.itemsclipboardoverlaypastewrap.classList.remove('fe_fileexplorer_hidden');\n\t\t\t\telems.itemsclipboardoverlay.focus();\n\n\t\t\t\telems.itemsclipboardoverlay.addEventListener('keyup', ClipboardOverlayKeyHandler);\n\t\t\t}\n\t\t\telse if (e.keyCode == 93)\n\t\t\t{\n\t\t\t\t// Context Menu.  Alternative method to Cut/Copy/Paste selections onto/from the clipboard.\n\t\t\t\telems.itemsclipboardoverlay.value = '   ';\n\t\t\t\telems.itemsclipboardoverlaypastewrap.classList.remove('fe_fileexplorer_hidden');\n\t\t\t\telems.itemsclipboardoverlay.classList.add('fe_fileexplorer_items_clipboard_contextmenu');\n\n\t\t\t\tStartClipboardOverlayMenu();\n\t\t\t}\n\n\t\t\t// Update scroll position and selections if the focus changed.\n\t\t\tif (updatefocus)\n\t\t\t{\n\t\t\t\t$this.ScrollToFocusedItem();\n\n\t\t\t\t// Update selections.\n\t\t\t\tif (focuseditem !== false)\n\t\t\t\t{\n\t\t\t\t\t// Select items starting at the last anchor position.  Skip updating the toolbar and selections.\n\t\t\t\t\tif (!e.ctrlKey)  $this.SelectItemsFromLastAnchor(false, true);\n\n\t\t\t\t\t// Update toolbar icons.\n\t\t\t\t\tUpdateToolbarIcons();\n\n\t\t\t\t\t// Update the status bar and notify listeners.\n\t\t\t\t\tUpdateSelectionsChanged();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\telems.itemsscrollwrap.addEventListener('keydown', ItemsKeyHandler);\n\n\t\tvar lastkey = '';\n\t\tvar ItemsKeypressHandler = function(e) {\n\t\t\tif (!elems.itemswrap.children.length)  return;\n\n\t\t\tvar ts = Date.now();\n\n\t\t\tif (lasttypingts > ts - 1000)  lasttypingstr += e.key;\n\t\t\telse  lasttypingstr = e.key;\n\n\t\t\tlasttypingts = ts;\n\n\t\t\t// Attempt to find the next match.\n\t\t\tvar found = false;\n\t\t\tvar entries = currfolder.GetEntries();\n\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\t\t\tvar node = (focuseditem !== false && focuseditem.nextSibling ? focuseditem.nextSibling : elems.itemswrap.firstChild);\n\t\t\tvar pos = entryidmap[node.dataset.feid];\n\n\t\t\twhile (node)\n\t\t\t{\n\t\t\t\tif (lasttypingstr.localeCompare(entries[pos].name.substring(0, lasttypingstr.length), undefined, { sensitivity: 'base' }) === 0)\n\t\t\t\t{\n\t\t\t\t\tfound = true;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tnode = node.nextSibling;\n\t\t\t\tpos++;\n\t\t\t}\n\n\t\t\tif (!found && focuseditem !== false)\n\t\t\t{\n\t\t\t\tnode = elems.itemswrap.firstChild;\n\t\t\t\tpos = 0;\n\t\t\t\twhile (node && node !== focuseditem)\n\t\t\t\t{\n\t\t\t\t\tif (lasttypingstr.localeCompare(entries[pos].name.substring(0, lasttypingstr.length), undefined, { sensitivity: 'base' }) === 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tfound = true;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tnode = node.nextSibling;\n\t\t\t\t\tpos++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If the same starting key is pressed multiple times, attempt to start over.\n\t\t\tif (!found && lasttypingstr.length == 2 && lastkey === e.key)\n\t\t\t{\n\t\t\t\tlasttypingstr = '';\n\t\t\t\tItemsKeypressHandler(e);\n\t\t\t}\n\n\t\t\tif (found)\n\t\t\t{\n\t\t\t\t// Focus on the node.\n\t\t\t\t$this.SetFocusItem(node.dataset.feid, true);\n\n\t\t\t\t$this.ScrollToFocusedItem();\n\n\t\t\t\t// Select items starting at the last anchor position.\n\t\t\t\t$this.SelectItemsFromLastAnchor();\n\t\t\t}\n\n\t\t\tlastkey = e.key;\n\t\t};\n\n\t\telems.itemsscrollwrap.addEventListener('keypress', ItemsKeypressHandler);\n\n\t\t// Global keyboard handler.\n\t\tvar MainKeyHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (e.ctrlKey && e.keyCode == 65)\n\t\t\t{\n\t\t\t\t// Ctrl + A.  Select all items.\n\t\t\t\te.preventDefault();\n\n\t\t\t\t$this.Focus(true);\n\n\t\t\t\t$this.SelectAllItems();\n\t\t\t}\n\t\t\telse if ((e.altKey && e.keyCode == 37) || e.keyCode == 8)\n\t\t\t{\n\t\t\t\t// Backspace or Alt + Left Arrow.  Navigate back.\n\t\t\t\te.preventDefault();\n\n\t\t\t\t$this.HistoryBack();\n\t\t\t}\n\t\t\telse if (e.altKey && e.keyCode == 39)\n\t\t\t{\n\t\t\t\t// Alt + Right Arrow.  Navigate forward.\n\t\t\t\te.preventDefault();\n\n\t\t\t\t$this.HistoryForward();\n\t\t\t}\n\t\t\telse if (e.altKey && e.keyCode == 38)\n\t\t\t{\n\t\t\t\t// Alt + Up Arrow.  Set the path to the parent folder.\n\t\t\t\te.preventDefault();\n\n\t\t\t\t$this.NavigateUp();\n\t\t\t}\n\t\t\telse if (e.keyCode == 113)\n\t\t\t{\n\t\t\t\t// F2.  Start renaming a selected item.\n\t\t\t\tif ($this.hasEventListener('rename'))\n\t\t\t\t{\n\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t$this.RenameSelectedItem();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Re-dispatch this event to tools.\n\t\t\tDispatchEvent('keydown', e);\n\t\t};\n\n\t\telems.innerwrap.addEventListener('keydown', MainKeyHandler);\n\n\n\t\t// Public functions.\n\n\t\t// Checks to see if the active element is part of the main UI.\n\t\t$this.HasFocus = function(itemsonly) {\n\t\t\tvar node = document.activeElement;\n\n\t\t\tif (itemsonly)\n\t\t\t{\n\t\t\t\twhile (node && node !== elems.itemsscrollwrap)  node = node.parentNode;\n\n\t\t\t\treturn (node === elems.itemsscrollwrap);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\twhile (node && node !== elems.mainwrap)  node = node.parentNode;\n\n\t\t\t\treturn (node === elems.mainwrap);\n\t\t\t}\n\t\t};\n\n\t\t// Triggers focusing of the main UI.  Useful for popups.\n\t\t$this.Focus = function(itemsonly, alwaysfocus) {\n\t\t\tvar node = document.activeElement;\n\n\t\t\tif (alwaysfocus)\n\t\t\t{\n\t\t\t}\n\t\t\telse if (itemsonly)\n\t\t\t{\n\t\t\t\twhile (node && node !== elems.itemsscrollwrap)  node = node.parentNode;\n\n\t\t\t\tif (node !== elems.itemsscrollwrap)  alwaysfocus = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\twhile (node && node !== elems.mainwrap)  node = node.parentNode;\n\n\t\t\t\tif (node !== elems.mainwrap)  alwaysfocus = true;\n\t\t\t}\n\n\t\t\tif (alwaysfocus)\n\t\t\t{\n\t\t\t\tif (focuseditem !== false)  focuseditem.firstChild.focus();\n\t\t\t\telse  elems.itemsscrollwrap.focus();\n\t\t\t}\n\t\t};\n\n\t\t// Checks to see if the active element is an item.\n\t\t$this.HasItemFocus = function() {\n\t\t\tvar node = document.activeElement;\n\n\t\t\treturn (focuseditem !== false && node && node.parentNode === focuseditem);\n\t\t};\n\n\t\t// Returns the currently focused item node.\n\t\t$this.GetFocusedItem = function() {\n\t\t\treturn focuseditem;\n\t\t};\n\n\t\t// Returns the currently focused item ID.\n\t\t$this.GetFocusedItemID = function() {\n\t\t\treturn (focuseditem !== false ? focuseditem.dataset.feid : false);\n\t\t};\n\n\t\t// Returns whether or not the specified folder is in the refcounted folder map.\n\t\t// This can return false if the user navigated back during a complex operation (e.g. rename, Destroy() called).\n\t\t$this.IsMappedFolder = function(folder) {\n\t\t\tif (currfolder === folder)  return true;\n\n\t\t\tfor (var x in foldermap)\n\t\t\t{\n\t\t\t\tif (foldermap.hasOwnProperty(x) && folder === foldermap[x])  return true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t};\n\n\t\t// Returns the current folder.\n\t\t$this.GetCurrentFolder = function() {\n\t\t\treturn currfolder;\n\t\t};\n\n\t\t// Returns selected item IDs.\n\t\t$this.GetSelectedItemIDs = function() {\n\t\t\tvar result = [];\n\n\t\t\tfor (var x in selecteditemsmap)\n\t\t\t{\n\t\t\t\tif (selecteditemsmap.hasOwnProperty(x))  result.push(x);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t};\n\n\t\t$this.GetSelectedFolderEntries = function() {\n\t\t\tvar entries = currfolder.GetEntries();\n\t\t\tvar result = [];\n\n\t\t\tfor (var x = 0; x < entries.length; x++)\n\t\t\t{\n\t\t\t\tif (entries[x].id in selecteditemsmap)  result.push(entries[x]);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t};\n\n\t\t// Returns whether or not the specified item is selected.\n\t\t$this.IsSelectedItem = function(id) {\n\t\t\treturn (id in selecteditemsmap);\n\t\t};\n\n\t\t// Sets selected items.\n\t\t$this.SetSelectedItems = function(ids, keepprev, skipuiupdate) {\n\t\t\t// If the current folder is busy, then queue the change for later.\n\t\t\tif (currfolder && currfolder.IsBusy())\n\t\t\t{\n\t\t\t\tcurrfolder.AddBusyQueueCallback($this.SetSelectedItems, [ids]);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!currfolder || currfolder.waiting)  return;\n\n\t\t\tif (!Array.isArray(ids))  return;\n\n\t\t\tif (!keepprev)  $this.ClearSelectedItems(false, true);\n\n\t\t\tvar entryidmap = currfolder.GetEntryIDMap();\n\n\t\t\tfor (var x = 0; x < ids.length; x++)\n\t\t\t{\n\t\t\t\tif ((ids[x] in entryidmap) && !(ids[x] in selecteditemsmap))\n\t\t\t\t{\n\t\t\t\t\tvar entrynum = entryidmap[ids[x]];\n\t\t\t\t\tvar elem = elems.itemswrap.children[entrynum];\n\n\t\t\t\t\telem.classList.add('fe_fileexplorer_item_selected');\n\t\t\t\t\telem.firstChild.firstChild.checked = true;\n\n\t\t\t\t\tselecteditemsmap[elem.dataset.feid] = entrynum;\n\t\t\t\t\tnumselecteditems++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!skipuiupdate)\n\t\t\t{\n\t\t\t\t// Update toolbar icons.\n\t\t\t\tUpdateToolbarIcons();\n\n\t\t\t\t// Update the status bar and notify listeners.\n\t\t\t\tUpdateSelectionsChanged();\n\t\t\t}\n\t\t};\n\n\t\t// Get the number of selected items.\n\t\t$this.GetNumSelectedItems = function() {\n\t\t\treturn numselecteditems;\n\t\t};\n\n\t\t// Navigates to the parent folder.\n\t\t$this.NavigateUp = function(e) {\n\t\t\tif (e)  e.preventDefault();\n\n\t\t\tif (!currfolder)  return;\n\n\t\t\tvar currpath = currfolder.GetPath();\n\n\t\t\tif (currpath.length > 1)  $this.SetPath(currpath.slice(0, -1));\n\t\t};\n\n\t\tvar ClickNavigateUpHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\t$this.NavigateUp(e);\n\t\t\t$this.Focus(true);\n\t\t};\n\n\t\telems.navtool_up.addEventListener('mouseup', ClickNavigateUpHandler);\n\n\t\tvar NavigateUpKeyHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (e.keyCode == 13 || e.keyCode == 32)\n\t\t\t{\n\t\t\t\t$this.NavigateUp(e);\n\n\t\t\t\t// Steal focus back from the main area.  This needs to happen to allow focused item scrolling to take place.\n\t\t\t\tif (elems.navtool_up.tabIndex == 0)  elems.navtool_up.focus();\n\t\t\t\telse  elems.navtool_history.focus();\n\t\t\t}\n\t\t};\n\n\t\telems.navtool_up.addEventListener('keydown', NavigateUpKeyHandler);\n\n\t\t// Navigates back one history level.\n\t\t$this.HistoryBack = function(e) {\n\t\t\tif (e)  e.preventDefault();\n\n\t\t\tif (currhistory > 0)\n\t\t\t{\n\t\t\t\tcurrhistory--;\n\n\t\t\t\tvar newpath = foldermap[historystack[currhistory].folderkeys[historystack[currhistory].folderkeys.length - 1]].GetPath();\n\n\t\t\t\t$this.SetPath(newpath);\n\t\t\t}\n\t\t};\n\n\t\tvar ClickHistoryBackHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\t$this.HistoryBack(e);\n\t\t\t$this.Focus(true);\n\t\t};\n\n\t\telems.navtool_back.addEventListener('mouseup', ClickHistoryBackHandler);\n\n\t\tvar HistoryBackKeyHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (e.keyCode == 13 || e.keyCode == 32)\n\t\t\t{\n\t\t\t\t$this.HistoryBack(e);\n\n\t\t\t\t// Steal focus back from the main area.  This needs to happen to allow focused item scrolling to take place.\n\t\t\t\tif (currhistory > 0)  elems.navtool_back.focus();\n\t\t\t\telse if (currhistory < historystack.length - 1)  elems.navtool_forward.focus();\n\t\t\t\telse  elems.navtool_history.focus();\n\t\t\t}\n\t\t};\n\n\t\telems.navtool_back.addEventListener('keydown', HistoryBackKeyHandler);\n\n\t\t// Navigates forward one history level.\n\t\t$this.HistoryForward = function(e) {\n\t\t\tif (e)  e.preventDefault();\n\n\t\t\tif (currhistory > -1 && currhistory < historystack.length - 1)\n\t\t\t{\n\t\t\t\tcurrhistory++;\n\n\t\t\t\tvar newpath = foldermap[historystack[currhistory].folderkeys[historystack[currhistory].folderkeys.length - 1]].GetPath();\n\n\t\t\t\t$this.SetPath(newpath);\n\t\t\t}\n\t\t};\n\n\t\tvar ClickHistoryForwardHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\t$this.HistoryForward(e);\n\t\t\t$this.Focus(true);\n\t\t};\n\n\t\telems.navtool_forward.addEventListener('mouseup', ClickHistoryForwardHandler);\n\n\t\tvar HistoryForwardKeyHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (e.keyCode == 13 || e.keyCode == 32)\n\t\t\t{\n\t\t\t\t$this.HistoryForward(e);\n\n\t\t\t\t// Steal focus back from the main area.  This needs to happen to allow focused item scrolling to take place.\n\t\t\t\tif (currhistory < historystack.length - 1)  elems.navtool_forward.focus();\n\t\t\t\telse if (currhistory > 0)  elems.navtool_back.focus();\n\t\t\t\telse  elems.navtool_history.focus();\n\t\t\t}\n\t\t};\n\n\t\telems.navtool_forward.addEventListener('keydown', HistoryForwardKeyHandler);\n\n\t\t// Returns the internal elements object for use with certain tools.\n\t\t$this.GetElements = function() {\n\t\t\treturn elems;\n\t\t};\n\n\t\t// Export internal functions.  Useful for creating custom tools.\n\t\t$this.EscapeHTML = EscapeHTML;\n\t\t$this.FormatStr = FormatStr;\n\t\t$this.GetDisplayFilesize = GetDisplayFilesize;\n\t\t$this.CreateNode = CreateNode;\n\t\t$this.DebounceAttributes = DebounceAttributes;\n\t\t$this.PrepareXHR = PrepareXHR;\n\n\t\t$this.GetScrollLineHeight = function() {\n\t\t\treturn scrolllineheight;\n\t\t};\n\n\t\t// Starts an indicator for a long-running operation (e.g rename).\n\t\tvar operationtimeout = null, operationrefs = 0;\n\t\t$this.StartOperationIndicator = function() {\n\t\t\toperationrefs++;\n\n\t\t\telems.innerwrap.classList.add('fe_fileexplorer_operation_in_progress');\n\n\t\t\tif (operationtimeout)  clearTimeout(operationtimeout);\n\n\t\t\toperationtimeout = setTimeout(function() {\n\t\t\t\telems.innerwrap.classList.remove('fe_fileexplorer_operation_in_progress');\n\n\t\t\t\toperationtimeout = null;\n\n\t\t\t\toperationrefs = 0;\n\t\t\t}, 15000);\n\t\t};\n\n\t\t// Stops the indicator used for long-running operations (e.g. rename).\n\t\t$this.StopOperationIndicator = function() {\n\t\t\toperationrefs--;\n\n\t\t\tif (operationrefs <= 0)\n\t\t\t{\n\t\t\t\telems.innerwrap.classList.remove('fe_fileexplorer_operation_in_progress');\n\n\t\t\t\tif (operationtimeout)\n\t\t\t\t{\n\t\t\t\t\tclearTimeout(operationtimeout);\n\n\t\t\t\t\toperationtimeout = null;\n\t\t\t\t}\n\n\t\t\t\toperationrefs = 0;\n\t\t\t}\n\t\t};\n\n\t\t// Renames the selected item if only one item is selected.\n\t\tvar textareaoverlayinst;\n\t\t$this.RenameSelectedItem = function() {\n\t\t\tif (currfolder && currfolder.IsBusy())\n\t\t\t{\n\t\t\t\tcurrfolder.AddBusyQueueCallback($this.RenameSelectedItem, []);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!currfolder || currfolder.waiting || (('canmodify' in currfolder.GetAttributes()) && !currfolder.GetAttributes().canmodify))  return;\n\n\t\t\tif (!$this.hasEventListener('rename') || numselecteditems !== 1)  return;\n\n\t\t\tvar pos = -1;\n\t\t\tvar node = null;\n\t\t\tfor (var x in selecteditemsmap)\n\t\t\t{\n\t\t\t\tif (selecteditemsmap.hasOwnProperty(x))\n\t\t\t\t{\n\t\t\t\t\tpos = selecteditemsmap[x];\n\t\t\t\t\tnode = elems.itemswrap.children[pos];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!node)  return;\n\n\t\t\t$this.SetFocusItem(node.dataset.feid, true);\n\n\t\t\tnode.firstChild.lastChild.classList.add('fe_fileexplorer_invisible');\n\n\t\t\tvar origfolder = currfolder;\n\t\t\tvar entries = currfolder.GetEntries();\n\t\t\tvar origentry = entries[pos];\n\t\t\tvar pos2 = origentry.name.lastIndexOf('.');\n\n\t\t\tcurrfolder.SetBusyRef(1);\n\n\t\t\tvar options = {\n\t\t\t\tinitvalue: origentry.name,\n\t\t\t\tinitselstart: 0,\n\t\t\t\tinitselend: (origentry.type === 'file' && pos2 > 0 ? pos2 : -1),\n\n\t\t\t\tresizewatchers: [\n\t\t\t\t\t{ elem: node, attr: 'offsetLeft', val: -1 },\n\t\t\t\t\t{ elem: elems.itemsscrollwrap, attr: 'offsetHeight', val: -1 }\n\t\t\t\t],\n\n\t\t\t\tonposition: function(textelem) {\n\t\t\t\t\t// Size the textarea so it expands first toward the bottom of the scroll region and then toward the top of the scroll region.\n\t\t\t\t\ttextelem.style.left = node.offsetLeft + 'px';\n\t\t\t\t\ttextelem.style.width = node.offsetWidth + 'px';\n\n\t\t\t\t\tvar finalheight = Math.min(elems.itemsscrollwrap.offsetHeight - 1, textelem.scrollHeight + 2);\n\t\t\t\t\ttextelem.style.top = (node.offsetTop + node.firstChild.lastChild.offsetTop - 2 + finalheight <= elems.itemsscrollwrap.scrollTop + elems.itemsscrollwrap.offsetHeight - 2 ? node.offsetTop + node.firstChild.lastChild.offsetTop - 2 : elems.itemsscrollwrap.scrollTop + elems.itemsscrollwrap.offsetHeight - 2 - finalheight) + 'px';\n\t\t\t\t\ttextelem.style.height = finalheight + 'px';\n\t\t\t\t},\n\n\t\t\t\tondone: function(val, lastelem, etype) {\n\t\t\t\t\tvar $this2 = this;\n\n\t\t\t\t\tvar calledback = false;\n\t\t\t\t\tvar renamecallback = function(newentry) {\n\t\t\t\t\t\tif (calledback || destroyinprogress)  return;\n\n\t\t\t\t\t\tcalledback = true;\n\n\t\t\t\t\t\t$this.StopOperationIndicator();\n\n\t\t\t\t\t\tif (typeof newentry === 'object')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tnode.firstChild.lastChild.classList.remove('fe_fileexplorer_invisible');\n\n\t\t\t\t\t\t\t$this.SetNamedStatusBarText('message', '');\n\n\t\t\t\t\t\t\tif (lastelem && focuseditem && lastelem === focuseditem.firstChild)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlastelem.focus();\n\n\t\t\t\t\t\t\t\t$this.ScrollToFocusedItem();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\ttextareaoverlayinst = null;\n\n\t\t\t\t\t\t\t// May trigger various changes including folder navigation.\n\t\t\t\t\t\t\tcurrfolder.SetBusyRef(-1);\n\n\t\t\t\t\t\t\tif ($this.IsMappedFolder(origfolder))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\torigfolder.SetEntry(newentry);\n\n\t\t\t\t\t\t\t\t// If the item ID changed, then update focus and selection information and remove the original entry.\n\t\t\t\t\t\t\t\tif (origentry.id !== newentry.id)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (currfolder === origfolder)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif (focuseditem !== false && origentry.id === focuseditem.dataset.feid)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t$this.SetFocusItem(newentry.id, true);\n\n\t\t\t\t\t\t\t\t\t\t\t$this.ScrollToFocusedItem();\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif (origentry.id in selecteditemsmap)  $this.SetSelectedItems([newentry.id], true);\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\torigfolder.RemoveEntry(origentry.id);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t$this2.Destroy();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Reset the widget status.\n\t\t\t\t\t\t\t$this2.ResetAllowCancelDone();\n\n\t\t\t\t\t\t\t$this.SetNamedStatusBarText('message', EscapeHTML(FormatStr($this.Translate('Renaming \"{0}\" to \"{1}\" failed.' + (typeof newentry === 'string' ? '  {2}' : '')), origentry.name, val, newentry)), $this.settings.messagetimeout);\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t$this.StartOperationIndicator();\n\n\t\t\t\t\t$this.SetNamedStatusBarText('message', EscapeHTML(FormatStr($this.Translate('Renaming \"{0}\" to \"{1}\"...'), origentry.name, val)), $this.settings.messagetimeout);\n\n\t\t\t\t\t// Creates a copy of the original entry to pass to the rename event handler.\n\t\t\t\t\tDispatchEvent('rename', [renamecallback, currfolder, Object.assign({}, origentry), val]);\n\t\t\t\t},\n\n\t\t\t\toncancel: function(lastelem, etype) {\n\t\t\t\t\tnode.firstChild.lastChild.classList.remove('fe_fileexplorer_invisible');\n\n\t\t\t\t\tif (lastelem && focuseditem && lastelem === focuseditem.firstChild)\n\t\t\t\t\t{\n\t\t\t\t\t\tlastelem.focus();\n\n\t\t\t\t\t\t$this.ScrollToFocusedItem();\n\t\t\t\t\t}\n\n\t\t\t\t\ttextareaoverlayinst = null;\n\n\t\t\t\t\tthis.Destroy();\n\n\t\t\t\t\tcurrfolder.SetBusyRef(-1);\n\t\t\t\t},\n\t\t\t};\n\n\t\t\ttextareaoverlayinst = new TextareaOverlay(elems.itemsscrollwrapinner, options);\n\t\t};\n\n\t\t// Deletes selected items.\n\t\t$this.DeleteSelectedItems = function(recycle) {\n\t\t\tif (currfolder && currfolder.IsBusy())\n\t\t\t{\n\t\t\t\tcurrfolder.AddBusyQueueCallback($this.DeleteSelectedItems, [recycle]);\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!currfolder || currfolder.waiting || (('canmodify' in currfolder.GetAttributes()) && !currfolder.GetAttributes().canmodify))  return;\n\n\t\t\tif (!$this.hasEventListener('delete') || !numselecteditems)  return;\n\n\t\t\tcurrfolder.SetBusyRef(1);\n\n\t\t\t// Copy existing objects for later use.\n\t\t\tvar origfolder = currfolder;\n\t\t\tvar selecteditemsmap2 = Object.assign({}, selecteditemsmap);\n\t\t\tvar numselecteditems2 = numselecteditems;\n\n\t\t\tvar calledback = false;\n\t\t\tvar deletecallback = function(success) {\n\t\t\t\tif (calledback || destroyinprogress)  return;\n\n\t\t\t\tcalledback = true;\n\n\t\t\t\t$this.StopOperationIndicator();\n\n\t\t\t\tif (!$this.IsMappedFolder(origfolder))  return;\n\n\t\t\t\tif (success === true)\n\t\t\t\t{\n\t\t\t\t\t$this.SetNamedStatusBarText('message', '');\n\n\t\t\t\t\tcurrfolder.SetBusyRef(-1);\n\n\t\t\t\t\tif (currfolder === origfolder)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (numselecteditems2 === 1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Removing a single entry is slightly less expensive than removing multiple entries.\n\t\t\t\t\t\t\tfor (var x in selecteditemsmap2)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (selecteditemsmap2.hasOwnProperty(x))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (focuseditem !== false && focuseditem.dataset.feid === x)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif (focuseditem.nextSibling)  $this.SetFocusItem(focuseditem.nextSibling.dataset.feid, true);\n\t\t\t\t\t\t\t\t\t\telse if (focuseditem.previousSibling)  $this.SetFocusItem(focuseditem.previousSibling.dataset.feid, true);\n\n\t\t\t\t\t\t\t\t\t\t$this.ScrollToFocusedItem();\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tcurrfolder.RemoveEntry(x);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvar entries = currfolder.GetEntries();\n\t\t\t\t\t\t\tvar entries2 = [];\n\t\t\t\t\t\t\tfor (var x = 0; x < entries.length; x++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (!(entries[x].id in selecteditemsmap2))  entries2.push(entries[x]);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Adjust the focused item.\n\t\t\t\t\t\t\tif (focuseditem !== false && (focuseditem.dataset.feid in selecteditemsmap2))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvar node = focuseditem.nextSibling;\n\t\t\t\t\t\t\t\twhile (node && (node.dataset.feid in selecteditemsmap2))  node = node.nextSibling;\n\n\t\t\t\t\t\t\t\tif (!node)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tnode = focuseditem.previousSibling;\n\t\t\t\t\t\t\t\t\twhile (node && (node.dataset.feid in selecteditemsmap2))  node = node.previousSibling;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (node)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t$this.SetFocusItem(node.dataset.feid, true);\n\t\t\t\t\t\t\t\t\t$this.ScrollToFocusedItem();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcurrfolder.SetEntries(entries2);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$this.RefreshFolders();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this.SetNamedStatusBarText('message', EscapeHTML(FormatStr($this.Translate('Deleting items failed.' + (typeof success === 'string' ? '  {0}' : '')), success)), $this.settings.messagetimeout);\n\n\t\t\t\t\tcurrfolder.SetBusyRef(-1);\n\n\t\t\t\t\tif (currfolder === origfolder)  $this.RefreshFolders(true);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t$this.StartOperationIndicator();\n\n\t\t\tif (numselecteditems === 1)  $this.SetNamedStatusBarText('message', EscapeHTML($this.Translate('Deleting 1 item...')), $this.settings.messagetimeout);\n\t\t\telse  $this.SetNamedStatusBarText('message', EscapeHTML(FormatStr($this.Translate('Deleting {0} items...'), numselecteditems)), $this.settings.messagetimeout);\n\n\t\t\tDispatchEvent('delete', [deletecallback, currfolder, $this.GetSelectedItemIDs(), $this.GetSelectedFolderEntries(), recycle]);\n\t\t};\n\n\t\t// Checks whether or not Destroy was called.\n\t\t$this.IsDestroyed = function() {\n\t\t\treturn destroyinprogress;\n\t\t};\n\n\t\t// Destroys the instance.\n\t\t$this.Destroy = function() {\n\t\t\t// Remove event listeners, timeouts, and intervals.  There are quite a few.\n\t\t\tdestroyinprogress = true;\n\n\t\t\t// Force clear all busy queue callbacks across all mapped folders.\n\t\t\tfor (var x in foldermap)\n\t\t\t{\n\t\t\t\tif (foldermap.hasOwnProperty(x))\n\t\t\t\t{\n\t\t\t\t\tfoldermap[x].ClearBusyQueueCallbacks();\n\n\t\t\t\t\tDecrementMappedFolderRefCount(foldermap[x]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Destroy tools and anything else that is listening for the destroy event.\n\t\t\tDispatchEvent('destroy');\n\t\t\ttools = [];\n\n\t\t\t// Reset a number of instance globals.\n\t\t\ttriggers = {};\n\t\t\thistorystack = [];\n\t\t\tcurrhistory = -1;\n\n\t\t\tselecteditemsmap = {};\n\t\t\tfocuseditem = false;\n\n\t\t\t// Cancel the popup menu and/or rename text overlay.\n\t\t\tif (popupmenu)  popupmenu.Cancel();\n\t\t\tif (textareaoverlayinst)  textareaoverlayinst.Cancel();\n\n\t\t\tfor (var x in elems.statusbartextsegmentmap)\n\t\t\t{\n\t\t\t\tif (elems.statusbartextsegmentmap.hasOwnProperty(x) && elems.statusbartextsegmentmap[x].timeout)\n\t\t\t\t{\n\t\t\t\t\tclearTimeout(elems.statusbartextsegmentmap[x].timeout);\n\n\t\t\t\t\telems.statusbartextsegmentmap[x].timeout = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\twindow.removeEventListener('resize', statusbarresizewatch.Start, true);\n\t\t\tstatusbarresizewatch.Destroy();\n\t\t\tstatusbarresizewatch = null;\n\n\t\t\tif (internalcapturerefs)\n\t\t\t{\n\t\t\t\tcapturingrefs -= internalcapturerefs;\n\t\t\t\tinternalcapturerefs = 0;\n\n\t\t\t\twindow.removeEventListener('popstate', CapturePopStateHandler, true);\n\n\t\t\t\tif (window.history.state && window.history.state._fileexplorer)  window.history.back();\n\t\t\t}\n\n\t\t\telems.mainwrap.removeEventListener('mouseenter', CaptureMouseEnterHandler);\n\t\t\telems.mainwrap.removeEventListener('mouseleave', CaptureMouseLeaveHandler);\n\n\t\t\telems.mainwrap.removeEventListener('mousedown', MainWrapFocusMouseHandler);\n\t\t\telems.mainwrap.removeEventListener('mouseup', MainWrapFocusMouseHandler);\n\t\t\telems.mainwrap.removeEventListener('click', MainWrapFocusMouseHandler);\n\n\t\t\twindow.removeEventListener('mousedown', InnerWrapBlurHandler, true);\n\t\t\twindow.removeEventListener('blur', InnerWrapWindowBlurHandler, true);\n\t\t\twindow.removeEventListener('focus', FocusKeyHandler, true);\n\n\t\t\telems.bodytoolbar.removeEventListener('keydown', ToolbarKeyHandler);\n\t\t\telems.bodytoolsscrollwrap.removeEventListener('focus', ToolbarToolFocusHandler, true);\n\n\t\t\t// Cancel all thumbnails.\n\t\t\tfor (var x in queuedthumbs)\n\t\t\t{\n\t\t\t\tif (queuedthumbs.hasOwnProperty(x))  fe_thumbnailloader.RemoveFromQueue(x);\n\t\t\t}\n\n\t\t\tqueuedthumbs = {};\n\t\t\tqueuedthumbfailed = {};\n\n\t\t\telems.itemsscrollwrap.removeEventListener('scroll', thumbnailscrollwatch.Start);\n\t\t\twindow.removeEventListener('resize', thumbnailscrollwatch.Start, true);\n\t\t\tthumbnailscrollwatch.Destroy();\n\t\t\tthumbnailscrollwatch = null;\n\n\t\t\tfolderitemcache = null;\n\n\t\t\telems.pathsegmentsscrollwrap.removeEventListener('wheel', ConvertVertToHorzScroll);\n\t\t\telems.navtools.removeEventListener('keydown', NavToolsKeyHandler);\n\n\t\t\tif (currfolder)\n\t\t\t{\n\t\t\t\tcurrfolder.removeEventListener('set_entries', SetFolderEntriesHandler);\n\t\t\t\tcurrfolder.removeEventListener('remove_entry', RemoveFolderEntryHandler);\n\t\t\t}\n\n\t\t\tselectanchorpos = null;\n\t\t\tprevselectrect = null;\n\t\t\tselectbox = null;\n\t\t\tlastmouseevent = null;\n\n\t\t\tif (autoscrolltimer)\n\t\t\t{\n\t\t\t\tclearInterval(autoscrolltimer);\n\t\t\t\tautoscrolltimer = null;\n\t\t\t}\n\n\t\t\tlastselecttouch = null;\n\t\t\tlastmousedownevent = null;\n\n\t\t\t// Clean up a ton of event handlers related to clipboard handling.  There are a couple of DOM changes too but it is not a big deal.\n\t\t\tClipboardOverlayExitContextMenuHandler();\n\n\t\t\t// Cancel any rename start operation in progress.\n\t\t\tCancelRenameHandler();\n\t\t\tstartrenamefolder = null;\n\t\t\tstartrenameid = null;\n\n\t\t\tscrollnomoveinfo = null;\n\n\t\t\tmovecopydata = false;\n\t\t\telems.itemswrap.removeEventListener('dragstart', MoveCopyDragStartHandler);\n\t\t\telems.itemswrap.removeEventListener('dragend', MoveCopyDragEndHandler);\n\t\t\telems.innerwrap.removeEventListener('dragenter', MoveCopyDragEnterHandler);\n\t\t\telems.innerwrap.removeEventListener('dragover', MoveCopyDragOverHandler);\n\t\t\telems.innerwrap.removeEventListener('dragleave', MoveCopyDragLeaveHandler);\n\t\t\telems.innerwrap.removeEventListener('drop', MoveCopyDropHandler);\n\n\t\t\t// Stop all progress trackers.\n\t\t\tif (progresstrackers.length)  ProgressCancelAllHandler();\n\n\t\t\tprogresstrackers = [];\n\t\t\tif (progresstrackerinterval)\n\t\t\t{\n\t\t\t\tclearInterval(progresstrackerinterval);\n\t\t\t\tprogresstrackerinterval = null;\n\t\t\t}\n\n\t\t\tPreFinishProgressDisplay();\n\n\t\t\telems.statusbaractionprogresscancelwrap.removeEventListener('click', ProgressCancelAllHandler);\n\t\t\telems.statusbaractionprogresscancelwrap.removeEventListener('keydown', ProgressCancelKeydownHandler);\n\n\t\t\t// Clear folder refresh interval used during uploads.\n\t\t\tif (uploadfolderinterval)\n\t\t\t{\n\t\t\t\tclearInterval(uploadfolderinterval);\n\t\t\t\tuploadfolderinterval = null;\n\t\t\t}\n\n\t\t\t// Remove a bunch more event handlers.\n\t\t\twindow.removeEventListener('mouseup', ScrollNoMoveHandler, true);\n\n\t\t\twindow.removeEventListener('mousemove', SelectBoxDragHandler, true);\n\t\t\twindow.removeEventListener('mouseup', SelectBoxEndHandler, true);\n\t\t\twindow.removeEventListener('blur', SelectBoxEndHandler, true);\n\t\t\telems.itemsscrollwrap.removeEventListener('wheel', SelectBoxScrollWheelHandler);\n\n\t\t\telems.itemsscrollwrapinner.removeEventListener('mousedown', StartSelectionHandler);\n\t\t\telems.itemsscrollwrapinner.removeEventListener('touchstart', StartSelectionHandler);\n\t\t\telems.itemsscrollwrapinner.removeEventListener('click', CheckboxSelectedFixHandler);\n\n\t\t\telems.navtool_history.removeEventListener('mousedown', RecentLocationsHandler);\n\t\t\telems.navtool_history.removeEventListener('keydown', RecentLocationsKeyHandler);\n\n\t\t\telems.pathsegmentsscrollwrap.removeEventListener('mousedown', PathSegmentMouseFocusHandler);\n\t\t\telems.pathsegmentsscrollwrap.removeEventListener('focus', PathSegmentFocusScrollHandler, true);\n\t\t\telems.pathsegmentsscrollwrap.removeEventListener('click', PathSegmentClickHandler);\n\t\t\telems.pathsegmentsscrollwrap.removeEventListener('keydown', PathSegmentKeyHandler);\n\n\t\t\telems.itemsscrollwrap.removeEventListener('cut', ClipboardCutCopyHandler);\n\t\t\telems.itemsscrollwrap.removeEventListener('copy', ClipboardCutCopyHandler);\n\t\t\telems.itemsscrollwrap.removeEventListener('paste', ClipboardPasteHandler);\n\n\t\t\telems.itemsclipboardoverlay.removeEventListener('cut', ClipboardCutCopyHandler);\n\t\t\telems.itemsclipboardoverlay.removeEventListener('copy', ClipboardCutCopyHandler);\n\t\t\telems.itemsclipboardoverlay.removeEventListener('paste', ClipboardPasteHandler);\n\n\t\t\tlasttypingstr = '';\n\t\t\tlastkey = '';\n\n\t\t\telems.itemsscrollwrap.removeEventListener('keydown', ItemsKeyHandler);\n\t\t\telems.itemsscrollwrap.removeEventListener('keypress', ItemsKeypressHandler);\n\n\t\t\telems.innerwrap.removeEventListener('keydown', MainKeyHandler);\n\n\t\t\telems.navtool_up.removeEventListener('mouseup', ClickNavigateUpHandler);\n\t\t\telems.navtool_up.removeEventListener('keydown', NavigateUpKeyHandler);\n\t\t\telems.navtool_back.removeEventListener('mouseup', ClickHistoryBackHandler);\n\t\t\telems.navtool_back.removeEventListener('keydown', HistoryBackKeyHandler);\n\t\t\telems.navtool_forward.removeEventListener('mouseup', ClickHistoryForwardHandler);\n\t\t\telems.navtool_forward.removeEventListener('keydown', HistoryForwardKeyHandler);\n\n\t\t\tif (operationtimeout)\n\t\t\t{\n\t\t\t\tclearTimeout(operationtimeout);\n\n\t\t\t\toperationtimeout = null;\n\t\t\t}\n\n\t\t\t// Remove DOM elements.\n\t\t\twhile (elems.pathsegmentswrap.firstChild)  elems.pathsegmentswrap.removeChild(elems.pathsegmentswrap.lastChild);\n\n\t\t\twhile (elems.itemswrap.firstChild)\n\t\t\t{\n\t\t\t\telems.itemswrap.removeChild(elems.itemswrap.lastChild);\n\t\t\t}\n\n\t\t\tfor (var node in elems)\n\t\t\t{\n\t\t\t\tif (Array.isArray(elems[node]))\n\t\t\t\t{\n\t\t\t\t\tfor (var x = 0; x < elems[node].length; x++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (elems[node][x].parentNode)  elems[node][x].parentNode.removeChild(elems[node][x]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (elems[node].parentNode)\n\t\t\t\t{\n\t\t\t\t\telems[node].parentNode.removeChild(elems[node]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remaining cleanup.\n\t\t\telems = null;\n\n\t\t\t$this.settings = Object.assign({}, defaults);\n\n\t\t\tcurrfolder = false;\n\t\t\t$this = null;\n\t\t\tparentelem = null;\n\t\t\toptions = null;\n\t\t};\n\n\n\t\t// Create tool instances.  Needs to come after DOM-style and public functions to allow tools to register for various events.\n\t\tvar tools = [], numtoolbuttons = 0, numtoolbuttongroups;\n\n\t\tvar UpdateLastUsedToolButtonHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tif (!e.target.classList.contains('fe_fileexplorer_disabled'))\n\t\t\t{\n\t\t\t\telems.bodytools.forEach(function(elem) {\n\t\t\t\t\telem.tabIndex = (elem === e.target && !elem.classList.contains('fe_fileexplorer_disabled') ? 0 : -1);\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\t$this.AddToolbarButton = function(classname, title) {\n\t\t\tvar node = CreateNode('button', [classname, 'fe_fileexplorer_disabled'], { title: title, tabIndex: -1 });\n\n\t\t\tnode.addEventListener('click', UpdateLastUsedToolButtonHandler);\n\n\t\t\tif (numtoolbuttons && !numtoolbuttongroups)  elems.bodytoolbar.appendChild(CreateNode('div', ['fe_fileexplorer_folder_tool_separator']));\n\n\t\t\telems.bodytoolbar.appendChild(node);\n\t\t\telems.bodytools.push(node);\n\n\t\t\tnumtoolbuttons++;\n\t\t\tnumtoolbuttongroups++;\n\n\t\t\treturn node;\n\t\t};\n\n\t\tfor (var x = 0; x < coretools.length; x++)\n\t\t{\n\t\t\tnumtoolbuttongroups = 0;\n\n\t\t\tfor (var x2 = 0; x2 < coretools[x].length; x2++)\n\t\t\t{\n\t\t\t\ttools.push(new coretools[x][x2]($this));\n\t\t\t}\n\t\t}\n\n\t\tif (numtoolbuttons)  elems.bodytoolsscrollwrap.classList.remove('fe_fileexplorer_hidden');\n\n\t\t// Set the initial path.\n\t\t$this.SetPath($this.settings.initpath);\n\t};\n\n\n\t// Export internal mini-classes for reusability purposes.\n\twindow.FileExplorer.ImageLoader = ImageLoader;\n\twindow.FileExplorer.PopupMenu = PopupMenu;\n\twindow.FileExplorer.TextareaOverlay = TextareaOverlay;\n\n\n\t// Global function to register a tool.\n\twindow.FileExplorer.RegisterTool = function(groupnum, tool) {\n\t\twhile (groupnum >= coretools.length)  coretools.push([]);\n\n\t\tcoretools[groupnum].push(tool);\n\t};\n\n\n\t// Core tools.\n\tvar FileExplorerTool_NewFolder = function(fe) {\n\t\tif (!(this instanceof FileExplorerTool_NewFolder))  return new FileExplorerTool_NewFolder(fe);\n\n\t\t// Do not create the tool if the tool is not enabled.\n\t\tif (!fe.settings.onnewfolder && !fe.settings.tools.new_folder)  return;\n\n\t\tvar enabled = false;\n\n\t\tvar node = fe.AddToolbarButton('fe_fileexplorer_folder_tool_new_folder', fe.Translate('New Folder (Ctrl + Ins)'));\n\n\t\tif (fe.settings.onnewfolder)  fe.addToolEventListener('new_folder', fe.settings.onnewfolder);\n\n\t\tvar CreateFolder = function() {\n\t\t\tif (!enabled)  return;\n\n\t\t\tvar origfolder = fe.GetCurrentFolder();\n\n\t\t\tvar calledback = false;\n\t\t\tvar createdcallback = function(newentry) {\n\t\t\t\tif (calledback || fe.IsDestroyed())  return;\n\n\t\t\t\tcalledback = true;\n\n\t\t\t\tfe.StopOperationIndicator();\n\n\t\t\t\tif (typeof newentry === 'object')\n\t\t\t\t{\n\t\t\t\t\tif (fe.IsMappedFolder(origfolder))\n\t\t\t\t\t{\n\t\t\t\t\t\tfe.SetNamedStatusBarText('message', '');\n\n\t\t\t\t\t\torigfolder.SetEntry(newentry);\n\n\t\t\t\t\t\tif (fe.GetCurrentFolder() === origfolder)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfe.SetFocusItem(newentry.id, true);\n\t\t\t\t\t\t\tfe.ScrollToFocusedItem();\n\t\t\t\t\t\t\tfe.SetSelectedItems([newentry.id]);\n\t\t\t\t\t\t\tfe.RenameSelectedItem();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfe.SetNamedStatusBarText('message', EscapeHTML(FormatStr(fe.Translate('Creating a new folder failed.' + (typeof newentry === 'string' ? '  {0}' : '')), newentry)), fe.settings.messagetimeout);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfe.StartOperationIndicator();\n\n\t\t\tfe.SetNamedStatusBarText('message', EscapeHTML(fe.Translate('Creating a new folder...')), fe.settings.messagetimeout);\n\n\t\t\tfe.DispatchToolEvent('new_folder', [createdcallback, origfolder]);\n\t\t};\n\n\t\tvar ClickHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tCreateFolder();\n\t\t};\n\n\t\tnode.addEventListener('click', ClickHandler);\n\n\t\tvar HotkeyHandler = function(e) {\n\t\t\tif (e.ctrlKey && !e.shiftKey && !e.altKey && e.keyCode == 45)\n\t\t\t{\n\t\t\t\t// Ctrl + Insert.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tCreateFolder();\n\t\t\t}\n\t\t};\n\n\t\tfe.addEventListener('keydown', HotkeyHandler);\n\n\t\tvar UpdateToolHandler = function(currfolder, attrs) {\n\t\t\tvar prevenabled = enabled;\n\n\t\t\tenabled = (!currfolder.waiting && (!('canmodify' in attrs) || attrs.canmodify));\n\n\t\t\tif (prevenabled !== enabled)\n\t\t\t{\n\t\t\t\tif (enabled)  node.classList.remove('fe_fileexplorer_disabled');\n\t\t\t\telse  node.classList.add('fe_fileexplorer_disabled');\n\n\t\t\t\tfe.ToolStateUpdated();\n\t\t\t}\n\t\t};\n\n\t\tfe.addEventListener('update_tool', UpdateToolHandler);\n\n\t\tvar DestroyToolHandler = function() {\n\t\t\tnode.removeEventListener('click', ClickHandler);\n\t\t};\n\n\t\tfe.addEventListener('destroy', DestroyToolHandler);\n\t};\n\n\twindow.FileExplorer.RegisterTool(0, FileExplorerTool_NewFolder);\n\n\n\tvar FileExplorerTool_NewFile = function(fe) {\n\t\tif (!(this instanceof FileExplorerTool_NewFile))  return new FileExplorerTool_NewFile(fe);\n\n\t\t// Do not create the tool if the tool is not enabled.\n\t\tif (!fe.settings.onnewfile && !fe.settings.tools.new_file)  return;\n\n\t\tvar enabled = false;\n\n\t\tvar node = fe.AddToolbarButton('fe_fileexplorer_folder_tool_new_file', fe.Translate('New File (Ins)'));\n\n\t\tif (fe.settings.onnewfile)  fe.addToolEventListener('new_file', fe.settings.onnewfile);\n\n\t\tvar CreateFile = function() {\n\t\t\tif (!enabled)  return;\n\n\t\t\tvar origfolder = fe.GetCurrentFolder();\n\n\t\t\tvar calledback = false;\n\t\t\tvar createdcallback = function(newentry) {\n\t\t\t\tif (calledback || fe.IsDestroyed())  return;\n\n\t\t\t\tcalledback = true;\n\n\t\t\t\tfe.StopOperationIndicator();\n\n\t\t\t\tif (typeof newentry === 'object')\n\t\t\t\t{\n\t\t\t\t\tif (fe.IsMappedFolder(origfolder))\n\t\t\t\t\t{\n\t\t\t\t\t\tfe.SetNamedStatusBarText('message', '');\n\n\t\t\t\t\t\torigfolder.SetEntry(newentry);\n\n\t\t\t\t\t\tif (fe.GetCurrentFolder() === origfolder)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfe.SetFocusItem(newentry.id, true);\n\t\t\t\t\t\t\tfe.ScrollToFocusedItem();\n\t\t\t\t\t\t\tfe.SetSelectedItems([newentry.id]);\n\t\t\t\t\t\t\tfe.RenameSelectedItem();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfe.SetNamedStatusBarText('message', EscapeHTML(FormatStr(fe.Translate('Creating a new file failed.' + (typeof newentry === 'string' ? '  {0}' : '')), newentry)), fe.settings.messagetimeout);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfe.StartOperationIndicator();\n\n\t\t\tfe.SetNamedStatusBarText('message', EscapeHTML(fe.Translate('Creating a new file...')), fe.settings.messagetimeout);\n\n\t\t\tfe.DispatchToolEvent('new_file', [createdcallback, origfolder]);\n\t\t};\n\n\t\tvar ClickHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tCreateFile();\n\t\t};\n\n\t\tnode.addEventListener('click', ClickHandler);\n\n\t\tvar HotkeyHandler = function(e) {\n\t\t\tif (!e.ctrlKey && !e.shiftKey && !e.altKey && e.keyCode == 45)\n\t\t\t{\n\t\t\t\t// Insert.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tCreateFile();\n\t\t\t}\n\t\t};\n\n\t\tfe.addEventListener('keydown', HotkeyHandler);\n\n\t\tvar UpdateToolHandler = function(currfolder, attrs) {\n\t\t\tvar prevenabled = enabled;\n\n\t\t\tenabled = (!currfolder.waiting && (!('canmodify' in attrs) || attrs.canmodify));\n\n\t\t\tif (prevenabled !== enabled)\n\t\t\t{\n\t\t\t\tif (enabled)  node.classList.remove('fe_fileexplorer_disabled');\n\t\t\t\telse  node.classList.add('fe_fileexplorer_disabled');\n\n\t\t\t\tfe.ToolStateUpdated();\n\t\t\t}\n\t\t};\n\n\t\tfe.addEventListener('update_tool', UpdateToolHandler);\n\n\t\tvar DestroyToolHandler = function() {\n\t\t\tnode.removeEventListener('click', ClickHandler);\n\t\t};\n\n\t\tfe.addEventListener('destroy', DestroyToolHandler);\n\t};\n\n\twindow.FileExplorer.RegisterTool(0, FileExplorerTool_NewFile);\n\n\n\tvar FileExplorerTool_Upload = function(fe) {\n\t\tif (!(this instanceof FileExplorerTool_Upload))  return new FileExplorerTool_Upload(fe);\n\n\t\t// Do not create the tool if uploading is disabled.\n\t\tif (!fe.hasEventListener('init_upload') && !fe.settings.tools.upload)  return;\n\n\t\tvar enabled = false;\n\t\tvar inputfield = null;\n\n\t\tvar node = fe.AddToolbarButton('fe_fileexplorer_folder_tool_upload', fe.Translate('Upload (Ctrl + U)'));\n\n\t\tvar RemoveInputField = function() {\n\t\t\tif (inputfield)\n\t\t\t{\n\t\t\t\tinputfield.removeEventListener('change', UploadFiles);\n\t\t\t\tinputfield.parentNode.removeChild(inputfield);\n\t\t\t\tinputfield = null;\n\t\t\t}\n\t\t};\n\n\t\tvar UploadFiles = function(e) {\n\t\t\tfe.ProcessFilesAndUpload('currfolder', null, inputfield);\n\n\t\t\t// Remove the field.\n\t\t\tRemoveInputField();\n\t\t};\n\n\t\tvar CreateInputField = function() {\n\t\t\tRemoveInputField();\n\n\t\t\tinputfield = CreateNode('input', ['fe_fileexplorer_hidden'], { type: 'file', multiple: true });\n\t\t\tinputfield.addEventListener('change', UploadFiles);\n\n\t\t\tfe.GetElements().mainwrap.appendChild(inputfield);\n\t\t};\n\n\t\tvar StartSelectFiles = function() {\n\t\t\tif (!enabled)  return;\n\n\t\t\tif (!inputfield)  CreateInputField();\n\n\t\t\tinputfield.click();\n\t\t};\n\n\t\tvar ClickHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tStartSelectFiles();\n\t\t};\n\n\t\tnode.addEventListener('click', ClickHandler);\n\n\t\tvar HotkeyHandler = function(e) {\n\t\t\tif (e.ctrlKey && !e.shiftKey && !e.altKey && e.keyCode == 85)\n\t\t\t{\n\t\t\t\t// Ctrl + U.\n\t\t\t\te.preventDefault();\n\n\t\t\t\tStartSelectFiles();\n\t\t\t}\n\t\t};\n\n\t\tfe.addEventListener('keydown', HotkeyHandler);\n\n\t\tvar UpdateToolHandler = function(currfolder, attrs) {\n\t\t\tvar prevenabled = enabled;\n\n\t\t\tenabled = (!currfolder.waiting && (!('canmodify' in attrs) || attrs.canmodify));\n\n\t\t\tif (prevenabled !== enabled)\n\t\t\t{\n\t\t\t\tif (enabled)  node.classList.remove('fe_fileexplorer_disabled');\n\t\t\t\telse  node.classList.add('fe_fileexplorer_disabled');\n\n\t\t\t\tfe.ToolStateUpdated();\n\t\t\t}\n\t\t};\n\n\t\tfe.addEventListener('update_tool', UpdateToolHandler);\n\n\t\tvar DestroyToolHandler = function() {\n\t\t\tRemoveInputField();\n\n\t\t\tnode.removeEventListener('click', ClickHandler);\n\t\t};\n\n\t\tfe.addEventListener('destroy', DestroyToolHandler);\n\t};\n\n\twindow.FileExplorer.RegisterTool(0, FileExplorerTool_Upload);\n\n\n\tvar FileExplorerTool_Download = function(fe) {\n\t\tif (!(this instanceof FileExplorerTool_Download))  return new FileExplorerTool_Download(fe);\n\n\t\t// Do not create the tool if downloading is disabled.\n\t\tif (!fe.settings.oninitdownload && !fe.settings.tools.download)  return;\n\n\t\tvar enabled = false;\n\n\t\tvar node = fe.AddToolbarButton('fe_fileexplorer_folder_tool_download', fe.Translate('Download'));\n\n\t\tif (fe.settings.oninitdownload)  fe.addToolEventListener('init_download', fe.settings.oninitdownload);\n\t\tif (fe.settings.ondownloadstarted)  fe.addToolEventListener('download_started', fe.settings.ondownloadstarted);\n\t\tif (fe.settings.ondownloaderror)  fe.addToolEventListener('download_error', fe.settings.ondownloaderror);\n\n\t\tvar ClickHandler = function(e) {\n\t\t\tif (!e.isTrusted || !enabled)  return;\n\n\t\t\tvar calledback = false;\n\t\t\tvar downloadcallback = function(options) {\n\t\t\t\tif (calledback || fe.IsDestroyed())  return;\n\n\t\t\t\tcalledback = true;\n\n\t\t\t\tif (typeof options === 'object')\n\t\t\t\t{\n\t\t\t\t\t// Create a form.\n\t\t\t\t\tvar method = (options.method || 'POST');\n\t\t\t\t\tvar formnode = CreateNode('form', ['fe_fileexplorer_hidden'], { action: options.url, method: method, enctype: 'multipart/form-data' });\n\n\t\t\t\t\tif (options.params)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (options.params instanceof FormData)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (var entry in options.params)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (typeof entry[1] === 'string')  formnode.appendChild(CreateNode('input', [], { type: 'hidden', name: entry[0], value: entry[1] }));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (Array.isArray(options.params))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (var x = 0; x < options.params.length; x++)  formnode.appendChild(CreateNode('input', [], { type: 'hidden', name: options.params[x].name, value: options.params[x].value }));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (var x in options.params)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif (options.params.hasOwnProperty(x) && typeof options.params[x] === 'string')  formnode.appendChild(CreateNode('input', [], { type: 'hidden', name: x, value: options.params[x] }));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Create an iframe.\n\t\t\t\t\tif (!('iframe' in options) || options.iframe)\n\t\t\t\t\t{\n\t\t\t\t\t\tvar iframenode = CreateNode('iframe', ['fe_fileexplorer_download_iframe_wrap']);\n\n\t\t\t\t\t\tvar removeiframe = function() {\n\t\t\t\t\t\t\tif (iframenode)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdocument.body.removeChild(iframenode);\n\n\t\t\t\t\t\t\t\tiframenode = null;\n\n\t\t\t\t\t\t\t\tfe.DispatchToolEvent('download_started', options);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// As soon as the response starts being delivered by the server, abort the request.\n\t\t\t\t\t\tvar requestresponsehandler = function(e) {\n\t\t\t\t\t\t\tfe.StopOperationIndicator();\n\n\t\t\t\t\t\t\t// Remove the iframe after 5 seconds.  It is extremely likely that the other download has successfully started too.\n\t\t\t\t\t\t\tsetTimeout(removeiframe, 5000);\n\n\t\t\t\t\t\t\tif (xhr)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvar tempxhr = xhr;\n\n\t\t\t\t\t\t\t\txhr = null;\n\n\t\t\t\t\t\t\t\ttempxhr.Destroy();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// Prepare a second, independent request for the download.\n\t\t\t\t\t\tvar xhr = new PrepareXHR(options);\n\n\t\t\t\t\t\txhr.addEventListener('progress', requestresponsehandler);\n\t\t\t\t\t\txhr.addEventListener('loadend', requestresponsehandler);\n\t\t\t\t\t\txhr.addEventListener('timeout', requestresponsehandler);\n\n\t\t\t\t\t\tvar iframeloadhandler = function(e) {\n\t\t\t\t\t\t\tif (formnode)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// First load.  Set the form in the iframe and submit it.\n\t\t\t\t\t\t\t\t// The iframe contents become immediately inaccessible so any security issues are mitigated.\n\t\t\t\t\t\t\t\tiframenode.contentWindow.document.body.appendChild(formnode);\n\t\t\t\t\t\t\t\tformnode.submit();\n\n\t\t\t\t\t\t\t\tformnode = null;\n\n\t\t\t\t\t\t\t\t// Start the second download.\n\t\t\t\t\t\t\t\txhr.Send();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (iframenode)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// Second load.  Remove the iframe and cancel the XHR request.  The download also failed for some reason.\n\t\t\t\t\t\t\t\tfe.StopOperationIndicator();\n\n\t\t\t\t\t\t\t\tdocument.body.removeChild(iframenode);\n\n\t\t\t\t\t\t\t\tiframenode = null;\n\n\t\t\t\t\t\t\t\tif (xhr)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tvar tempxhr = xhr;\n\n\t\t\t\t\t\t\t\t\txhr = null;\n\n\t\t\t\t\t\t\t\t\ttempxhr.Destroy();\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tfe.SetNamedStatusBarText('message', EscapeHTML(FormatStr(fe.Translate('Download failed to start'))), fe.settings.messagetimeout);\n\n\t\t\t\t\t\t\t\tfe.DispatchToolEvent('download_error', options);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tiframenode.addEventListener('load', iframeloadhandler);\n\n\t\t\t\t\t\tdocument.body.appendChild(iframenode);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// Create a new tab/window when submitting the form.  Most browsers will close the tab/window as soon as the download dialog shows.\n\t\t\t\t\t\tfe.StopOperationIndicator();\n\n\t\t\t\t\t\tformnode.target = '_blank';\n\n\t\t\t\t\t\tdocument.body.appendChild(formnode);\n\t\t\t\t\t\tformnode.submit();\n\t\t\t\t\t\tdocument.body.removeChild(formnode);\n\t\t\t\t\t}\n\n\t\t\t\t\tfe.SetNamedStatusBarText('message', EscapeHTML(FormatStr(fe.Translate('Starting download...'))), fe.settings.messagetimeout);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tfe.StopOperationIndicator();\n\n\t\t\t\t\tfe.SetNamedStatusBarText('message', EscapeHTML(FormatStr(fe.Translate('Download initialization failed.' + (typeof options === 'string' ? '  {0}' : '')), options)), fe.settings.messagetimeout);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfe.StartOperationIndicator();\n\n\t\t\tfe.SetNamedStatusBarText('message', EscapeHTML(fe.Translate('Initializing download...')), fe.settings.messagetimeout);\n\n\t\t\tfe.DispatchToolEvent('init_download', [downloadcallback, fe.GetCurrentFolder(), fe.GetSelectedItemIDs(), fe.GetSelectedFolderEntries()]);\n\t\t};\n\n\t\tnode.addEventListener('click', ClickHandler);\n\n\t\tvar UpdateToolHandler = function(currfolder, attrs) {\n\t\t\tvar prevenabled = enabled;\n\n\t\t\tenabled = (!currfolder.waiting && fe.GetNumSelectedItems() > 0);\n\n\t\t\tif (prevenabled !== enabled)\n\t\t\t{\n\t\t\t\tif (enabled)  node.classList.remove('fe_fileexplorer_disabled');\n\t\t\t\telse  node.classList.add('fe_fileexplorer_disabled');\n\n\t\t\t\tfe.ToolStateUpdated();\n\t\t\t}\n\t\t};\n\n\t\tfe.addEventListener('update_tool', UpdateToolHandler);\n\n\t\tvar DestroyToolHandler = function() {\n\t\t\tnode.removeEventListener('click', ClickHandler);\n\t\t};\n\n\t\tfe.addEventListener('destroy', DestroyToolHandler);\n\t};\n\n\twindow.FileExplorer.RegisterTool(0, FileExplorerTool_Download);\n\n\n\tvar FileExplorerTool_Copy = function(fe) {\n\t\tif (!(this instanceof FileExplorerTool_Copy))  return new FileExplorerTool_Copy(fe);\n\n\t\t// Do not create the tool if copying is disabled.\n\t\tif (!fe.hasEventListener('copy') && !fe.settings.tools.copy)  return;\n\n\t\tvar enabled = false;\n\n\t\tvar node = fe.AddToolbarButton('fe_fileexplorer_folder_tool_copy', fe.Translate('Copy (' + (navigator.platform.indexOf('Mac') > -1 ? '\\u2318' : 'Ctrl') + ' + C)'));\n\n\t\tvar ClickHandler = function(e) {\n\t\t\tif (!e.isTrusted || !enabled)  return;\n\n\t\t\tvar elems = fe.GetElements();\n\n\t\t\telems.itemsclipboardoverlay.value = '';\n\t\t\telems.itemsclipboardoverlaypastewrap.classList.remove('fe_fileexplorer_hidden');\n\t\t\telems.itemsclipboardoverlay.focus();\n\n\t\t\tdocument.execCommand('copy');\n\t\t};\n\n\t\tnode.addEventListener('click', ClickHandler);\n\n\t\tvar UpdateToolHandler = function(currfolder, attrs) {\n\t\t\tvar prevenabled = enabled;\n\n\t\t\tenabled = (!currfolder.waiting && fe.GetNumSelectedItems() > 0);\n\n\t\t\tif (prevenabled !== enabled)\n\t\t\t{\n\t\t\t\tif (enabled)  node.classList.remove('fe_fileexplorer_disabled');\n\t\t\t\telse  node.classList.add('fe_fileexplorer_disabled');\n\n\t\t\t\tfe.ToolStateUpdated();\n\t\t\t}\n\t\t};\n\n\t\tfe.addEventListener('update_tool', UpdateToolHandler);\n\n\t\tvar DestroyToolHandler = function() {\n\t\t\tnode.removeEventListener('click', ClickHandler);\n\t\t};\n\n\t\tfe.addEventListener('destroy', DestroyToolHandler);\n\t};\n\n\twindow.FileExplorer.RegisterTool(1, FileExplorerTool_Copy);\n\n\n\tvar FileExplorerTool_Paste = function(fe) {\n\t\tif (!(this instanceof FileExplorerTool_Paste))  return new FileExplorerTool_Paste(fe);\n\n\t\t// Do not create the tool if copying and moving are disabled.\n\t\tif (!fe.hasEventListener('copy') && !fe.hasEventListener('move') && !fe.settings.tools.paste)  return;\n\n\t\tvar enabled = false;\n\n\t\tvar node = fe.AddToolbarButton('fe_fileexplorer_folder_tool_paste', fe.Translate('Paste (' + (navigator.platform.indexOf('Mac') > -1 ? '\\u2318' : 'Ctrl') + ' + V)'));\n\n\t\tvar ClickHandler = function(e) {\n\t\t\tif (!e.isTrusted || !enabled)  return;\n\n\t\t\tfe.ShowClipboardPasteBox();\n\t\t};\n\n\t\tvar ToolKeyHandler = function(e) {\n\t\t\tif (!e.isTrusted || !enabled)  return;\n\n\t\t\tif (e.keyCode == 13 || e.keyCode == 32)\n\t\t\t{\n\t\t\t\tfe.ShowClipboardPasteBox();\n\n\t\t\t\tfe.GetElements().itemsclipboardoverlay.focus();\n\t\t\t}\n\t\t};\n\n\t\tnode.addEventListener('mouseup', ClickHandler);\n\t\tnode.addEventListener('keyup', ToolKeyHandler);\n\n\t\tvar UpdateToolHandler = function(currfolder, attrs) {\n\t\t\tvar prevenabled = enabled;\n\n\t\t\tenabled = (!currfolder.waiting && (!('canmodify' in attrs) || attrs.canmodify));\n\n\t\t\tif (prevenabled !== enabled)\n\t\t\t{\n\t\t\t\tif (enabled)  node.classList.remove('fe_fileexplorer_disabled');\n\t\t\t\telse  node.classList.add('fe_fileexplorer_disabled');\n\n\t\t\t\tfe.ToolStateUpdated();\n\t\t\t}\n\t\t};\n\n\t\tfe.addEventListener('update_tool', UpdateToolHandler);\n\n\t\tvar DestroyToolHandler = function() {\n\t\t\tnode.removeEventListener('mouseup', ClickHandler);\n\t\t\tnode.removeEventListener('keyup', ToolKeyHandler);\n\t\t};\n\n\t\tfe.addEventListener('destroy', DestroyToolHandler);\n\t};\n\n\twindow.FileExplorer.RegisterTool(1, FileExplorerTool_Paste);\n\n\n\tvar FileExplorerTool_Cut = function(fe) {\n\t\tif (!(this instanceof FileExplorerTool_Cut))  return new FileExplorerTool_Cut(fe);\n\n\t\t// Do not create the tool if moving is disabled.\n\t\tif (!fe.hasEventListener('move') && !fe.settings.tools.cut)  return;\n\n\t\tvar enabled = false;\n\n\t\tvar node = fe.AddToolbarButton('fe_fileexplorer_folder_tool_cut', fe.Translate('Cut (' + (navigator.platform.indexOf('Mac') > -1 ? '\\u2318' : 'Ctrl') + ' + X)'));\n\n\t\tvar ClickHandler = function(e) {\n\t\t\tif (!e.isTrusted || !enabled)  return;\n\n\t\t\tvar elems = fe.GetElements();\n\n\t\t\telems.itemsclipboardoverlay.value = '';\n\t\t\telems.itemsclipboardoverlaypastewrap.classList.remove('fe_fileexplorer_hidden');\n\t\t\telems.itemsclipboardoverlay.focus();\n\n\t\t\tdocument.execCommand('cut');\n\t\t};\n\n\t\tnode.addEventListener('click', ClickHandler);\n\n\t\tvar UpdateToolHandler = function(currfolder, attrs) {\n\t\t\tvar prevenabled = enabled;\n\n\t\t\tenabled = (!currfolder.waiting && (!('canmodify' in attrs) || attrs.canmodify) && fe.GetNumSelectedItems() > 0);\n\n\t\t\tif (prevenabled !== enabled)\n\t\t\t{\n\t\t\t\tif (enabled)  node.classList.remove('fe_fileexplorer_disabled');\n\t\t\t\telse  node.classList.add('fe_fileexplorer_disabled');\n\n\t\t\t\tfe.ToolStateUpdated();\n\t\t\t}\n\t\t};\n\n\t\tfe.addEventListener('update_tool', UpdateToolHandler);\n\n\t\tvar DestroyToolHandler = function() {\n\t\t\tnode.removeEventListener('click', ClickHandler);\n\t\t};\n\n\t\tfe.addEventListener('destroy', DestroyToolHandler);\n\t};\n\n\twindow.FileExplorer.RegisterTool(1, FileExplorerTool_Cut);\n\n\n\tvar FileExplorerTool_Delete = function(fe) {\n\t\tif (!(this instanceof FileExplorerTool_Delete))  return new FileExplorerTool_Delete(fe);\n\n\t\t// Do not create the tool if deleting is disabled.\n\t\tif (!fe.hasEventListener('delete') && !fe.settings.tools.delete)  return;\n\n\t\tvar enabled = false;\n\n\t\tvar node = fe.AddToolbarButton('fe_fileexplorer_folder_tool_delete', fe.Translate('Delete (Del)'));\n\n\t\tvar ClickHandler = function(e) {\n\t\t\tif (e.isTrusted && enabled)  fe.DeleteSelectedItems(!e.shiftKey);\n\t\t};\n\n\t\tnode.addEventListener('click', ClickHandler);\n\n\t\tvar UpdateToolHandler = function(currfolder, attrs) {\n\t\t\tvar prevenabled = enabled;\n\n\t\t\tenabled = (!currfolder.waiting && (!('canmodify' in attrs) || attrs.canmodify) && fe.GetNumSelectedItems());\n\n\t\t\tif (prevenabled !== enabled)\n\t\t\t{\n\t\t\t\tif (enabled)  node.classList.remove('fe_fileexplorer_disabled');\n\t\t\t\telse  node.classList.add('fe_fileexplorer_disabled');\n\n\t\t\t\tfe.ToolStateUpdated();\n\t\t\t}\n\t\t};\n\n\t\tfe.addEventListener('update_tool', UpdateToolHandler);\n\n\t\tvar DestroyToolHandler = function() {\n\t\t\tnode.removeEventListener('click', ClickHandler);\n\t\t};\n\n\t\tfe.addEventListener('destroy', DestroyToolHandler);\n\t};\n\n\twindow.FileExplorer.RegisterTool(1, FileExplorerTool_Delete);\n\n\n\tvar FileExplorerTool_ItemCheckboxes = function(fe) {\n\t\tif (!(this instanceof FileExplorerTool_ItemCheckboxes))  return new FileExplorerTool_ItemCheckboxes(fe);\n\n\t\t// Do not create the tool if the device's primary input is not coarse and the tool is not specifically enabled.\n\t\tif (!matchMedia('(pointer: coarse)').matches && !fe.settings.tools.item_checkboxes)  return;\n\n\t\tvar node = fe.AddToolbarButton('fe_fileexplorer_folder_tool_item_checkboxes', fe.Translate('Item Checkboxes'));\n\n\t\t// Always enabled.\n\t\tnode.classList.remove('fe_fileexplorer_disabled');\n\n\t\tvar ClickHandler = function(e) {\n\t\t\tif (!e.isTrusted)  return;\n\n\t\t\tfe.GetElements().innerwrap.classList.toggle('fe_fileexplorer_show_item_checkboxes');\n\t\t};\n\n\t\tnode.addEventListener('click', ClickHandler);\n\n\t\tvar DestroyToolHandler = function() {\n\t\t\tnode.removeEventListener('click', ClickHandler);\n\t\t};\n\n\t\tfe.addEventListener('destroy', DestroyToolHandler);\n\t};\n\n\twindow.FileExplorer.RegisterTool(2, FileExplorerTool_ItemCheckboxes);\n})();\n"]}