Your IP : 216.73.216.63


Current Path : /home/theafprt/fnf.group/wp-content/plugins/wp-smush-pro/app/assets/js/
Upload File :
Current File : //home/theafprt/fnf.group/wp-content/plugins/wp-smush-pro/app/assets/js/smush-admin.min.js.map

{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./_src/js/smush/smush.js","webpack:///external \"jQuery\"","webpack:///./node_modules/jquery.fancytree/dist/modules/jquery.fancytree.js","webpack:///./_src/js/app.js","webpack:///./_src/js/modules/helpers.js","webpack:///./_src/js/modules/admin.js","webpack:///./_src/js/modules/bulk-smush.js","webpack:///./_src/js/modules/onboarding.js","webpack:///./node_modules/jquery.fancytree/dist/modules/jquery.fancytree.ui-deps.js","webpack:///./_src/js/smush/cdn.js","webpack:///./_src/js/smush/lazy-load.js","webpack:///./_src/js/modules/bulk-restore.js","webpack:///./_src/js/modules/notice.js","webpack:///./_src/js/modules/directory-smush.js","webpack:///./_src/js/smush/directory-scanner.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","perf","Smush","button","bulk","type","this","errors","progressBar","jQuery","smushed","parseInt","find","html","total","skip_resmush","data","is_bulk","url","ajaxurl","log","deferred","Deferred","ids","wp_smushit_data","resmush","length","unsmushed","concat","filter","itm","a","indexOf","is_bulk_resmush","status","parent","prev","smush_type","single_ajax_suffix","bulk_ajax_suffix","smushAddParams","action","start","run","bindDeferredEvents","cancelAjax","isEmptyObject","param","memberValidityNotice","show_warning","show","hide","isBulkResmush","id","sendUrl","nonce","attachment_id","_nonce","ajax","timeout","dataType","savings","savings_percent","savingsBytes","savings_bytes","origDiff","pro_savings","percent","WP_Smush","helpers","precise_round","formatBytes","scanType","isNextgen","superSavings","size_before","size_after","formattedSize","statsHuman","getFormatFromString","getSizeFromString","isNaN","savings_resize","count_images","count_resize","smushedCountDiv","count_supersmushed","smushConversionSavings","savings_conversion","conversionSavings","smushResizeSavings","savingsValue","resizeSavings","resizeMessage","setProSavings","smushProSavings","proSavingsPercent","proSavingsBytes","sidenavCountDiv","count","addClass","removeClass","newSize","attachmentSize","contents","nodeType","text","sizeStrongEl","imageStats","window","is_lossy","bytes","errorMsg","fileName","thumbnail","tableDiv","wp_smush_msgs","error_ignore","currentId","uIndex","splice","index","attr","bulkStart","singleStart","remove","smushing","removeAttr","self","all_done","request","done","response","membershipValidity","success","error_msg","smush_vars","strings","stats_label","updateImageStats","new_size","enableButton","fail","messageHolder","progressMessage","sync_stats","extend","count_smushed","count_total","updateStats","always","statusIcon","notice","progress","document","getElementById","classList","resumeCountDiv","wrapperCountDiv","_res","stats","updateLocalizedStats","syncStats","updateRemainingCount","_updateProgress","width","css","continueSmush","performance","now","freeExceeded","nonceValue","current_id","shift","updateSmushIds","nonceField","val","res","error","push","prepareErrorRow","error_message","file_name","append","state","unshift","updateProgress","singleDone","continue","callAjax","resolve","msg","error_in_bulk","replace","bulkDone","on","abort","$","ui","fancytree","FT","TEST_IMG","RegExp","REX_HTML","REX_TOOLTIP","ENTITY_MAP","IGNORE_KEYCODES","16","17","18","SPECIAL_KEYCODES","8","9","10","13","19","20","27","32","33","34","35","36","37","38","39","40","45","46","59","61","96","97","98","99","100","101","102","103","104","105","106","107","109","110","111","112","113","114","115","116","117","118","119","120","121","122","123","144","145","173","186","187","188","189","190","191","192","219","220","221","222","MODIFIERS","91","93","MOUSE_BUTTONS","0","1","2","3","CLASS_ATTRS","split","CLASS_ATTR_MAP","TREE_ATTRS","NODE_ATTRS","NODE_ATTR_MAP","NODE_ATTR_LOWERCASE_MAP","NONE_NODE_DATA_MAP","active","children","focus","toLowerCase","_assert","Date","getTime","FancytreeNode","_findDirectChild","ptr","cl","_setChildren","tree","_callHook","addChildren","insertBefore","pos","firstNode","origFirstChild","getFirstChild","origLastChild","getLastChild","nodeList","isPlainObject","inArray","apply","render","renderStatus","ul","tr","options","selectMode","fixSelection3FromEndNodes","triggerModifyChild","className","toggleClass","addNode","node","undefined","getParent","getNextSibling","addPagingNode","title","moreData","statusNodeType","icon","partload","removeChild","appendSibling","applyCommand","cmd","opts","applyPatch","patch","_getResolvedPromise","v","IGNORE_MAP","expanded","isFunction","removeChildren","isVisible","renderTitle","setExpanded","collapseSiblings","copyTo","map","toDict","countChildren","deep","debug","debugLevel","Array","arguments","toString","consoleApply","discard","warn","resetLazy","discardMarkup","includeSelf","fn","findAll","match","_makeNodeTitleMatcher","visit","findFirst","findRelatedNode","where","includeHidden","_changeSelectStatusAttrs","changed","unselectable","evalOption","unselectableStatus","selected","partsel","fixSelection3AfterClick","callOpts","flag","isSelected","radiogroup","_walk","child","allSelected","someSelected","unselState","lazy","visitParents","fromDict","dict","getChildren","hasChildren","getIndex","getIndexHier","separator","digits","each","getParentList","substr","join","getKeyPath","excludeSelf","sep","keyPathSeparator","getPath","getLevel","level","dtn","ac","includeRoot","part","path","isFunc","getPrevSibling","getSelectedNodes","stopOnParents","isStatusNode","hasClass","extraClasses","hasFocus","focusNode","info","isActive","activeNode","isBelowOf","otherNode","isChildOf","isDescendantOf","isExpanded","isFirstSibling","isFolder","folder","isLastSibling","isLazy","isLoaded","isLoading","_isLoading","isRoot","isRootNode","isPartsel","isPartload","rootNode","isPagingNode","isTopLevel","isUndefined","hasFilter","enableFilter","parents","subMatchCount","lazyLoad","load","forceReload","source","wasExpanded","_triggerNodeEvent","makeVisible","deferreds","dfd","len","effects","noAnimation","scroll","scrollIntoView","when","promise","moveTo","targetNode","prevParent","targetParent","navigate","activate","KC","keyCode","LEFT","RIGHT","e","setFocus","setActive","childNode","force","replaceWith","scheduleAction","ms","timer","clearTimeout","setTimeout","x","Error","duration","queue","scrollOfs","scrollParent","topNode","$scrollParent","$container","overflowY","jquery","tbody","body","topNodeY","nodeY","containerOffsetTop","nodeHeight","span","height","topOfs","top","bottomOfs","bottom","containerHeight","scrollTop","$animateTarget","isParentWindow","newScrollTop","offset","Math","max","innerHeight","clientHeight","resolveWith","complete","stop","animate","setSelected","setStatus","message","details","setTitle","triggerModify","sortChildren","cmp","b","y","sort","recursive","callback","classNames","wasAdded","statusElem","statusClassPropName","curClasses","trim","toggleExpanded","toggleSelected","operation","extra","modifyChild","visitAndLoad","_recursion","loaders","reject","then","visitSiblings","Fancytree","_makeHookContext","obj","originalEvent","ctx","widget","typeInfo","types","funcName","contextObject","_extraArgs","args","slice","_setExpiringValue","_tempCache","expire","_getExpiringValue","entry","_usesExtension","extensions","_requireExtension","required","before","thisName","_local","extList","isBefore","isMissing","ext","badOrder","activateKey","getNodeByKey","opts_","refNode","getActiveNode","editCreateNode","editStart","patchList","p2","patchCount","deferredList","_makeResolveFunc","clear","destroy","enable","disable","enableUpdate","_enableUpdate","expandAll","findNextNode","startNode","reMatch","_checkNode","test","visitRows","BACKSPACE","HOME","END","UP","reverse","DOWN","generateFormElements","selectedName","_id","activeName","$result","_appender","checked","empty","insertAfter","idx","getFocusNode","getOption","optionName","option","searchRoot","el","idPrefix","ftnode","getRootNode","_hasFocus","_requestId","loadKeyPath","keyPathList","optsOrCallback","pathSegList","notifyWith","matchKey","isArray","charAt","_loadKeyPathImpl","nodeKey","remain","remainMap","tmpParent","segList","subDfd","__findChild","__lazyload","errMsg","rejectWith","reactivate","noFocus","reload","selectAll","setOption","debugTime","label","console","time","debugTimeEnd","timeEnd","_trigger","result","_triggerTreeEvent","_visitRowsUp","siblings","siblingOfs","skipFirstNode","checkFilter","nodeClick","expand","targetType","focusOnSelect","clickFolderMode","nodeSetFocus","nodeCollapseSiblings","nodeDblclick","preventDefault","nodeKeydown","matchNode","stamp","event","which","String","fromCharCode","specialModifiers","altKey","ctrlKey","metaKey","isAlnum","$target","target","handled","autoActivate","quicksearch","is","lastQuicksearchTime","lastQuicksearchTerm","eventToString","nodeSetExpanded","nodeToggleSelected","nodeSetActive","nodeLoadChildren","delay","requestId","debugDelay","random","round","textStatus","jqXHR","errorObj","postProcess","enableAspx","parseJSON","errorThrown","catch","reason","nodeSetStatus","ctxErr","metaData","noDataRes","nodata","nodeLoadKeyPath","nodeRemoveChild","subCtx","nodeRemoveChildren","nodeRemoveMarkup","nodeRemoveChildMarkup","li","nodeRenderStatus","nodeRender","collapsed","_recursive","childLI","childNode1","childNode2","next","aria","firstTime","successorLi","parentNode","nextSibling","createElement","generateIds","appendChild","nodeRenderTitle","createNode","renderNode","style","display","$div","firstChild","checkbox","nodeTitle","role","tooltip","iconTooltip","ares","minExpandLevel","iconClass","_escapeTooltip","imagePath","escapeHtml","titlesTabbable","escapeTitles","innerHTML","enhanceTitle","$title","$ariaElem","isLastSib","cn","_classNames","cnList","focused","Boolean","lastsib","loading","_error","statusNodePrefix","combinedExpanderPrefix","combinedIconPrefix","noEvents","_getRejectedPromise","activeVisible","_afterLoad","prevAC","autoCollapse","lastChild","autoScroll","effect","toggleEffect","animating","toggle","ctx2","isInput","calledByNode","uniqueId","activeElement","nodeSetSelected","_lastSelectIntent","lastSelectedNode","_setStatusNode","_clearStatusNode","loadError","noData","nodeToggleExpanded","treeClear","treeCreate","treeDestroy","$source","treeInit","tabindex","checkboxAutoHide","rtl","treeLoad","$ul","element","rootCtx","not","first","parseHtml","_getElementDataAsDict","treeRegisterNode","add","treeSetFocus","_lastMousedownNode","treeSetOption","callDefault","callCreate","callRender","_super","Widget","_setOption","treeStructureChanged","cache","disabled","keyboard","treeId","radio","_deprecationWarning","_create","extension","extName","_extensions","_simpleDeepMerge","_subclassObject","base","icons","tabbable","_init","_bind","_destroy","_unbind","_ns","off","getNode","prevPhase","phase","et","getEventTarget","getTree","version","buildType","_nextId","_nextNodeKey","_FancytreeClass","_FancytreeNodeClass","jquerySupports","positionMyOfs","dottedVersion","major","minor","verParts","testParts","isVersionAtLeast","assert","cond","createTree","$tree","debounce","invokeAsap","fixPositionOptions","my","at","myParts","exec","atParts","dx","dy","tcn","closest","getEventTargetType","orgEl","eq","Element","HTMLDocument","nodeObject","treeOptions","defaultValue","treeOpt","nodeOpt","setSpanIcon","baseClass","$span","shiftKey","keyEventToString","overrideMethod","instance","methodName","handler","context","prevSuper","noop","classes","iPos","tmp","tmp2","$children","allData","lowerCaseAttr","$li","$liSpan","$liA","href","search","substring","registerExtension","definition","unescapeHtml","childNodes","nodeValue","method","src","copy","clone","_makeVirtualFunction","prevFunc","baseFunc","_superApply","prevLocal","prevSuperApply","attrName","argArray","$el","json","uiFancytree","unselectableIgnore","hideCheckbox","defaultKey","lazyload","loaderror","fx","removeNode","columns","systemFocusElement","viewport","ariaPropName","nodeContainerAttrName","fakeParent","class","appendTo","includes","require","init","units","abs","u","toFixed","num","decimals","sign","pow","resetSettings","xhr","XMLHttpRequest","open","setRequestHeader","onload","JSON","parse","location","smush_url","send","get_smush_status","remove_element","fadeTo","slideUp","process_smush_action","currentButton","smushAction","params","c_element","opacity","disable_links","post","enable_links","run_re_check","process_settings","blur","scan_type","notices","get_ui","wp_smush_options_nonce","resmush_ids","count_image","content","after","slideDown","super_smush","enable_lossy","super_smush_stats","resmush_complete","resmush_check","reCheckMessage","goToByScroll","selector","prop","slide_symbol","slideToggle","links","not_processed","current_button","otherClass","setting_type","setting_input","serialize","submit","checking","container","smush_percent","progress_bar","savings_dir_smush","orig_size","image_size","remainingCountDiv","scroll_and_enable_resize","scroll_and_enable_lossy","hash","setting_hash","dataset","click","keypress","wrapper_div","width_only","height_only","resize_checkbox","width_input","width_error_note","height_input","height_error_note","width_error","height_error","resize_sizes","validate_resize_settings","settings_wrap","notice_wrap","warning_wrap","membership_valid","membership_invalid","wp_smush_run_re_check","dir_smush","ajax_error","stats_human","stats_percent","human","combined_stats","c_stats","total_count","update_cummulative_stats","prepend","keyup","modal","SUI","dialogs","bulkWarning","ignored","onboarding","membership","onboardingModal","scanFilesModal","settings","last","slide","selection","auto","lossy","strip_exif","original","lazy_load","usage","contentContainer","onboardingSlides","touchX","touchY","renderTemplate","skipButton","querySelector","addEventListener","skipSetup","openModal","handleTouchStart","firstTouch","touches","clientX","clientY","handleTouchMove","xUp","yUp","xDiff","yDiff","directionClass","input","template","bindSubmit","submitButton","showScanDialog","stringify","whereTo","newIndex","contains","goTo","closeModal","elem","_","memoize","compiled","evaluate","interpolate","escape","variable","templateSettings","orig","uuid","widgetUuid","widgetSlice","cleanData","elems","events","_data","triggerHandler","existingConstructor","constructor","basePrototype","proxiedPrototype","namespace","fullName","expr","_createWidget","_proto","_childConstructors","returnValue","__super","__superApply","widgetEventPrefix","widgetName","widgetFullName","childPrototype","bridge","inputIndex","inputLength","isMethodCall","methodValue","pushStack","defaultElement","eventNamespace","bindings","hoverable","focusable","classesElementLookup","_on","ownerDocument","defaultView","parentWindow","_getCreateOptions","_setOptionDisabled","_getCreateEventData","that","_removeClass","removeData","parts","curOption","pop","_setOptions","_setOptionClasses","classKey","elements","currentElements","_classes","keys","_toggleClass","full","processClassString","checkOption","current","unique","_untrackClassesElement","_addClass","suppressDisabledCheck","handlers","delegateElement","handlerProxy","guid","eventName","_off","_delay","_hoverable","mouseenter","currentTarget","mouseleave","_focusable","focusin","focusout","Event","trigger","isDefaultPrevented","defaultEffect","hasOptions","effectName","easing","cachedScrollbarWidth","rhorizontal","rvertical","roffset","rposition","rpercent","_position","position","getOffsets","offsets","parseFloat","parseCss","getDimensions","raw","left","isWindow","scrollLeft","pageY","pageX","outerWidth","outerHeight","scrollbarWidth","w1","w2","div","innerDiv","offsetWidth","clientWidth","getScrollInfo","within","overflowX","isDocument","hasOverflowX","scrollWidth","scrollHeight","getWithinInfo","withinElement","of","atOffset","targetWidth","targetHeight","targetOffset","basePosition","dimensions","scrollInfo","collision","horizontalOffset","verticalOffset","collisionPosition","using","elemWidth","elemHeight","marginLeft","marginTop","collisionWidth","collisionHeight","myOffset","dir","props","right","feedback","horizontal","vertical","important","fit","newOverRight","withinOffset","collisionPosLeft","overLeft","overRight","newOverBottom","collisionPosTop","overTop","overBottom","flip","newOverLeft","offsetLeft","newOverTop","offsetTop","flipfit","COMMA","DELETE","ENTER","ESCAPE","PAGE_DOWN","PAGE_UP","PERIOD","SPACE","TAB","excludeStaticParent","overflowRegex","removeUniqueId","CDN","cdnEnableButton","cdnDisableButton","cdnStatsBox","loader","toggle_cdn","updateStatsBox","getElementsByName","showNotice","toggleElements","spinner","querySelectorAll","Lazyload","lazyloadEnableButton","lazyloadDisableButton","offsetHeight","toggle_lazy_load","removeSpinner","removeLoaderIcon","removePlaceholder","items","forEach","addLoaderIcon","frame","wp","media","multiple","attachment","toJSON","imageIcon","backgroundImage","setAttribute","removeDiv","filename","restore","currentStep","totalSteps","resetModalWidth","maxWidth","confirmButton","initScan","cancel","updateProgressBar","min","statusDiv","step","item","thumb","link","elNotice","btnAct","removeNotice","notifyWordpress","fadeIn","DirectoryScanner","cancelling","failedItems","scan","remainingSteps","getProgress","onFinishStep","progress_smushed","directory","onFinish","directory_url","limitReached","dialog","bulk_resume","resume","failed","progressDialog","currentScanStep","scanner","Scanner","initFileTree","unbind","selectedFolders","absPath","paths","smush_path","image_list_nonce","showProgressDialog","smushButton","ajaxSettings","list_nonce","entries","Promise","add_dir","loadChildren","select"],"mappings":"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","file":"smush-admin.min.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 12);\n","/* global WP_Smush */\n/* global ajaxurl */\n/* global wp_smushit_data */\n\nlet perf = 0;\n\n/**\n * Smush class.\n *\n * @since 2.9.0  Moved from admin.js into a dedicated ES6 class.\n */\nclass Smush {\n\t/**\n\t * Class constructor.\n\t *\n\t * @param {Object}  button  Button object that made the call.\n\t * @param {boolean} bulk    Bulk smush or not.\n\t * @param {string}  type    Accepts: 'nextgen', 'media'.\n\t */\n\tconstructor( button, bulk, type = 'media' ) {\n\t\t// TODO: errors will reset after bulk smush limit is reached and user clicks continue.\n\t\tthis.errors = [];\n\t\t// Smushed and total we take from the progress bar... I don't like this :-(\n\t\tconst progressBar = jQuery( '.bulk-smush-wrapper .sui-progress-state-text' );\n\t\tthis.smushed = parseInt( progressBar.find( 'span:first-child' ).html() );\n\t\tthis.total = parseInt( progressBar.find( 'span:last-child' ).html() );\n\n\t\t//If smush attribute is not defined, Need not skip re-Smush IDs.\n\t\tthis.skip_resmush = ! ( 'undefined' === typeof button.data( 'smush' ) || ! button.data( 'smush' ) );\n\t\tthis.button = jQuery( button[ 0 ] );\n\t\tthis.is_bulk = typeof bulk ? bulk : false;\n\t\tthis.url = ajaxurl;\n\t\tthis.log = jQuery( '.smush-final-log' );\n\t\tthis.deferred = jQuery.Deferred();\n\t\tthis.deferred.errors = [];\n\n\t\tconst ids = 0 < wp_smushit_data.resmush.length && ! this.skip_resmush ? ( wp_smushit_data.unsmushed.length > 0 ? wp_smushit_data.resmush.concat( wp_smushit_data.unsmushed ) : wp_smushit_data.resmush ) : wp_smushit_data.unsmushed;\n\t\tif ( 'object' === typeof ids ) {\n\t\t\t// If button has re-Smush class, and we do have ids that needs to re-Smushed, put them in the list.\n\t\t\tthis.ids = ids.filter( function( itm, i, a ) {\n\t\t\t\treturn i === a.indexOf( itm );\n\t\t\t} );\n\t\t} else {\n\t\t\tthis.ids = ids;\n\t\t}\n\n\t\tthis.is_bulk_resmush = 0 < wp_smushit_data.resmush.length && ! this.skip_resmush;\n\t\tthis.status = this.button.parent().prev( '.smush-status' );\n\n\t\t// Added for NextGen support.\n\t\tthis.smush_type = type;\n\t\tthis.single_ajax_suffix = 'nextgen' === this.smush_type ? 'smush_manual_nextgen' : 'wp_smushit_manual';\n\t\tthis.bulk_ajax_suffix = 'nextgen' === this.smush_type ? 'wp_smushit_nextgen_bulk' : 'wp_smushit_bulk';\n\t\tthis.url = this.is_bulk ? Smush.smushAddParams( this.url, { action: this.bulk_ajax_suffix } ) : Smush.smushAddParams( this.url, { action: this.single_ajax_suffix } );\n\n\t\tthis.start();\n\t\tthis.run();\n\t\tthis.bindDeferredEvents();\n\n\t\t// Handle cancel ajax.\n\t\tthis.cancelAjax();\n\n\t\treturn this.deferred;\n\t}\n\n\t/**\n\t * Add params to the URL.\n\t *\n\t * @param {string} url   URL to add the params to.\n\t * @param {Object} data  Object with params.\n\t * @return {string}  URL with params.\n\t */\n\tstatic smushAddParams( url, data ) {\n\t\tif ( ! jQuery.isEmptyObject( data ) ) {\n\t\t\turl += ( url.indexOf( '?' ) >= 0 ? '&' : '?' ) + jQuery.param( data );\n\t\t}\n\n\t\treturn url;\n\t}\n\n\t/**\n\t * Check membership validity.\n\t *\n\t * @param {Object} data\n\t * @param {number} data.show_warning\n\t */\n\tstatic membershipValidity( data ) {\n\t\tconst memberValidityNotice = jQuery( '#wp-smush-invalid-member' );\n\n\t\t// Check for membership warning.\n\t\tif ( 'undefined' !== typeof data && 'undefined' !== typeof data.show_warning && memberValidityNotice.length > 0 ) {\n\t\t\tif ( data.show_warning ) {\n\t\t\t\tmemberValidityNotice.show();\n\t\t\t} else {\n\t\t\t\tmemberValidityNotice.hide();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Send Ajax request for compressing the image.\n\t *\n\t * @param {boolean} isBulkResmush\n\t * @param {number}  id\n\t * @param {string}  sendUrl\n\t * @param {string}  nonce\n\t * @return {*|jQuery.promise|void}  Compression results.\n\t */\n\tstatic ajax( isBulkResmush, id, sendUrl, nonce ) {\n\t\tconst param = jQuery.param( {\n\t\t\tis_bulk_resmush: isBulkResmush,\n\t\t\tattachment_id: id,\n\t\t\t_nonce: nonce,\n\t\t} );\n\n\t\treturn jQuery.ajax( {\n\t\t\ttype: 'GET',\n\t\t\tdata: param,\n\t\t\turl: sendUrl,\n\t\t\t/** @param {Array} wp_smushit_data */\n\t\t\ttimeout: wp_smushit_data.timeout,\n\t\t\tdataType: 'json',\n\t\t} );\n\t}\n\n\t/**\n\t * Show loader in button for single and bulk Smush.\n\t */\n\tstart() {\n\t\tthis.button.attr( 'disabled', 'disabled' );\n\t\tthis.button.addClass( 'wp-smush-started' );\n\n\t\tthis.bulkStart();\n\t\tthis.singleStart();\n\t}\n\n\t/**\n\t * Start bulk Smush.\n\t */\n\tbulkStart() {\n\t\tif ( ! this.is_bulk ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Hide the bulk div.\n\t\tjQuery( '.wp-smush-bulk-wrapper' ).hide();\n\n\t\t// Remove any global notices if there.\n\t\tjQuery( '.sui-notice-top' ).remove();\n\n\t\t// Hide the bulk limit message.\n\t\tjQuery( '.wp-smush-bulk-progress-bar-wrapper .sui-notice-warning:first-of-type' ).hide();\n\n\t\t// Hide parent wrapper, if there are no other messages.\n\t\tif ( 0 >= jQuery( 'div.smush-final-log .smush-bulk-error-row' ).length ) {\n\t\t\tjQuery( 'div.smush-final-log' ).hide();\n\t\t}\n\n\t\t// Show the progress bar.\n\t\tjQuery( '.bulk-smush-wrapper .wp-smush-bulk-progress-bar-wrapper' ).show();\n\t}\n\n\t/**\n\t * Start single image Smush.\n\t */\n\tsingleStart() {\n\t\tif ( this.is_bulk ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.button.html( '<span class=\"spinner wp-smush-progress\">' + window.wp_smush_msgs.smushing + '</span>' );\n\t\tthis.status.removeClass( 'error' );\n\t}\n\n\t/**\n\t * Enable button.\n\t */\n\tenableButton() {\n\t\tthis.button.removeAttr( 'disabled' );\n\t\t// For bulk process, enable other buttons.\n\t\tjQuery( '.wp-smush-all' ).removeAttr( 'disabled' );\n\t\tjQuery( 'button.wp-smush-scan, a.wp-smush-lossy-enable, button.wp-smush-resize-enable, button#wp-smush-save-settings' ).removeAttr( 'disabled' );\n\t}\n\n\t/**\n\t * Finish single image Smush.\n\t */\n\tsingleDone() {\n\t\tif ( this.is_bulk ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst self = this;\n\n\t\tthis.button.html( window.wp_smush_msgs.all_done );\n\n\t\tthis.request.done( function( response ) {\n\t\t\tif ( 'undefined' !== typeof response.data ) {\n\t\t\t\t// Check if stats div exists.\n\t\t\t\tconst parent = self.status.parent();\n\n\t\t\t\t// Check whether to show membership validity notice or not.\n\t\t\t\tSmush.membershipValidity( response.data );\n\n\t\t\t\tif ( ! response.success ) {\n\t\t\t\t\tself.status.addClass( 'error' );\n\t\t\t\t\t/** @param {string} response.data.error_msg */\n\t\t\t\t\tself.status.html( response.data.error_msg );\n\t\t\t\t\tself.button.html( window.smush_vars.strings.stats_label );\n\t\t\t\t} else {\n\t\t\t\t\t// If we've updated status, replace the content.\n\t\t\t\t\tparent.html( response.data );\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * Update image size in attachment info panel.\n\t\t\t\t *\n\t\t\t\t * @param {string|number} response.data.new_size\n\t\t\t\t */\n\t\t\t\tSmush.updateImageStats( response.data.new_size );\n\t\t\t}\n\t\t\tself.enableButton();\n\t\t} ).fail( function( response ) {\n\t\t\tself.status.html( response.data );\n\t\t\tself.status.addClass( 'error' );\n\t\t\tself.enableButton();\n\t\t} );\n\t}\n\n\t/**\n\t * Set pro savings stats if not premium user.\n\t *\n\t * For non-premium users, show expected average savings based\n\t * on the free version savings.\n\t */\n\tstatic setProSavings() {\n\t\t// Default values.\n\t\tlet savings = wp_smushit_data.savings_percent > 0 ? wp_smushit_data.savings_percent : 0,\n\t\t\tsavingsBytes = wp_smushit_data.savings_bytes > 0 ? wp_smushit_data.savings_bytes : 0,\n\t\t\torigDiff = 2.22058824;\n\n\t\tif ( savings > 49 ) {\n\t\t\torigDiff = 1.22054412;\n\t\t}\n\n\t\t// Calculate Pro savings.\n\t\tif ( savings > 0 ) {\n\t\t\tsavings = origDiff * savings;\n\t\t\tsavingsBytes = origDiff * savingsBytes;\n\t\t}\n\n\t\twp_smushit_data.pro_savings = {\n\t\t\tpercent: WP_Smush.helpers.precise_round( savings, 1 ),\n\t\t\tsavings_bytes: WP_Smush.helpers.formatBytes( savingsBytes, 1 ),\n\t\t};\n\t}\n\n\t/**\n\t * Update all stats sections based on the response.\n\t *\n\t * @param {string} scanType Current scan type.\n\t */\n\tstatic updateStats( scanType ) {\n\t\tconst isNextgen = 'undefined' !== typeof scanType && 'nextgen' === scanType;\n\t\tlet superSavings = 0;\n\n\t\t// Calculate updated savings in bytes.\n\t\twp_smushit_data.savings_bytes = parseInt( wp_smushit_data.size_before ) - parseInt( wp_smushit_data.size_after );\n\n\t\tconst formattedSize = WP_Smush.helpers.formatBytes( wp_smushit_data.savings_bytes, 1 );\n\t\tconst statsHuman = jQuery( '.wp-smush-savings .wp-smush-stats-human' );\n\n\t\tif ( isNextgen ) {\n\t\t\tstatsHuman.html( formattedSize );\n\t\t} else {\n\t\t\tstatsHuman.html( WP_Smush.helpers.getFormatFromString( formattedSize ) );\n\t\t\tjQuery( '.sui-summary-large.wp-smush-stats-human' ).html( WP_Smush.helpers.getSizeFromString( formattedSize ) );\n\t\t}\n\n\t\t// Update the savings percent.\n\t\twp_smushit_data.savings_percent = WP_Smush.helpers.precise_round( ( parseInt( wp_smushit_data.savings_bytes ) / parseInt( wp_smushit_data.size_before ) ) * 100, 1 );\n\t\tif ( ! isNaN( wp_smushit_data.savings_percent ) ) {\n\t\t\tjQuery( '.wp-smush-savings .wp-smush-stats-percent' ).html( wp_smushit_data.savings_percent );\n\t\t}\n\n\t\t// Super-Smush savings.\n\t\tif ( 'undefined' !== typeof wp_smushit_data.savings_bytes && 'undefined' !== typeof wp_smushit_data.savings_resize ) {\n\t\t\tsuperSavings = parseInt( wp_smushit_data.savings_bytes ) - parseInt( wp_smushit_data.savings_resize );\n\t\t\tif ( superSavings > 0 ) {\n\t\t\t\tjQuery( 'li.super-smush-attachments span.smushed-savings' ).html( WP_Smush.helpers.formatBytes( superSavings, 1 ) );\n\t\t\t}\n\t\t}\n\n\t\t// Update image count.\n\t\tif ( isNextgen ) {\n\t\t\tjQuery( '.sui-summary-details span.wp-smush-total-optimised' ).html( wp_smushit_data.count_images );\n\t\t} else {\n\t\t\tjQuery( 'span.smushed-items-count span.wp-smush-count-total span.wp-smush-total-optimised' ).html( wp_smushit_data.count_images );\n\t\t}\n\n\t\t// Update resize image count.\n\t\tjQuery( 'span.smushed-items-count span.wp-smush-count-resize-total span.wp-smush-total-optimised' ).html( wp_smushit_data.count_resize );\n\n\t\t// Update super-Smushed image count.\n\t\tconst smushedCountDiv = jQuery( 'li.super-smush-attachments .smushed-count' );\n\t\tif ( smushedCountDiv.length && 'undefined' !== typeof wp_smushit_data.count_supersmushed ) {\n\t\t\tsmushedCountDiv.html( wp_smushit_data.count_supersmushed );\n\t\t}\n\n\t\t// Update conversion savings.\n\t\tconst smushConversionSavings = jQuery( '.smush-conversion-savings' );\n\t\tif ( smushConversionSavings.length > 0 && 'undefined' !== typeof ( wp_smushit_data.savings_conversion ) && wp_smushit_data.savings_conversion !== '' ) {\n\t\t\tconst conversionSavings = smushConversionSavings.find( '.wp-smush-stats' );\n\t\t\tif ( conversionSavings.length > 0 ) {\n\t\t\t\tconversionSavings.html( WP_Smush.helpers.formatBytes( wp_smushit_data.savings_conversion, 1 ) );\n\t\t\t}\n\t\t}\n\n\t\t// Update resize savings.\n\t\tconst smushResizeSavings = jQuery( '.smush-resize-savings' );\n\t\tif ( smushResizeSavings.length > 0 && 'undefined' !== typeof ( wp_smushit_data.savings_resize ) && wp_smushit_data.savings_resize !== '' ) {\n\t\t\t// Get the resize savings in number.\n\t\t\tconst savingsValue = parseInt( wp_smushit_data.savings_resize );\n\t\t\tconst resizeSavings = smushResizeSavings.find( '.wp-smush-stats' );\n\t\t\tconst resizeMessage = smushResizeSavings.find( '.wp-smush-stats-label-message' );\n\t\t\t// Replace only if value is grater than 0.\n\t\t\tif ( savingsValue > 0 && resizeSavings.length > 0 ) {\n\t\t\t\t// Hide message.\n\t\t\t\tif ( resizeMessage.length > 0 ) {\n\t\t\t\t\tresizeMessage.hide();\n\t\t\t\t}\n\t\t\t\tresizeSavings.html( WP_Smush.helpers.formatBytes( wp_smushit_data.savings_resize, 1 ) );\n\t\t\t}\n\t\t}\n\n\t\t//Update pro Savings\n\t\tSmush.setProSavings();\n\n\t\t// Updating pro savings stats.\n\t\tif ( 'undefined' !== typeof wp_smushit_data.pro_savings ) {\n\t\t\t// Pro stats section.\n\t\t\tconst smushProSavings = jQuery( '.smush-avg-pro-savings' );\n\t\t\tif ( smushProSavings.length > 0 ) {\n\t\t\t\tconst proSavingsPercent = smushProSavings.find( '.wp-smush-stats-percent' );\n\t\t\t\tconst proSavingsBytes = smushProSavings.find( '.wp-smush-stats-human' );\n\t\t\t\tif ( proSavingsPercent.length > 0 && 'undefined' !== typeof wp_smushit_data.pro_savings.percent && wp_smushit_data.pro_savings.percent !== '' ) {\n\t\t\t\t\tproSavingsPercent.html( wp_smushit_data.pro_savings.percent );\n\t\t\t\t}\n\t\t\t\tif ( proSavingsBytes.length > 0 && 'undefined' !== typeof wp_smushit_data.pro_savings.savings_bytes && wp_smushit_data.pro_savings.savings_bytes !== '' ) {\n\t\t\t\t\tproSavingsBytes.html( wp_smushit_data.pro_savings.savings_bytes );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Update remaining count.\n\t\t// Update sidebar count.\n\t\tconst sidenavCountDiv = jQuery( '.smush-sidenav .wp-smush-remaining-count' );\n\t\tif ( sidenavCountDiv.length ) {\n\t\t\tlet count = 0;\n\n\t\t\t// Unsmushed\n\t\t\tif ( 'undefined' !== typeof wp_smushit_data.unsmushed && wp_smushit_data.unsmushed.length > 0 ) {\n\t\t\t\tcount += wp_smushit_data.unsmushed.length;\n\t\t\t}\n\n\t\t\t// Re-smush\n\t\t\tif ( 'undefined' !== typeof wp_smushit_data.resmush && wp_smushit_data.resmush.length > 0 ) {\n\t\t\t\tcount += wp_smushit_data.resmush.length;\n\t\t\t}\n\n\t\t\tif ( count > 0 ) {\n\t\t\t\tsidenavCountDiv.html( count );\n\t\t\t} else {\n\t\t\t\tjQuery( '.sui-summary-smush .smush-stats-icon' ).addClass( 'sui-hidden' );\n\t\t\t\tsidenavCountDiv.removeClass( 'sui-tag sui-tag-warning' ).html( '' );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Update image size in attachment info panel.\n\t *\n\t * @since 2.8\n\t *\n\t * @param {number} newSize\n\t */\n\tstatic updateImageStats( newSize ) {\n\t\tif ( 0 === newSize ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst attachmentSize = jQuery( '.attachment-info .file-size' );\n\t\tconst currentSize = attachmentSize.contents().filter( function() {\n\t\t\treturn this.nodeType === 3;\n\t\t} ).text();\n\n\t\t// There is a space before the size.\n\t\tif ( currentSize !== ( ' ' + newSize ) ) {\n\t\t\tconst sizeStrongEl = attachmentSize.contents().filter( function() {\n\t\t\t\treturn this.nodeType === 1;\n\t\t\t} ).text();\n\t\t\tattachmentSize.html( '<strong>' + sizeStrongEl + '</strong> ' + newSize );\n\t\t}\n\t}\n\n\t/**\n\t * Sync stats.\n\t */\n\tsyncStats() {\n\t\tconst messageHolder = jQuery( 'div.wp-smush-bulk-progress-bar-wrapper div.wp-smush-count.tc' );\n\t\t// Store the existing content in a variable.\n\t\tconst progressMessage = messageHolder.html();\n\t\t/** @param {string} wp_smush_msgs.sync_stats */\n\t\tmessageHolder.html( window.wp_smush_msgs.sync_stats );\n\n\t\t// Send ajax.\n\t\tjQuery.ajax( {\n\t\t\ttype: 'GET',\n\t\t\turl: this.url,\n\t\t\tdata: {\n\t\t\t\taction: 'get_stats',\n\t\t\t},\n\t\t\tsuccess( response ) {\n\t\t\t\tif ( response && 'undefined' !== typeof response ) {\n\t\t\t\t\tresponse = response.data;\n\t\t\t\t\tjQuery.extend( wp_smushit_data, {\n\t\t\t\t\t\tcount_images: response.count_images,\n\t\t\t\t\t\tcount_smushed: response.count_smushed,\n\t\t\t\t\t\tcount_total: response.count_total,\n\t\t\t\t\t\tcount_resize: response.count_resize,\n\t\t\t\t\t\tcount_supersmushed: response.count_supersmushed,\n\t\t\t\t\t\tsavings_bytes: response.savings_bytes,\n\t\t\t\t\t\tsavings_conversion: response.savings_conversion,\n\t\t\t\t\t\tsavings_resize: response.savings_resize,\n\t\t\t\t\t\tsize_before: response.size_before,\n\t\t\t\t\t\tsize_after: response.size_after,\n\t\t\t\t\t} );\n\t\t\t\t\t// Got the stats, update it.\n\t\t\t\t\tSmush.updateStats( this.smush_type );\n\t\t\t\t}\n\t\t\t},\n\t\t} ).always( () => messageHolder.html( progressMessage ) );\n\t}\n\n\t/**\n\t * After the bulk optimization has been finished.\n\t */\n\tbulkDone() {\n\t\tif ( ! this.is_bulk ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Enable the button.\n\t\tthis.enableButton();\n\n\t\tconst statusIcon = jQuery( '.sui-summary-smush .smush-stats-icon' );\n\n\t\t// Show notice.\n\t\tif ( 0 === this.ids.length ) {\n\t\t\tstatusIcon.addClass( 'sui-hidden' );\n\t\t\tjQuery( '.bulk-smush-wrapper .wp-smush-all-done, .wp-smush-pagespeed-recommendation' ).show();\n\t\t\tjQuery( '.wp-smush-bulk-wrapper' ).hide();\n\t\t\t// Hide the progress bar if scan is finished.\n\t\t\tjQuery( '.wp-smush-bulk-progress-bar-wrapper' ).hide();\n\t\t} else {\n\t\t\t// Show loader.\n\t\t\tstatusIcon.removeClass( 'sui-icon-loader sui-loading sui-hidden' ).addClass( 'sui-icon-info sui-warning' );\n\n\t\t\tconst notice = jQuery( '.bulk-smush-wrapper .wp-smush-resmush-notice' );\n\n\t\t\tif ( notice.length > 0 ) {\n\t\t\t\tnotice.show();\n\t\t\t} else {\n\t\t\t\tjQuery( '.bulk-smush-wrapper .wp-smush-remaining' ).show();\n\t\t\t}\n\t\t}\n\n\t\t// Enable re-Smush and scan button.\n\t\tjQuery( '.wp-resmush.wp-smush-action, .wp-smush-scan' ).removeAttr( 'disabled' );\n\t}\n\n\t/**\n\t * Free Smush limit exceeded.\n\t */\n\tfreeExceeded() {\n\t\tconst progress = jQuery( '.wp-smush-bulk-progress-bar-wrapper' );\n\t\tprogress.addClass( 'wp-smush-exceed-limit' );\n\t\tprogress.find( '.sui-progress-block .wp-smush-cancel-bulk' ).addClass( 'sui-hidden' );\n\t\tprogress.find( '.sui-progress-block .wp-smush-all' ).removeClass( 'sui-hidden' );\n\n\t\tprogress.find( 'i.sui-icon-loader' ).addClass( 'sui-icon-info' )\n\t\t\t.removeClass( 'sui-icon-loader' )\n\t\t\t.removeClass( 'sui-loading' );\n\n\t\tdocument.getElementById( 'bulk-smush-resume-button' ).classList.remove( 'sui-hidden' );\n\t}\n\n\t/**\n\t * Update remaining count.\n\t */\n\tupdateRemainingCount() {\n\t\tif ( this.is_bulk_resmush ) {\n\t\t\t// Re-Smush notice.\n\t\t\tconst resumeCountDiv = jQuery( '.wp-smush-resmush-notice .wp-smush-remaining-count' );\n\t\t\tif ( resumeCountDiv.length && 'undefined' !== typeof this.ids ) {\n\t\t\t\tresumeCountDiv.html( this.ids.length );\n\t\t\t}\n\t\t} else {\n\t\t\t// Smush notice.\n\t\t\tconst wrapperCountDiv = jQuery( '.bulk-smush-wrapper .wp-smush-remaining-count' );\n\t\t\tif ( wrapperCountDiv.length && 'undefined' !== typeof this.ids ) {\n\t\t\t\twrapperCountDiv.html( this.ids.length );\n\t\t\t}\n\t\t}\n\n\t\t// Update sidebar count.\n\t\tconst sidenavCountDiv = jQuery( '.smush-sidenav .wp-smush-remaining-count' );\n\t\tif ( sidenavCountDiv.length && 'undefined' !== typeof this.ids ) {\n\t\t\tif ( this.ids.length > 0 ) {\n\t\t\t\tsidenavCountDiv.html( this.ids.length );\n\t\t\t} else {\n\t\t\t\tjQuery( '.sui-summary-smush .smush-stats-icon' ).addClass( 'sui-hidden' );\n\t\t\t\tsidenavCountDiv.removeClass( 'sui-tag sui-tag-warning' ).html( '' );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Adds the stats for the current image to existing stats.\n\t *\n\t * @param {Array}   imageStats\n\t * @param {string}  imageStats.count\n\t * @param {boolean} imageStats.is_lossy\n\t * @param {Array}   imageStats.savings_resize\n\t * @param {Array}   imageStats.savings_conversion\n\t * @param {string}  imageStats.size_before\n\t * @param {string}  imageStats.size_after\n\t * @param {string}  type\n\t */\n\tstatic updateLocalizedStats( imageStats, type ) {\n\t\t// Increase the Smush count.\n\t\tif ( 'undefined' === typeof window.wp_smushit_data ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// No need to increase attachment count, resize, conversion savings for directory Smush.\n\t\tif ( 'media' === type ) {\n\t\t\t// Increase Smushed image count.\n\t\t\twp_smushit_data.count_images = parseInt( wp_smushit_data.count_images ) + parseInt( imageStats.count );\n\n\t\t\t// Increase super Smush count, if applicable.\n\t\t\tif ( imageStats.is_lossy ) {\n\t\t\t\twp_smushit_data.count_supersmushed = parseInt( wp_smushit_data.count_supersmushed ) + 1;\n\t\t\t}\n\n\t\t\t// Add to resize savings.\n\t\t\twp_smushit_data.savings_resize = 'undefined' !== typeof imageStats.savings_resize.bytes ? parseInt( wp_smushit_data.savings_resize ) + parseInt( imageStats.savings_resize.bytes ) : parseInt( wp_smushit_data.savings_resize );\n\n\t\t\t// Update resize count.\n\t\t\twp_smushit_data.count_resize = 'undefined' !== typeof imageStats.savings_resize.bytes ? parseInt( wp_smushit_data.count_resize ) + 1 : wp_smushit_data.count_resize;\n\n\t\t\t// Add to conversion savings.\n\t\t\twp_smushit_data.savings_conversion = 'undefined' !== typeof imageStats.savings_conversion && 'undefined' !== typeof imageStats.savings_conversion.bytes ? parseInt( wp_smushit_data.savings_conversion ) + parseInt( imageStats.savings_conversion.bytes ) : parseInt( wp_smushit_data.savings_conversion );\n\t\t} else if ( 'directory_smush' === type ) {\n\t\t\t//Increase smushed image count\n\t\t\twp_smushit_data.count_images = parseInt( wp_smushit_data.count_images ) + 1;\n\t\t} else if ( 'nextgen' === type ) {\n\t\t\twp_smushit_data.count_supersmushed = parseInt( wp_smushit_data.count_supersmushed ) + 1;\n\n\t\t\t// Increase Smushed image count.\n\t\t\twp_smushit_data.count_images = parseInt( wp_smushit_data.count_images ) + parseInt( imageStats.count );\n\t\t}\n\n\t\t// If we have savings. Update savings.\n\t\tif ( imageStats.size_before > imageStats.size_after ) {\n\t\t\twp_smushit_data.size_before = 'undefined' !== typeof imageStats.size_before ? parseInt( wp_smushit_data.size_before ) + parseInt( imageStats.size_before ) : parseInt( wp_smushit_data.size_before );\n\t\t\twp_smushit_data.size_after = 'undefined' !== typeof imageStats.size_after ? parseInt( wp_smushit_data.size_after ) + parseInt( imageStats.size_after ) : parseInt( wp_smushit_data.size_after );\n\t\t}\n\n\t\t// Add stats for resizing. Update savings.\n\t\tif ( 'undefined' !== typeof imageStats.savings_resize ) {\n\t\t\twp_smushit_data.size_before = 'undefined' !== typeof imageStats.savings_resize.size_before ? parseInt( wp_smushit_data.size_before ) + parseInt( imageStats.savings_resize.size_before ) : parseInt( wp_smushit_data.size_before );\n\t\t\twp_smushit_data.size_after = 'undefined' !== typeof imageStats.savings_resize.size_after ? parseInt( wp_smushit_data.size_after ) + parseInt( imageStats.savings_resize.size_after ) : parseInt( wp_smushit_data.size_after );\n\t\t}\n\n\t\t// Add stats for conversion. Update savings.\n\t\tif ( 'undefined' !== typeof imageStats.savings_conversion ) {\n\t\t\twp_smushit_data.size_before = 'undefined' !== typeof imageStats.savings_conversion.size_before ? parseInt( wp_smushit_data.size_before ) + parseInt( imageStats.savings_conversion.size_before ) : parseInt( wp_smushit_data.size_before );\n\t\t\twp_smushit_data.size_after = 'undefined' !== typeof imageStats.savings_conversion.size_after ? parseInt( wp_smushit_data.size_after ) + parseInt( imageStats.savings_conversion.size_after ) : parseInt( wp_smushit_data.size_after );\n\t\t}\n\t}\n\n\t/**\n\t * Update progress.\n\t *\n\t * @param {Object} _res\n\t */\n\tupdateProgress( _res ) {\n\t\tif ( ! this.is_bulk_resmush && ! this.is_bulk ) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet progress = 0;\n\n\t\t// Update localized stats.\n\t\tif ( _res && ( 'undefined' !== typeof _res.data && 'undefined' !== typeof _res.data.stats ) ) {\n\t\t\tSmush.updateLocalizedStats( _res.data.stats, this.smush_type );\n\t\t}\n\n\t\tif ( ! this.is_bulk_resmush ) {\n\t\t\t// Handle progress for normal bulk smush.\n\t\t\tprogress = ( ( this.smushed + this.errors.length ) / this.total ) * 100;\n\t\t} else {\n\t\t\t// If the request was successful, update the progress bar.\n\t\t\tif ( _res.success ) {\n\t\t\t\t// Handle progress for super Smush progress bar.\n\t\t\t\tif ( wp_smushit_data.resmush.length > 0 ) {\n\t\t\t\t\t// Update the count.\n\t\t\t\t\tjQuery( '.wp-smush-images-remaining' ).html( wp_smushit_data.resmush.length );\n\t\t\t\t} else if ( 0 === wp_smushit_data.resmush.length && 0 === this.ids.length ) {\n\t\t\t\t\t// If all images are re-Smushed, show the All Smushed message.\n\t\t\t\t\tjQuery( '.bulk-resmush-wrapper .wp-smush-all-done, .wp-smush-pagespeed-recommendation' ).removeClass( 'sui-hidden' );\n\n\t\t\t\t\t// Hide everything else.\n\t\t\t\t\tjQuery( '.wp-smush-resmush-wrap, .wp-smush-bulk-progress-bar-wrapper' ).hide();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle progress for normal bulk Smush. Set progress bar width.\n\t\t\tif ( 'undefined' !== typeof this.ids && 'undefined' !== typeof this.total && this.total > 0 ) {\n\t\t\t\tprogress = ( ( this.smushed + this.errors.length ) / this.total ) * 100;\n\t\t\t}\n\t\t}\n\n\t\t// No more images left. Show bulk wrapper and Smush notice.\n\t\tif ( 0 === this.ids.length ) {\n\t\t\t// Sync stats for bulk Smush media library ( skip for Nextgen ).\n\t\t\tif ( 'nextgen' !== this.smush_type ) {\n\t\t\t\tthis.syncStats();\n\t\t\t}\n\t\t\tjQuery( '.bulk-smush-wrapper .wp-smush-all-done, .wp-smush-pagespeed-recommendation' ).show();\n\t\t\tjQuery( '.wp-smush-bulk-wrapper' ).hide();\n\t\t}\n\n\t\t// Update remaining count.\n\t\tthis.updateRemainingCount();\n\n\t\t// Increase the progress bar and counter.\n\t\tthis._updateProgress( this.smushed + this.errors.length, WP_Smush.helpers.precise_round( progress, 1 ) );\n\n\t\t// Update stats and counts.\n\t\tSmush.updateStats( this.smush_type );\n\t}\n\n\t/**\n\t * Update progress.\n\t *\n\t * @param {number} count  Number of images optimized.\n\t * @param {string} width  Percentage complete.\n\t * @private\n\t */\n\t_updateProgress( count, width ) {\n\t\tif ( ! this.is_bulk && ! this.is_bulk_resmush ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Progress bar label.\n\t\tjQuery( 'span.wp-smush-images-percent' ).html( width + '%' );\n\t\t// Progress bar.\n\t\tjQuery( '.bulk-smush-wrapper .wp-smush-progress-inner' ).css( 'width', width + '%' );\n\n\t\t// Progress bar status.\n\t\tjQuery( '.bulk-smush-wrapper .sui-progress-state-text' )\n\t\t\t.find( 'span:first-child' ).html( count )\n\t\t\t.find( 'span:last-child' ).html( this.total );\n\t}\n\n\t/**\n\t * Whether to send the ajax requests further or not.\n\t *\n\t * @return {*|boolean}  Should continue or not.\n\t */\n\tcontinue() {\n\t\tlet continueSmush = this.button.attr( 'continue_smush' );\n\n\t\tif ( 'undefined' === typeof continueSmush ) {\n\t\t\tcontinueSmush = true;\n\t\t}\n\n\t\tif ( 'false' === continueSmush || ! continueSmush ) {\n\t\t\tcontinueSmush = false;\n\t\t}\n\n\t\treturn continueSmush && this.ids.length > 0 && this.is_bulk;\n\t}\n\n\t/**\n\t * Send ajax request for optimizing single and bulk, call update_progress on ajax response.\n\t *\n\t * @return {*}  Ajax call response.\n\t */\n\tcallAjax() {\n\t\t/**\n\t\t * This here little piece of code allows to track auto continue clicks and halts bulk Smush until the page\n\t\t * is reloaded.\n\t\t *\n\t\t * @since 3.5.0\n\t\t * @see https://wordpress.org/plugins/wp-nonstop-smushit/\n\t\t */\n\t\tif ( 0 !== perf && 'undefined' !== typeof perf && 10 > performance.now() - perf ) {\n\t\t\tthis.freeExceeded();\n\t\t\treturn this.deferred;\n\t\t}\n\n\t\tlet nonceValue = '';\n\t\t// Remove from array while processing so we can continue where left off.\n\t\tthis.current_id = this.is_bulk ? this.ids.shift() : this.button.data( 'id' );\n\n\t\t// Remove the ID from respective variable as well.\n\t\tSmush.updateSmushIds( this.current_id );\n\n\t\tconst nonceField = this.button.parent().find( '#_wp_smush_nonce' );\n\t\tif ( nonceField ) {\n\t\t\tnonceValue = nonceField.val();\n\t\t}\n\n\t\tconst self = this;\n\n\t\tthis.request = Smush.ajax( this.is_bulk_resmush, this.current_id, this.url, nonceValue )\n\t\t\t.done( function( res ) {\n\t\t\t\t// If no response or success is false, do not process further. Increase the error count except if bulk request limit exceeded.\n\t\t\t\tif ( 'undefined' === typeof res.success || ( 'undefined' !== typeof res.success && false === res.success && 'undefined' !== typeof res.data && 'limit_exceeded' !== res.data.error ) ) {\n\t\t\t\t\tself.errors.push( self.current_id );\n\n\t\t\t\t\t/** @param {string} res.data.file_name */\n\t\t\t\t\tconst errorMsg = Smush.prepareErrorRow( res.data.error_message, res.data.file_name, res.data.thumbnail, self.current_id, self.smush_type );\n\n\t\t\t\t\tself.log.show();\n\n\t\t\t\t\tif ( self.errors.length > 5 ) {\n\t\t\t\t\t\tjQuery( '.smush-bulk-errors-actions' ).removeClass( 'sui-hidden' );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Print the error on screen.\n\t\t\t\t\t\tself.log.find( '.smush-bulk-errors' ).append( errorMsg );\n\t\t\t\t\t}\n\t\t\t\t} else if ( 'undefined' !== typeof res.success && res.success ) {\n\t\t\t\t\t// Increment the smushed count if image smushed without errors.\n\t\t\t\t\tself.smushed++;\n\t\t\t\t}\n\n\t\t\t\t// Check whether to show the warning notice or not.\n\t\t\t\tSmush.membershipValidity( res.data );\n\n\t\t\t\t/**\n\t\t\t\t * Bulk Smush limit exceeded: Stop ajax requests, remove progress bar, append the last image ID\n\t\t\t\t * back to Smush variable, and reset variables to allow the user to continue bulk Smush.\n\t\t\t\t */\n\t\t\t\tif ( 'undefined' !== typeof res.data && 'limit_exceeded' === res.data.error && 'resolved' !== self.deferred.state() ) {\n\t\t\t\t\t// Show error message.\n\t\t\t\t\tconst bulkWarning = document.getElementById( 'bulk_smush_warning' );\n\t\t\t\t\tbulkWarning.classList.remove( 'sui-hidden' );\n\n\t\t\t\t\t// Add a data attribute to the Smush button, to stop sending ajax.\n\t\t\t\t\tself.button.attr( 'continue_smush', false );\n\n\t\t\t\t\t// Reinsert the current ID.\n\t\t\t\t\twp_smushit_data.unsmushed.unshift( self.current_id );\n\t\t\t\t\tself.ids.unshift( self.current_id );\n\n\t\t\t\t\tperf = performance.now();\n\t\t\t\t\tself.freeExceeded();\n\t\t\t\t} else if ( self.is_bulk ) {\n\t\t\t\t\tself.updateProgress( res );\n\t\t\t\t} else if ( 0 === self.ids.length ) {\n\t\t\t\t\t// Sync stats anyway.\n\t\t\t\t\tself.syncStats();\n\t\t\t\t}\n\n\t\t\t\tself.singleDone();\n\t\t\t} )\n\t\t\t.always( function() {\n\t\t\t\tif ( ! self.continue() || ! self.is_bulk ) {\n\t\t\t\t\t// Calls deferred.done()\n\t\t\t\t\tself.deferred.resolve();\n\t\t\t\t} else {\n\t\t\t\t\tself.callAjax();\n\t\t\t\t}\n\t\t\t} );\n\n\t\tthis.deferred.errors = this.errors;\n\t\treturn this.deferred;\n\t}\n\n\t/**\n\t * Prepare error row. Will only allow to hide errors for WP media attachments (not nextgen).\n\t *\n\t * @since 1.9.0\n\t *\n\t * @param {string} errorMsg   Error message.\n\t * @param {string} fileName   File name.\n\t * @param {string} thumbnail  Thumbnail for image (if available).\n\t * @param {number} id         Image ID.\n\t * @param {string} type       Smush type: media or netxgen.\n\t *\n\t * @return {string}  Row with error.\n\t */\n\tstatic prepareErrorRow( errorMsg, fileName, thumbnail, id, type ) {\n\t\tconst thumbDiv = ( 'undefined' === typeof thumbnail ) ? '<i class=\"sui-icon-photo-picture\" aria-hidden=\"true\"></i>' : thumbnail;\n\t\tconst fileLink = ( 'undefined' === fileName || 'undefined' === typeof fileName ) ? 'undefined' : fileName;\n\n\t\tlet tableDiv =\n\t\t\t'<div class=\"smush-bulk-error-row\">' +\n\t\t\t\t'<div class=\"smush-bulk-image-data\">' + thumbDiv +\n\t\t\t\t\t'<span class=\"smush-image-name\">' + fileLink + '</span>' +\n\t\t\t\t\t'<span class=\"smush-image-error\">' + errorMsg + '</span>' +\n\t\t\t\t'</div>';\n\n\t\tif ( 'media' === type ) {\n\t\t\ttableDiv = tableDiv +\n\t\t\t\t'<div class=\"smush-bulk-image-actions\">' +\n\t\t\t\t\t'<button type=\"button\" class=\"sui-button-icon sui-tooltip sui-tooltip-constrained sui-tooltip-top-right smush-ignore-image\" data-tooltip=\"' + window.wp_smush_msgs.error_ignore + '\" data-id=\"' + id + '\">' +\n\t\t\t\t\t\t'<i class=\"sui-icon-eye-hide\" aria-hidden=\"true\"></i>' +\n\t\t\t\t\t'</button>' +\n\t\t\t\t'</div>';\n\t\t}\n\n\t\ttableDiv = tableDiv + '</div>';\n\n\t\treturn tableDiv;\n\t}\n\n\t/**\n\t * Send ajax request for single and bulk Smushing.\n\t */\n\trun() {\n\t\t// If bulk and we have a definite number of IDs.\n\t\tif ( this.is_bulk && this.ids.length > 0 ) {\n\t\t\tthis.callAjax();\n\t\t}\n\n\t\tif ( ! this.is_bulk ) {\n\t\t\tthis.callAjax();\n\t\t}\n\t}\n\n\t/**\n\t * Show bulk Smush errors, and disable bulk Smush button on completion.\n\t */\n\tbindDeferredEvents() {\n\t\tconst self = this;\n\n\t\tthis.deferred.done( function() {\n\t\t\tself.button.removeAttr( 'continue_smush' );\n\n\t\t\tif ( self.errors.length ) {\n\t\t\t\t/** @param {string} wp_smush_msgs.error_in_bulk */\n\t\t\t\tconst msg = window.wp_smush_msgs.error_in_bulk\n\t\t\t\t\t.replace( '{{errors}}', self.errors.length )\n\t\t\t\t\t.replace( '{{total}}', self.total )\n\t\t\t\t\t.replace( '{{smushed}}', self.smushed );\n\n\t\t\t\tjQuery( '.wp-smush-all-done' )\n\t\t\t\t\t.addClass( 'sui-notice-warning' )\n\t\t\t\t\t.removeClass( 'sui-notice-success' )\n\t\t\t\t\t.find( 'p' ).html( msg );\n\t\t\t}\n\n\t\t\tself.bulkDone();\n\n\t\t\t// Re-enable the buttons.\n\t\t\tjQuery( '.wp-smush-all:not(.wp-smush-finished), .wp-smush-scan' ).removeAttr( 'disabled' );\n\t\t} );\n\t}\n\n\t/**\n\t * Handles the cancel button click.\n\t * Update the UI, and enable the bulk Smush button.\n\t */\n\tcancelAjax() {\n\t\tconst self = this;\n\n\t\tjQuery( '.wp-smush-cancel-bulk' ).on( 'click', function() {\n\t\t\t// Add a data attribute to the Smush button, to stop sending ajax.\n\t\t\tself.button.attr( 'continue_smush', false );\n\t\t\t// Sync and update stats.\n\t\t\tself.syncStats();\n\t\t\tSmush.updateStats( this.smush_type );\n\n\t\t\tself.request.abort();\n\t\t\tself.enableButton();\n\t\t\tself.button.removeClass( 'wp-smush-started' );\n\t\t\twp_smushit_data.unsmushed.unshift( self.current_id );\n\t\t\tjQuery( '.wp-smush-bulk-wrapper' ).show();\n\n\t\t\t// Hide the progress bar.\n\t\t\tjQuery( '.wp-smush-bulk-progress-bar-wrapper' ).hide();\n\t\t} );\n\t}\n\n\t/**\n\t * Remove the current ID from the unSmushed/re-Smush variable.\n\t *\n\t * @param {number} currentId\n\t */\n\tstatic updateSmushIds( currentId ) {\n\t\tif ( 'undefined' !== typeof wp_smushit_data.unsmushed && wp_smushit_data.unsmushed.length > 0 ) {\n\t\t\tconst uIndex = wp_smushit_data.unsmushed.indexOf( currentId );\n\t\t\tif ( uIndex > -1 ) {\n\t\t\t\twp_smushit_data.unsmushed.splice( uIndex, 1 );\n\t\t\t}\n\t\t}\n\n\t\t// Remove from the re-Smush list.\n\t\tif ( 'undefined' !== typeof wp_smushit_data.resmush && wp_smushit_data.resmush.length > 0 ) {\n\t\t\tconst index = wp_smushit_data.resmush.indexOf( currentId );\n\t\t\tif ( index > -1 ) {\n\t\t\t\twp_smushit_data.resmush.splice( index, 1 );\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport default Smush;\n","module.exports = jQuery;","/*!\n * jquery.fancytree.js\n * Tree view control with support for lazy loading and much more.\n * https://github.com/mar10/fancytree/\n *\n * Copyright (c) 2008-2019, Martin Wendt (https://wwWendt.de)\n * Released under the MIT license\n * https://github.com/mar10/fancytree/wiki/LicenseInfo\n *\n * @version 2.34.0\n * @date 2019-12-26T14:16:19Z\n */\n\n/** Core Fancytree module.\n */\n\n// UMD wrapper for the Fancytree core module\n(function(factory) {\n\tif (typeof define === \"function\" && define.amd) {\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine([\"jquery\", \"./jquery.fancytree.ui-deps\"], factory);\n\t} else if (typeof module === \"object\" && module.exports) {\n\t\t// Node/CommonJS\n\t\trequire(\"./jquery.fancytree.ui-deps\");\n\t\tmodule.exports = factory(require(\"jquery\"));\n\t} else {\n\t\t// Browser globals\n\t\tfactory(jQuery);\n\t}\n})(function($) {\n\t\"use strict\";\n\n\t// prevent duplicate loading\n\tif ($.ui && $.ui.fancytree) {\n\t\t$.ui.fancytree.warn(\"Fancytree: ignored duplicate include\");\n\t\treturn;\n\t}\n\n\t/******************************************************************************\n\t * Private functions and variables\n\t */\n\n\tvar i,\n\t\tattr,\n\t\tFT = null, // initialized below\n\t\tTEST_IMG = new RegExp(/\\.|\\//), // strings are considered image urls if they contain '.' or '/'\n\t\tREX_HTML = /[&<>\"'/]/g, // Escape those characters\n\t\tREX_TOOLTIP = /[<>\"'/]/g, // Don't escape `&` in tooltips\n\t\tRECURSIVE_REQUEST_ERROR = \"$recursive_request\",\n\t\t// CLIPBOARD = null,\n\t\tENTITY_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\"'\": \"&#39;\",\n\t\t\t\"/\": \"&#x2F;\",\n\t\t},\n\t\tIGNORE_KEYCODES = { 16: true, 17: true, 18: true },\n\t\tSPECIAL_KEYCODES = {\n\t\t\t8: \"backspace\",\n\t\t\t9: \"tab\",\n\t\t\t10: \"return\",\n\t\t\t13: \"return\",\n\t\t\t// 16: null, 17: null, 18: null,  // ignore shift, ctrl, alt\n\t\t\t19: \"pause\",\n\t\t\t20: \"capslock\",\n\t\t\t27: \"esc\",\n\t\t\t32: \"space\",\n\t\t\t33: \"pageup\",\n\t\t\t34: \"pagedown\",\n\t\t\t35: \"end\",\n\t\t\t36: \"home\",\n\t\t\t37: \"left\",\n\t\t\t38: \"up\",\n\t\t\t39: \"right\",\n\t\t\t40: \"down\",\n\t\t\t45: \"insert\",\n\t\t\t46: \"del\",\n\t\t\t59: \";\",\n\t\t\t61: \"=\",\n\t\t\t// 91: null, 93: null,  // ignore left and right meta\n\t\t\t96: \"0\",\n\t\t\t97: \"1\",\n\t\t\t98: \"2\",\n\t\t\t99: \"3\",\n\t\t\t100: \"4\",\n\t\t\t101: \"5\",\n\t\t\t102: \"6\",\n\t\t\t103: \"7\",\n\t\t\t104: \"8\",\n\t\t\t105: \"9\",\n\t\t\t106: \"*\",\n\t\t\t107: \"+\",\n\t\t\t109: \"-\",\n\t\t\t110: \".\",\n\t\t\t111: \"/\",\n\t\t\t112: \"f1\",\n\t\t\t113: \"f2\",\n\t\t\t114: \"f3\",\n\t\t\t115: \"f4\",\n\t\t\t116: \"f5\",\n\t\t\t117: \"f6\",\n\t\t\t118: \"f7\",\n\t\t\t119: \"f8\",\n\t\t\t120: \"f9\",\n\t\t\t121: \"f10\",\n\t\t\t122: \"f11\",\n\t\t\t123: \"f12\",\n\t\t\t144: \"numlock\",\n\t\t\t145: \"scroll\",\n\t\t\t173: \"-\",\n\t\t\t186: \";\",\n\t\t\t187: \"=\",\n\t\t\t188: \",\",\n\t\t\t189: \"-\",\n\t\t\t190: \".\",\n\t\t\t191: \"/\",\n\t\t\t192: \"`\",\n\t\t\t219: \"[\",\n\t\t\t220: \"\\\\\",\n\t\t\t221: \"]\",\n\t\t\t222: \"'\",\n\t\t},\n\t\tMODIFIERS = {\n\t\t\t16: \"shift\",\n\t\t\t17: \"ctrl\",\n\t\t\t18: \"alt\",\n\t\t\t91: \"meta\",\n\t\t\t93: \"meta\",\n\t\t},\n\t\tMOUSE_BUTTONS = { 0: \"\", 1: \"left\", 2: \"middle\", 3: \"right\" },\n\t\t// Boolean attributes that can be set with equivalent class names in the LI tags\n\t\t// Note: v2.23: checkbox and hideCheckbox are *not* in this list\n\t\tCLASS_ATTRS = \"active expanded focus folder lazy radiogroup selected unselectable unselectableIgnore\".split(\n\t\t\t\" \"\n\t\t),\n\t\tCLASS_ATTR_MAP = {},\n\t\t// Top-level Fancytree attributes, that can be set by dict\n\t\tTREE_ATTRS = \"columns types\".split(\" \"),\n\t\t// TREE_ATTR_MAP = {},\n\t\t// Top-level FancytreeNode attributes, that can be set by dict\n\t\tNODE_ATTRS = \"checkbox expanded extraClasses folder icon iconTooltip key lazy partsel radiogroup refKey selected statusNodeType title tooltip type unselectable unselectableIgnore unselectableStatus\".split(\n\t\t\t\" \"\n\t\t),\n\t\tNODE_ATTR_MAP = {},\n\t\t// Mapping of lowercase -> real name (because HTML5 data-... attribute only supports lowercase)\n\t\tNODE_ATTR_LOWERCASE_MAP = {},\n\t\t// Attribute names that should NOT be added to node.data\n\t\tNONE_NODE_DATA_MAP = {\n\t\t\tactive: true,\n\t\t\tchildren: true,\n\t\t\tdata: true,\n\t\t\tfocus: true,\n\t\t};\n\n\tfor (i = 0; i < CLASS_ATTRS.length; i++) {\n\t\tCLASS_ATTR_MAP[CLASS_ATTRS[i]] = true;\n\t}\n\tfor (i = 0; i < NODE_ATTRS.length; i++) {\n\t\tattr = NODE_ATTRS[i];\n\t\tNODE_ATTR_MAP[attr] = true;\n\t\tif (attr !== attr.toLowerCase()) {\n\t\t\tNODE_ATTR_LOWERCASE_MAP[attr.toLowerCase()] = attr;\n\t\t}\n\t}\n\t// for(i=0; i<TREE_ATTRS.length; i++) {\n\t// \tTREE_ATTR_MAP[TREE_ATTRS[i]] = true;\n\t// }\n\n\tfunction _assert(cond, msg) {\n\t\t// TODO: see qunit.js extractStacktrace()\n\t\tif (!cond) {\n\t\t\tmsg = msg ? \": \" + msg : \"\";\n\t\t\t// consoleApply(\"assert\", [!!cond, msg]);\n\t\t\t$.error(\"Fancytree assertion failed\" + msg);\n\t\t}\n\t}\n\n\t_assert($.ui, \"Fancytree requires jQuery UI (http://jqueryui.com)\");\n\n\tfunction consoleApply(method, args) {\n\t\tvar i,\n\t\t\ts,\n\t\t\tfn = window.console ? window.console[method] : null;\n\n\t\tif (fn) {\n\t\t\ttry {\n\t\t\t\tfn.apply(window.console, args);\n\t\t\t} catch (e) {\n\t\t\t\t// IE 8?\n\t\t\t\ts = \"\";\n\t\t\t\tfor (i = 0; i < args.length; i++) {\n\t\t\t\t\ts += args[i];\n\t\t\t\t}\n\t\t\t\tfn(s);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* support: IE8 Polyfil for Date.now() */\n\tif (!Date.now) {\n\t\tDate.now = function now() {\n\t\t\treturn new Date().getTime();\n\t\t};\n\t}\n\n\t/*Return true if x is a FancytreeNode.*/\n\tfunction _isNode(x) {\n\t\treturn !!(x.tree && x.statusNodeType !== undefined);\n\t}\n\n\t/** Return true if dotted version string is equal or higher than requested version.\n\t *\n\t * See http://jsfiddle.net/mar10/FjSAN/\n\t */\n\tfunction isVersionAtLeast(dottedVersion, major, minor, patch) {\n\t\tvar i,\n\t\t\tv,\n\t\t\tt,\n\t\t\tverParts = $.map($.trim(dottedVersion).split(\".\"), function(e) {\n\t\t\t\treturn parseInt(e, 10);\n\t\t\t}),\n\t\t\ttestParts = $.map(\n\t\t\t\tArray.prototype.slice.call(arguments, 1),\n\t\t\t\tfunction(e) {\n\t\t\t\t\treturn parseInt(e, 10);\n\t\t\t\t}\n\t\t\t);\n\n\t\tfor (i = 0; i < testParts.length; i++) {\n\t\t\tv = verParts[i] || 0;\n\t\t\tt = testParts[i] || 0;\n\t\t\tif (v !== t) {\n\t\t\t\treturn v > t;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Deep-merge a list of objects (but replace array-type options).\n\t *\n\t * jQuery's $.extend(true, ...) method does a deep merge, that also merges Arrays.\n\t * This variant is used to merge extension defaults with user options, and should\n\t * merge objects, but override arrays (for example the `triggerStart: [...]` option\n\t * of ext-edit). Also `null` values are copied over and not skipped.\n\t *\n\t * See issue #876\n\t *\n\t * Example:\n\t * _simpleDeepMerge({}, o1, o2);\n\t */\n\tfunction _simpleDeepMerge() {\n\t\tvar options,\n\t\t\tname,\n\t\t\tsrc,\n\t\t\tcopy,\n\t\t\tclone,\n\t\t\ttarget = arguments[0] || {},\n\t\t\ti = 1,\n\t\t\tlength = arguments.length;\n\n\t\t// Handle case when target is a string or something (possible in deep copy)\n\t\tif (typeof target !== \"object\" && !$.isFunction(target)) {\n\t\t\ttarget = {};\n\t\t}\n\t\tif (i === length) {\n\t\t\tthrow Error(\"need at least two args\");\n\t\t}\n\t\tfor (; i < length; i++) {\n\t\t\t// Only deal with non-null/undefined values\n\t\t\tif ((options = arguments[i]) != null) {\n\t\t\t\t// Extend the base object\n\t\t\t\tfor (name in options) {\n\t\t\t\t\tif (options.hasOwnProperty(name)) {\n\t\t\t\t\t\tsrc = target[name];\n\t\t\t\t\t\tcopy = options[name];\n\t\t\t\t\t\t// Prevent never-ending loop\n\t\t\t\t\t\tif (target === copy) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Recurse if we're merging plain objects\n\t\t\t\t\t\t// (NOTE: unlike $.extend, we don't merge arrays, but replace them)\n\t\t\t\t\t\tif (copy && $.isPlainObject(copy)) {\n\t\t\t\t\t\t\tclone = src && $.isPlainObject(src) ? src : {};\n\t\t\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\t\t\ttarget[name] = _simpleDeepMerge(clone, copy);\n\t\t\t\t\t\t\t// Don't bring in undefined values\n\t\t\t\t\t\t} else if (copy !== undefined) {\n\t\t\t\t\t\t\ttarget[name] = copy;\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\t\t// Return the modified object\n\t\treturn target;\n\t}\n\n\t/** Return a wrapper that calls sub.methodName() and exposes\n\t *  this             : tree\n\t *  this._local      : tree.ext.EXTNAME\n\t *  this._super      : base.methodName.call()\n\t *  this._superApply : base.methodName.apply()\n\t */\n\tfunction _makeVirtualFunction(methodName, tree, base, extension, extName) {\n\t\t// $.ui.fancytree.debug(\"_makeVirtualFunction\", methodName, tree, base, extension, extName);\n\t\t// if(rexTestSuper && !rexTestSuper.test(func)){\n\t\t//     // extension.methodName() doesn't call _super(), so no wrapper required\n\t\t//     return func;\n\t\t// }\n\t\t// Use an immediate function as closure\n\t\tvar proxy = (function() {\n\t\t\tvar prevFunc = tree[methodName], // org. tree method or prev. proxy\n\t\t\t\tbaseFunc = extension[methodName], //\n\t\t\t\t_local = tree.ext[extName],\n\t\t\t\t_super = function() {\n\t\t\t\t\treturn prevFunc.apply(tree, arguments);\n\t\t\t\t},\n\t\t\t\t_superApply = function(args) {\n\t\t\t\t\treturn prevFunc.apply(tree, args);\n\t\t\t\t};\n\n\t\t\t// Return the wrapper function\n\t\t\treturn function() {\n\t\t\t\tvar prevLocal = tree._local,\n\t\t\t\t\tprevSuper = tree._super,\n\t\t\t\t\tprevSuperApply = tree._superApply;\n\n\t\t\t\ttry {\n\t\t\t\t\ttree._local = _local;\n\t\t\t\t\ttree._super = _super;\n\t\t\t\t\ttree._superApply = _superApply;\n\t\t\t\t\treturn baseFunc.apply(tree, arguments);\n\t\t\t\t} finally {\n\t\t\t\t\ttree._local = prevLocal;\n\t\t\t\t\ttree._super = prevSuper;\n\t\t\t\t\ttree._superApply = prevSuperApply;\n\t\t\t\t}\n\t\t\t};\n\t\t})(); // end of Immediate Function\n\t\treturn proxy;\n\t}\n\n\t/**\n\t * Subclass `base` by creating proxy functions\n\t */\n\tfunction _subclassObject(tree, base, extension, extName) {\n\t\t// $.ui.fancytree.debug(\"_subclassObject\", tree, base, extension, extName);\n\t\tfor (var attrName in extension) {\n\t\t\tif (typeof extension[attrName] === \"function\") {\n\t\t\t\tif (typeof tree[attrName] === \"function\") {\n\t\t\t\t\t// override existing method\n\t\t\t\t\ttree[attrName] = _makeVirtualFunction(\n\t\t\t\t\t\tattrName,\n\t\t\t\t\t\ttree,\n\t\t\t\t\t\tbase,\n\t\t\t\t\t\textension,\n\t\t\t\t\t\textName\n\t\t\t\t\t);\n\t\t\t\t} else if (attrName.charAt(0) === \"_\") {\n\t\t\t\t\t// Create private methods in tree.ext.EXTENSION namespace\n\t\t\t\t\ttree.ext[extName][attrName] = _makeVirtualFunction(\n\t\t\t\t\t\tattrName,\n\t\t\t\t\t\ttree,\n\t\t\t\t\t\tbase,\n\t\t\t\t\t\textension,\n\t\t\t\t\t\textName\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t$.error(\n\t\t\t\t\t\t\"Could not override tree.\" +\n\t\t\t\t\t\t\tattrName +\n\t\t\t\t\t\t\t\". Use prefix '_' to create tree.\" +\n\t\t\t\t\t\t\textName +\n\t\t\t\t\t\t\t\"._\" +\n\t\t\t\t\t\t\tattrName\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Create member variables in tree.ext.EXTENSION namespace\n\t\t\t\tif (attrName !== \"options\") {\n\t\t\t\t\ttree.ext[extName][attrName] = extension[attrName];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction _getResolvedPromise(context, argArray) {\n\t\tif (context === undefined) {\n\t\t\treturn $.Deferred(function() {\n\t\t\t\tthis.resolve();\n\t\t\t}).promise();\n\t\t}\n\t\treturn $.Deferred(function() {\n\t\t\tthis.resolveWith(context, argArray);\n\t\t}).promise();\n\t}\n\n\tfunction _getRejectedPromise(context, argArray) {\n\t\tif (context === undefined) {\n\t\t\treturn $.Deferred(function() {\n\t\t\t\tthis.reject();\n\t\t\t}).promise();\n\t\t}\n\t\treturn $.Deferred(function() {\n\t\t\tthis.rejectWith(context, argArray);\n\t\t}).promise();\n\t}\n\n\tfunction _makeResolveFunc(deferred, context) {\n\t\treturn function() {\n\t\t\tdeferred.resolveWith(context);\n\t\t};\n\t}\n\n\tfunction _getElementDataAsDict($el) {\n\t\t// Evaluate 'data-NAME' attributes with special treatment for 'data-json'.\n\t\tvar d = $.extend({}, $el.data()),\n\t\t\tjson = d.json;\n\n\t\tdelete d.fancytree; // added to container by widget factory (old jQuery UI)\n\t\tdelete d.uiFancytree; // added to container by widget factory\n\n\t\tif (json) {\n\t\t\tdelete d.json;\n\t\t\t// <li data-json='...'> is already returned as object (http://api.jquery.com/data/#data-html5)\n\t\t\td = $.extend(d, json);\n\t\t}\n\t\treturn d;\n\t}\n\n\tfunction _escapeTooltip(s) {\n\t\treturn (\"\" + s).replace(REX_TOOLTIP, function(s) {\n\t\t\treturn ENTITY_MAP[s];\n\t\t});\n\t}\n\n\t// TODO: use currying\n\tfunction _makeNodeTitleMatcher(s) {\n\t\ts = s.toLowerCase();\n\t\treturn function(node) {\n\t\t\treturn node.title.toLowerCase().indexOf(s) >= 0;\n\t\t};\n\t}\n\n\tfunction _makeNodeTitleStartMatcher(s) {\n\t\tvar reMatch = new RegExp(\"^\" + s, \"i\");\n\t\treturn function(node) {\n\t\t\treturn reMatch.test(node.title);\n\t\t};\n\t}\n\n\t/******************************************************************************\n\t * FancytreeNode\n\t */\n\n\t/**\n\t * Creates a new FancytreeNode\n\t *\n\t * @class FancytreeNode\n\t * @classdesc A FancytreeNode represents the hierarchical data model and operations.\n\t *\n\t * @param {FancytreeNode} parent\n\t * @param {NodeData} obj\n\t *\n\t * @property {Fancytree} tree The tree instance\n\t * @property {FancytreeNode} parent The parent node\n\t * @property {string} key Node id (must be unique inside the tree)\n\t * @property {string} title Display name (may contain HTML)\n\t * @property {object} data Contains all extra data that was passed on node creation\n\t * @property {FancytreeNode[] | null | undefined} children Array of child nodes.<br>\n\t *     For lazy nodes, null or undefined means 'not yet loaded'. Use an empty array\n\t *     to define a node that has no children.\n\t * @property {boolean} expanded Use isExpanded(), setExpanded() to access this property.\n\t * @property {string} extraClasses Additional CSS classes, added to the node's `<span>`.<br>\n\t *     Note: use `node.add/remove/toggleClass()` to modify.\n\t * @property {boolean} folder Folder nodes have different default icons and click behavior.<br>\n\t *     Note: Also non-folders may have children.\n\t * @property {string} statusNodeType null for standard nodes. Otherwise type of special system node: 'error', 'loading', 'nodata', or 'paging'.\n\t * @property {boolean} lazy True if this node is loaded on demand, i.e. on first expansion.\n\t * @property {boolean} selected Use isSelected(), setSelected() to access this property.\n\t * @property {string} tooltip Alternative description used as hover popup\n\t * @property {string} iconTooltip Description used as hover popup for icon. @since 2.27\n\t * @property {string} type Node type, used with tree.types map. @since 2.27\n\t */\n\tfunction FancytreeNode(parent, obj) {\n\t\tvar i, l, name, cl;\n\n\t\tthis.parent = parent;\n\t\tthis.tree = parent.tree;\n\t\tthis.ul = null;\n\t\tthis.li = null; // <li id='key' ftnode=this> tag\n\t\tthis.statusNodeType = null; // if this is a temp. node to display the status of its parent\n\t\tthis._isLoading = false; // if this node itself is loading\n\t\tthis._error = null; // {message: '...'} if a load error occurred\n\t\tthis.data = {};\n\n\t\t// TODO: merge this code with node.toDict()\n\t\t// copy attributes from obj object\n\t\tfor (i = 0, l = NODE_ATTRS.length; i < l; i++) {\n\t\t\tname = NODE_ATTRS[i];\n\t\t\tthis[name] = obj[name];\n\t\t}\n\t\t// unselectableIgnore and unselectableStatus imply unselectable\n\t\tif (\n\t\t\tthis.unselectableIgnore != null ||\n\t\t\tthis.unselectableStatus != null\n\t\t) {\n\t\t\tthis.unselectable = true;\n\t\t}\n\t\tif (obj.hideCheckbox) {\n\t\t\t$.error(\n\t\t\t\t\"'hideCheckbox' node option was removed in v2.23.0: use 'checkbox: false'\"\n\t\t\t);\n\t\t}\n\t\t// node.data += obj.data\n\t\tif (obj.data) {\n\t\t\t$.extend(this.data, obj.data);\n\t\t}\n\t\t// Copy all other attributes to this.data.NAME\n\t\tfor (name in obj) {\n\t\t\tif (\n\t\t\t\t!NODE_ATTR_MAP[name] &&\n\t\t\t\t!$.isFunction(obj[name]) &&\n\t\t\t\t!NONE_NODE_DATA_MAP[name]\n\t\t\t) {\n\t\t\t\t// node.data.NAME = obj.NAME\n\t\t\t\tthis.data[name] = obj[name];\n\t\t\t}\n\t\t}\n\n\t\t// Fix missing key\n\t\tif (this.key == null) {\n\t\t\t// test for null OR undefined\n\t\t\tif (this.tree.options.defaultKey) {\n\t\t\t\tthis.key = this.tree.options.defaultKey(this);\n\t\t\t\t_assert(this.key, \"defaultKey() must return a unique key\");\n\t\t\t} else {\n\t\t\t\tthis.key = \"_\" + FT._nextNodeKey++;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.key = \"\" + this.key; // Convert to string (#217)\n\t\t}\n\n\t\t// Fix tree.activeNode\n\t\t// TODO: not elegant: we use obj.active as marker to set tree.activeNode\n\t\t// when loading from a dictionary.\n\t\tif (obj.active) {\n\t\t\t_assert(\n\t\t\t\tthis.tree.activeNode === null,\n\t\t\t\t\"only one active node allowed\"\n\t\t\t);\n\t\t\tthis.tree.activeNode = this;\n\t\t}\n\t\tif (obj.selected) {\n\t\t\t// #186\n\t\t\tthis.tree.lastSelectedNode = this;\n\t\t}\n\t\t// TODO: handle obj.focus = true\n\n\t\t// Create child nodes\n\t\tcl = obj.children;\n\t\tif (cl) {\n\t\t\tif (cl.length) {\n\t\t\t\tthis._setChildren(cl);\n\t\t\t} else {\n\t\t\t\t// if an empty array was passed for a lazy node, keep it, in order to mark it 'loaded'\n\t\t\t\tthis.children = this.lazy ? [] : null;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.children = null;\n\t\t}\n\t\t// Add to key/ref map (except for root node)\n\t\t//\tif( parent ) {\n\t\tthis.tree._callHook(\"treeRegisterNode\", this.tree, true, this);\n\t\t//\t}\n\t}\n\n\tFancytreeNode.prototype = /** @lends FancytreeNode# */ {\n\t\t/* Return the direct child FancytreeNode with a given key, index. */\n\t\t_findDirectChild: function(ptr) {\n\t\t\tvar i,\n\t\t\t\tl,\n\t\t\t\tcl = this.children;\n\n\t\t\tif (cl) {\n\t\t\t\tif (typeof ptr === \"string\") {\n\t\t\t\t\tfor (i = 0, l = cl.length; i < l; i++) {\n\t\t\t\t\t\tif (cl[i].key === ptr) {\n\t\t\t\t\t\t\treturn cl[i];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (typeof ptr === \"number\") {\n\t\t\t\t\treturn this.children[ptr];\n\t\t\t\t} else if (ptr.parent === this) {\n\t\t\t\t\treturn ptr;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\t// TODO: activate()\n\t\t// TODO: activateSilently()\n\t\t/* Internal helper called in recursive addChildren sequence.*/\n\t\t_setChildren: function(children) {\n\t\t\t_assert(\n\t\t\t\tchildren && (!this.children || this.children.length === 0),\n\t\t\t\t\"only init supported\"\n\t\t\t);\n\t\t\tthis.children = [];\n\t\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\t\tthis.children.push(new FancytreeNode(this, children[i]));\n\t\t\t}\n\t\t\tthis.tree._callHook(\n\t\t\t\t\"treeStructureChanged\",\n\t\t\t\tthis.tree,\n\t\t\t\t\"setChildren\"\n\t\t\t);\n\t\t},\n\t\t/**\n\t\t * Append (or insert) a list of child nodes.\n\t\t *\n\t\t * @param {NodeData[]} children array of child node definitions (also single child accepted)\n\t\t * @param {FancytreeNode | string | Integer} [insertBefore] child node (or key or index of such).\n\t\t *     If omitted, the new children are appended.\n\t\t * @returns {FancytreeNode} first child added\n\t\t *\n\t\t * @see FancytreeNode#applyPatch\n\t\t */\n\t\taddChildren: function(children, insertBefore) {\n\t\t\tvar i,\n\t\t\t\tl,\n\t\t\t\tpos,\n\t\t\t\torigFirstChild = this.getFirstChild(),\n\t\t\t\torigLastChild = this.getLastChild(),\n\t\t\t\tfirstNode = null,\n\t\t\t\tnodeList = [];\n\n\t\t\tif ($.isPlainObject(children)) {\n\t\t\t\tchildren = [children];\n\t\t\t}\n\t\t\tif (!this.children) {\n\t\t\t\tthis.children = [];\n\t\t\t}\n\t\t\tfor (i = 0, l = children.length; i < l; i++) {\n\t\t\t\tnodeList.push(new FancytreeNode(this, children[i]));\n\t\t\t}\n\t\t\tfirstNode = nodeList[0];\n\t\t\tif (insertBefore == null) {\n\t\t\t\tthis.children = this.children.concat(nodeList);\n\t\t\t} else {\n\t\t\t\t// Returns null if insertBefore is not a direct child:\n\t\t\t\tinsertBefore = this._findDirectChild(insertBefore);\n\t\t\t\tpos = $.inArray(insertBefore, this.children);\n\t\t\t\t_assert(pos >= 0, \"insertBefore must be an existing child\");\n\t\t\t\t// insert nodeList after children[pos]\n\t\t\t\tthis.children.splice.apply(\n\t\t\t\t\tthis.children,\n\t\t\t\t\t[pos, 0].concat(nodeList)\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (origFirstChild && !insertBefore) {\n\t\t\t\t// #708: Fast path -- don't render every child of root, just the new ones!\n\t\t\t\t// #723, #729: but only if it's appended to an existing child list\n\t\t\t\tfor (i = 0, l = nodeList.length; i < l; i++) {\n\t\t\t\t\tnodeList[i].render(); // New nodes were never rendered before\n\t\t\t\t}\n\t\t\t\t// Adjust classes where status may have changed\n\t\t\t\t// Has a first child\n\t\t\t\tif (origFirstChild !== this.getFirstChild()) {\n\t\t\t\t\t// Different first child -- recompute classes\n\t\t\t\t\torigFirstChild.renderStatus();\n\t\t\t\t}\n\t\t\t\tif (origLastChild !== this.getLastChild()) {\n\t\t\t\t\t// Different last child -- recompute classes\n\t\t\t\t\torigLastChild.renderStatus();\n\t\t\t\t}\n\t\t\t} else if (!this.parent || this.parent.ul || this.tr) {\n\t\t\t\t// render if the parent was rendered (or this is a root node)\n\t\t\t\tthis.render();\n\t\t\t}\n\t\t\tif (this.tree.options.selectMode === 3) {\n\t\t\t\tthis.fixSelection3FromEndNodes();\n\t\t\t}\n\t\t\tthis.triggerModifyChild(\n\t\t\t\t\"add\",\n\t\t\t\tnodeList.length === 1 ? nodeList[0] : null\n\t\t\t);\n\t\t\treturn firstNode;\n\t\t},\n\t\t/**\n\t\t * Add class to node's span tag and to .extraClasses.\n\t\t *\n\t\t * @param {string} className class name\n\t\t *\n\t\t * @since 2.17\n\t\t */\n\t\taddClass: function(className) {\n\t\t\treturn this.toggleClass(className, true);\n\t\t},\n\t\t/**\n\t\t * Append or prepend a node, or append a child node.\n\t\t *\n\t\t * This a convenience function that calls addChildren()\n\t\t *\n\t\t * @param {NodeData} node node definition\n\t\t * @param {string} [mode=child] 'before', 'after', 'firstChild', or 'child' ('over' is a synonym for 'child')\n\t\t * @returns {FancytreeNode} new node\n\t\t */\n\t\taddNode: function(node, mode) {\n\t\t\tif (mode === undefined || mode === \"over\") {\n\t\t\t\tmode = \"child\";\n\t\t\t}\n\t\t\tswitch (mode) {\n\t\t\t\tcase \"after\":\n\t\t\t\t\treturn this.getParent().addChildren(\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\tthis.getNextSibling()\n\t\t\t\t\t);\n\t\t\t\tcase \"before\":\n\t\t\t\t\treturn this.getParent().addChildren(node, this);\n\t\t\t\tcase \"firstChild\":\n\t\t\t\t\t// Insert before the first child if any\n\t\t\t\t\tvar insertBefore = this.children ? this.children[0] : null;\n\t\t\t\t\treturn this.addChildren(node, insertBefore);\n\t\t\t\tcase \"child\":\n\t\t\t\tcase \"over\":\n\t\t\t\t\treturn this.addChildren(node);\n\t\t\t}\n\t\t\t_assert(false, \"Invalid mode: \" + mode);\n\t\t},\n\t\t/**Add child status nodes that indicate 'More...', etc.\n\t\t *\n\t\t * This also maintains the node's `partload` property.\n\t\t * @param {boolean|object} node optional node definition. Pass `false` to remove all paging nodes.\n\t\t * @param {string} [mode='child'] 'child'|firstChild'\n\t\t * @since 2.15\n\t\t */\n\t\taddPagingNode: function(node, mode) {\n\t\t\tvar i, n;\n\n\t\t\tmode = mode || \"child\";\n\t\t\tif (node === false) {\n\t\t\t\tfor (i = this.children.length - 1; i >= 0; i--) {\n\t\t\t\t\tn = this.children[i];\n\t\t\t\t\tif (n.statusNodeType === \"paging\") {\n\t\t\t\t\t\tthis.removeChild(n);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.partload = false;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tnode = $.extend(\n\t\t\t\t{\n\t\t\t\t\ttitle: this.tree.options.strings.moreData,\n\t\t\t\t\tstatusNodeType: \"paging\",\n\t\t\t\t\ticon: false,\n\t\t\t\t},\n\t\t\t\tnode\n\t\t\t);\n\t\t\tthis.partload = true;\n\t\t\treturn this.addNode(node, mode);\n\t\t},\n\t\t/**\n\t\t * Append new node after this.\n\t\t *\n\t\t * This a convenience function that calls addNode(node, 'after')\n\t\t *\n\t\t * @param {NodeData} node node definition\n\t\t * @returns {FancytreeNode} new node\n\t\t */\n\t\tappendSibling: function(node) {\n\t\t\treturn this.addNode(node, \"after\");\n\t\t},\n\t\t/**\n\t\t * (experimental) Apply a modification (or navigation) operation.\n\t\t *\n\t\t * @param {string} cmd\n\t\t * @param {object} [opts]\n\t\t * @see Fancytree#applyCommand\n\t\t * @since 2.32\n\t\t */\n\t\tapplyCommand: function(cmd, opts) {\n\t\t\treturn this.tree.applyCommand(cmd, this, opts);\n\t\t},\n\t\t/**\n\t\t * Modify existing child nodes.\n\t\t *\n\t\t * @param {NodePatch} patch\n\t\t * @returns {$.Promise}\n\t\t * @see FancytreeNode#addChildren\n\t\t */\n\t\tapplyPatch: function(patch) {\n\t\t\t// patch [key, null] means 'remove'\n\t\t\tif (patch === null) {\n\t\t\t\tthis.remove();\n\t\t\t\treturn _getResolvedPromise(this);\n\t\t\t}\n\t\t\t// TODO: make sure that root node is not collapsed or modified\n\t\t\t// copy (most) attributes to node.ATTR or node.data.ATTR\n\t\t\tvar name,\n\t\t\t\tpromise,\n\t\t\t\tv,\n\t\t\t\tIGNORE_MAP = { children: true, expanded: true, parent: true }; // TODO: should be global\n\n\t\t\tfor (name in patch) {\n\t\t\t\tif (patch.hasOwnProperty(name)) {\n\t\t\t\t\tv = patch[name];\n\t\t\t\t\tif (!IGNORE_MAP[name] && !$.isFunction(v)) {\n\t\t\t\t\t\tif (NODE_ATTR_MAP[name]) {\n\t\t\t\t\t\t\tthis[name] = v;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.data[name] = v;\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\t// Remove and/or create children\n\t\t\tif (patch.hasOwnProperty(\"children\")) {\n\t\t\t\tthis.removeChildren();\n\t\t\t\tif (patch.children) {\n\t\t\t\t\t// only if not null and not empty list\n\t\t\t\t\t// TODO: addChildren instead?\n\t\t\t\t\tthis._setChildren(patch.children);\n\t\t\t\t}\n\t\t\t\t// TODO: how can we APPEND or INSERT child nodes?\n\t\t\t}\n\t\t\tif (this.isVisible()) {\n\t\t\t\tthis.renderTitle();\n\t\t\t\tthis.renderStatus();\n\t\t\t}\n\t\t\t// Expand collapse (final step, since this may be async)\n\t\t\tif (patch.hasOwnProperty(\"expanded\")) {\n\t\t\t\tpromise = this.setExpanded(patch.expanded);\n\t\t\t} else {\n\t\t\t\tpromise = _getResolvedPromise(this);\n\t\t\t}\n\t\t\treturn promise;\n\t\t},\n\t\t/** Collapse all sibling nodes.\n\t\t * @returns {$.Promise}\n\t\t */\n\t\tcollapseSiblings: function() {\n\t\t\treturn this.tree._callHook(\"nodeCollapseSiblings\", this);\n\t\t},\n\t\t/** Copy this node as sibling or child of `node`.\n\t\t *\n\t\t * @param {FancytreeNode} node source node\n\t\t * @param {string} [mode=child] 'before' | 'after' | 'child'\n\t\t * @param {Function} [map] callback function(NodeData) that could modify the new node\n\t\t * @returns {FancytreeNode} new\n\t\t */\n\t\tcopyTo: function(node, mode, map) {\n\t\t\treturn node.addNode(this.toDict(true, map), mode);\n\t\t},\n\t\t/** Count direct and indirect children.\n\t\t *\n\t\t * @param {boolean} [deep=true] pass 'false' to only count direct children\n\t\t * @returns {int} number of child nodes\n\t\t */\n\t\tcountChildren: function(deep) {\n\t\t\tvar cl = this.children,\n\t\t\t\ti,\n\t\t\t\tl,\n\t\t\t\tn;\n\t\t\tif (!cl) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tn = cl.length;\n\t\t\tif (deep !== false) {\n\t\t\t\tfor (i = 0, l = n; i < l; i++) {\n\t\t\t\t\tn += cl[i].countChildren();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn n;\n\t\t},\n\t\t// TODO: deactivate()\n\t\t/** Write to browser console if debugLevel >= 4 (prepending node info)\n\t\t *\n\t\t * @param {*} msg string or object or array of such\n\t\t */\n\t\tdebug: function(msg) {\n\t\t\tif (this.tree.options.debugLevel >= 4) {\n\t\t\t\tArray.prototype.unshift.call(arguments, this.toString());\n\t\t\t\tconsoleApply(\"log\", arguments);\n\t\t\t}\n\t\t},\n\t\t/** Deprecated.\n\t\t * @deprecated since 2014-02-16. Use resetLazy() instead.\n\t\t */\n\t\tdiscard: function() {\n\t\t\tthis.warn(\n\t\t\t\t\"FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead.\"\n\t\t\t);\n\t\t\treturn this.resetLazy();\n\t\t},\n\t\t/** Remove DOM elements for all descendents. May be called on .collapse event\n\t\t * to keep the DOM small.\n\t\t * @param {boolean} [includeSelf=false]\n\t\t */\n\t\tdiscardMarkup: function(includeSelf) {\n\t\t\tvar fn = includeSelf ? \"nodeRemoveMarkup\" : \"nodeRemoveChildMarkup\";\n\t\t\tthis.tree._callHook(fn, this);\n\t\t},\n\t\t/** Write error to browser console if debugLevel >= 1 (prepending tree info)\n\t\t *\n\t\t * @param {*} msg string or object or array of such\n\t\t */\n\t\terror: function(msg) {\n\t\t\tif (this.tree.options.debugLevel >= 1) {\n\t\t\t\tArray.prototype.unshift.call(arguments, this.toString());\n\t\t\t\tconsoleApply(\"error\", arguments);\n\t\t\t}\n\t\t},\n\t\t/**Find all nodes that match condition (excluding self).\n\t\t *\n\t\t * @param {string | function(node)} match title string to search for, or a\n\t\t *     callback function that returns `true` if a node is matched.\n\t\t * @returns {FancytreeNode[]} array of nodes (may be empty)\n\t\t */\n\t\tfindAll: function(match) {\n\t\t\tmatch = $.isFunction(match) ? match : _makeNodeTitleMatcher(match);\n\t\t\tvar res = [];\n\t\t\tthis.visit(function(n) {\n\t\t\t\tif (match(n)) {\n\t\t\t\t\tres.push(n);\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn res;\n\t\t},\n\t\t/**Find first node that matches condition (excluding self).\n\t\t *\n\t\t * @param {string | function(node)} match title string to search for, or a\n\t\t *     callback function that returns `true` if a node is matched.\n\t\t * @returns {FancytreeNode} matching node or null\n\t\t * @see FancytreeNode#findAll\n\t\t */\n\t\tfindFirst: function(match) {\n\t\t\tmatch = $.isFunction(match) ? match : _makeNodeTitleMatcher(match);\n\t\t\tvar res = null;\n\t\t\tthis.visit(function(n) {\n\t\t\t\tif (match(n)) {\n\t\t\t\t\tres = n;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn res;\n\t\t},\n\t\t/** Find a node relative to self.\n\t\t *\n\t\t * @param {number|string} where The keyCode that would normally trigger this move,\n\t\t *\t\tor a keyword ('down', 'first', 'last', 'left', 'parent', 'right', 'up').\n\t\t * @returns {FancytreeNode}\n\t\t * @since v2.31\n\t\t */\n\t\tfindRelatedNode: function(where, includeHidden) {\n\t\t\treturn this.tree.findRelatedNode(this, where, includeHidden);\n\t\t},\n\t\t/* Apply selection state (internal use only) */\n\t\t_changeSelectStatusAttrs: function(state) {\n\t\t\tvar changed = false,\n\t\t\t\topts = this.tree.options,\n\t\t\t\tunselectable = FT.evalOption(\n\t\t\t\t\t\"unselectable\",\n\t\t\t\t\tthis,\n\t\t\t\t\tthis,\n\t\t\t\t\topts,\n\t\t\t\t\tfalse\n\t\t\t\t),\n\t\t\t\tunselectableStatus = FT.evalOption(\n\t\t\t\t\t\"unselectableStatus\",\n\t\t\t\t\tthis,\n\t\t\t\t\tthis,\n\t\t\t\t\topts,\n\t\t\t\t\tundefined\n\t\t\t\t);\n\n\t\t\tif (unselectable && unselectableStatus != null) {\n\t\t\t\tstate = unselectableStatus;\n\t\t\t}\n\t\t\tswitch (state) {\n\t\t\t\tcase false:\n\t\t\t\t\tchanged = this.selected || this.partsel;\n\t\t\t\t\tthis.selected = false;\n\t\t\t\t\tthis.partsel = false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase true:\n\t\t\t\t\tchanged = !this.selected || !this.partsel;\n\t\t\t\t\tthis.selected = true;\n\t\t\t\t\tthis.partsel = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase undefined:\n\t\t\t\t\tchanged = this.selected || !this.partsel;\n\t\t\t\t\tthis.selected = false;\n\t\t\t\t\tthis.partsel = true;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t_assert(false, \"invalid state: \" + state);\n\t\t\t}\n\t\t\t// this.debug(\"fixSelection3AfterLoad() _changeSelectStatusAttrs()\", state, changed);\n\t\t\tif (changed) {\n\t\t\t\tthis.renderStatus();\n\t\t\t}\n\t\t\treturn changed;\n\t\t},\n\t\t/**\n\t\t * Fix selection status, after this node was (de)selected in multi-hier mode.\n\t\t * This includes (de)selecting all children.\n\t\t */\n\t\tfixSelection3AfterClick: function(callOpts) {\n\t\t\tvar flag = this.isSelected();\n\n\t\t\t// this.debug(\"fixSelection3AfterClick()\");\n\n\t\t\tthis.visit(function(node) {\n\t\t\t\tnode._changeSelectStatusAttrs(flag);\n\t\t\t\tif (node.radiogroup) {\n\t\t\t\t\t// #931: don't (de)select this branch\n\t\t\t\t\treturn \"skip\";\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.fixSelection3FromEndNodes(callOpts);\n\t\t},\n\t\t/**\n\t\t * Fix selection status for multi-hier mode.\n\t\t * Only end-nodes are considered to update the descendants branch and parents.\n\t\t * Should be called after this node has loaded new children or after\n\t\t * children have been modified using the API.\n\t\t */\n\t\tfixSelection3FromEndNodes: function(callOpts) {\n\t\t\tvar opts = this.tree.options;\n\n\t\t\t// this.debug(\"fixSelection3FromEndNodes()\");\n\t\t\t_assert(opts.selectMode === 3, \"expected selectMode 3\");\n\n\t\t\t// Visit all end nodes and adjust their parent's `selected` and `partsel`\n\t\t\t// attributes. Return selection state true, false, or undefined.\n\t\t\tfunction _walk(node) {\n\t\t\t\tvar i,\n\t\t\t\t\tl,\n\t\t\t\t\tchild,\n\t\t\t\t\ts,\n\t\t\t\t\tstate,\n\t\t\t\t\tallSelected,\n\t\t\t\t\tsomeSelected,\n\t\t\t\t\tunselIgnore,\n\t\t\t\t\tunselState,\n\t\t\t\t\tchildren = node.children;\n\n\t\t\t\tif (children && children.length) {\n\t\t\t\t\t// check all children recursively\n\t\t\t\t\tallSelected = true;\n\t\t\t\t\tsomeSelected = false;\n\n\t\t\t\t\tfor (i = 0, l = children.length; i < l; i++) {\n\t\t\t\t\t\tchild = children[i];\n\t\t\t\t\t\t// the selection state of a node is not relevant; we need the end-nodes\n\t\t\t\t\t\ts = _walk(child);\n\t\t\t\t\t\t// if( !child.unselectableIgnore ) {\n\t\t\t\t\t\tunselIgnore = FT.evalOption(\n\t\t\t\t\t\t\t\"unselectableIgnore\",\n\t\t\t\t\t\t\tchild,\n\t\t\t\t\t\t\tchild,\n\t\t\t\t\t\t\topts,\n\t\t\t\t\t\t\tfalse\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (!unselIgnore) {\n\t\t\t\t\t\t\tif (s !== false) {\n\t\t\t\t\t\t\t\tsomeSelected = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (s !== true) {\n\t\t\t\t\t\t\t\tallSelected = false;\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\t// eslint-disable-next-line no-nested-ternary\n\t\t\t\t\tstate = allSelected\n\t\t\t\t\t\t? true\n\t\t\t\t\t\t: someSelected\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: false;\n\t\t\t\t} else {\n\t\t\t\t\t// This is an end-node: simply report the status\n\t\t\t\t\tunselState = FT.evalOption(\n\t\t\t\t\t\t\"unselectableStatus\",\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\topts,\n\t\t\t\t\t\tundefined\n\t\t\t\t\t);\n\t\t\t\t\tstate = unselState == null ? !!node.selected : !!unselState;\n\t\t\t\t}\n\t\t\t\t// #939: Keep a `partsel` flag that was explicitly set on a lazy node\n\t\t\t\tif (\n\t\t\t\t\tnode.partsel &&\n\t\t\t\t\t!node.selected &&\n\t\t\t\t\tnode.lazy &&\n\t\t\t\t\tnode.children == null\n\t\t\t\t) {\n\t\t\t\t\tstate = undefined;\n\t\t\t\t}\n\t\t\t\tnode._changeSelectStatusAttrs(state);\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\t_walk(this);\n\n\t\t\t// Update parent's state\n\t\t\tthis.visitParents(function(node) {\n\t\t\t\tvar i,\n\t\t\t\t\tl,\n\t\t\t\t\tchild,\n\t\t\t\t\tstate,\n\t\t\t\t\tunselIgnore,\n\t\t\t\t\tunselState,\n\t\t\t\t\tchildren = node.children,\n\t\t\t\t\tallSelected = true,\n\t\t\t\t\tsomeSelected = false;\n\n\t\t\t\tfor (i = 0, l = children.length; i < l; i++) {\n\t\t\t\t\tchild = children[i];\n\t\t\t\t\tunselIgnore = FT.evalOption(\n\t\t\t\t\t\t\"unselectableIgnore\",\n\t\t\t\t\t\tchild,\n\t\t\t\t\t\tchild,\n\t\t\t\t\t\topts,\n\t\t\t\t\t\tfalse\n\t\t\t\t\t);\n\t\t\t\t\tif (!unselIgnore) {\n\t\t\t\t\t\tunselState = FT.evalOption(\n\t\t\t\t\t\t\t\"unselectableStatus\",\n\t\t\t\t\t\t\tchild,\n\t\t\t\t\t\t\tchild,\n\t\t\t\t\t\t\topts,\n\t\t\t\t\t\t\tundefined\n\t\t\t\t\t\t);\n\t\t\t\t\t\tstate =\n\t\t\t\t\t\t\tunselState == null\n\t\t\t\t\t\t\t\t? !!child.selected\n\t\t\t\t\t\t\t\t: !!unselState;\n\t\t\t\t\t\t// When fixing the parents, we trust the sibling status (i.e.\n\t\t\t\t\t\t// we don't recurse)\n\t\t\t\t\t\tif (state || child.partsel) {\n\t\t\t\t\t\t\tsomeSelected = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!state) {\n\t\t\t\t\t\t\tallSelected = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// eslint-disable-next-line no-nested-ternary\n\t\t\t\tstate = allSelected ? true : someSelected ? undefined : false;\n\t\t\t\tnode._changeSelectStatusAttrs(state);\n\t\t\t});\n\t\t},\n\t\t// TODO: focus()\n\t\t/**\n\t\t * Update node data. If dict contains 'children', then also replace\n\t\t * the hole sub tree.\n\t\t * @param {NodeData} dict\n\t\t *\n\t\t * @see FancytreeNode#addChildren\n\t\t * @see FancytreeNode#applyPatch\n\t\t */\n\t\tfromDict: function(dict) {\n\t\t\t// copy all other attributes to this.data.xxx\n\t\t\tfor (var name in dict) {\n\t\t\t\tif (NODE_ATTR_MAP[name]) {\n\t\t\t\t\t// node.NAME = dict.NAME\n\t\t\t\t\tthis[name] = dict[name];\n\t\t\t\t} else if (name === \"data\") {\n\t\t\t\t\t// node.data += dict.data\n\t\t\t\t\t$.extend(this.data, dict.data);\n\t\t\t\t} else if (\n\t\t\t\t\t!$.isFunction(dict[name]) &&\n\t\t\t\t\t!NONE_NODE_DATA_MAP[name]\n\t\t\t\t) {\n\t\t\t\t\t// node.data.NAME = dict.NAME\n\t\t\t\t\tthis.data[name] = dict[name];\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (dict.children) {\n\t\t\t\t// recursively set children and render\n\t\t\t\tthis.removeChildren();\n\t\t\t\tthis.addChildren(dict.children);\n\t\t\t}\n\t\t\tthis.renderTitle();\n\t\t\t/*\n\t\t\tvar children = dict.children;\n\t\t\tif(children === undefined){\n\t\t\t\tthis.data = $.extend(this.data, dict);\n\t\t\t\tthis.render();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdict = $.extend({}, dict);\n\t\t\tdict.children = undefined;\n\t\t\tthis.data = $.extend(this.data, dict);\n\t\t\tthis.removeChildren();\n\t\t\tthis.addChild(children);\n\t\t\t*/\n\t\t},\n\t\t/** Return the list of child nodes (undefined for unexpanded lazy nodes).\n\t\t * @returns {FancytreeNode[] | undefined}\n\t\t */\n\t\tgetChildren: function() {\n\t\t\tif (this.hasChildren() === undefined) {\n\t\t\t\t// TODO: only required for lazy nodes?\n\t\t\t\treturn undefined; // Lazy node: unloaded, currently loading, or load error\n\t\t\t}\n\t\t\treturn this.children;\n\t\t},\n\t\t/** Return the first child node or null.\n\t\t * @returns {FancytreeNode | null}\n\t\t */\n\t\tgetFirstChild: function() {\n\t\t\treturn this.children ? this.children[0] : null;\n\t\t},\n\t\t/** Return the 0-based child index.\n\t\t * @returns {int}\n\t\t */\n\t\tgetIndex: function() {\n\t\t\t// return this.parent.children.indexOf(this);\n\t\t\treturn $.inArray(this, this.parent.children); // indexOf doesn't work in IE7\n\t\t},\n\t\t/** Return the hierarchical child index (1-based, e.g. '3.2.4').\n\t\t * @param {string} [separator=\".\"]\n\t\t * @param {int} [digits=1]\n\t\t * @returns {string}\n\t\t */\n\t\tgetIndexHier: function(separator, digits) {\n\t\t\tseparator = separator || \".\";\n\t\t\tvar s,\n\t\t\t\tres = [];\n\t\t\t$.each(this.getParentList(false, true), function(i, o) {\n\t\t\t\ts = \"\" + (o.getIndex() + 1);\n\t\t\t\tif (digits) {\n\t\t\t\t\t// prepend leading zeroes\n\t\t\t\t\ts = (\"0000000\" + s).substr(-digits);\n\t\t\t\t}\n\t\t\t\tres.push(s);\n\t\t\t});\n\t\t\treturn res.join(separator);\n\t\t},\n\t\t/** Return the parent keys separated by options.keyPathSeparator, e.g. \"/id_1/id_17/id_32\".\n\t\t *\n\t\t * (Unlike `node.getPath()`, this method prepends a \"/\" and inverts the first argument.)\n\t\t *\n\t\t * @see FancytreeNode#getPath\n\t\t * @param {boolean} [excludeSelf=false]\n\t\t * @returns {string}\n\t\t */\n\t\tgetKeyPath: function(excludeSelf) {\n\t\t\tvar sep = this.tree.options.keyPathSeparator;\n\n\t\t\treturn sep + this.getPath(!excludeSelf, \"key\", sep);\n\t\t},\n\t\t/** Return the last child of this node or null.\n\t\t * @returns {FancytreeNode | null}\n\t\t */\n\t\tgetLastChild: function() {\n\t\t\treturn this.children\n\t\t\t\t? this.children[this.children.length - 1]\n\t\t\t\t: null;\n\t\t},\n\t\t/** Return node depth. 0: System root node, 1: visible top-level node, 2: first sub-level, ... .\n\t\t * @returns {int}\n\t\t */\n\t\tgetLevel: function() {\n\t\t\tvar level = 0,\n\t\t\t\tdtn = this.parent;\n\t\t\twhile (dtn) {\n\t\t\t\tlevel++;\n\t\t\t\tdtn = dtn.parent;\n\t\t\t}\n\t\t\treturn level;\n\t\t},\n\t\t/** Return the successor node (under the same parent) or null.\n\t\t * @returns {FancytreeNode | null}\n\t\t */\n\t\tgetNextSibling: function() {\n\t\t\t// TODO: use indexOf, if available: (not in IE6)\n\t\t\tif (this.parent) {\n\t\t\t\tvar i,\n\t\t\t\t\tl,\n\t\t\t\t\tac = this.parent.children;\n\n\t\t\t\tfor (i = 0, l = ac.length - 1; i < l; i++) {\n\t\t\t\t\t// up to length-2, so next(last) = null\n\t\t\t\t\tif (ac[i] === this) {\n\t\t\t\t\t\treturn ac[i + 1];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\t/** Return the parent node (null for the system root node).\n\t\t * @returns {FancytreeNode | null}\n\t\t */\n\t\tgetParent: function() {\n\t\t\t// TODO: return null for top-level nodes?\n\t\t\treturn this.parent;\n\t\t},\n\t\t/** Return an array of all parent nodes (top-down).\n\t\t * @param {boolean} [includeRoot=false] Include the invisible system root node.\n\t\t * @param {boolean} [includeSelf=false] Include the node itself.\n\t\t * @returns {FancytreeNode[]}\n\t\t */\n\t\tgetParentList: function(includeRoot, includeSelf) {\n\t\t\tvar l = [],\n\t\t\t\tdtn = includeSelf ? this : this.parent;\n\t\t\twhile (dtn) {\n\t\t\t\tif (includeRoot || dtn.parent) {\n\t\t\t\t\tl.unshift(dtn);\n\t\t\t\t}\n\t\t\t\tdtn = dtn.parent;\n\t\t\t}\n\t\t\treturn l;\n\t\t},\n\t\t/** Return a string representing the hierachical node path, e.g. \"a/b/c\".\n\t\t * @param {boolean} [includeSelf=true]\n\t\t * @param {string | function} [part=\"title\"] node property name or callback\n\t\t * @param {string} [separator=\"/\"]\n\t\t * @returns {string}\n\t\t * @since v2.31\n\t\t */\n\t\tgetPath: function(includeSelf, part, separator) {\n\t\t\tincludeSelf = includeSelf !== false;\n\t\t\tpart = part || \"title\";\n\t\t\tseparator = separator || \"/\";\n\n\t\t\tvar val,\n\t\t\t\tpath = [],\n\t\t\t\tisFunc = $.isFunction(part);\n\n\t\t\tthis.visitParents(function(n) {\n\t\t\t\tif (n.parent) {\n\t\t\t\t\tval = isFunc ? part(n) : n[part];\n\t\t\t\t\tpath.unshift(val);\n\t\t\t\t}\n\t\t\t}, includeSelf);\n\t\t\treturn path.join(separator);\n\t\t},\n\t\t/** Return the predecessor node (under the same parent) or null.\n\t\t * @returns {FancytreeNode | null}\n\t\t */\n\t\tgetPrevSibling: function() {\n\t\t\tif (this.parent) {\n\t\t\t\tvar i,\n\t\t\t\t\tl,\n\t\t\t\t\tac = this.parent.children;\n\n\t\t\t\tfor (i = 1, l = ac.length; i < l; i++) {\n\t\t\t\t\t// start with 1, so prev(first) = null\n\t\t\t\t\tif (ac[i] === this) {\n\t\t\t\t\t\treturn ac[i - 1];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\t/**\n\t\t * Return an array of selected descendant nodes.\n\t\t * @param {boolean} [stopOnParents=false] only return the topmost selected\n\t\t *     node (useful with selectMode 3)\n\t\t * @returns {FancytreeNode[]}\n\t\t */\n\t\tgetSelectedNodes: function(stopOnParents) {\n\t\t\tvar nodeList = [];\n\t\t\tthis.visit(function(node) {\n\t\t\t\tif (node.selected) {\n\t\t\t\t\tnodeList.push(node);\n\t\t\t\t\tif (stopOnParents === true) {\n\t\t\t\t\t\treturn \"skip\"; // stop processing this branch\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn nodeList;\n\t\t},\n\t\t/** Return true if node has children. Return undefined if not sure, i.e. the node is lazy and not yet loaded).\n\t\t * @returns {boolean | undefined}\n\t\t */\n\t\thasChildren: function() {\n\t\t\tif (this.lazy) {\n\t\t\t\tif (this.children == null) {\n\t\t\t\t\t// null or undefined: Not yet loaded\n\t\t\t\t\treturn undefined;\n\t\t\t\t} else if (this.children.length === 0) {\n\t\t\t\t\t// Loaded, but response was empty\n\t\t\t\t\treturn false;\n\t\t\t\t} else if (\n\t\t\t\t\tthis.children.length === 1 &&\n\t\t\t\t\tthis.children[0].isStatusNode()\n\t\t\t\t) {\n\t\t\t\t\t// Currently loading or load error\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn !!(this.children && this.children.length);\n\t\t},\n\t\t/**\n\t\t * Return true if node has `className` defined in .extraClasses.\n\t\t *\n\t\t * @param {string} className class name (separate multiple classes by space)\n\t\t * @returns {boolean}\n\t\t *\n\t\t * @since 2.32\n\t\t */\n\t\thasClass: function(className) {\n\t\t\treturn (\n\t\t\t\t(\" \" + (this.extraClasses || \"\") + \" \").indexOf(\n\t\t\t\t\t\" \" + className + \" \"\n\t\t\t\t) >= 0\n\t\t\t);\n\t\t},\n\t\t/** Return true if node has keyboard focus.\n\t\t * @returns {boolean}\n\t\t */\n\t\thasFocus: function() {\n\t\t\treturn this.tree.hasFocus() && this.tree.focusNode === this;\n\t\t},\n\t\t/** Write to browser console if debugLevel >= 3 (prepending node info)\n\t\t *\n\t\t * @param {*} msg string or object or array of such\n\t\t */\n\t\tinfo: function(msg) {\n\t\t\tif (this.tree.options.debugLevel >= 3) {\n\t\t\t\tArray.prototype.unshift.call(arguments, this.toString());\n\t\t\t\tconsoleApply(\"info\", arguments);\n\t\t\t}\n\t\t},\n\t\t/** Return true if node is active (see also FancytreeNode#isSelected).\n\t\t * @returns {boolean}\n\t\t */\n\t\tisActive: function() {\n\t\t\treturn this.tree.activeNode === this;\n\t\t},\n\t\t/** Return true if node is vertically below `otherNode`, i.e. rendered in a subsequent row.\n\t\t * @param {FancytreeNode} otherNode\n\t\t * @returns {boolean}\n\t\t * @since 2.28\n\t\t */\n\t\tisBelowOf: function(otherNode) {\n\t\t\treturn this.getIndexHier(\".\", 5) > otherNode.getIndexHier(\".\", 5);\n\t\t},\n\t\t/** Return true if node is a direct child of otherNode.\n\t\t * @param {FancytreeNode} otherNode\n\t\t * @returns {boolean}\n\t\t */\n\t\tisChildOf: function(otherNode) {\n\t\t\treturn this.parent && this.parent === otherNode;\n\t\t},\n\t\t/** Return true, if node is a direct or indirect sub node of otherNode.\n\t\t * @param {FancytreeNode} otherNode\n\t\t * @returns {boolean}\n\t\t */\n\t\tisDescendantOf: function(otherNode) {\n\t\t\tif (!otherNode || otherNode.tree !== this.tree) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar p = this.parent;\n\t\t\twhile (p) {\n\t\t\t\tif (p === otherNode) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (p === p.parent) {\n\t\t\t\t\t$.error(\"Recursive parent link: \" + p);\n\t\t\t\t}\n\t\t\t\tp = p.parent;\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\t\t/** Return true if node is expanded.\n\t\t * @returns {boolean}\n\t\t */\n\t\tisExpanded: function() {\n\t\t\treturn !!this.expanded;\n\t\t},\n\t\t/** Return true if node is the first node of its parent's children.\n\t\t * @returns {boolean}\n\t\t */\n\t\tisFirstSibling: function() {\n\t\t\tvar p = this.parent;\n\t\t\treturn !p || p.children[0] === this;\n\t\t},\n\t\t/** Return true if node is a folder, i.e. has the node.folder attribute set.\n\t\t * @returns {boolean}\n\t\t */\n\t\tisFolder: function() {\n\t\t\treturn !!this.folder;\n\t\t},\n\t\t/** Return true if node is the last node of its parent's children.\n\t\t * @returns {boolean}\n\t\t */\n\t\tisLastSibling: function() {\n\t\t\tvar p = this.parent;\n\t\t\treturn !p || p.children[p.children.length - 1] === this;\n\t\t},\n\t\t/** Return true if node is lazy (even if data was already loaded)\n\t\t * @returns {boolean}\n\t\t */\n\t\tisLazy: function() {\n\t\t\treturn !!this.lazy;\n\t\t},\n\t\t/** Return true if node is lazy and loaded. For non-lazy nodes always return true.\n\t\t * @returns {boolean}\n\t\t */\n\t\tisLoaded: function() {\n\t\t\treturn !this.lazy || this.hasChildren() !== undefined; // Also checks if the only child is a status node\n\t\t},\n\t\t/** Return true if children are currently beeing loaded, i.e. a Ajax request is pending.\n\t\t * @returns {boolean}\n\t\t */\n\t\tisLoading: function() {\n\t\t\treturn !!this._isLoading;\n\t\t},\n\t\t/*\n\t\t * @deprecated since v2.4.0:  Use isRootNode() instead\n\t\t */\n\t\tisRoot: function() {\n\t\t\treturn this.isRootNode();\n\t\t},\n\t\t/** Return true if node is partially selected (tri-state).\n\t\t * @returns {boolean}\n\t\t * @since 2.23\n\t\t */\n\t\tisPartsel: function() {\n\t\t\treturn !this.selected && !!this.partsel;\n\t\t},\n\t\t/** (experimental) Return true if this is partially loaded.\n\t\t * @returns {boolean}\n\t\t * @since 2.15\n\t\t */\n\t\tisPartload: function() {\n\t\t\treturn !!this.partload;\n\t\t},\n\t\t/** Return true if this is the (invisible) system root node.\n\t\t * @returns {boolean}\n\t\t * @since 2.4\n\t\t */\n\t\tisRootNode: function() {\n\t\t\treturn this.tree.rootNode === this;\n\t\t},\n\t\t/** Return true if node is selected, i.e. has a checkmark set (see also FancytreeNode#isActive).\n\t\t * @returns {boolean}\n\t\t */\n\t\tisSelected: function() {\n\t\t\treturn !!this.selected;\n\t\t},\n\t\t/** Return true if this node is a temporarily generated system node like\n\t\t * 'loading', 'paging', or 'error' (node.statusNodeType contains the type).\n\t\t * @returns {boolean}\n\t\t */\n\t\tisStatusNode: function() {\n\t\t\treturn !!this.statusNodeType;\n\t\t},\n\t\t/** Return true if this node is a status node of type 'paging'.\n\t\t * @returns {boolean}\n\t\t * @since 2.15\n\t\t */\n\t\tisPagingNode: function() {\n\t\t\treturn this.statusNodeType === \"paging\";\n\t\t},\n\t\t/** Return true if this a top level node, i.e. a direct child of the (invisible) system root node.\n\t\t * @returns {boolean}\n\t\t * @since 2.4\n\t\t */\n\t\tisTopLevel: function() {\n\t\t\treturn this.tree.rootNode === this.parent;\n\t\t},\n\t\t/** Return true if node is lazy and not yet loaded. For non-lazy nodes always return false.\n\t\t * @returns {boolean}\n\t\t */\n\t\tisUndefined: function() {\n\t\t\treturn this.hasChildren() === undefined; // also checks if the only child is a status node\n\t\t},\n\t\t/** Return true if all parent nodes are expanded. Note: this does not check\n\t\t * whether the node is scrolled into the visible part of the screen.\n\t\t * @returns {boolean}\n\t\t */\n\t\tisVisible: function() {\n\t\t\tvar i,\n\t\t\t\tl,\n\t\t\t\tn,\n\t\t\t\thasFilter = this.tree.enableFilter,\n\t\t\t\tparents = this.getParentList(false, false);\n\n\t\t\t// TODO: check $(n.span).is(\":visible\")\n\t\t\t// i.e. return false for nodes (but not parents) that are hidden\n\t\t\t// by a filter\n\t\t\tif (hasFilter && !this.match && !this.subMatchCount) {\n\t\t\t\t// this.debug( \"isVisible: HIDDEN (\" + hasFilter + \", \" + this.match + \", \" + this.match + \")\" );\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor (i = 0, l = parents.length; i < l; i++) {\n\t\t\t\tn = parents[i];\n\n\t\t\t\tif (!n.expanded) {\n\t\t\t\t\t// this.debug(\"isVisible: HIDDEN (parent collapsed)\");\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t// if (hasFilter && !n.match && !n.subMatchCount) {\n\t\t\t\t// \tthis.debug(\"isVisible: HIDDEN (\" + hasFilter + \", \" + this.match + \", \" + this.match + \")\");\n\t\t\t\t// \treturn false;\n\t\t\t\t// }\n\t\t\t}\n\t\t\t// this.debug(\"isVisible: VISIBLE\");\n\t\t\treturn true;\n\t\t},\n\t\t/** Deprecated.\n\t\t * @deprecated since 2014-02-16: use load() instead.\n\t\t */\n\t\tlazyLoad: function(discard) {\n\t\t\tthis.warn(\n\t\t\t\t\"FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead.\"\n\t\t\t);\n\t\t\treturn this.load(discard);\n\t\t},\n\t\t/**\n\t\t * Load all children of a lazy node if neccessary. The <i>expanded</i> state is maintained.\n\t\t * @param {boolean} [forceReload=false] Pass true to discard any existing nodes before. Otherwise this method does nothing if the node was already loaded.\n\t\t * @returns {$.Promise}\n\t\t */\n\t\tload: function(forceReload) {\n\t\t\tvar res,\n\t\t\t\tsource,\n\t\t\t\tself = this,\n\t\t\t\twasExpanded = this.isExpanded();\n\n\t\t\t_assert(this.isLazy(), \"load() requires a lazy node\");\n\t\t\t// _assert( forceReload || this.isUndefined(), \"Pass forceReload=true to re-load a lazy node\" );\n\t\t\tif (!forceReload && !this.isUndefined()) {\n\t\t\t\treturn _getResolvedPromise(this);\n\t\t\t}\n\t\t\tif (this.isLoaded()) {\n\t\t\t\tthis.resetLazy(); // also collapses\n\t\t\t}\n\t\t\t// This method is also called by setExpanded() and loadKeyPath(), so we\n\t\t\t// have to avoid recursion.\n\t\t\tsource = this.tree._triggerNodeEvent(\"lazyLoad\", this);\n\t\t\tif (source === false) {\n\t\t\t\t// #69\n\t\t\t\treturn _getResolvedPromise(this);\n\t\t\t}\n\t\t\t_assert(\n\t\t\t\ttypeof source !== \"boolean\",\n\t\t\t\t\"lazyLoad event must return source in data.result\"\n\t\t\t);\n\t\t\tres = this.tree._callHook(\"nodeLoadChildren\", this, source);\n\t\t\tif (wasExpanded) {\n\t\t\t\tthis.expanded = true;\n\t\t\t\tres.always(function() {\n\t\t\t\t\tself.render();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tres.always(function() {\n\t\t\t\t\tself.renderStatus(); // fix expander icon to 'loaded'\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\t/** Expand all parents and optionally scroll into visible area as neccessary.\n\t\t * Promise is resolved, when lazy loading and animations are done.\n\t\t * @param {object} [opts] passed to `setExpanded()`.\n\t\t *     Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true}\n\t\t * @returns {$.Promise}\n\t\t */\n\t\tmakeVisible: function(opts) {\n\t\t\tvar i,\n\t\t\t\tself = this,\n\t\t\t\tdeferreds = [],\n\t\t\t\tdfd = new $.Deferred(),\n\t\t\t\tparents = this.getParentList(false, false),\n\t\t\t\tlen = parents.length,\n\t\t\t\teffects = !(opts && opts.noAnimation === true),\n\t\t\t\tscroll = !(opts && opts.scrollIntoView === false);\n\n\t\t\t// Expand bottom-up, so only the top node is animated\n\t\t\tfor (i = len - 1; i >= 0; i--) {\n\t\t\t\t// self.debug(\"pushexpand\" + parents[i]);\n\t\t\t\tdeferreds.push(parents[i].setExpanded(true, opts));\n\t\t\t}\n\t\t\t$.when.apply($, deferreds).done(function() {\n\t\t\t\t// All expands have finished\n\t\t\t\t// self.debug(\"expand DONE\", scroll);\n\t\t\t\tif (scroll) {\n\t\t\t\t\tself.scrollIntoView(effects).done(function() {\n\t\t\t\t\t\t// self.debug(\"scroll DONE\");\n\t\t\t\t\t\tdfd.resolve();\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tdfd.resolve();\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn dfd.promise();\n\t\t},\n\t\t/** Move this node to targetNode.\n\t\t *  @param {FancytreeNode} targetNode\n\t\t *  @param {string} mode <pre>\n\t\t *      'child': append this node as last child of targetNode.\n\t\t *               This is the default. To be compatble with the D'n'd\n\t\t *               hitMode, we also accept 'over'.\n\t\t *      'firstChild': add this node as first child of targetNode.\n\t\t *      'before': add this node as sibling before targetNode.\n\t\t *      'after': add this node as sibling after targetNode.</pre>\n\t\t *  @param {function} [map] optional callback(FancytreeNode) to allow modifcations\n\t\t */\n\t\tmoveTo: function(targetNode, mode, map) {\n\t\t\tif (mode === undefined || mode === \"over\") {\n\t\t\t\tmode = \"child\";\n\t\t\t} else if (mode === \"firstChild\") {\n\t\t\t\tif (targetNode.children && targetNode.children.length) {\n\t\t\t\t\tmode = \"before\";\n\t\t\t\t\ttargetNode = targetNode.children[0];\n\t\t\t\t} else {\n\t\t\t\t\tmode = \"child\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar pos,\n\t\t\t\ttree = this.tree,\n\t\t\t\tprevParent = this.parent,\n\t\t\t\ttargetParent =\n\t\t\t\t\tmode === \"child\" ? targetNode : targetNode.parent;\n\n\t\t\tif (this === targetNode) {\n\t\t\t\treturn;\n\t\t\t} else if (!this.parent) {\n\t\t\t\t$.error(\"Cannot move system root\");\n\t\t\t} else if (targetParent.isDescendantOf(this)) {\n\t\t\t\t$.error(\"Cannot move a node to its own descendant\");\n\t\t\t}\n\t\t\tif (targetParent !== prevParent) {\n\t\t\t\tprevParent.triggerModifyChild(\"remove\", this);\n\t\t\t}\n\t\t\t// Unlink this node from current parent\n\t\t\tif (this.parent.children.length === 1) {\n\t\t\t\tif (this.parent === targetParent) {\n\t\t\t\t\treturn; // #258\n\t\t\t\t}\n\t\t\t\tthis.parent.children = this.parent.lazy ? [] : null;\n\t\t\t\tthis.parent.expanded = false;\n\t\t\t} else {\n\t\t\t\tpos = $.inArray(this, this.parent.children);\n\t\t\t\t_assert(pos >= 0, \"invalid source parent\");\n\t\t\t\tthis.parent.children.splice(pos, 1);\n\t\t\t}\n\t\t\t// Remove from source DOM parent\n\t\t\t// if(this.parent.ul){\n\t\t\t// \tthis.parent.ul.removeChild(this.li);\n\t\t\t// }\n\n\t\t\t// Insert this node to target parent's child list\n\t\t\tthis.parent = targetParent;\n\t\t\tif (targetParent.hasChildren()) {\n\t\t\t\tswitch (mode) {\n\t\t\t\t\tcase \"child\":\n\t\t\t\t\t\t// Append to existing target children\n\t\t\t\t\t\ttargetParent.children.push(this);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"before\":\n\t\t\t\t\t\t// Insert this node before target node\n\t\t\t\t\t\tpos = $.inArray(targetNode, targetParent.children);\n\t\t\t\t\t\t_assert(pos >= 0, \"invalid target parent\");\n\t\t\t\t\t\ttargetParent.children.splice(pos, 0, this);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"after\":\n\t\t\t\t\t\t// Insert this node after target node\n\t\t\t\t\t\tpos = $.inArray(targetNode, targetParent.children);\n\t\t\t\t\t\t_assert(pos >= 0, \"invalid target parent\");\n\t\t\t\t\t\ttargetParent.children.splice(pos + 1, 0, this);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t$.error(\"Invalid mode \" + mode);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttargetParent.children = [this];\n\t\t\t}\n\t\t\t// Parent has no <ul> tag yet:\n\t\t\t// if( !targetParent.ul ) {\n\t\t\t// \t// This is the parent's first child: create UL tag\n\t\t\t// \t// (Hidden, because it will be\n\t\t\t// \ttargetParent.ul = document.createElement(\"ul\");\n\t\t\t// \ttargetParent.ul.style.display = \"none\";\n\t\t\t// \ttargetParent.li.appendChild(targetParent.ul);\n\t\t\t// }\n\t\t\t// // Issue 319: Add to target DOM parent (only if node was already rendered(expanded))\n\t\t\t// if(this.li){\n\t\t\t// \ttargetParent.ul.appendChild(this.li);\n\t\t\t// }\n\n\t\t\t// Let caller modify the nodes\n\t\t\tif (map) {\n\t\t\t\ttargetNode.visit(map, true);\n\t\t\t}\n\t\t\tif (targetParent === prevParent) {\n\t\t\t\ttargetParent.triggerModifyChild(\"move\", this);\n\t\t\t} else {\n\t\t\t\t// prevParent.triggerModifyChild(\"remove\", this);\n\t\t\t\ttargetParent.triggerModifyChild(\"add\", this);\n\t\t\t}\n\t\t\t// Handle cross-tree moves\n\t\t\tif (tree !== targetNode.tree) {\n\t\t\t\t// Fix node.tree for all source nodes\n\t\t\t\t// \t_assert(false, \"Cross-tree move is not yet implemented.\");\n\t\t\t\tthis.warn(\"Cross-tree moveTo is experimental!\");\n\t\t\t\tthis.visit(function(n) {\n\t\t\t\t\t// TODO: fix selection state and activation, ...\n\t\t\t\t\tn.tree = targetNode.tree;\n\t\t\t\t}, true);\n\t\t\t}\n\n\t\t\t// A collaposed node won't re-render children, so we have to remove it manually\n\t\t\t// if( !targetParent.expanded ){\n\t\t\t//   prevParent.ul.removeChild(this.li);\n\t\t\t// }\n\t\t\ttree._callHook(\"treeStructureChanged\", tree, \"moveTo\");\n\n\t\t\t// Update HTML markup\n\t\t\tif (!prevParent.isDescendantOf(targetParent)) {\n\t\t\t\tprevParent.render();\n\t\t\t}\n\t\t\tif (\n\t\t\t\t!targetParent.isDescendantOf(prevParent) &&\n\t\t\t\ttargetParent !== prevParent\n\t\t\t) {\n\t\t\t\ttargetParent.render();\n\t\t\t}\n\t\t\t// TODO: fix selection state\n\t\t\t// TODO: fix active state\n\n\t\t\t/*\n\t\t\tvar tree = this.tree;\n\t\t\tvar opts = tree.options;\n\t\t\tvar pers = tree.persistence;\n\n\t\t\t// Always expand, if it's below minExpandLevel\n\t\t\t// tree.logDebug (\"%s._addChildNode(%o), l=%o\", this, ftnode, ftnode.getLevel());\n\t\t\tif ( opts.minExpandLevel >= ftnode.getLevel() ) {\n\t\t\t\t// tree.logDebug (\"Force expand for %o\", ftnode);\n\t\t\t\tthis.bExpanded = true;\n\t\t\t}\n\n\t\t\t// In multi-hier mode, update the parents selection state\n\t\t\t// DT issue #82: only if not initializing, because the children may not exist yet\n\t\t\t// if( !ftnode.data.isStatusNode() && opts.selectMode==3 && !isInitializing )\n\t\t\t// \tftnode._fixSelectionState();\n\n\t\t\t// In multi-hier mode, update the parents selection state\n\t\t\tif( ftnode.bSelected && opts.selectMode==3 ) {\n\t\t\t\tvar p = this;\n\t\t\t\twhile( p ) {\n\t\t\t\t\tif( !p.hasSubSel )\n\t\t\t\t\t\tp._setSubSel(true);\n\t\t\t\t\tp = p.parent;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// render this node and the new child\n\t\t\tif ( tree.bEnableUpdate )\n\t\t\t\tthis.render();\n\t\t\treturn ftnode;\n\t\t\t*/\n\t\t},\n\t\t/** Set focus relative to this node and optionally activate.\n\t\t *\n\t\t * 'left' collapses the node if it is expanded, or move to the parent\n\t\t * otherwise.\n\t\t * 'right' expands the node if it is collapsed, or move to the first\n\t\t * child otherwise.\n\t\t *\n\t\t * @param {string|number} where 'down', 'first', 'last', 'left', 'parent', 'right', or 'up'.\n\t\t *   (Alternatively the keyCode that would normally trigger this move,\n\t\t *   e.g. `$.ui.keyCode.LEFT` = 'left'.\n\t\t * @param {boolean} [activate=true]\n\t\t * @returns {$.Promise}\n\t\t */\n\t\tnavigate: function(where, activate) {\n\t\t\tvar node,\n\t\t\t\tKC = $.ui.keyCode;\n\n\t\t\t// Handle optional expand/collapse action for LEFT/RIGHT\n\t\t\tswitch (where) {\n\t\t\t\tcase \"left\":\n\t\t\t\tcase KC.LEFT:\n\t\t\t\t\tif (this.expanded) {\n\t\t\t\t\t\treturn this.setExpanded(false);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"right\":\n\t\t\t\tcase KC.RIGHT:\n\t\t\t\t\tif (!this.expanded && (this.children || this.lazy)) {\n\t\t\t\t\t\treturn this.setExpanded();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// Otherwise activate or focus the related node\n\t\t\tnode = this.findRelatedNode(where);\n\t\t\tif (node) {\n\t\t\t\t// setFocus/setActive will scroll later (if autoScroll is specified)\n\t\t\t\ttry {\n\t\t\t\t\tnode.makeVisible({ scrollIntoView: false });\n\t\t\t\t} catch (e) {} // #272\n\t\t\t\tif (activate === false) {\n\t\t\t\t\tnode.setFocus();\n\t\t\t\t\treturn _getResolvedPromise();\n\t\t\t\t}\n\t\t\t\treturn node.setActive();\n\t\t\t}\n\t\t\tthis.warn(\"Could not find related node '\" + where + \"'.\");\n\t\t\treturn _getResolvedPromise();\n\t\t},\n\t\t/**\n\t\t * Remove this node (not allowed for system root).\n\t\t */\n\t\tremove: function() {\n\t\t\treturn this.parent.removeChild(this);\n\t\t},\n\t\t/**\n\t\t * Remove childNode from list of direct children.\n\t\t * @param {FancytreeNode} childNode\n\t\t */\n\t\tremoveChild: function(childNode) {\n\t\t\treturn this.tree._callHook(\"nodeRemoveChild\", this, childNode);\n\t\t},\n\t\t/**\n\t\t * Remove all child nodes and descendents. This converts the node into a leaf.<br>\n\t\t * If this was a lazy node, it is still considered 'loaded'; call node.resetLazy()\n\t\t * in order to trigger lazyLoad on next expand.\n\t\t */\n\t\tremoveChildren: function() {\n\t\t\treturn this.tree._callHook(\"nodeRemoveChildren\", this);\n\t\t},\n\t\t/**\n\t\t * Remove class from node's span tag and .extraClasses.\n\t\t *\n\t\t * @param {string} className class name\n\t\t *\n\t\t * @since 2.17\n\t\t */\n\t\tremoveClass: function(className) {\n\t\t\treturn this.toggleClass(className, false);\n\t\t},\n\t\t/**\n\t\t * This method renders and updates all HTML markup that is required\n\t\t * to display this node in its current state.<br>\n\t\t * Note:\n\t\t * <ul>\n\t\t * <li>It should only be neccessary to call this method after the node object\n\t\t *     was modified by direct access to its properties, because the common\n\t\t *     API methods (node.setTitle(), moveTo(), addChildren(), remove(), ...)\n\t\t *     already handle this.\n\t\t * <li> {@link FancytreeNode#renderTitle} and {@link FancytreeNode#renderStatus}\n\t\t *     are implied. If changes are more local, calling only renderTitle() or\n\t\t *     renderStatus() may be sufficient and faster.\n\t\t * </ul>\n\t\t *\n\t\t * @param {boolean} [force=false] re-render, even if html markup was already created\n\t\t * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed\n\t\t */\n\t\trender: function(force, deep) {\n\t\t\treturn this.tree._callHook(\"nodeRender\", this, force, deep);\n\t\t},\n\t\t/** Create HTML markup for the node's outer `<span>` (expander, checkbox, icon, and title).\n\t\t * Implies {@link FancytreeNode#renderStatus}.\n\t\t * @see Fancytree_Hooks#nodeRenderTitle\n\t\t */\n\t\trenderTitle: function() {\n\t\t\treturn this.tree._callHook(\"nodeRenderTitle\", this);\n\t\t},\n\t\t/** Update element's CSS classes according to node state.\n\t\t * @see Fancytree_Hooks#nodeRenderStatus\n\t\t */\n\t\trenderStatus: function() {\n\t\t\treturn this.tree._callHook(\"nodeRenderStatus\", this);\n\t\t},\n\t\t/**\n\t\t * (experimental) Replace this node with `source`.\n\t\t * (Currently only available for paging nodes.)\n\t\t * @param {NodeData[]} source List of child node definitions\n\t\t * @since 2.15\n\t\t */\n\t\treplaceWith: function(source) {\n\t\t\tvar res,\n\t\t\t\tparent = this.parent,\n\t\t\t\tpos = $.inArray(this, parent.children),\n\t\t\t\tself = this;\n\n\t\t\t_assert(\n\t\t\t\tthis.isPagingNode(),\n\t\t\t\t\"replaceWith() currently requires a paging status node\"\n\t\t\t);\n\n\t\t\tres = this.tree._callHook(\"nodeLoadChildren\", this, source);\n\t\t\tres.done(function(data) {\n\t\t\t\t// New nodes are currently children of `this`.\n\t\t\t\tvar children = self.children;\n\t\t\t\t// Prepend newly loaded child nodes to `this`\n\t\t\t\t// Move new children after self\n\t\t\t\tfor (i = 0; i < children.length; i++) {\n\t\t\t\t\tchildren[i].parent = parent;\n\t\t\t\t}\n\t\t\t\tparent.children.splice.apply(\n\t\t\t\t\tparent.children,\n\t\t\t\t\t[pos + 1, 0].concat(children)\n\t\t\t\t);\n\n\t\t\t\t// Remove self\n\t\t\t\tself.children = null;\n\t\t\t\tself.remove();\n\t\t\t\t// Redraw new nodes\n\t\t\t\tparent.render();\n\t\t\t\t// TODO: set node.partload = false if this was tha last paging node?\n\t\t\t\t// parent.addPagingNode(false);\n\t\t\t}).fail(function() {\n\t\t\t\tself.setExpanded();\n\t\t\t});\n\t\t\treturn res;\n\t\t\t// $.error(\"Not implemented: replaceWith()\");\n\t\t},\n\t\t/**\n\t\t * Remove all children, collapse, and set the lazy-flag, so that the lazyLoad\n\t\t * event is triggered on next expand.\n\t\t */\n\t\tresetLazy: function() {\n\t\t\tthis.removeChildren();\n\t\t\tthis.expanded = false;\n\t\t\tthis.lazy = true;\n\t\t\tthis.children = undefined;\n\t\t\tthis.renderStatus();\n\t\t},\n\t\t/** Schedule activity for delayed execution (cancel any pending request).\n\t\t *  scheduleAction('cancel') will only cancel a pending request (if any).\n\t\t * @param {string} mode\n\t\t * @param {number} ms\n\t\t */\n\t\tscheduleAction: function(mode, ms) {\n\t\t\tif (this.tree.timer) {\n\t\t\t\tclearTimeout(this.tree.timer);\n\t\t\t\tthis.tree.debug(\"clearTimeout(%o)\", this.tree.timer);\n\t\t\t}\n\t\t\tthis.tree.timer = null;\n\t\t\tvar self = this; // required for closures\n\t\t\tswitch (mode) {\n\t\t\t\tcase \"cancel\":\n\t\t\t\t\t// Simply made sure that timer was cleared\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"expand\":\n\t\t\t\t\tthis.tree.timer = setTimeout(function() {\n\t\t\t\t\t\tself.tree.debug(\"setTimeout: trigger expand\");\n\t\t\t\t\t\tself.setExpanded(true);\n\t\t\t\t\t}, ms);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"activate\":\n\t\t\t\t\tthis.tree.timer = setTimeout(function() {\n\t\t\t\t\t\tself.tree.debug(\"setTimeout: trigger activate\");\n\t\t\t\t\t\tself.setActive(true);\n\t\t\t\t\t}, ms);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t$.error(\"Invalid mode \" + mode);\n\t\t\t}\n\t\t\t// this.tree.debug(\"setTimeout(%s, %s): %s\", mode, ms, this.tree.timer);\n\t\t},\n\t\t/**\n\t\t *\n\t\t * @param {boolean | PlainObject} [effects=false] animation options.\n\t\t * @param {object} [options=null] {topNode: null, effects: ..., parent: ...} this node will remain visible in\n\t\t *     any case, even if `this` is outside the scroll pane.\n\t\t * @returns {$.Promise}\n\t\t */\n\t\tscrollIntoView: function(effects, options) {\n\t\t\tif (options !== undefined && _isNode(options)) {\n\t\t\t\tthrow Error(\n\t\t\t\t\t\"scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead.\"\n\t\t\t\t);\n\t\t\t}\n\t\t\t// The scroll parent is typically the plain tree's <UL> container.\n\t\t\t// For ext-table, we choose the nearest parent that has `position: relative`\n\t\t\t// and `overflow` set.\n\t\t\t// (This default can be overridden by the local or global `scrollParent` option.)\n\t\t\tvar opts = $.extend(\n\t\t\t\t\t{\n\t\t\t\t\t\teffects:\n\t\t\t\t\t\t\teffects === true\n\t\t\t\t\t\t\t\t? { duration: 200, queue: false }\n\t\t\t\t\t\t\t\t: effects,\n\t\t\t\t\t\tscrollOfs: this.tree.options.scrollOfs,\n\t\t\t\t\t\tscrollParent: this.tree.options.scrollParent,\n\t\t\t\t\t\ttopNode: null,\n\t\t\t\t\t},\n\t\t\t\t\toptions\n\t\t\t\t),\n\t\t\t\t$scrollParent = opts.scrollParent,\n\t\t\t\t$container = this.tree.$container,\n\t\t\t\toverflowY = $container.css(\"overflow-y\");\n\n\t\t\tif (!$scrollParent) {\n\t\t\t\tif (this.tree.tbody) {\n\t\t\t\t\t$scrollParent = $container.scrollParent();\n\t\t\t\t} else if (overflowY === \"scroll\" || overflowY === \"auto\") {\n\t\t\t\t\t$scrollParent = $container;\n\t\t\t\t} else {\n\t\t\t\t\t// #922 plain tree in a non-fixed-sized UL scrolls inside its parent\n\t\t\t\t\t$scrollParent = $container.scrollParent();\n\t\t\t\t}\n\t\t\t} else if (!$scrollParent.jquery) {\n\t\t\t\t// Make sure we have a jQuery object\n\t\t\t\t$scrollParent = $($scrollParent);\n\t\t\t}\n\t\t\tif (\n\t\t\t\t$scrollParent[0] === document ||\n\t\t\t\t$scrollParent[0] === document.body\n\t\t\t) {\n\t\t\t\t// `document` may be returned by $().scrollParent(), if nothing is found,\n\t\t\t\t// but would not work: (see #894)\n\t\t\t\tthis.debug(\n\t\t\t\t\t\"scrollIntoView(): normalizing scrollParent to 'window':\",\n\t\t\t\t\t$scrollParent[0]\n\t\t\t\t);\n\t\t\t\t$scrollParent = $(window);\n\t\t\t}\n\t\t\t// eslint-disable-next-line one-var\n\t\t\tvar topNodeY,\n\t\t\t\tnodeY,\n\t\t\t\thorzScrollbarHeight,\n\t\t\t\tcontainerOffsetTop,\n\t\t\t\tdfd = new $.Deferred(),\n\t\t\t\tself = this,\n\t\t\t\tnodeHeight = $(this.span).height(),\n\t\t\t\ttopOfs = opts.scrollOfs.top || 0,\n\t\t\t\tbottomOfs = opts.scrollOfs.bottom || 0,\n\t\t\t\tcontainerHeight = $scrollParent.height(),\n\t\t\t\tscrollTop = $scrollParent.scrollTop(),\n\t\t\t\t$animateTarget = $scrollParent,\n\t\t\t\tisParentWindow = $scrollParent[0] === window,\n\t\t\t\ttopNode = opts.topNode || null,\n\t\t\t\tnewScrollTop = null;\n\n\t\t\t// this.debug(\"scrollIntoView(), scrollTop=\" + scrollTop, opts.scrollOfs);\n\t\t\t// _assert($(this.span).is(\":visible\"), \"scrollIntoView node is invisible\"); // otherwise we cannot calc offsets\n\t\t\tif (!this.isVisible()) {\n\t\t\t\t// We cannot calc offsets for hidden elements\n\t\t\t\tthis.warn(\"scrollIntoView(): node is invisible.\");\n\t\t\t\treturn _getResolvedPromise();\n\t\t\t}\n\t\t\tif (isParentWindow) {\n\t\t\t\tnodeY = $(this.span).offset().top;\n\t\t\t\ttopNodeY =\n\t\t\t\t\ttopNode && topNode.span ? $(topNode.span).offset().top : 0;\n\t\t\t\t$animateTarget = $(\"html,body\");\n\t\t\t} else {\n\t\t\t\t_assert(\n\t\t\t\t\t$scrollParent[0] !== document &&\n\t\t\t\t\t\t$scrollParent[0] !== document.body,\n\t\t\t\t\t\"scrollParent should be a simple element or `window`, not document or body.\"\n\t\t\t\t);\n\n\t\t\t\tcontainerOffsetTop = $scrollParent.offset().top;\n\t\t\t\tnodeY =\n\t\t\t\t\t$(this.span).offset().top - containerOffsetTop + scrollTop; // relative to scroll parent\n\t\t\t\ttopNodeY = topNode\n\t\t\t\t\t? $(topNode.span).offset().top -\n\t\t\t\t\t  containerOffsetTop +\n\t\t\t\t\t  scrollTop\n\t\t\t\t\t: 0;\n\t\t\t\thorzScrollbarHeight = Math.max(\n\t\t\t\t\t0,\n\t\t\t\t\t$scrollParent.innerHeight() - $scrollParent[0].clientHeight\n\t\t\t\t);\n\t\t\t\tcontainerHeight -= horzScrollbarHeight;\n\t\t\t}\n\n\t\t\t// this.debug(\"    scrollIntoView(), nodeY=\" + nodeY + \", containerHeight=\" + containerHeight);\n\t\t\tif (nodeY < scrollTop + topOfs) {\n\t\t\t\t// Node is above visible container area\n\t\t\t\tnewScrollTop = nodeY - topOfs;\n\t\t\t\t// this.debug(\"    scrollIntoView(), UPPER newScrollTop=\" + newScrollTop);\n\t\t\t} else if (\n\t\t\t\tnodeY + nodeHeight >\n\t\t\t\tscrollTop + containerHeight - bottomOfs\n\t\t\t) {\n\t\t\t\tnewScrollTop = nodeY + nodeHeight - containerHeight + bottomOfs;\n\t\t\t\t// this.debug(\"    scrollIntoView(), LOWER newScrollTop=\" + newScrollTop);\n\t\t\t\t// If a topNode was passed, make sure that it is never scrolled\n\t\t\t\t// outside the upper border\n\t\t\t\tif (topNode) {\n\t\t\t\t\t_assert(\n\t\t\t\t\t\ttopNode.isRootNode() || topNode.isVisible(),\n\t\t\t\t\t\t\"topNode must be visible\"\n\t\t\t\t\t);\n\t\t\t\t\tif (topNodeY < newScrollTop) {\n\t\t\t\t\t\tnewScrollTop = topNodeY - topOfs;\n\t\t\t\t\t\t// this.debug(\"    scrollIntoView(), TOP newScrollTop=\" + newScrollTop);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (newScrollTop === null) {\n\t\t\t\tdfd.resolveWith(this);\n\t\t\t} else {\n\t\t\t\t// this.debug(\"    scrollIntoView(), SET newScrollTop=\" + newScrollTop);\n\t\t\t\tif (opts.effects) {\n\t\t\t\t\topts.effects.complete = function() {\n\t\t\t\t\t\tdfd.resolveWith(self);\n\t\t\t\t\t};\n\t\t\t\t\t$animateTarget.stop(true).animate(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tscrollTop: newScrollTop,\n\t\t\t\t\t\t},\n\t\t\t\t\t\topts.effects\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t$animateTarget[0].scrollTop = newScrollTop;\n\t\t\t\t\tdfd.resolveWith(this);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn dfd.promise();\n\t\t},\n\n\t\t/**Activate this node.\n\t\t *\n\t\t * The `cell` option requires the ext-table and ext-ariagrid extensions.\n\t\t *\n\t\t * @param {boolean} [flag=true] pass false to deactivate\n\t\t * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false, cell: null}\n\t\t * @returns {$.Promise}\n\t\t */\n\t\tsetActive: function(flag, opts) {\n\t\t\treturn this.tree._callHook(\"nodeSetActive\", this, flag, opts);\n\t\t},\n\t\t/**Expand or collapse this node. Promise is resolved, when lazy loading and animations are done.\n\t\t * @param {boolean} [flag=true] pass false to collapse\n\t\t * @param {object} [opts] additional options. Defaults to {noAnimation: false, noEvents: false}\n\t\t * @returns {$.Promise}\n\t\t */\n\t\tsetExpanded: function(flag, opts) {\n\t\t\treturn this.tree._callHook(\"nodeSetExpanded\", this, flag, opts);\n\t\t},\n\t\t/**Set keyboard focus to this node.\n\t\t * @param {boolean} [flag=true] pass false to blur\n\t\t * @see Fancytree#setFocus\n\t\t */\n\t\tsetFocus: function(flag) {\n\t\t\treturn this.tree._callHook(\"nodeSetFocus\", this, flag);\n\t\t},\n\t\t/**Select this node, i.e. check the checkbox.\n\t\t * @param {boolean} [flag=true] pass false to deselect\n\t\t * @param {object} [opts] additional options. Defaults to {noEvents: false, p\n\t\t *     propagateDown: null, propagateUp: null, callback: null }\n\t\t */\n\t\tsetSelected: function(flag, opts) {\n\t\t\treturn this.tree._callHook(\"nodeSetSelected\", this, flag, opts);\n\t\t},\n\t\t/**Mark a lazy node as 'error', 'loading', 'nodata', or 'ok'.\n\t\t * @param {string} status 'error'|'empty'|'ok'\n\t\t * @param {string} [message]\n\t\t * @param {string} [details]\n\t\t */\n\t\tsetStatus: function(status, message, details) {\n\t\t\treturn this.tree._callHook(\n\t\t\t\t\"nodeSetStatus\",\n\t\t\t\tthis,\n\t\t\t\tstatus,\n\t\t\t\tmessage,\n\t\t\t\tdetails\n\t\t\t);\n\t\t},\n\t\t/**Rename this node.\n\t\t * @param {string} title\n\t\t */\n\t\tsetTitle: function(title) {\n\t\t\tthis.title = title;\n\t\t\tthis.renderTitle();\n\t\t\tthis.triggerModify(\"rename\");\n\t\t},\n\t\t/**Sort child list by title.\n\t\t * @param {function} [cmp] custom compare function(a, b) that returns -1, 0, or 1 (defaults to sort by title).\n\t\t * @param {boolean} [deep=false] pass true to sort all descendant nodes\n\t\t */\n\t\tsortChildren: function(cmp, deep) {\n\t\t\tvar i,\n\t\t\t\tl,\n\t\t\t\tcl = this.children;\n\n\t\t\tif (!cl) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcmp =\n\t\t\t\tcmp ||\n\t\t\t\tfunction(a, b) {\n\t\t\t\t\tvar x = a.title.toLowerCase(),\n\t\t\t\t\t\ty = b.title.toLowerCase();\n\n\t\t\t\t\t// eslint-disable-next-line no-nested-ternary\n\t\t\t\t\treturn x === y ? 0 : x > y ? 1 : -1;\n\t\t\t\t};\n\t\t\tcl.sort(cmp);\n\t\t\tif (deep) {\n\t\t\t\tfor (i = 0, l = cl.length; i < l; i++) {\n\t\t\t\t\tif (cl[i].children) {\n\t\t\t\t\t\tcl[i].sortChildren(cmp, \"$norender$\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (deep !== \"$norender$\") {\n\t\t\t\tthis.render();\n\t\t\t}\n\t\t\tthis.triggerModifyChild(\"sort\");\n\t\t},\n\t\t/** Convert node (or whole branch) into a plain object.\n\t\t *\n\t\t * The result is compatible with node.addChildren().\n\t\t *\n\t\t * @param {boolean} [recursive=false] include child nodes\n\t\t * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications.\n\t\t *     Return `false` to ignore this node or \"skip\" to include this node without its children.\n\t\t * @returns {NodeData}\n\t\t */\n\t\ttoDict: function(recursive, callback) {\n\t\t\tvar i,\n\t\t\t\tl,\n\t\t\t\tnode,\n\t\t\t\tres,\n\t\t\t\tdict = {},\n\t\t\t\tself = this;\n\n\t\t\t$.each(NODE_ATTRS, function(i, a) {\n\t\t\t\tif (self[a] || self[a] === false) {\n\t\t\t\t\tdict[a] = self[a];\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (!$.isEmptyObject(this.data)) {\n\t\t\t\tdict.data = $.extend({}, this.data);\n\t\t\t\tif ($.isEmptyObject(dict.data)) {\n\t\t\t\t\tdelete dict.data;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (callback) {\n\t\t\t\tres = callback(dict, self);\n\t\t\t\tif (res === false) {\n\t\t\t\t\treturn false; // Don't include this node nor its children\n\t\t\t\t}\n\t\t\t\tif (res === \"skip\") {\n\t\t\t\t\trecursive = false; // Include this node, but not the children\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (recursive) {\n\t\t\t\tif (this.hasChildren()) {\n\t\t\t\t\tdict.children = [];\n\t\t\t\t\tfor (i = 0, l = this.children.length; i < l; i++) {\n\t\t\t\t\t\tnode = this.children[i];\n\t\t\t\t\t\tif (!node.isStatusNode()) {\n\t\t\t\t\t\t\tres = node.toDict(true, callback);\n\t\t\t\t\t\t\tif (res !== false) {\n\t\t\t\t\t\t\t\tdict.children.push(res);\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\t\t\treturn dict;\n\t\t},\n\t\t/**\n\t\t * Set, clear, or toggle class of node's span tag and .extraClasses.\n\t\t *\n\t\t * @param {string} className class name (separate multiple classes by space)\n\t\t * @param {boolean} [flag] true/false to add/remove class. If omitted, class is toggled.\n\t\t * @returns {boolean} true if a class was added\n\t\t *\n\t\t * @since 2.17\n\t\t */\n\t\ttoggleClass: function(value, flag) {\n\t\t\tvar className,\n\t\t\t\thasClass,\n\t\t\t\trnotwhite = /\\S+/g,\n\t\t\t\tclassNames = value.match(rnotwhite) || [],\n\t\t\t\ti = 0,\n\t\t\t\twasAdded = false,\n\t\t\t\tstatusElem = this[this.tree.statusClassPropName],\n\t\t\t\tcurClasses = \" \" + (this.extraClasses || \"\") + \" \";\n\n\t\t\t// this.info(\"toggleClass('\" + value + \"', \" + flag + \")\", curClasses);\n\t\t\t// Modify DOM element directly if it already exists\n\t\t\tif (statusElem) {\n\t\t\t\t$(statusElem).toggleClass(value, flag);\n\t\t\t}\n\t\t\t// Modify node.extraClasses to make this change persistent\n\t\t\t// Toggle if flag was not passed\n\t\t\twhile ((className = classNames[i++])) {\n\t\t\t\thasClass = curClasses.indexOf(\" \" + className + \" \") >= 0;\n\t\t\t\tflag = flag === undefined ? !hasClass : !!flag;\n\t\t\t\tif (flag) {\n\t\t\t\t\tif (!hasClass) {\n\t\t\t\t\t\tcurClasses += className + \" \";\n\t\t\t\t\t\twasAdded = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\twhile (curClasses.indexOf(\" \" + className + \" \") > -1) {\n\t\t\t\t\t\tcurClasses = curClasses.replace(\n\t\t\t\t\t\t\t\" \" + className + \" \",\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\t\t\tthis.extraClasses = $.trim(curClasses);\n\t\t\t// this.info(\"-> toggleClass('\" + value + \"', \" + flag + \"): '\" + this.extraClasses + \"'\");\n\t\t\treturn wasAdded;\n\t\t},\n\t\t/** Flip expanded status. */\n\t\ttoggleExpanded: function() {\n\t\t\treturn this.tree._callHook(\"nodeToggleExpanded\", this);\n\t\t},\n\t\t/** Flip selection status. */\n\t\ttoggleSelected: function() {\n\t\t\treturn this.tree._callHook(\"nodeToggleSelected\", this);\n\t\t},\n\t\ttoString: function() {\n\t\t\treturn \"FancytreeNode@\" + this.key + \"[title='\" + this.title + \"']\";\n\t\t\t// return \"<FancytreeNode(#\" + this.key + \", '\" + this.title + \"')>\";\n\t\t},\n\t\t/**\n\t\t * Trigger `modifyChild` event on a parent to signal that a child was modified.\n\t\t * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...\n\t\t * @param {FancytreeNode} [childNode]\n\t\t * @param {object} [extra]\n\t\t */\n\t\ttriggerModifyChild: function(operation, childNode, extra) {\n\t\t\tvar data,\n\t\t\t\tmodifyChild = this.tree.options.modifyChild;\n\n\t\t\tif (modifyChild) {\n\t\t\t\tif (childNode && childNode.parent !== this) {\n\t\t\t\t\t$.error(\n\t\t\t\t\t\t\"childNode \" + childNode + \" is not a child of \" + this\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tdata = {\n\t\t\t\t\tnode: this,\n\t\t\t\t\ttree: this.tree,\n\t\t\t\t\toperation: operation,\n\t\t\t\t\tchildNode: childNode || null,\n\t\t\t\t};\n\t\t\t\tif (extra) {\n\t\t\t\t\t$.extend(data, extra);\n\t\t\t\t}\n\t\t\t\tmodifyChild({ type: \"modifyChild\" }, data);\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * Trigger `modifyChild` event on node.parent(!).\n\t\t * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...\n\t\t * @param {object} [extra]\n\t\t */\n\t\ttriggerModify: function(operation, extra) {\n\t\t\tthis.parent.triggerModifyChild(operation, this, extra);\n\t\t},\n\t\t/** Call fn(node) for all child nodes in hierarchical order (depth-first).<br>\n\t\t * Stop iteration, if fn() returns false. Skip current branch, if fn() returns \"skip\".<br>\n\t\t * Return false if iteration was stopped.\n\t\t *\n\t\t * @param {function} fn the callback function.\n\t\t *     Return false to stop iteration, return \"skip\" to skip this node and\n\t\t *     its children only.\n\t\t * @param {boolean} [includeSelf=false]\n\t\t * @returns {boolean}\n\t\t */\n\t\tvisit: function(fn, includeSelf) {\n\t\t\tvar i,\n\t\t\t\tl,\n\t\t\t\tres = true,\n\t\t\t\tchildren = this.children;\n\n\t\t\tif (includeSelf === true) {\n\t\t\t\tres = fn(this);\n\t\t\t\tif (res === false || res === \"skip\") {\n\t\t\t\t\treturn res;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (children) {\n\t\t\t\tfor (i = 0, l = children.length; i < l; i++) {\n\t\t\t\t\tres = children[i].visit(fn, true);\n\t\t\t\t\tif (res === false) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\t/** Call fn(node) for all child nodes and recursively load lazy children.<br>\n\t\t * <b>Note:</b> If you need this method, you probably should consider to review\n\t\t * your architecture! Recursivley loading nodes is a perfect way for lazy\n\t\t * programmers to flood the server with requests ;-)\n\t\t *\n\t\t * @param {function} [fn] optional callback function.\n\t\t *     Return false to stop iteration, return \"skip\" to skip this node and\n\t\t *     its children only.\n\t\t * @param {boolean} [includeSelf=false]\n\t\t * @returns {$.Promise}\n\t\t * @since 2.4\n\t\t */\n\t\tvisitAndLoad: function(fn, includeSelf, _recursion) {\n\t\t\tvar dfd,\n\t\t\t\tres,\n\t\t\t\tloaders,\n\t\t\t\tnode = this;\n\n\t\t\t// node.debug(\"visitAndLoad\");\n\t\t\tif (fn && includeSelf === true) {\n\t\t\t\tres = fn(node);\n\t\t\t\tif (res === false || res === \"skip\") {\n\t\t\t\t\treturn _recursion ? res : _getResolvedPromise();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!node.children && !node.lazy) {\n\t\t\t\treturn _getResolvedPromise();\n\t\t\t}\n\t\t\tdfd = new $.Deferred();\n\t\t\tloaders = [];\n\t\t\t// node.debug(\"load()...\");\n\t\t\tnode.load().done(function() {\n\t\t\t\t// node.debug(\"load()... done.\");\n\t\t\t\tfor (var i = 0, l = node.children.length; i < l; i++) {\n\t\t\t\t\tres = node.children[i].visitAndLoad(fn, true, true);\n\t\t\t\t\tif (res === false) {\n\t\t\t\t\t\tdfd.reject();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else if (res !== \"skip\") {\n\t\t\t\t\t\tloaders.push(res); // Add promise to the list\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$.when.apply(this, loaders).then(function() {\n\t\t\t\t\tdfd.resolve();\n\t\t\t\t});\n\t\t\t});\n\t\t\treturn dfd.promise();\n\t\t},\n\t\t/** Call fn(node) for all parent nodes, bottom-up, including invisible system root.<br>\n\t\t * Stop iteration, if fn() returns false.<br>\n\t\t * Return false if iteration was stopped.\n\t\t *\n\t\t * @param {function} fn the callback function.\n\t\t *     Return false to stop iteration, return \"skip\" to skip this node and children only.\n\t\t * @param {boolean} [includeSelf=false]\n\t\t * @returns {boolean}\n\t\t */\n\t\tvisitParents: function(fn, includeSelf) {\n\t\t\t// Visit parent nodes (bottom up)\n\t\t\tif (includeSelf && fn(this) === false) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar p = this.parent;\n\t\t\twhile (p) {\n\t\t\t\tif (fn(p) === false) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tp = p.parent;\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\t/** Call fn(node) for all sibling nodes.<br>\n\t\t * Stop iteration, if fn() returns false.<br>\n\t\t * Return false if iteration was stopped.\n\t\t *\n\t\t * @param {function} fn the callback function.\n\t\t *     Return false to stop iteration.\n\t\t * @param {boolean} [includeSelf=false]\n\t\t * @returns {boolean}\n\t\t */\n\t\tvisitSiblings: function(fn, includeSelf) {\n\t\t\tvar i,\n\t\t\t\tl,\n\t\t\t\tn,\n\t\t\t\tac = this.parent.children;\n\n\t\t\tfor (i = 0, l = ac.length; i < l; i++) {\n\t\t\t\tn = ac[i];\n\t\t\t\tif (includeSelf || n !== this) {\n\t\t\t\t\tif (fn(n) === false) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\t/** Write warning to browser console if debugLevel >= 2 (prepending node info)\n\t\t *\n\t\t * @param {*} msg string or object or array of such\n\t\t */\n\t\twarn: function(msg) {\n\t\t\tif (this.tree.options.debugLevel >= 2) {\n\t\t\t\tArray.prototype.unshift.call(arguments, this.toString());\n\t\t\t\tconsoleApply(\"warn\", arguments);\n\t\t\t}\n\t\t},\n\t};\n\n\t/******************************************************************************\n\t * Fancytree\n\t */\n\t/**\n\t * Construct a new tree object.\n\t *\n\t * @class Fancytree\n\t * @classdesc The controller behind a fancytree.\n\t * This class also contains 'hook methods': see {@link Fancytree_Hooks}.\n\t *\n\t * @param {Widget} widget\n\t *\n\t * @property {string} _id Automatically generated unique tree instance ID, e.g. \"1\".\n\t * @property {string} _ns Automatically generated unique tree namespace, e.g. \".fancytree-1\".\n\t * @property {FancytreeNode} activeNode Currently active node or null.\n\t * @property {string} ariaPropName Property name of FancytreeNode that contains the element which will receive the aria attributes.\n\t *     Typically \"li\", but \"tr\" for table extension.\n\t * @property {jQueryObject} $container Outer `<ul>` element (or `<table>` element for ext-table).\n\t * @property {jQueryObject} $div A jQuery object containing the element used to instantiate the tree widget (`widget.element`)\n\t * @property {object|array} columns Recommended place to store shared column meta data. @since 2.27\n\t * @property {object} data Metadata, i.e. properties that may be passed to `source` in addition to a children array.\n\t * @property {object} ext Hash of all active plugin instances.\n\t * @property {FancytreeNode} focusNode Currently focused node or null.\n\t * @property {FancytreeNode} lastSelectedNode Used to implement selectMode 1 (single select)\n\t * @property {string} nodeContainerAttrName Property name of FancytreeNode that contains the outer element of single nodes.\n\t *     Typically \"li\", but \"tr\" for table extension.\n\t * @property {FancytreeOptions} options Current options, i.e. default options + options passed to constructor.\n\t * @property {FancytreeNode} rootNode Invisible system root node.\n\t * @property {string} statusClassPropName Property name of FancytreeNode that contains the element which will receive the status classes.\n\t *     Typically \"span\", but \"tr\" for table extension.\n\t * @property {object} types Map for shared type specific meta data, used with node.type attribute. @since 2.27\n\t * @property {object} viewport See ext-vieport. @since v2.31\n\t * @property {object} widget Base widget instance.\n\t */\n\tfunction Fancytree(widget) {\n\t\tthis.widget = widget;\n\t\tthis.$div = widget.element;\n\t\tthis.options = widget.options;\n\t\tif (this.options) {\n\t\t\tif (this.options.lazyload !== undefined) {\n\t\t\t\t$.error(\n\t\t\t\t\t\"The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead.\"\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.options.loaderror !== undefined) {\n\t\t\t\t$.error(\n\t\t\t\t\t\"The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead.\"\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.options.fx !== undefined) {\n\t\t\t\t$.error(\n\t\t\t\t\t\"The 'fx' option was replaced by 'toggleEffect' since 2014-11-30.\"\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.options.removeNode !== undefined) {\n\t\t\t\t$.error(\n\t\t\t\t\t\"The 'removeNode' event was replaced by 'modifyChild' since 2.20 (2016-09-10).\"\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tthis.ext = {}; // Active extension instances\n\t\tthis.types = {};\n\t\tthis.columns = {};\n\t\t// allow to init tree.data.foo from <div data-foo=''>\n\t\tthis.data = _getElementDataAsDict(this.$div);\n\t\t// TODO: use widget.uuid instead?\n\t\tthis._id = \"\" + (this.options.treeId || $.ui.fancytree._nextId++);\n\t\t// TODO: use widget.eventNamespace instead?\n\t\tthis._ns = \".fancytree-\" + this._id; // append for namespaced events\n\t\tthis.activeNode = null;\n\t\tthis.focusNode = null;\n\t\tthis._hasFocus = null;\n\t\tthis._tempCache = {};\n\t\tthis._lastMousedownNode = null;\n\t\tthis._enableUpdate = true;\n\t\tthis.lastSelectedNode = null;\n\t\tthis.systemFocusElement = null;\n\t\tthis.lastQuicksearchTerm = \"\";\n\t\tthis.lastQuicksearchTime = 0;\n\t\tthis.viewport = null; // ext-grid\n\n\t\tthis.statusClassPropName = \"span\";\n\t\tthis.ariaPropName = \"li\";\n\t\tthis.nodeContainerAttrName = \"li\";\n\n\t\t// Remove previous markup if any\n\t\tthis.$div.find(\">ul.fancytree-container\").remove();\n\n\t\t// Create a node without parent.\n\t\tvar fakeParent = { tree: this },\n\t\t\t$ul;\n\t\tthis.rootNode = new FancytreeNode(fakeParent, {\n\t\t\ttitle: \"root\",\n\t\t\tkey: \"root_\" + this._id,\n\t\t\tchildren: null,\n\t\t\texpanded: true,\n\t\t});\n\t\tthis.rootNode.parent = null;\n\n\t\t// Create root markup\n\t\t$ul = $(\"<ul>\", {\n\t\t\tid: \"ft-id-\" + this._id,\n\t\t\tclass: \"ui-fancytree fancytree-container fancytree-plain\",\n\t\t}).appendTo(this.$div);\n\t\tthis.$container = $ul;\n\t\tthis.rootNode.ul = $ul[0];\n\n\t\tif (this.options.debugLevel == null) {\n\t\t\tthis.options.debugLevel = FT.debugLevel;\n\t\t}\n\t\t// // Add container to the TAB chain\n\t\t// // See http://www.w3.org/TR/wai-aria-practices/#focus_activedescendant\n\t\t// // #577: Allow to set tabindex to \"0\", \"-1\" and \"\"\n\t\t// this.$container.attr(\"tabindex\", this.options.tabindex);\n\n\t\t// if( this.options.rtl ) {\n\t\t// \tthis.$container.attr(\"DIR\", \"RTL\").addClass(\"fancytree-rtl\");\n\t\t// // }else{\n\t\t// //\tthis.$container.attr(\"DIR\", null).removeClass(\"fancytree-rtl\");\n\t\t// }\n\t\t// if(this.options.aria){\n\t\t// \tthis.$container.attr(\"role\", \"tree\");\n\t\t// \tif( this.options.selectMode !== 1 ) {\n\t\t// \t\tthis.$container.attr(\"aria-multiselectable\", true);\n\t\t// \t}\n\t\t// }\n\t}\n\n\tFancytree.prototype = /** @lends Fancytree# */ {\n\t\t/* Return a context object that can be re-used for _callHook().\n\t\t * @param {Fancytree | FancytreeNode | EventData} obj\n\t\t * @param {Event} originalEvent\n\t\t * @param {Object} extra\n\t\t * @returns {EventData}\n\t\t */\n\t\t_makeHookContext: function(obj, originalEvent, extra) {\n\t\t\tvar ctx, tree;\n\t\t\tif (obj.node !== undefined) {\n\t\t\t\t// obj is already a context object\n\t\t\t\tif (originalEvent && obj.originalEvent !== originalEvent) {\n\t\t\t\t\t$.error(\"invalid args\");\n\t\t\t\t}\n\t\t\t\tctx = obj;\n\t\t\t} else if (obj.tree) {\n\t\t\t\t// obj is a FancytreeNode\n\t\t\t\ttree = obj.tree;\n\t\t\t\tctx = {\n\t\t\t\t\tnode: obj,\n\t\t\t\t\ttree: tree,\n\t\t\t\t\twidget: tree.widget,\n\t\t\t\t\toptions: tree.widget.options,\n\t\t\t\t\toriginalEvent: originalEvent,\n\t\t\t\t\ttypeInfo: tree.types[obj.type] || {},\n\t\t\t\t};\n\t\t\t} else if (obj.widget) {\n\t\t\t\t// obj is a Fancytree\n\t\t\t\tctx = {\n\t\t\t\t\tnode: null,\n\t\t\t\t\ttree: obj,\n\t\t\t\t\twidget: obj.widget,\n\t\t\t\t\toptions: obj.widget.options,\n\t\t\t\t\toriginalEvent: originalEvent,\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\t$.error(\"invalid args\");\n\t\t\t}\n\t\t\tif (extra) {\n\t\t\t\t$.extend(ctx, extra);\n\t\t\t}\n\t\t\treturn ctx;\n\t\t},\n\t\t/* Trigger a hook function: funcName(ctx, [...]).\n\t\t *\n\t\t * @param {string} funcName\n\t\t * @param {Fancytree|FancytreeNode|EventData} contextObject\n\t\t * @param {any}  [_extraArgs] optional additional arguments\n\t\t * @returns {any}\n\t\t */\n\t\t_callHook: function(funcName, contextObject, _extraArgs) {\n\t\t\tvar ctx = this._makeHookContext(contextObject),\n\t\t\t\tfn = this[funcName],\n\t\t\t\targs = Array.prototype.slice.call(arguments, 2);\n\t\t\tif (!$.isFunction(fn)) {\n\t\t\t\t$.error(\"_callHook('\" + funcName + \"') is not a function\");\n\t\t\t}\n\t\t\targs.unshift(ctx);\n\t\t\t// this.debug(\"_hook\", funcName, ctx.node && ctx.node.toString() || ctx.tree.toString(), args);\n\t\t\treturn fn.apply(this, args);\n\t\t},\n\t\t_setExpiringValue: function(key, value, ms) {\n\t\t\tthis._tempCache[key] = {\n\t\t\t\tvalue: value,\n\t\t\t\texpire: Date.now() + (+ms || 50),\n\t\t\t};\n\t\t},\n\t\t_getExpiringValue: function(key) {\n\t\t\tvar entry = this._tempCache[key];\n\t\t\tif (entry && entry.expire > Date.now()) {\n\t\t\t\treturn entry.value;\n\t\t\t}\n\t\t\tdelete this._tempCache[key];\n\t\t\treturn null;\n\t\t},\n\t\t/* Check if this tree has extension `name` enabled.\n\t\t *\n\t\t * @param {string} name name of the required extension\n\t\t */\n\t\t_usesExtension: function(name) {\n\t\t\treturn $.inArray(name, this.options.extensions) >= 0;\n\t\t},\n\t\t/* Check if current extensions dependencies are met and throw an error if not.\n\t\t *\n\t\t * This method may be called inside the `treeInit` hook for custom extensions.\n\t\t *\n\t\t * @param {string} name name of the required extension\n\t\t * @param {boolean} [required=true] pass `false` if the extension is optional, but we want to check for order if it is present\n\t\t * @param {boolean} [before] `true` if `name` must be included before this, `false` otherwise (use `null` if order doesn't matter)\n\t\t * @param {string} [message] optional error message (defaults to a descriptve error message)\n\t\t */\n\t\t_requireExtension: function(name, required, before, message) {\n\t\t\tif (before != null) {\n\t\t\t\tbefore = !!before;\n\t\t\t}\n\t\t\tvar thisName = this._local.name,\n\t\t\t\textList = this.options.extensions,\n\t\t\t\tisBefore =\n\t\t\t\t\t$.inArray(name, extList) < $.inArray(thisName, extList),\n\t\t\t\tisMissing = required && this.ext[name] == null,\n\t\t\t\tbadOrder = !isMissing && before != null && before !== isBefore;\n\n\t\t\t_assert(\n\t\t\t\tthisName && thisName !== name,\n\t\t\t\t\"invalid or same name '\" + thisName + \"' (require yourself?)\"\n\t\t\t);\n\n\t\t\tif (isMissing || badOrder) {\n\t\t\t\tif (!message) {\n\t\t\t\t\tif (isMissing || required) {\n\t\t\t\t\t\tmessage =\n\t\t\t\t\t\t\t\"'\" +\n\t\t\t\t\t\t\tthisName +\n\t\t\t\t\t\t\t\"' extension requires '\" +\n\t\t\t\t\t\t\tname +\n\t\t\t\t\t\t\t\"'\";\n\t\t\t\t\t\tif (badOrder) {\n\t\t\t\t\t\t\tmessage +=\n\t\t\t\t\t\t\t\t\" to be registered \" +\n\t\t\t\t\t\t\t\t(before ? \"before\" : \"after\") +\n\t\t\t\t\t\t\t\t\" itself\";\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmessage =\n\t\t\t\t\t\t\t\"If used together, `\" +\n\t\t\t\t\t\t\tname +\n\t\t\t\t\t\t\t\"` must be registered \" +\n\t\t\t\t\t\t\t(before ? \"before\" : \"after\") +\n\t\t\t\t\t\t\t\" `\" +\n\t\t\t\t\t\t\tthisName +\n\t\t\t\t\t\t\t\"`\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$.error(message);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\t/** Activate node with a given key and fire focus and activate events.\n\t\t *\n\t\t * A previously activated node will be deactivated.\n\t\t * If activeVisible option is set, all parents will be expanded as necessary.\n\t\t * Pass key = false, to deactivate the current node only.\n\t\t * @param {string} key\n\t\t * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false}\n\t\t * @returns {FancytreeNode} activated node (null, if not found)\n\t\t */\n\t\tactivateKey: function(key, opts) {\n\t\t\tvar node = this.getNodeByKey(key);\n\t\t\tif (node) {\n\t\t\t\tnode.setActive(true, opts);\n\t\t\t} else if (this.activeNode) {\n\t\t\t\tthis.activeNode.setActive(false, opts);\n\t\t\t}\n\t\t\treturn node;\n\t\t},\n\t\t/** (experimental) Add child status nodes that indicate 'More...', ....\n\t\t * @param {boolean|object} node optional node definition. Pass `false` to remove all paging nodes.\n\t\t * @param {string} [mode='append'] 'child'|firstChild'\n\t\t * @since 2.15\n\t\t */\n\t\taddPagingNode: function(node, mode) {\n\t\t\treturn this.rootNode.addPagingNode(node, mode);\n\t\t},\n\t\t/**\n\t\t * (experimental) Apply a modification (or navigation) operation.\n\t\t *\n\t\t * Valid commands:\n\t\t *   - 'moveUp', 'moveDown'\n\t\t *   - 'indent', 'outdent'\n\t\t *   - 'remove'\n\t\t *   - 'edit', 'addChild', 'addSibling': (reqires ext-edit extension)\n\t\t *   - 'cut', 'copy', 'paste': (use an internal singleton 'clipboard')\n\t\t *   - 'down', 'first', 'last', 'left', 'parent', 'right', 'up': navigate\n\t\t *\n\t\t * @param {string} cmd\n\t\t * @param {FancytreeNode} [node=active_node]\n\t\t * @param {object} [opts] Currently unused\n\t\t *\n\t\t * @since 2.32\n\t\t */\n\t\tapplyCommand: function(cmd, node, opts_) {\n\t\t\tvar // clipboard,\n\t\t\t\trefNode;\n\t\t\t// opts = $.extend(\n\t\t\t// \t{ setActive: true, clipboard: CLIPBOARD },\n\t\t\t// \topts_\n\t\t\t// );\n\n\t\t\tnode = node || this.getActiveNode();\n\t\t\t// clipboard = opts.clipboard;\n\n\t\t\tswitch (cmd) {\n\t\t\t\t// Sorting and indentation:\n\t\t\t\tcase \"moveUp\":\n\t\t\t\t\trefNode = node.getPrevSibling();\n\t\t\t\t\tif (refNode) {\n\t\t\t\t\t\tnode.moveTo(refNode, \"before\");\n\t\t\t\t\t\tnode.setActive();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"moveDown\":\n\t\t\t\t\trefNode = node.getNextSibling();\n\t\t\t\t\tif (refNode) {\n\t\t\t\t\t\tnode.moveTo(refNode, \"after\");\n\t\t\t\t\t\tnode.setActive();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"indent\":\n\t\t\t\t\trefNode = node.getPrevSibling();\n\t\t\t\t\tif (refNode) {\n\t\t\t\t\t\tnode.moveTo(refNode, \"child\");\n\t\t\t\t\t\trefNode.setExpanded();\n\t\t\t\t\t\tnode.setActive();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"outdent\":\n\t\t\t\t\tif (!node.isTopLevel()) {\n\t\t\t\t\t\tnode.moveTo(node.getParent(), \"after\");\n\t\t\t\t\t\tnode.setActive();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t// Remove:\n\t\t\t\tcase \"remove\":\n\t\t\t\t\trefNode = node.getPrevSibling() || node.getParent();\n\t\t\t\t\tnode.remove();\n\t\t\t\t\tif (refNode) {\n\t\t\t\t\t\trefNode.setActive();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t// Add, edit (requires ext-edit):\n\t\t\t\tcase \"addChild\":\n\t\t\t\t\tnode.editCreateNode(\"child\", \"\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"addSibling\":\n\t\t\t\t\tnode.editCreateNode(\"after\", \"\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"rename\":\n\t\t\t\t\tnode.editStart();\n\t\t\t\t\tbreak;\n\t\t\t\t// Simple clipboard simulation:\n\t\t\t\t// case \"cut\":\n\t\t\t\t// \tclipboard = { mode: cmd, data: node };\n\t\t\t\t// \tbreak;\n\t\t\t\t// case \"copy\":\n\t\t\t\t// \tclipboard = {\n\t\t\t\t// \t\tmode: cmd,\n\t\t\t\t// \t\tdata: node.toDict(function(n) {\n\t\t\t\t// \t\t\tdelete n.key;\n\t\t\t\t// \t\t}),\n\t\t\t\t// \t};\n\t\t\t\t// \tbreak;\n\t\t\t\t// case \"clear\":\n\t\t\t\t// \tclipboard = null;\n\t\t\t\t// \tbreak;\n\t\t\t\t// case \"paste\":\n\t\t\t\t// \tif (clipboard.mode === \"cut\") {\n\t\t\t\t// \t\t// refNode = node.getPrevSibling();\n\t\t\t\t// \t\tclipboard.data.moveTo(node, \"child\");\n\t\t\t\t// \t\tclipboard.data.setActive();\n\t\t\t\t// \t} else if (clipboard.mode === \"copy\") {\n\t\t\t\t// \t\tnode.addChildren(clipboard.data).setActive();\n\t\t\t\t// \t}\n\t\t\t\t// \tbreak;\n\t\t\t\t// Navigation commands:\n\t\t\t\tcase \"down\":\n\t\t\t\tcase \"first\":\n\t\t\t\tcase \"last\":\n\t\t\t\tcase \"left\":\n\t\t\t\tcase \"parent\":\n\t\t\t\tcase \"right\":\n\t\t\t\tcase \"up\":\n\t\t\t\t\treturn node.navigate(cmd);\n\t\t\t\tdefault:\n\t\t\t\t\t$.error(\"Unhandled command: '\" + cmd + \"'\");\n\t\t\t}\n\t\t},\n\t\t/** (experimental) Modify existing data model.\n\t\t *\n\t\t * @param {Array} patchList array of [key, NodePatch] arrays\n\t\t * @returns {$.Promise} resolved, when all patches have been applied\n\t\t * @see TreePatch\n\t\t */\n\t\tapplyPatch: function(patchList) {\n\t\t\tvar dfd,\n\t\t\t\ti,\n\t\t\t\tp2,\n\t\t\t\tkey,\n\t\t\t\tpatch,\n\t\t\t\tnode,\n\t\t\t\tpatchCount = patchList.length,\n\t\t\t\tdeferredList = [];\n\n\t\t\tfor (i = 0; i < patchCount; i++) {\n\t\t\t\tp2 = patchList[i];\n\t\t\t\t_assert(\n\t\t\t\t\tp2.length === 2,\n\t\t\t\t\t\"patchList must be an array of length-2-arrays\"\n\t\t\t\t);\n\t\t\t\tkey = p2[0];\n\t\t\t\tpatch = p2[1];\n\t\t\t\tnode = key === null ? this.rootNode : this.getNodeByKey(key);\n\t\t\t\tif (node) {\n\t\t\t\t\tdfd = new $.Deferred();\n\t\t\t\t\tdeferredList.push(dfd);\n\t\t\t\t\tnode.applyPatch(patch).always(_makeResolveFunc(dfd, node));\n\t\t\t\t} else {\n\t\t\t\t\tthis.warn(\"could not find node with key '\" + key + \"'\");\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Return a promise that is resolved, when ALL patches were applied\n\t\t\treturn $.when.apply($, deferredList).promise();\n\t\t},\n\t\t/* TODO: implement in dnd extension\n\t\tcancelDrag: function() {\n\t\t\t\tvar dd = $.ui.ddmanager.current;\n\t\t\t\tif(dd){\n\t\t\t\t\tdd.cancel();\n\t\t\t\t}\n\t\t\t},\n\t\t*/\n\t\t/** Remove all nodes.\n\t\t * @since 2.14\n\t\t */\n\t\tclear: function(source) {\n\t\t\tthis._callHook(\"treeClear\", this);\n\t\t},\n\t\t/** Return the number of nodes.\n\t\t * @returns {integer}\n\t\t */\n\t\tcount: function() {\n\t\t\treturn this.rootNode.countChildren();\n\t\t},\n\t\t/** Write to browser console if debugLevel >= 4 (prepending tree name)\n\t\t *\n\t\t * @param {*} msg string or object or array of such\n\t\t */\n\t\tdebug: function(msg) {\n\t\t\tif (this.options.debugLevel >= 4) {\n\t\t\t\tArray.prototype.unshift.call(arguments, this.toString());\n\t\t\t\tconsoleApply(\"log\", arguments);\n\t\t\t}\n\t\t},\n\t\t/** Destroy this widget, restore previous markup and cleanup resources.\n\t\t *\n\t\t * @since 2.34\n\t\t */\n\t\tdestroy: function() {\n\t\t\tthis.widget.destroy();\n\t\t},\n\t\t/** Enable (or disable) the tree control.\n\t\t *\n\t\t * @param {boolean} [flag=true] pass false to disable\n\t\t * @since 2.30\n\t\t */\n\t\tenable: function(flag) {\n\t\t\tif (flag === false) {\n\t\t\t\tthis.widget.disable();\n\t\t\t} else {\n\t\t\t\tthis.widget.enable();\n\t\t\t}\n\t\t},\n\t\t/** Temporarily suppress rendering to improve performance on bulk-updates.\n\t\t *\n\t\t * @param {boolean} flag\n\t\t * @returns {boolean} previous status\n\t\t * @since 2.19\n\t\t */\n\t\tenableUpdate: function(flag) {\n\t\t\tflag = flag !== false;\n\t\t\tif (!!this._enableUpdate === !!flag) {\n\t\t\t\treturn flag;\n\t\t\t}\n\t\t\tthis._enableUpdate = flag;\n\t\t\tif (flag) {\n\t\t\t\tthis.debug(\"enableUpdate(true): redraw \"); //, this._dirtyRoots);\n\t\t\t\tthis._callHook(\"treeStructureChanged\", this, \"enableUpdate\");\n\t\t\t\tthis.render();\n\t\t\t} else {\n\t\t\t\t// \tthis._dirtyRoots = null;\n\t\t\t\tthis.debug(\"enableUpdate(false)...\");\n\t\t\t}\n\t\t\treturn !flag; // return previous value\n\t\t},\n\t\t/** Write error to browser console if debugLevel >= 1 (prepending tree info)\n\t\t *\n\t\t * @param {*} msg string or object or array of such\n\t\t */\n\t\terror: function(msg) {\n\t\t\tif (this.options.debugLevel >= 1) {\n\t\t\t\tArray.prototype.unshift.call(arguments, this.toString());\n\t\t\t\tconsoleApply(\"error\", arguments);\n\t\t\t}\n\t\t},\n\t\t/** Expand (or collapse) all parent nodes.\n\t\t *\n\t\t * This convenience method uses `tree.visit()` and `tree.setExpanded()`\n\t\t * internally.\n\t\t *\n\t\t * @param {boolean} [flag=true] pass false to collapse\n\t\t * @param {object} [opts] passed to setExpanded()\n\t\t * @since 2.30\n\t\t */\n\t\texpandAll: function(flag, opts) {\n\t\t\tvar prev = this.enableUpdate(false);\n\n\t\t\tflag = flag !== false;\n\t\t\tthis.visit(function(node) {\n\t\t\t\tif (\n\t\t\t\t\tnode.hasChildren() !== false &&\n\t\t\t\t\tnode.isExpanded() !== flag\n\t\t\t\t) {\n\t\t\t\t\tnode.setExpanded(flag, opts);\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.enableUpdate(prev);\n\t\t},\n\t\t/**Find all nodes that matches condition.\n\t\t *\n\t\t * @param {string | function(node)} match title string to search for, or a\n\t\t *     callback function that returns `true` if a node is matched.\n\t\t * @returns {FancytreeNode[]} array of nodes (may be empty)\n\t\t * @see FancytreeNode#findAll\n\t\t * @since 2.12\n\t\t */\n\t\tfindAll: function(match) {\n\t\t\treturn this.rootNode.findAll(match);\n\t\t},\n\t\t/**Find first node that matches condition.\n\t\t *\n\t\t * @param {string | function(node)} match title string to search for, or a\n\t\t *     callback function that returns `true` if a node is matched.\n\t\t * @returns {FancytreeNode} matching node or null\n\t\t * @see FancytreeNode#findFirst\n\t\t * @since 2.12\n\t\t */\n\t\tfindFirst: function(match) {\n\t\t\treturn this.rootNode.findFirst(match);\n\t\t},\n\t\t/** Find the next visible node that starts with `match`, starting at `startNode`\n\t\t * and wrap-around at the end.\n\t\t *\n\t\t * @param {string|function} match\n\t\t * @param {FancytreeNode} [startNode] defaults to first node\n\t\t * @returns {FancytreeNode} matching node or null\n\t\t */\n\t\tfindNextNode: function(match, startNode) {\n\t\t\t//, visibleOnly) {\n\t\t\tvar res = null,\n\t\t\t\tfirstNode = this.getFirstChild();\n\n\t\t\tmatch =\n\t\t\t\ttypeof match === \"string\"\n\t\t\t\t\t? _makeNodeTitleStartMatcher(match)\n\t\t\t\t\t: match;\n\t\t\tstartNode = startNode || firstNode;\n\n\t\t\tfunction _checkNode(n) {\n\t\t\t\t// console.log(\"_check \" + n)\n\t\t\t\tif (match(n)) {\n\t\t\t\t\tres = n;\n\t\t\t\t}\n\t\t\t\tif (res || n === startNode) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.visitRows(_checkNode, {\n\t\t\t\tstart: startNode,\n\t\t\t\tincludeSelf: false,\n\t\t\t});\n\t\t\t// Wrap around search\n\t\t\tif (!res && startNode !== firstNode) {\n\t\t\t\tthis.visitRows(_checkNode, {\n\t\t\t\t\tstart: firstNode,\n\t\t\t\t\tincludeSelf: true,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\t/** Find a node relative to another node.\n\t\t *\n\t\t * @param {FancytreeNode} node\n\t\t * @param {string|number} where 'down', 'first', 'last', 'left', 'parent', 'right', or 'up'.\n\t\t *   (Alternatively the keyCode that would normally trigger this move,\n\t\t *   e.g. `$.ui.keyCode.LEFT` = 'left'.\n\t\t * @param {boolean} [includeHidden=false] Not yet implemented\n\t\t * @returns {FancytreeNode|null}\n\t\t * @since v2.31\n\t\t */\n\t\tfindRelatedNode: function(node, where, includeHidden) {\n\t\t\tvar res = null,\n\t\t\t\tKC = $.ui.keyCode;\n\n\t\t\tswitch (where) {\n\t\t\t\tcase \"parent\":\n\t\t\t\tcase KC.BACKSPACE:\n\t\t\t\t\tif (node.parent && node.parent.parent) {\n\t\t\t\t\t\tres = node.parent;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"first\":\n\t\t\t\tcase KC.HOME:\n\t\t\t\t\t// First visible node\n\t\t\t\t\tthis.visit(function(n) {\n\t\t\t\t\t\tif (n.isVisible()) {\n\t\t\t\t\t\t\tres = n;\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"last\":\n\t\t\t\tcase KC.END:\n\t\t\t\t\tthis.visit(function(n) {\n\t\t\t\t\t\t// last visible node\n\t\t\t\t\t\tif (n.isVisible()) {\n\t\t\t\t\t\t\tres = n;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"left\":\n\t\t\t\tcase KC.LEFT:\n\t\t\t\t\tif (node.expanded) {\n\t\t\t\t\t\tnode.setExpanded(false);\n\t\t\t\t\t} else if (node.parent && node.parent.parent) {\n\t\t\t\t\t\tres = node.parent;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"right\":\n\t\t\t\tcase KC.RIGHT:\n\t\t\t\t\tif (!node.expanded && (node.children || node.lazy)) {\n\t\t\t\t\t\tnode.setExpanded();\n\t\t\t\t\t\tres = node;\n\t\t\t\t\t} else if (node.children && node.children.length) {\n\t\t\t\t\t\tres = node.children[0];\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"up\":\n\t\t\t\tcase KC.UP:\n\t\t\t\t\tthis.visitRows(\n\t\t\t\t\t\tfunction(n) {\n\t\t\t\t\t\t\tres = n;\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ start: node, reverse: true, includeSelf: false }\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"down\":\n\t\t\t\tcase KC.DOWN:\n\t\t\t\t\tthis.visitRows(\n\t\t\t\t\t\tfunction(n) {\n\t\t\t\t\t\t\tres = n;\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ start: node, includeSelf: false }\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthis.tree.warn(\"Unknown relation '\" + where + \"'.\");\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\t// TODO: fromDict\n\t\t/**\n\t\t * Generate INPUT elements that can be submitted with html forms.\n\t\t *\n\t\t * In selectMode 3 only the topmost selected nodes are considered, unless\n\t\t * `opts.stopOnParents: false` is passed.\n\t\t *\n\t\t * @example\n\t\t * // Generate input elements for active and selected nodes\n\t\t * tree.generateFormElements();\n\t\t * // Generate input elements selected nodes, using a custom `name` attribute\n\t\t * tree.generateFormElements(\"cust_sel\", false);\n\t\t * // Generate input elements using a custom filter\n\t\t * tree.generateFormElements(true, true, { filter: function(node) {\n\t\t *     return node.isSelected() && node.data.yes;\n\t\t * }});\n\t\t *\n\t\t * @param {boolean | string} [selected=true] Pass false to disable, pass a string to override the field name (default: 'ft_ID[]')\n\t\t * @param {boolean | string} [active=true] Pass false to disable, pass a string to override the field name (default: 'ft_ID_active')\n\t\t * @param {object} [opts] default { filter: null, stopOnParents: true }\n\t\t */\n\t\tgenerateFormElements: function(selected, active, opts) {\n\t\t\topts = opts || {};\n\n\t\t\tvar nodeList,\n\t\t\t\tselectedName =\n\t\t\t\t\ttypeof selected === \"string\"\n\t\t\t\t\t\t? selected\n\t\t\t\t\t\t: \"ft_\" + this._id + \"[]\",\n\t\t\t\tactiveName =\n\t\t\t\t\ttypeof active === \"string\"\n\t\t\t\t\t\t? active\n\t\t\t\t\t\t: \"ft_\" + this._id + \"_active\",\n\t\t\t\tid = \"fancytree_result_\" + this._id,\n\t\t\t\t$result = $(\"#\" + id),\n\t\t\t\tstopOnParents =\n\t\t\t\t\tthis.options.selectMode === 3 &&\n\t\t\t\t\topts.stopOnParents !== false;\n\n\t\t\tif ($result.length) {\n\t\t\t\t$result.empty();\n\t\t\t} else {\n\t\t\t\t$result = $(\"<div>\", {\n\t\t\t\t\tid: id,\n\t\t\t\t})\n\t\t\t\t\t.hide()\n\t\t\t\t\t.insertAfter(this.$container);\n\t\t\t}\n\t\t\tif (active !== false && this.activeNode) {\n\t\t\t\t$result.append(\n\t\t\t\t\t$(\"<input>\", {\n\t\t\t\t\t\ttype: \"radio\",\n\t\t\t\t\t\tname: activeName,\n\t\t\t\t\t\tvalue: this.activeNode.key,\n\t\t\t\t\t\tchecked: true,\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t\tfunction _appender(node) {\n\t\t\t\t$result.append(\n\t\t\t\t\t$(\"<input>\", {\n\t\t\t\t\t\ttype: \"checkbox\",\n\t\t\t\t\t\tname: selectedName,\n\t\t\t\t\t\tvalue: node.key,\n\t\t\t\t\t\tchecked: true,\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (opts.filter) {\n\t\t\t\tthis.visit(function(node) {\n\t\t\t\t\tvar res = opts.filter(node);\n\t\t\t\t\tif (res === \"skip\") {\n\t\t\t\t\t\treturn res;\n\t\t\t\t\t}\n\t\t\t\t\tif (res !== false) {\n\t\t\t\t\t\t_appender(node);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else if (selected !== false) {\n\t\t\t\tnodeList = this.getSelectedNodes(stopOnParents);\n\t\t\t\t$.each(nodeList, function(idx, node) {\n\t\t\t\t\t_appender(node);\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * Return the currently active node or null.\n\t\t * @returns {FancytreeNode}\n\t\t */\n\t\tgetActiveNode: function() {\n\t\t\treturn this.activeNode;\n\t\t},\n\t\t/** Return the first top level node if any (not the invisible root node).\n\t\t * @returns {FancytreeNode | null}\n\t\t */\n\t\tgetFirstChild: function() {\n\t\t\treturn this.rootNode.getFirstChild();\n\t\t},\n\t\t/**\n\t\t * Return node that has keyboard focus or null.\n\t\t * @returns {FancytreeNode}\n\t\t */\n\t\tgetFocusNode: function() {\n\t\t\treturn this.focusNode;\n\t\t},\n\t\t/**\n\t\t * Return current option value.\n\t\t * (Note: this is the preferred variant of `$().fancytree(\"option\", \"KEY\")`)\n\t\t *\n\t\t * @param {string} name option name (may contain '.')\n\t\t * @returns {any}\n\t\t */\n\t\tgetOption: function(optionName) {\n\t\t\treturn this.widget.option(optionName);\n\t\t},\n\t\t/**\n\t\t * Return node with a given key or null if not found.\n\t\t *\n\t\t * @param {string} key\n\t\t * @param {FancytreeNode} [searchRoot] only search below this node\n\t\t * @returns {FancytreeNode | null}\n\t\t */\n\t\tgetNodeByKey: function(key, searchRoot) {\n\t\t\t// Search the DOM by element ID (assuming this is faster than traversing all nodes).\n\t\t\tvar el, match;\n\t\t\t// TODO: use tree.keyMap if available\n\t\t\t// TODO: check opts.generateIds === true\n\t\t\tif (!searchRoot) {\n\t\t\t\tel = document.getElementById(this.options.idPrefix + key);\n\t\t\t\tif (el) {\n\t\t\t\t\treturn el.ftnode ? el.ftnode : null;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Not found in the DOM, but still may be in an unrendered part of tree\n\t\t\tsearchRoot = searchRoot || this.rootNode;\n\t\t\tmatch = null;\n\t\t\tsearchRoot.visit(function(node) {\n\t\t\t\tif (node.key === key) {\n\t\t\t\t\tmatch = node;\n\t\t\t\t\treturn false; // Stop iteration\n\t\t\t\t}\n\t\t\t}, true);\n\t\t\treturn match;\n\t\t},\n\t\t/** Return the invisible system root node.\n\t\t * @returns {FancytreeNode}\n\t\t */\n\t\tgetRootNode: function() {\n\t\t\treturn this.rootNode;\n\t\t},\n\t\t/**\n\t\t * Return an array of selected nodes.\n\t\t *\n\t\t * Note: you cannot send this result via Ajax directly. Instead the\n\t\t * node object need to be converted to plain objects, for example\n\t\t * by using `$.map()` and `node.toDict()`.\n\t\t * @param {boolean} [stopOnParents=false] only return the topmost selected\n\t\t *     node (useful with selectMode 3)\n\t\t * @returns {FancytreeNode[]}\n\t\t */\n\t\tgetSelectedNodes: function(stopOnParents) {\n\t\t\treturn this.rootNode.getSelectedNodes(stopOnParents);\n\t\t},\n\t\t/** Return true if the tree control has keyboard focus\n\t\t * @returns {boolean}\n\t\t */\n\t\thasFocus: function() {\n\t\t\t// var ae = document.activeElement,\n\t\t\t// \thasFocus = !!(\n\t\t\t// \t\tae && $(ae).closest(\".fancytree-container\").length\n\t\t\t// \t);\n\n\t\t\t// if (hasFocus !== !!this._hasFocus) {\n\t\t\t// \tthis.warn(\n\t\t\t// \t\t\"hasFocus(): fix inconsistent container state, now: \" +\n\t\t\t// \t\t\thasFocus\n\t\t\t// \t);\n\t\t\t// \tthis._hasFocus = hasFocus;\n\t\t\t// \tthis.$container.toggleClass(\"fancytree-treefocus\", hasFocus);\n\t\t\t// }\n\t\t\t// return hasFocus;\n\t\t\treturn !!this._hasFocus;\n\t\t},\n\t\t/** Write to browser console if debugLevel >= 3 (prepending tree name)\n\t\t * @param {*} msg string or object or array of such\n\t\t */\n\t\tinfo: function(msg) {\n\t\t\tif (this.options.debugLevel >= 3) {\n\t\t\t\tArray.prototype.unshift.call(arguments, this.toString());\n\t\t\t\tconsoleApply(\"info\", arguments);\n\t\t\t}\n\t\t},\n\t\t/** Return true if any node is currently beeing loaded, i.e. a Ajax request is pending.\n\t\t * @returns {boolean}\n\t\t * @since 2.32\n\t\t */\n\t\tisLoading: function() {\n\t\t\tvar res = false;\n\n\t\t\tthis.rootNode.visit(function(n) {\n\t\t\t\t// also visit rootNode\n\t\t\t\tif (n._isLoading || n._requestId) {\n\t\t\t\t\tres = true;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}, true);\n\t\t\treturn res;\n\t\t},\n\t\t/*\n\t\tTODO: isInitializing: function() {\n\t\t\treturn ( this.phase==\"init\" || this.phase==\"postInit\" );\n\t\t},\n\t\tTODO: isReloading: function() {\n\t\t\treturn ( this.phase==\"init\" || this.phase==\"postInit\" ) && this.options.persist && this.persistence.cookiesFound;\n\t\t},\n\t\tTODO: isUserEvent: function() {\n\t\t\treturn ( this.phase==\"userEvent\" );\n\t\t},\n\t\t*/\n\n\t\t/**\n\t\t * Make sure that a node with a given ID is loaded, by traversing - and\n\t\t * loading - its parents. This method is meant for lazy hierarchies.\n\t\t * A callback is executed for every node as we go.\n\t\t * @example\n\t\t * // Resolve using node.key:\n\t\t * tree.loadKeyPath(\"/_3/_23/_26/_27\", function(node, status){\n\t\t *   if(status === \"loaded\") {\n\t\t *     console.log(\"loaded intermediate node \" + node);\n\t\t *   }else if(status === \"ok\") {\n\t\t *     node.activate();\n\t\t *   }\n\t\t * });\n\t\t * // Use deferred promise:\n\t\t * tree.loadKeyPath(\"/_3/_23/_26/_27\").progress(function(data){\n\t\t *   if(data.status === \"loaded\") {\n\t\t *     console.log(\"loaded intermediate node \" + data.node);\n\t\t *   }else if(data.status === \"ok\") {\n\t\t *     node.activate();\n\t\t *   }\n\t\t * }).done(function(){\n\t\t *    ...\n\t\t * });\n\t\t * // Custom path segment resolver:\n\t\t * tree.loadKeyPath(\"/321/431/21/2\", {\n\t\t *   matchKey: function(node, key){\n\t\t *     return node.data.refKey === key;\n\t\t *   },\n\t\t *   callback: function(node, status){\n\t\t *     if(status === \"loaded\") {\n\t\t *       console.log(\"loaded intermediate node \" + node);\n\t\t *     }else if(status === \"ok\") {\n\t\t *       node.activate();\n\t\t *     }\n\t\t *   }\n\t\t * });\n\t\t * @param {string | string[]} keyPathList one or more key paths (e.g. '/3/2_1/7')\n\t\t * @param {function | object} optsOrCallback callback(node, status) is called for every visited node ('loading', 'loaded', 'ok', 'error').\n\t\t *     Pass an object to define custom key matchers for the path segments: {callback: function, matchKey: function}.\n\t\t * @returns {$.Promise}\n\t\t */\n\t\tloadKeyPath: function(keyPathList, optsOrCallback) {\n\t\t\tvar callback,\n\t\t\t\ti,\n\t\t\t\tpath,\n\t\t\t\tself = this,\n\t\t\t\tdfd = new $.Deferred(),\n\t\t\t\tparent = this.getRootNode(),\n\t\t\t\tsep = this.options.keyPathSeparator,\n\t\t\t\tpathSegList = [],\n\t\t\t\topts = $.extend({}, optsOrCallback);\n\n\t\t\t// Prepare options\n\t\t\tif (typeof optsOrCallback === \"function\") {\n\t\t\t\tcallback = optsOrCallback;\n\t\t\t} else if (optsOrCallback && optsOrCallback.callback) {\n\t\t\t\tcallback = optsOrCallback.callback;\n\t\t\t}\n\t\t\topts.callback = function(ctx, node, status) {\n\t\t\t\tif (callback) {\n\t\t\t\t\tcallback.call(ctx, node, status);\n\t\t\t\t}\n\t\t\t\tdfd.notifyWith(ctx, [{ node: node, status: status }]);\n\t\t\t};\n\t\t\tif (opts.matchKey == null) {\n\t\t\t\topts.matchKey = function(node, key) {\n\t\t\t\t\treturn node.key === key;\n\t\t\t\t};\n\t\t\t}\n\t\t\t// Convert array of path strings to array of segment arrays\n\t\t\tif (!$.isArray(keyPathList)) {\n\t\t\t\tkeyPathList = [keyPathList];\n\t\t\t}\n\t\t\tfor (i = 0; i < keyPathList.length; i++) {\n\t\t\t\tpath = keyPathList[i];\n\t\t\t\t// strip leading slash\n\t\t\t\tif (path.charAt(0) === sep) {\n\t\t\t\t\tpath = path.substr(1);\n\t\t\t\t}\n\t\t\t\t// segListMap[path] = { parent: parent, segList: path.split(sep) };\n\t\t\t\tpathSegList.push(path.split(sep));\n\t\t\t\t// targetList.push({ parent: parent, segList: path.split(sep)/* , path: path*/});\n\t\t\t}\n\t\t\t// The timeout forces async behavior always (even if nodes are all loaded)\n\t\t\t// This way a potential progress() event will fire.\n\t\t\tsetTimeout(function() {\n\t\t\t\tself._loadKeyPathImpl(dfd, opts, parent, pathSegList).done(\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\tdfd.resolve();\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}, 0);\n\t\t\treturn dfd.promise();\n\t\t},\n\t\t/*\n\t\t * Resolve a list of paths, relative to one parent node.\n\t\t */\n\t\t_loadKeyPathImpl: function(dfd, opts, parent, pathSegList) {\n\t\t\tvar deferredList,\n\t\t\t\ti,\n\t\t\t\tkey,\n\t\t\t\tnode,\n\t\t\t\tnodeKey,\n\t\t\t\tremain,\n\t\t\t\tremainMap,\n\t\t\t\ttmpParent,\n\t\t\t\tsegList,\n\t\t\t\tsubDfd,\n\t\t\t\tself = this;\n\n\t\t\tfunction __findChild(parent, key) {\n\t\t\t\t// console.log(\"__findChild\", key, parent);\n\t\t\t\tvar i,\n\t\t\t\t\tl,\n\t\t\t\t\tcl = parent.children;\n\n\t\t\t\tif (cl) {\n\t\t\t\t\tfor (i = 0, l = cl.length; i < l; i++) {\n\t\t\t\t\t\tif (opts.matchKey(cl[i], key)) {\n\t\t\t\t\t\t\treturn cl[i];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// console.log(\"_loadKeyPathImpl, parent=\", parent, \", pathSegList=\", pathSegList);\n\n\t\t\t// Pass 1:\n\t\t\t// Handle all path segments for nodes that are already loaded.\n\t\t\t// Collect distinct top-most lazy nodes in a map.\n\t\t\t// Note that we can use node.key to de-dupe entries, even if a custom matcher would\n\t\t\t// look for other node attributes.\n\t\t\t// map[node.key] => {node: node, pathList: [list of remaining rest-paths]}\n\t\t\tremainMap = {};\n\n\t\t\tfor (i = 0; i < pathSegList.length; i++) {\n\t\t\t\tsegList = pathSegList[i];\n\t\t\t\t// target = targetList[i];\n\n\t\t\t\t// Traverse and pop path segments (i.e. keys), until we hit a lazy, unloaded node\n\t\t\t\ttmpParent = parent;\n\t\t\t\twhile (segList.length) {\n\t\t\t\t\tkey = segList.shift();\n\t\t\t\t\tnode = __findChild(tmpParent, key);\n\t\t\t\t\tif (!node) {\n\t\t\t\t\t\tthis.warn(\n\t\t\t\t\t\t\t\"loadKeyPath: key not found: \" +\n\t\t\t\t\t\t\t\tkey +\n\t\t\t\t\t\t\t\t\" (parent: \" +\n\t\t\t\t\t\t\t\ttmpParent +\n\t\t\t\t\t\t\t\t\")\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\topts.callback(this, key, \"error\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else if (segList.length === 0) {\n\t\t\t\t\t\topts.callback(this, node, \"ok\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else if (!node.lazy || node.hasChildren() !== undefined) {\n\t\t\t\t\t\topts.callback(this, node, \"loaded\");\n\t\t\t\t\t\ttmpParent = node;\n\t\t\t\t\t} else {\n\t\t\t\t\t\topts.callback(this, node, \"loaded\");\n\t\t\t\t\t\tkey = node.key; //target.segList.join(sep);\n\t\t\t\t\t\tif (remainMap[key]) {\n\t\t\t\t\t\t\tremainMap[key].pathSegList.push(segList);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tremainMap[key] = {\n\t\t\t\t\t\t\t\tparent: node,\n\t\t\t\t\t\t\t\tpathSegList: [segList],\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// console.log(\"_loadKeyPathImpl AFTER pass 1, remainMap=\", remainMap);\n\n\t\t\t// Now load all lazy nodes and continue iteration for remaining paths\n\t\t\tdeferredList = [];\n\n\t\t\t// Avoid jshint warning 'Don't make functions within a loop.':\n\t\t\tfunction __lazyload(dfd, parent, pathSegList) {\n\t\t\t\t// console.log(\"__lazyload\", parent, \"pathSegList=\", pathSegList);\n\t\t\t\topts.callback(self, parent, \"loading\");\n\t\t\t\tparent\n\t\t\t\t\t.load()\n\t\t\t\t\t.done(function() {\n\t\t\t\t\t\tself._loadKeyPathImpl\n\t\t\t\t\t\t\t.call(self, dfd, opts, parent, pathSegList)\n\t\t\t\t\t\t\t.always(_makeResolveFunc(dfd, self));\n\t\t\t\t\t})\n\t\t\t\t\t.fail(function(errMsg) {\n\t\t\t\t\t\tself.warn(\"loadKeyPath: error loading lazy \" + parent);\n\t\t\t\t\t\topts.callback(self, node, \"error\");\n\t\t\t\t\t\tdfd.rejectWith(self);\n\t\t\t\t\t});\n\t\t\t}\n\t\t\t// remainMap contains parent nodes, each with a list of relative sub-paths.\n\t\t\t// We start loading all of them now, and pass the the list to each loader.\n\t\t\tfor (nodeKey in remainMap) {\n\t\t\t\tif (remainMap.hasOwnProperty(nodeKey)) {\n\t\t\t\t\tremain = remainMap[nodeKey];\n\t\t\t\t\t// console.log(\"for(): remain=\", remain, \"remainMap=\", remainMap);\n\t\t\t\t\t// key = remain.segList.shift();\n\t\t\t\t\t// node = __findChild(remain.parent, key);\n\t\t\t\t\t// if (node == null) {  // #576\n\t\t\t\t\t// \t// Issue #576, refactored for v2.27:\n\t\t\t\t\t// \t// The root cause was, that sometimes the wrong parent was used here\n\t\t\t\t\t// \t// to find the next segment.\n\t\t\t\t\t// \t// Falling back to getNodeByKey() was a hack that no longer works if a custom\n\t\t\t\t\t// \t// matcher is used, because we cannot assume that a single segment-key is unique\n\t\t\t\t\t// \t// throughout the tree.\n\t\t\t\t\t// \tself.error(\"loadKeyPath: error loading child by key '\" + key + \"' (parent: \" + target.parent + \")\", target);\n\t\t\t\t\t// \t// \tnode = self.getNodeByKey(key);\n\t\t\t\t\t// \tcontinue;\n\t\t\t\t\t// }\n\t\t\t\t\tsubDfd = new $.Deferred();\n\t\t\t\t\tdeferredList.push(subDfd);\n\t\t\t\t\t__lazyload(subDfd, remain.parent, remain.pathSegList);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Return a promise that is resolved, when ALL paths were loaded\n\t\t\treturn $.when.apply($, deferredList).promise();\n\t\t},\n\t\t/** Re-fire beforeActivate, activate, and (optional) focus events.\n\t\t * Calling this method in the `init` event, will activate the node that\n\t\t * was marked 'active' in the source data, and optionally set the keyboard\n\t\t * focus.\n\t\t * @param [setFocus=false]\n\t\t */\n\t\treactivate: function(setFocus) {\n\t\t\tvar res,\n\t\t\t\tnode = this.activeNode;\n\n\t\t\tif (!node) {\n\t\t\t\treturn _getResolvedPromise();\n\t\t\t}\n\t\t\tthis.activeNode = null; // Force re-activating\n\t\t\tres = node.setActive(true, { noFocus: true });\n\t\t\tif (setFocus) {\n\t\t\t\tnode.setFocus();\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\t/** Reload tree from source and return a promise.\n\t\t * @param [source] optional new source (defaults to initial source data)\n\t\t * @returns {$.Promise}\n\t\t */\n\t\treload: function(source) {\n\t\t\tthis._callHook(\"treeClear\", this);\n\t\t\treturn this._callHook(\"treeLoad\", this, source);\n\t\t},\n\t\t/**Render tree (i.e. create DOM elements for all top-level nodes).\n\t\t * @param {boolean} [force=false] create DOM elemnts, even if parent is collapsed\n\t\t * @param {boolean} [deep=false]\n\t\t */\n\t\trender: function(force, deep) {\n\t\t\treturn this.rootNode.render(force, deep);\n\t\t},\n\t\t/**(De)select all nodes.\n\t\t * @param {boolean} [flag=true]\n\t\t * @since 2.28\n\t\t */\n\t\tselectAll: function(flag) {\n\t\t\tthis.visit(function(node) {\n\t\t\t\tnode.setSelected(flag);\n\t\t\t});\n\t\t},\n\t\t// TODO: selectKey: function(key, select)\n\t\t// TODO: serializeArray: function(stopOnParents)\n\t\t/**\n\t\t * @param {boolean} [flag=true]\n\t\t */\n\t\tsetFocus: function(flag) {\n\t\t\treturn this._callHook(\"treeSetFocus\", this, flag);\n\t\t},\n\t\t/**\n\t\t * Set current option value.\n\t\t * (Note: this is the preferred variant of `$().fancytree(\"option\", \"KEY\", VALUE)`)\n\t\t * @param {string} name option name (may contain '.')\n\t\t * @param {any} new value\n\t\t */\n\t\tsetOption: function(optionName, value) {\n\t\t\treturn this.widget.option(optionName, value);\n\t\t},\n\t\t/**\n\t\t * Call console.time() when in debug mode (verbose >= 4).\n\t\t *\n\t\t * @param {string} label\n\t\t */\n\t\tdebugTime: function(label) {\n\t\t\tif (this.options.debugLevel >= 4) {\n\t\t\t\twindow.console.time(this + \" - \" + label);\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * Call console.timeEnd() when in debug mode (verbose >= 4).\n\t\t *\n\t\t * @param {string} label\n\t\t */\n\t\tdebugTimeEnd: function(label) {\n\t\t\tif (this.options.debugLevel >= 4) {\n\t\t\t\twindow.console.timeEnd(this + \" - \" + label);\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * Return all nodes as nested list of {@link NodeData}.\n\t\t *\n\t\t * @param {boolean} [includeRoot=false] Returns the hidden system root node (and its children)\n\t\t * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications.\n\t\t *     Return `false` to ignore this node or \"skip\" to include this node without its children.\n\t\t * @returns {Array | object}\n\t\t * @see FancytreeNode#toDict\n\t\t */\n\t\ttoDict: function(includeRoot, callback) {\n\t\t\tvar res = this.rootNode.toDict(true, callback);\n\t\t\treturn includeRoot ? res : res.children;\n\t\t},\n\t\t/* Implicitly called for string conversions.\n\t\t * @returns {string}\n\t\t */\n\t\ttoString: function() {\n\t\t\treturn \"Fancytree@\" + this._id;\n\t\t\t// return \"<Fancytree(#\" + this._id + \")>\";\n\t\t},\n\t\t/* _trigger a widget event with additional node ctx.\n\t\t * @see EventData\n\t\t */\n\t\t_triggerNodeEvent: function(type, node, originalEvent, extra) {\n\t\t\t// this.debug(\"_trigger(\" + type + \"): '\" + ctx.node.title + \"'\", ctx);\n\t\t\tvar ctx = this._makeHookContext(node, originalEvent, extra),\n\t\t\t\tres = this.widget._trigger(type, originalEvent, ctx);\n\t\t\tif (res !== false && ctx.result !== undefined) {\n\t\t\t\treturn ctx.result;\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\t/* _trigger a widget event with additional tree data. */\n\t\t_triggerTreeEvent: function(type, originalEvent, extra) {\n\t\t\t// this.debug(\"_trigger(\" + type + \")\", ctx);\n\t\t\tvar ctx = this._makeHookContext(this, originalEvent, extra),\n\t\t\t\tres = this.widget._trigger(type, originalEvent, ctx);\n\n\t\t\tif (res !== false && ctx.result !== undefined) {\n\t\t\t\treturn ctx.result;\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\t/** Call fn(node) for all nodes in hierarchical order (depth-first).\n\t\t *\n\t\t * @param {function} fn the callback function.\n\t\t *     Return false to stop iteration, return \"skip\" to skip this node and children only.\n\t\t * @returns {boolean} false, if the iterator was stopped.\n\t\t */\n\t\tvisit: function(fn) {\n\t\t\treturn this.rootNode.visit(fn, false);\n\t\t},\n\t\t/** Call fn(node) for all nodes in vertical order, top down (or bottom up).<br>\n\t\t * Stop iteration, if fn() returns false.<br>\n\t\t * Return false if iteration was stopped.\n\t\t *\n\t\t * @param {function} fn the callback function.\n\t\t *     Return false to stop iteration, return \"skip\" to skip this node and children only.\n\t\t * @param {object} [options]\n\t\t *     Defaults:\n\t\t *     {start: First top node, reverse: false, includeSelf: true, includeHidden: false}\n\t\t * @returns {boolean} false if iteration was cancelled\n\t\t * @since 2.28\n\t\t */\n\t\tvisitRows: function(fn, opts) {\n\t\t\tif (!this.rootNode.hasChildren()) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (opts && opts.reverse) {\n\t\t\t\tdelete opts.reverse;\n\t\t\t\treturn this._visitRowsUp(fn, opts);\n\t\t\t}\n\t\t\topts = opts || {};\n\n\t\t\tvar i,\n\t\t\t\tnextIdx,\n\t\t\t\tparent,\n\t\t\t\tres,\n\t\t\t\tsiblings,\n\t\t\t\tsiblingOfs = 0,\n\t\t\t\tskipFirstNode = opts.includeSelf === false,\n\t\t\t\tincludeHidden = !!opts.includeHidden,\n\t\t\t\tcheckFilter = !includeHidden && this.enableFilter,\n\t\t\t\tnode = opts.start || this.rootNode.children[0];\n\n\t\t\tparent = node.parent;\n\t\t\twhile (parent) {\n\t\t\t\t// visit siblings\n\t\t\t\tsiblings = parent.children;\n\t\t\t\tnextIdx = siblings.indexOf(node) + siblingOfs;\n\n\t\t\t\tfor (i = nextIdx; i < siblings.length; i++) {\n\t\t\t\t\tnode = siblings[i];\n\t\t\t\t\tif (checkFilter && !node.match && !node.subMatchCount) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (!skipFirstNode && fn(node) === false) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tskipFirstNode = false;\n\t\t\t\t\t// Dive into node's child nodes\n\t\t\t\t\tif (\n\t\t\t\t\t\tnode.children &&\n\t\t\t\t\t\tnode.children.length &&\n\t\t\t\t\t\t(includeHidden || node.expanded)\n\t\t\t\t\t) {\n\t\t\t\t\t\t// Disable warning: Functions declared within loops referencing an outer\n\t\t\t\t\t\t// scoped variable may lead to confusing semantics:\n\t\t\t\t\t\t/*jshint -W083 */\n\t\t\t\t\t\tres = node.visit(function(n) {\n\t\t\t\t\t\t\tif (checkFilter && !n.match && !n.subMatchCount) {\n\t\t\t\t\t\t\t\treturn \"skip\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (fn(n) === false) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!includeHidden && n.children && !n.expanded) {\n\t\t\t\t\t\t\t\treturn \"skip\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, false);\n\t\t\t\t\t\t/*jshint +W083 */\n\t\t\t\t\t\tif (res === false) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Visit parent nodes (bottom up)\n\t\t\t\tnode = parent;\n\t\t\t\tparent = parent.parent;\n\t\t\t\tsiblingOfs = 1; //\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\t/* Call fn(node) for all nodes in vertical order, bottom up.\n\t\t */\n\t\t_visitRowsUp: function(fn, opts) {\n\t\t\tvar children,\n\t\t\t\tidx,\n\t\t\t\tparent,\n\t\t\t\tincludeHidden = !!opts.includeHidden,\n\t\t\t\tnode = opts.start || this.rootNode.children[0];\n\n\t\t\twhile (true) {\n\t\t\t\tparent = node.parent;\n\t\t\t\tchildren = parent.children;\n\n\t\t\t\tif (children[0] === node) {\n\t\t\t\t\t// If this is already the first sibling, goto parent\n\t\t\t\t\tnode = parent;\n\t\t\t\t\tif (!node.parent) {\n\t\t\t\t\t\tbreak; // first node of the tree\n\t\t\t\t\t}\n\t\t\t\t\tchildren = parent.children;\n\t\t\t\t} else {\n\t\t\t\t\t// Otherwise, goto prev. sibling\n\t\t\t\t\tidx = children.indexOf(node);\n\t\t\t\t\tnode = children[idx - 1];\n\t\t\t\t\t// If the prev. sibling has children, follow down to last descendant\n\t\t\t\t\twhile (\n\t\t\t\t\t\t// See: https://github.com/eslint/eslint/issues/11302\n\t\t\t\t\t\t// eslint-disable-next-line no-unmodified-loop-condition\n\t\t\t\t\t\t(includeHidden || node.expanded) &&\n\t\t\t\t\t\tnode.children &&\n\t\t\t\t\t\tnode.children.length\n\t\t\t\t\t) {\n\t\t\t\t\t\tchildren = node.children;\n\t\t\t\t\t\tparent = node;\n\t\t\t\t\t\tnode = children[children.length - 1];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Skip invisible\n\t\t\t\tif (!includeHidden && !node.isVisible()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (fn(node) === false) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t/** Write warning to browser console if debugLevel >= 2 (prepending tree info)\n\t\t *\n\t\t * @param {*} msg string or object or array of such\n\t\t */\n\t\twarn: function(msg) {\n\t\t\tif (this.options.debugLevel >= 2) {\n\t\t\t\tArray.prototype.unshift.call(arguments, this.toString());\n\t\t\t\tconsoleApply(\"warn\", arguments);\n\t\t\t}\n\t\t},\n\t};\n\n\t/**\n\t * These additional methods of the {@link Fancytree} class are 'hook functions'\n\t * that can be used and overloaded by extensions.\n\t *\n\t * @see [writing extensions](https://github.com/mar10/fancytree/wiki/TutorialExtensions)\n\t * @mixin Fancytree_Hooks\n\t */\n\t$.extend(\n\t\tFancytree.prototype,\n\t\t/** @lends Fancytree_Hooks# */\n\t\t{\n\t\t\t/** Default handling for mouse click events.\n\t\t\t *\n\t\t\t * @param {EventData} ctx\n\t\t\t */\n\t\t\tnodeClick: function(ctx) {\n\t\t\t\tvar activate,\n\t\t\t\t\texpand,\n\t\t\t\t\t// event = ctx.originalEvent,\n\t\t\t\t\ttargetType = ctx.targetType,\n\t\t\t\t\tnode = ctx.node;\n\n\t\t\t\t// this.debug(\"ftnode.onClick(\" + event.type + \"): ftnode:\" + this + \", button:\" + event.button + \", which: \" + event.which, ctx);\n\t\t\t\t// TODO: use switch\n\t\t\t\t// TODO: make sure clicks on embedded <input> doesn't steal focus (see table sample)\n\t\t\t\tif (targetType === \"expander\") {\n\t\t\t\t\tif (node.isLoading()) {\n\t\t\t\t\t\t// #495: we probably got a click event while a lazy load is pending.\n\t\t\t\t\t\t// The 'expanded' state is not yet set, so 'toggle' would expand\n\t\t\t\t\t\t// and trigger lazyLoad again.\n\t\t\t\t\t\t// It would be better to allow to collapse/expand the status node\n\t\t\t\t\t\t// while loading (instead of ignoring), but that would require some\n\t\t\t\t\t\t// more work.\n\t\t\t\t\t\tnode.debug(\"Got 2nd click while loading: ignored\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// Clicking the expander icon always expands/collapses\n\t\t\t\t\tthis._callHook(\"nodeToggleExpanded\", ctx);\n\t\t\t\t} else if (targetType === \"checkbox\") {\n\t\t\t\t\t// Clicking the checkbox always (de)selects\n\t\t\t\t\tthis._callHook(\"nodeToggleSelected\", ctx);\n\t\t\t\t\tif (ctx.options.focusOnSelect) {\n\t\t\t\t\t\t// #358\n\t\t\t\t\t\tthis._callHook(\"nodeSetFocus\", ctx, true);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Honor `clickFolderMode` for\n\t\t\t\t\texpand = false;\n\t\t\t\t\tactivate = true;\n\t\t\t\t\tif (node.folder) {\n\t\t\t\t\t\tswitch (ctx.options.clickFolderMode) {\n\t\t\t\t\t\t\tcase 2: // expand only\n\t\t\t\t\t\t\t\texpand = true;\n\t\t\t\t\t\t\t\tactivate = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 3: // expand and activate\n\t\t\t\t\t\t\t\tactivate = true;\n\t\t\t\t\t\t\t\texpand = true; //!node.isExpanded();\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t// else 1 or 4: just activate\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (activate) {\n\t\t\t\t\t\tthis.nodeSetFocus(ctx);\n\t\t\t\t\t\tthis._callHook(\"nodeSetActive\", ctx, true);\n\t\t\t\t\t}\n\t\t\t\t\tif (expand) {\n\t\t\t\t\t\tif (!activate) {\n\t\t\t\t\t\t\t// this._callHook(\"nodeSetFocus\", ctx);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// this._callHook(\"nodeSetExpanded\", ctx, true);\n\t\t\t\t\t\tthis._callHook(\"nodeToggleExpanded\", ctx);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Make sure that clicks stop, otherwise <a href='#'> jumps to the top\n\t\t\t\t// if(event.target.localName === \"a\" && event.target.className === \"fancytree-title\"){\n\t\t\t\t// \tevent.preventDefault();\n\t\t\t\t// }\n\t\t\t\t// TODO: return promise?\n\t\t\t},\n\t\t\t/** Collapse all other  children of same parent.\n\t\t\t *\n\t\t\t * @param {EventData} ctx\n\t\t\t * @param {object} callOpts\n\t\t\t */\n\t\t\tnodeCollapseSiblings: function(ctx, callOpts) {\n\t\t\t\t// TODO: return promise?\n\t\t\t\tvar ac,\n\t\t\t\t\ti,\n\t\t\t\t\tl,\n\t\t\t\t\tnode = ctx.node;\n\n\t\t\t\tif (node.parent) {\n\t\t\t\t\tac = node.parent.children;\n\t\t\t\t\tfor (i = 0, l = ac.length; i < l; i++) {\n\t\t\t\t\t\tif (ac[i] !== node && ac[i].expanded) {\n\t\t\t\t\t\t\tthis._callHook(\n\t\t\t\t\t\t\t\t\"nodeSetExpanded\",\n\t\t\t\t\t\t\t\tac[i],\n\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\tcallOpts\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\t\t\t/** Default handling for mouse douleclick events.\n\t\t\t * @param {EventData} ctx\n\t\t\t */\n\t\t\tnodeDblclick: function(ctx) {\n\t\t\t\t// TODO: return promise?\n\t\t\t\tif (\n\t\t\t\t\tctx.targetType === \"title\" &&\n\t\t\t\t\tctx.options.clickFolderMode === 4\n\t\t\t\t) {\n\t\t\t\t\t// this.nodeSetFocus(ctx);\n\t\t\t\t\t// this._callHook(\"nodeSetActive\", ctx, true);\n\t\t\t\t\tthis._callHook(\"nodeToggleExpanded\", ctx);\n\t\t\t\t}\n\t\t\t\t// TODO: prevent text selection on dblclicks\n\t\t\t\tif (ctx.targetType === \"title\") {\n\t\t\t\t\tctx.originalEvent.preventDefault();\n\t\t\t\t}\n\t\t\t},\n\t\t\t/** Default handling for mouse keydown events.\n\t\t\t *\n\t\t\t * NOTE: this may be called with node == null if tree (but no node) has focus.\n\t\t\t * @param {EventData} ctx\n\t\t\t */\n\t\t\tnodeKeydown: function(ctx) {\n\t\t\t\t// TODO: return promise?\n\t\t\t\tvar matchNode,\n\t\t\t\t\tstamp,\n\t\t\t\t\t_res,\n\t\t\t\t\tfocusNode,\n\t\t\t\t\tevent = ctx.originalEvent,\n\t\t\t\t\tnode = ctx.node,\n\t\t\t\t\ttree = ctx.tree,\n\t\t\t\t\topts = ctx.options,\n\t\t\t\t\twhich = event.which,\n\t\t\t\t\t// #909: Use event.key, to get unicode characters.\n\t\t\t\t\t// We can't use `/\\w/.test(key)`, because that would\n\t\t\t\t\t// only detect plain ascii alpha-numerics. But we still need\n\t\t\t\t\t// to ignore modifier-only, whitespace, cursor-keys, etc.\n\t\t\t\t\tkey = event.key || String.fromCharCode(which),\n\t\t\t\t\tspecialModifiers = !!(\n\t\t\t\t\t\tevent.altKey ||\n\t\t\t\t\t\tevent.ctrlKey ||\n\t\t\t\t\t\tevent.metaKey\n\t\t\t\t\t),\n\t\t\t\t\tisAlnum =\n\t\t\t\t\t\t!MODIFIERS[which] &&\n\t\t\t\t\t\t!SPECIAL_KEYCODES[which] &&\n\t\t\t\t\t\t!specialModifiers,\n\t\t\t\t\t$target = $(event.target),\n\t\t\t\t\thandled = true,\n\t\t\t\t\tactivate = !(event.ctrlKey || !opts.autoActivate);\n\n\t\t\t\t// (node || FT).debug(\"ftnode.nodeKeydown(\" + event.type + \"): ftnode:\" + this + \", charCode:\" + event.charCode + \", keyCode: \" + event.keyCode + \", which: \" + event.which);\n\t\t\t\t// FT.debug( \"eventToString(): \" + FT.eventToString(event) + \", key='\" + key + \"', isAlnum: \" + isAlnum );\n\n\t\t\t\t// Set focus to active (or first node) if no other node has the focus yet\n\t\t\t\tif (!node) {\n\t\t\t\t\tfocusNode = this.getActiveNode() || this.getFirstChild();\n\t\t\t\t\tif (focusNode) {\n\t\t\t\t\t\tfocusNode.setFocus();\n\t\t\t\t\t\tnode = ctx.node = this.focusNode;\n\t\t\t\t\t\tnode.debug(\"Keydown force focus on active node\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\topts.quicksearch &&\n\t\t\t\t\tisAlnum &&\n\t\t\t\t\t!$target.is(\":input:enabled\")\n\t\t\t\t) {\n\t\t\t\t\t// Allow to search for longer streaks if typed in quickly\n\t\t\t\t\tstamp = Date.now();\n\t\t\t\t\tif (stamp - tree.lastQuicksearchTime > 500) {\n\t\t\t\t\t\ttree.lastQuicksearchTerm = \"\";\n\t\t\t\t\t}\n\t\t\t\t\ttree.lastQuicksearchTime = stamp;\n\t\t\t\t\ttree.lastQuicksearchTerm += key;\n\t\t\t\t\t// tree.debug(\"quicksearch find\", tree.lastQuicksearchTerm);\n\t\t\t\t\tmatchNode = tree.findNextNode(\n\t\t\t\t\t\ttree.lastQuicksearchTerm,\n\t\t\t\t\t\ttree.getActiveNode()\n\t\t\t\t\t);\n\t\t\t\t\tif (matchNode) {\n\t\t\t\t\t\tmatchNode.setActive();\n\t\t\t\t\t}\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tswitch (FT.eventToString(event)) {\n\t\t\t\t\tcase \"+\":\n\t\t\t\t\tcase \"=\": // 187: '+' @ Chrome, Safari\n\t\t\t\t\t\ttree.nodeSetExpanded(ctx, true);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"-\":\n\t\t\t\t\t\ttree.nodeSetExpanded(ctx, false);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"space\":\n\t\t\t\t\t\tif (node.isPagingNode()) {\n\t\t\t\t\t\t\ttree._triggerNodeEvent(\"clickPaging\", ctx, event);\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tFT.evalOption(\"checkbox\", node, node, opts, false)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// #768\n\t\t\t\t\t\t\ttree.nodeToggleSelected(ctx);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttree.nodeSetActive(ctx, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"return\":\n\t\t\t\t\t\ttree.nodeSetActive(ctx, true);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"home\":\n\t\t\t\t\tcase \"end\":\n\t\t\t\t\tcase \"backspace\":\n\t\t\t\t\tcase \"left\":\n\t\t\t\t\tcase \"right\":\n\t\t\t\t\tcase \"up\":\n\t\t\t\t\tcase \"down\":\n\t\t\t\t\t\t_res = node.navigate(event.which, activate);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\thandled = false;\n\t\t\t\t}\n\t\t\t\tif (handled) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// /** Default handling for mouse keypress events. */\n\t\t\t// nodeKeypress: function(ctx) {\n\t\t\t//     var event = ctx.originalEvent;\n\t\t\t// },\n\n\t\t\t// /** Trigger lazyLoad event (async). */\n\t\t\t// nodeLazyLoad: function(ctx) {\n\t\t\t//     var node = ctx.node;\n\t\t\t//     if(this._triggerNodeEvent())\n\t\t\t// },\n\t\t\t/** Load child nodes (async).\n\t\t\t *\n\t\t\t * @param {EventData} ctx\n\t\t\t * @param {object[]|object|string|$.Promise|function} source\n\t\t\t * @returns {$.Promise} The deferred will be resolved as soon as the (ajax)\n\t\t\t *     data was rendered.\n\t\t\t */\n\t\t\tnodeLoadChildren: function(ctx, source) {\n\t\t\t\tvar ajax,\n\t\t\t\t\tdelay,\n\t\t\t\t\tdfd,\n\t\t\t\t\tres,\n\t\t\t\t\ttree = ctx.tree,\n\t\t\t\t\tnode = ctx.node,\n\t\t\t\t\trequestId = Date.now();\n\n\t\t\t\tif ($.isFunction(source)) {\n\t\t\t\t\tsource = source.call(tree, { type: \"source\" }, ctx);\n\t\t\t\t\t_assert(\n\t\t\t\t\t\t!$.isFunction(source),\n\t\t\t\t\t\t\"source callback must not return another function\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (source.url) {\n\t\t\t\t\tif (node._requestId) {\n\t\t\t\t\t\tnode.warn(\n\t\t\t\t\t\t\t\"Recursive load request #\" +\n\t\t\t\t\t\t\t\trequestId +\n\t\t\t\t\t\t\t\t\" while #\" +\n\t\t\t\t\t\t\t\tnode._requestId +\n\t\t\t\t\t\t\t\t\" is pending.\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\t// } else {\n\t\t\t\t\t\t// \tnode.debug(\"Send load request #\" + requestId);\n\t\t\t\t\t}\n\t\t\t\t\t// `source` is an Ajax options object\n\t\t\t\t\tajax = $.extend({}, ctx.options.ajax, source);\n\t\t\t\t\tnode._requestId = requestId;\n\t\t\t\t\tif (ajax.debugDelay) {\n\t\t\t\t\t\t// simulate a slow server\n\t\t\t\t\t\tdelay = ajax.debugDelay;\n\t\t\t\t\t\tdelete ajax.debugDelay; // remove debug option\n\t\t\t\t\t\tif ($.isArray(delay)) {\n\t\t\t\t\t\t\t// random delay range [min..max]\n\t\t\t\t\t\t\tdelay =\n\t\t\t\t\t\t\t\tdelay[0] +\n\t\t\t\t\t\t\t\tMath.random() * (delay[1] - delay[0]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnode.warn(\n\t\t\t\t\t\t\t\"nodeLoadChildren waiting debugDelay \" +\n\t\t\t\t\t\t\t\tMath.round(delay) +\n\t\t\t\t\t\t\t\t\" ms ...\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\tdfd = $.Deferred(function(dfd) {\n\t\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\t\t$.ajax(ajax)\n\t\t\t\t\t\t\t\t\t.done(function() {\n\t\t\t\t\t\t\t\t\t\tdfd.resolveWith(this, arguments);\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t.fail(function() {\n\t\t\t\t\t\t\t\t\t\tdfd.rejectWith(this, arguments);\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}, delay);\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdfd = $.ajax(ajax);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Defer the deferred: we want to be able to reject, even if ajax\n\t\t\t\t\t// resolved ok.\n\t\t\t\t\tsource = new $.Deferred();\n\t\t\t\t\tdfd.done(function(data, textStatus, jqXHR) {\n\t\t\t\t\t\tvar errorObj, res;\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t(this.dataType === \"json\" ||\n\t\t\t\t\t\t\t\tthis.dataType === \"jsonp\") &&\n\t\t\t\t\t\t\ttypeof data === \"string\"\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t$.error(\n\t\t\t\t\t\t\t\t\"Ajax request returned a string (did you get the JSON dataType wrong?).\"\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (node._requestId && node._requestId > requestId) {\n\t\t\t\t\t\t\t// The expected request time stamp is later than `requestId`\n\t\t\t\t\t\t\t// (which was kept as as closure variable to this handler function)\n\t\t\t\t\t\t\t// node.warn(\"Ignored load response for obsolete request #\" + requestId + \" (expected #\" + node._requestId + \")\");\n\t\t\t\t\t\t\tsource.rejectWith(this, [RECURSIVE_REQUEST_ERROR]);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t// } else {\n\t\t\t\t\t\t\t// \tnode.debug(\"Response returned for load request #\" + requestId);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// postProcess is similar to the standard ajax dataFilter hook,\n\t\t\t\t\t\t// but it is also called for JSONP\n\t\t\t\t\t\tif (ctx.options.postProcess) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t// The handler may either\n\t\t\t\t\t\t\t\t//   - modify `ctx.response` in-place (and leave `ctx.result` undefined)\n\t\t\t\t\t\t\t\t//     => res = undefined\n\t\t\t\t\t\t\t\t//   - return a replacement in `ctx.result`\n\t\t\t\t\t\t\t\t//     => res = <new data>\n\t\t\t\t\t\t\t\t// If res contains an `error` property, an error status is displayed\n\t\t\t\t\t\t\t\tres = tree._triggerNodeEvent(\n\t\t\t\t\t\t\t\t\t\"postProcess\",\n\t\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\t\tctx.originalEvent,\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tresponse: data,\n\t\t\t\t\t\t\t\t\t\terror: null,\n\t\t\t\t\t\t\t\t\t\tdataType: this.dataType,\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} catch (e) {\n\t\t\t\t\t\t\t\tres = {\n\t\t\t\t\t\t\t\t\terror: e,\n\t\t\t\t\t\t\t\t\tmessage: \"\" + e,\n\t\t\t\t\t\t\t\t\tdetails: \"postProcess failed\",\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (res.error) {\n\t\t\t\t\t\t\t\terrorObj = $.isPlainObject(res.error)\n\t\t\t\t\t\t\t\t\t? res.error\n\t\t\t\t\t\t\t\t\t: { message: res.error };\n\t\t\t\t\t\t\t\terrorObj = tree._makeHookContext(\n\t\t\t\t\t\t\t\t\tnode,\n\t\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t\terrorObj\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tsource.rejectWith(this, [errorObj]);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t$.isArray(res) ||\n\t\t\t\t\t\t\t\t($.isPlainObject(res) &&\n\t\t\t\t\t\t\t\t\t$.isArray(res.children))\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t// Use `ctx.result` if valid\n\t\t\t\t\t\t\t\t// (otherwise use existing data, which may have been modified in-place)\n\t\t\t\t\t\t\t\tdata = res;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\tdata &&\n\t\t\t\t\t\t\tdata.hasOwnProperty(\"d\") &&\n\t\t\t\t\t\t\tctx.options.enableAspx\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// Process ASPX WebMethod JSON object inside \"d\" property\n\t\t\t\t\t\t\tdata =\n\t\t\t\t\t\t\t\ttypeof data.d === \"string\"\n\t\t\t\t\t\t\t\t\t? $.parseJSON(data.d)\n\t\t\t\t\t\t\t\t\t: data.d;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsource.resolveWith(this, [data]);\n\t\t\t\t\t}).fail(function(jqXHR, textStatus, errorThrown) {\n\t\t\t\t\t\tvar errorObj = tree._makeHookContext(node, null, {\n\t\t\t\t\t\t\terror: jqXHR,\n\t\t\t\t\t\t\targs: Array.prototype.slice.call(arguments),\n\t\t\t\t\t\t\tmessage: errorThrown,\n\t\t\t\t\t\t\tdetails: jqXHR.status + \": \" + errorThrown,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tsource.rejectWith(this, [errorObj]);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t// #383: accept and convert ECMAScript 6 Promise\n\t\t\t\tif ($.isFunction(source.then) && $.isFunction(source.catch)) {\n\t\t\t\t\tdfd = source;\n\t\t\t\t\tsource = new $.Deferred();\n\t\t\t\t\tdfd.then(\n\t\t\t\t\t\tfunction(value) {\n\t\t\t\t\t\t\tsource.resolve(value);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfunction(reason) {\n\t\t\t\t\t\t\tsource.reject(reason);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif ($.isFunction(source.promise)) {\n\t\t\t\t\t// `source` is a deferred, i.e. ajax request\n\t\t\t\t\t// _assert(!node.isLoading(), \"recursive load\");\n\t\t\t\t\ttree.nodeSetStatus(ctx, \"loading\");\n\n\t\t\t\t\tsource\n\t\t\t\t\t\t.done(function(children) {\n\t\t\t\t\t\t\ttree.nodeSetStatus(ctx, \"ok\");\n\t\t\t\t\t\t\tnode._requestId = null;\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.fail(function(error) {\n\t\t\t\t\t\t\tvar ctxErr;\n\n\t\t\t\t\t\t\tif (error === RECURSIVE_REQUEST_ERROR) {\n\t\t\t\t\t\t\t\tnode.warn(\n\t\t\t\t\t\t\t\t\t\"Ignored response for obsolete load request #\" +\n\t\t\t\t\t\t\t\t\t\trequestId +\n\t\t\t\t\t\t\t\t\t\t\" (expected #\" +\n\t\t\t\t\t\t\t\t\t\tnode._requestId +\n\t\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\treturn;\n\t\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\t\terror.node &&\n\t\t\t\t\t\t\t\terror.error &&\n\t\t\t\t\t\t\t\terror.message\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t// error is already a context object\n\t\t\t\t\t\t\t\tctxErr = error;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tctxErr = tree._makeHookContext(node, null, {\n\t\t\t\t\t\t\t\t\terror: error, // it can be jqXHR or any custom error\n\t\t\t\t\t\t\t\t\targs: Array.prototype.slice.call(arguments),\n\t\t\t\t\t\t\t\t\tmessage: error\n\t\t\t\t\t\t\t\t\t\t? error.message || error.toString()\n\t\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\tif (ctxErr.message === \"[object Object]\") {\n\t\t\t\t\t\t\t\t\tctxErr.message = \"\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnode.warn(\n\t\t\t\t\t\t\t\t\"Load children failed (\" + ctxErr.message + \")\",\n\t\t\t\t\t\t\t\tctxErr\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\ttree._triggerNodeEvent(\n\t\t\t\t\t\t\t\t\t\"loadError\",\n\t\t\t\t\t\t\t\t\tctxErr,\n\t\t\t\t\t\t\t\t\tnull\n\t\t\t\t\t\t\t\t) !== false\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\ttree.nodeSetStatus(\n\t\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\t\t\t\tctxErr.message,\n\t\t\t\t\t\t\t\t\tctxErr.details\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} else {\n\t\t\t\t\tif (ctx.options.postProcess) {\n\t\t\t\t\t\t// #792: Call postProcess for non-deferred source\n\t\t\t\t\t\tres = tree._triggerNodeEvent(\n\t\t\t\t\t\t\t\"postProcess\",\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\tctx.originalEvent,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tresponse: source,\n\t\t\t\t\t\t\t\terror: null,\n\t\t\t\t\t\t\t\tdataType: typeof source,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t$.isArray(res) ||\n\t\t\t\t\t\t\t($.isPlainObject(res) && $.isArray(res.children))\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// Use `ctx.result` if valid\n\t\t\t\t\t\t\t// (otherwise use existing data, which may have been modified in-place)\n\t\t\t\t\t\t\tsource = res;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// $.when(source) resolves also for non-deferreds\n\t\t\t\treturn $.when(source).done(function(children) {\n\t\t\t\t\tvar metaData, noDataRes;\n\n\t\t\t\t\tif ($.isPlainObject(children)) {\n\t\t\t\t\t\t// We got {foo: 'abc', children: [...]}\n\t\t\t\t\t\t// Copy extra properties to tree.data.foo\n\t\t\t\t\t\t_assert(\n\t\t\t\t\t\t\tnode.isRootNode(),\n\t\t\t\t\t\t\t\"source may only be an object for root nodes (expecting an array of child objects otherwise)\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\t_assert(\n\t\t\t\t\t\t\t$.isArray(children.children),\n\t\t\t\t\t\t\t\"if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\tmetaData = children;\n\t\t\t\t\t\tchildren = children.children;\n\t\t\t\t\t\tdelete metaData.children;\n\t\t\t\t\t\t// Copy some attributes to tree.data\n\t\t\t\t\t\t$.each(TREE_ATTRS, function(i, attr) {\n\t\t\t\t\t\t\tif (metaData[attr] !== undefined) {\n\t\t\t\t\t\t\t\ttree[attr] = metaData[attr];\n\t\t\t\t\t\t\t\tdelete metaData[attr];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\t// Copy all other attributes to tree.data.NAME\n\t\t\t\t\t\t$.extend(tree.data, metaData);\n\t\t\t\t\t}\n\t\t\t\t\t_assert($.isArray(children), \"expected array of children\");\n\t\t\t\t\tnode._setChildren(children);\n\n\t\t\t\t\tif (tree.options.nodata && children.length === 0) {\n\t\t\t\t\t\tif ($.isFunction(tree.options.nodata)) {\n\t\t\t\t\t\t\tnoDataRes = tree.options.nodata.call(\n\t\t\t\t\t\t\t\ttree,\n\t\t\t\t\t\t\t\t{ type: \"nodata\" },\n\t\t\t\t\t\t\t\tctx\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\ttree.options.nodata === true &&\n\t\t\t\t\t\t\tnode.isRootNode()\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tnoDataRes = tree.options.strings.nodata;\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\ttypeof tree.options.nodata === \"string\" &&\n\t\t\t\t\t\t\tnode.isRootNode()\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tnoDataRes = tree.options.nodata;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (noDataRes) {\n\t\t\t\t\t\t\tnode.setStatus(\"nodata\", noDataRes);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// trigger fancytreeloadchildren\n\t\t\t\t\ttree._triggerNodeEvent(\"loadChildren\", node);\n\t\t\t\t});\n\t\t\t},\n\t\t\t/** [Not Implemented]  */\n\t\t\tnodeLoadKeyPath: function(ctx, keyPathList) {\n\t\t\t\t// TODO: implement and improve\n\t\t\t\t// http://code.google.com/p/dynatree/issues/detail?id=222\n\t\t\t},\n\t\t\t/**\n\t\t\t * Remove a single direct child of ctx.node.\n\t\t\t * @param {EventData} ctx\n\t\t\t * @param {FancytreeNode} childNode dircect child of ctx.node\n\t\t\t */\n\t\t\tnodeRemoveChild: function(ctx, childNode) {\n\t\t\t\tvar idx,\n\t\t\t\t\tnode = ctx.node,\n\t\t\t\t\t// opts = ctx.options,\n\t\t\t\t\tsubCtx = $.extend({}, ctx, { node: childNode }),\n\t\t\t\t\tchildren = node.children;\n\n\t\t\t\t// FT.debug(\"nodeRemoveChild()\", node.toString(), childNode.toString());\n\n\t\t\t\tif (children.length === 1) {\n\t\t\t\t\t_assert(childNode === children[0], \"invalid single child\");\n\t\t\t\t\treturn this.nodeRemoveChildren(ctx);\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tthis.activeNode &&\n\t\t\t\t\t(childNode === this.activeNode ||\n\t\t\t\t\t\tthis.activeNode.isDescendantOf(childNode))\n\t\t\t\t) {\n\t\t\t\t\tthis.activeNode.setActive(false); // TODO: don't fire events\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tthis.focusNode &&\n\t\t\t\t\t(childNode === this.focusNode ||\n\t\t\t\t\t\tthis.focusNode.isDescendantOf(childNode))\n\t\t\t\t) {\n\t\t\t\t\tthis.focusNode = null;\n\t\t\t\t}\n\t\t\t\t// TODO: persist must take care to clear select and expand cookies\n\t\t\t\tthis.nodeRemoveMarkup(subCtx);\n\t\t\t\tthis.nodeRemoveChildren(subCtx);\n\t\t\t\tidx = $.inArray(childNode, children);\n\t\t\t\t_assert(idx >= 0, \"invalid child\");\n\t\t\t\t// Notify listeners\n\t\t\t\tnode.triggerModifyChild(\"remove\", childNode);\n\t\t\t\t// Unlink to support GC\n\t\t\t\tchildNode.visit(function(n) {\n\t\t\t\t\tn.parent = null;\n\t\t\t\t}, true);\n\t\t\t\tthis._callHook(\"treeRegisterNode\", this, false, childNode);\n\t\t\t\t// remove from child list\n\t\t\t\tchildren.splice(idx, 1);\n\t\t\t},\n\t\t\t/**Remove HTML markup for all descendents of ctx.node.\n\t\t\t * @param {EventData} ctx\n\t\t\t */\n\t\t\tnodeRemoveChildMarkup: function(ctx) {\n\t\t\t\tvar node = ctx.node;\n\n\t\t\t\t// FT.debug(\"nodeRemoveChildMarkup()\", node.toString());\n\t\t\t\t// TODO: Unlink attr.ftnode to support GC\n\t\t\t\tif (node.ul) {\n\t\t\t\t\tif (node.isRootNode()) {\n\t\t\t\t\t\t$(node.ul).empty();\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$(node.ul).remove();\n\t\t\t\t\t\tnode.ul = null;\n\t\t\t\t\t}\n\t\t\t\t\tnode.visit(function(n) {\n\t\t\t\t\t\tn.li = n.ul = null;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\t/**Remove all descendants of ctx.node.\n\t\t\t * @param {EventData} ctx\n\t\t\t */\n\t\t\tnodeRemoveChildren: function(ctx) {\n\t\t\t\tvar //subCtx,\n\t\t\t\t\ttree = ctx.tree,\n\t\t\t\t\tnode = ctx.node,\n\t\t\t\t\tchildren = node.children;\n\t\t\t\t// opts = ctx.options;\n\n\t\t\t\t// FT.debug(\"nodeRemoveChildren()\", node.toString());\n\t\t\t\tif (!children) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (this.activeNode && this.activeNode.isDescendantOf(node)) {\n\t\t\t\t\tthis.activeNode.setActive(false); // TODO: don't fire events\n\t\t\t\t}\n\t\t\t\tif (this.focusNode && this.focusNode.isDescendantOf(node)) {\n\t\t\t\t\tthis.focusNode = null;\n\t\t\t\t}\n\t\t\t\t// TODO: persist must take care to clear select and expand cookies\n\t\t\t\tthis.nodeRemoveChildMarkup(ctx);\n\t\t\t\t// Unlink children to support GC\n\t\t\t\t// TODO: also delete this.children (not possible using visit())\n\t\t\t\t// subCtx = $.extend({}, ctx);\n\t\t\t\tnode.triggerModifyChild(\"remove\", null);\n\t\t\t\tnode.visit(function(n) {\n\t\t\t\t\tn.parent = null;\n\t\t\t\t\ttree._callHook(\"treeRegisterNode\", tree, false, n);\n\t\t\t\t});\n\t\t\t\tif (node.lazy) {\n\t\t\t\t\t// 'undefined' would be interpreted as 'not yet loaded' for lazy nodes\n\t\t\t\t\tnode.children = [];\n\t\t\t\t} else {\n\t\t\t\t\tnode.children = null;\n\t\t\t\t}\n\t\t\t\tif (!node.isRootNode()) {\n\t\t\t\t\tnode.expanded = false; // #449, #459\n\t\t\t\t}\n\t\t\t\tthis.nodeRenderStatus(ctx);\n\t\t\t},\n\t\t\t/**Remove HTML markup for ctx.node and all its descendents.\n\t\t\t * @param {EventData} ctx\n\t\t\t */\n\t\t\tnodeRemoveMarkup: function(ctx) {\n\t\t\t\tvar node = ctx.node;\n\t\t\t\t// FT.debug(\"nodeRemoveMarkup()\", node.toString());\n\t\t\t\t// TODO: Unlink attr.ftnode to support GC\n\t\t\t\tif (node.li) {\n\t\t\t\t\t$(node.li).remove();\n\t\t\t\t\tnode.li = null;\n\t\t\t\t}\n\t\t\t\tthis.nodeRemoveChildMarkup(ctx);\n\t\t\t},\n\t\t\t/**\n\t\t\t * Create `<li><span>..</span> .. </li>` tags for this node.\n\t\t\t *\n\t\t\t * This method takes care that all HTML markup is created that is required\n\t\t\t * to display this node in its current state.\n\t\t\t *\n\t\t\t * Call this method to create new nodes, or after the strucuture\n\t\t\t * was changed (e.g. after moving this node or adding/removing children)\n\t\t\t * nodeRenderTitle() and nodeRenderStatus() are implied.\n\t\t\t *\n\t\t\t * ```html\n\t\t\t * <li id='KEY' ftnode=NODE>\n\t\t\t *     <span class='fancytree-node fancytree-expanded fancytree-has-children fancytree-lastsib fancytree-exp-el fancytree-ico-e'>\n\t\t\t *         <span class=\"fancytree-expander\"></span>\n\t\t\t *         <span class=\"fancytree-checkbox\"></span> // only present in checkbox mode\n\t\t\t *         <span class=\"fancytree-icon\"></span>\n\t\t\t *         <a href=\"#\" class=\"fancytree-title\"> Node 1 </a>\n\t\t\t *     </span>\n\t\t\t *     <ul> // only present if node has children\n\t\t\t *         <li id='KEY' ftnode=NODE> child1 ... </li>\n\t\t\t *         <li id='KEY' ftnode=NODE> child2 ... </li>\n\t\t\t *     </ul>\n\t\t\t * </li>\n\t\t\t * ```\n\t\t\t *\n\t\t\t * @param {EventData} ctx\n\t\t\t * @param {boolean} [force=false] re-render, even if html markup was already created\n\t\t\t * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed\n\t\t\t * @param {boolean} [collapsed=false] force root node to be collapsed, so we can apply animated expand later\n\t\t\t */\n\t\t\tnodeRender: function(ctx, force, deep, collapsed, _recursive) {\n\t\t\t\t/* This method must take care of all cases where the current data mode\n\t\t\t\t * (i.e. node hierarchy) does not match the current markup.\n\t\t\t\t *\n\t\t\t\t * - node was not yet rendered:\n\t\t\t\t *   create markup\n\t\t\t\t * - node was rendered: exit fast\n\t\t\t\t * - children have been added\n\t\t\t\t * - children have been removed\n\t\t\t\t */\n\t\t\t\tvar childLI,\n\t\t\t\t\tchildNode1,\n\t\t\t\t\tchildNode2,\n\t\t\t\t\ti,\n\t\t\t\t\tl,\n\t\t\t\t\tnext,\n\t\t\t\t\tsubCtx,\n\t\t\t\t\tnode = ctx.node,\n\t\t\t\t\ttree = ctx.tree,\n\t\t\t\t\topts = ctx.options,\n\t\t\t\t\taria = opts.aria,\n\t\t\t\t\tfirstTime = false,\n\t\t\t\t\tparent = node.parent,\n\t\t\t\t\tisRootNode = !parent,\n\t\t\t\t\tchildren = node.children,\n\t\t\t\t\tsuccessorLi = null;\n\t\t\t\t// FT.debug(\"nodeRender(\" + !!force + \", \" + !!deep + \")\", node.toString());\n\n\t\t\t\tif (tree._enableUpdate === false) {\n\t\t\t\t\t// tree.debug(\"no render\", tree._enableUpdate);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!isRootNode && !parent.ul) {\n\t\t\t\t\t// Calling node.collapse on a deep, unrendered node\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t_assert(isRootNode || parent.ul, \"parent UL must exist\");\n\n\t\t\t\t// Render the node\n\t\t\t\tif (!isRootNode) {\n\t\t\t\t\t// Discard markup on force-mode, or if it is not linked to parent <ul>\n\t\t\t\t\tif (\n\t\t\t\t\t\tnode.li &&\n\t\t\t\t\t\t(force || node.li.parentNode !== node.parent.ul)\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (node.li.parentNode === node.parent.ul) {\n\t\t\t\t\t\t\t// #486: store following node, so we can insert the new markup there later\n\t\t\t\t\t\t\tsuccessorLi = node.li.nextSibling;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// May happen, when a top-level node was dropped over another\n\t\t\t\t\t\t\tthis.debug(\n\t\t\t\t\t\t\t\t\"Unlinking \" +\n\t\t\t\t\t\t\t\t\tnode +\n\t\t\t\t\t\t\t\t\t\" (must be child of \" +\n\t\t\t\t\t\t\t\t\tnode.parent +\n\t\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\t//\t            this.debug(\"nodeRemoveMarkup...\");\n\t\t\t\t\t\tthis.nodeRemoveMarkup(ctx);\n\t\t\t\t\t}\n\t\t\t\t\t// Create <li><span /> </li>\n\t\t\t\t\t// node.debug(\"render...\");\n\t\t\t\t\tif (node.li) {\n\t\t\t\t\t\t// this.nodeRenderTitle(ctx);\n\t\t\t\t\t\tthis.nodeRenderStatus(ctx);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// node.debug(\"render... really\");\n\t\t\t\t\t\tfirstTime = true;\n\t\t\t\t\t\tnode.li = document.createElement(\"li\");\n\t\t\t\t\t\tnode.li.ftnode = node;\n\n\t\t\t\t\t\tif (node.key && opts.generateIds) {\n\t\t\t\t\t\t\tnode.li.id = opts.idPrefix + node.key;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnode.span = document.createElement(\"span\");\n\t\t\t\t\t\tnode.span.className = \"fancytree-node\";\n\t\t\t\t\t\tif (aria && !node.tr) {\n\t\t\t\t\t\t\t$(node.li).attr(\"role\", \"treeitem\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnode.li.appendChild(node.span);\n\n\t\t\t\t\t\t// Create inner HTML for the <span> (expander, checkbox, icon, and title)\n\t\t\t\t\t\tthis.nodeRenderTitle(ctx);\n\n\t\t\t\t\t\t// Allow tweaking and binding, after node was created for the first time\n\t\t\t\t\t\tif (opts.createNode) {\n\t\t\t\t\t\t\topts.createNode.call(\n\t\t\t\t\t\t\t\ttree,\n\t\t\t\t\t\t\t\t{ type: \"createNode\" },\n\t\t\t\t\t\t\t\tctx\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\t// Allow tweaking after node state was rendered\n\t\t\t\t\tif (opts.renderNode) {\n\t\t\t\t\t\topts.renderNode.call(tree, { type: \"renderNode\" }, ctx);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Visit child nodes\n\t\t\t\tif (children) {\n\t\t\t\t\tif (isRootNode || node.expanded || deep === true) {\n\t\t\t\t\t\t// Create a UL to hold the children\n\t\t\t\t\t\tif (!node.ul) {\n\t\t\t\t\t\t\tnode.ul = document.createElement(\"ul\");\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t(collapsed === true && !_recursive) ||\n\t\t\t\t\t\t\t\t!node.expanded\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t// hide top UL, so we can use an animation to show it later\n\t\t\t\t\t\t\t\tnode.ul.style.display = \"none\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (aria) {\n\t\t\t\t\t\t\t\t$(node.ul).attr(\"role\", \"group\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (node.li) {\n\t\t\t\t\t\t\t\t// issue #67\n\t\t\t\t\t\t\t\tnode.li.appendChild(node.ul);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tnode.tree.$div.append(node.ul);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Add child markup\n\t\t\t\t\t\tfor (i = 0, l = children.length; i < l; i++) {\n\t\t\t\t\t\t\tsubCtx = $.extend({}, ctx, { node: children[i] });\n\t\t\t\t\t\t\tthis.nodeRender(subCtx, force, deep, false, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Remove <li> if nodes have moved to another parent\n\t\t\t\t\t\tchildLI = node.ul.firstChild;\n\t\t\t\t\t\twhile (childLI) {\n\t\t\t\t\t\t\tchildNode2 = childLI.ftnode;\n\t\t\t\t\t\t\tif (childNode2 && childNode2.parent !== node) {\n\t\t\t\t\t\t\t\tnode.debug(\n\t\t\t\t\t\t\t\t\t\"_fixParent: remove missing \" + childNode2,\n\t\t\t\t\t\t\t\t\tchildLI\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tnext = childLI.nextSibling;\n\t\t\t\t\t\t\t\tchildLI.parentNode.removeChild(childLI);\n\t\t\t\t\t\t\t\tchildLI = next;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tchildLI = childLI.nextSibling;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Make sure, that <li> order matches node.children order.\n\t\t\t\t\t\tchildLI = node.ul.firstChild;\n\t\t\t\t\t\tfor (i = 0, l = children.length - 1; i < l; i++) {\n\t\t\t\t\t\t\tchildNode1 = children[i];\n\t\t\t\t\t\t\tchildNode2 = childLI.ftnode;\n\t\t\t\t\t\t\tif (childNode1 === childNode2) {\n\t\t\t\t\t\t\t\tchildLI = childLI.nextSibling;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// node.debug(\"_fixOrder: mismatch at index \" + i + \": \" + childNode1 + \" != \" + childNode2);\n\t\t\t\t\t\t\t\tnode.ul.insertBefore(\n\t\t\t\t\t\t\t\t\tchildNode1.li,\n\t\t\t\t\t\t\t\t\tchildNode2.li\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}\n\t\t\t\t} else {\n\t\t\t\t\t// No children: remove markup if any\n\t\t\t\t\tif (node.ul) {\n\t\t\t\t\t\t// alert(\"remove child markup for \" + node);\n\t\t\t\t\t\tthis.warn(\"remove child markup for \" + node);\n\t\t\t\t\t\tthis.nodeRemoveChildMarkup(ctx);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!isRootNode) {\n\t\t\t\t\t// Update element classes according to node state\n\t\t\t\t\t// this.nodeRenderStatus(ctx);\n\t\t\t\t\t// Finally add the whole structure to the DOM, so the browser can render\n\t\t\t\t\tif (firstTime) {\n\t\t\t\t\t\t// #486: successorLi is set, if we re-rendered (i.e. discarded)\n\t\t\t\t\t\t// existing markup, which  we want to insert at the same position.\n\t\t\t\t\t\t// (null is equivalent to append)\n\t\t\t\t\t\t// \t\tparent.ul.appendChild(node.li);\n\t\t\t\t\t\tparent.ul.insertBefore(node.li, successorLi);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t/** Create HTML inside the node's outer `<span>` (i.e. expander, checkbox,\n\t\t\t * icon, and title).\n\t\t\t *\n\t\t\t * nodeRenderStatus() is implied.\n\t\t\t * @param {EventData} ctx\n\t\t\t * @param {string} [title] optinal new title\n\t\t\t */\n\t\t\tnodeRenderTitle: function(ctx, title) {\n\t\t\t\t// set node connector images, links and text\n\t\t\t\tvar checkbox,\n\t\t\t\t\tclassName,\n\t\t\t\t\ticon,\n\t\t\t\t\tnodeTitle,\n\t\t\t\t\trole,\n\t\t\t\t\ttabindex,\n\t\t\t\t\ttooltip,\n\t\t\t\t\ticonTooltip,\n\t\t\t\t\tnode = ctx.node,\n\t\t\t\t\ttree = ctx.tree,\n\t\t\t\t\topts = ctx.options,\n\t\t\t\t\taria = opts.aria,\n\t\t\t\t\tlevel = node.getLevel(),\n\t\t\t\t\tares = [];\n\n\t\t\t\tif (title !== undefined) {\n\t\t\t\t\tnode.title = title;\n\t\t\t\t}\n\t\t\t\tif (!node.span || tree._enableUpdate === false) {\n\t\t\t\t\t// Silently bail out if node was not rendered yet, assuming\n\t\t\t\t\t// node.render() will be called as the node becomes visible\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// Connector (expanded, expandable or simple)\n\t\t\t\trole =\n\t\t\t\t\taria && node.hasChildren() !== false\n\t\t\t\t\t\t? \" role='button'\"\n\t\t\t\t\t\t: \"\";\n\t\t\t\tif (level < opts.minExpandLevel) {\n\t\t\t\t\tif (!node.lazy) {\n\t\t\t\t\t\tnode.expanded = true;\n\t\t\t\t\t}\n\t\t\t\t\tif (level > 1) {\n\t\t\t\t\t\tares.push(\n\t\t\t\t\t\t\t\"<span \" +\n\t\t\t\t\t\t\t\trole +\n\t\t\t\t\t\t\t\t\" class='fancytree-expander fancytree-expander-fixed'></span>\"\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\t// .. else (i.e. for root level) skip expander/connector alltogether\n\t\t\t\t} else {\n\t\t\t\t\tares.push(\n\t\t\t\t\t\t\"<span \" + role + \" class='fancytree-expander'></span>\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// Checkbox mode\n\t\t\t\tcheckbox = FT.evalOption(\"checkbox\", node, node, opts, false);\n\n\t\t\t\tif (checkbox && !node.isStatusNode()) {\n\t\t\t\t\trole = aria ? \" role='checkbox'\" : \"\";\n\t\t\t\t\tclassName = \"fancytree-checkbox\";\n\t\t\t\t\tif (\n\t\t\t\t\t\tcheckbox === \"radio\" ||\n\t\t\t\t\t\t(node.parent && node.parent.radiogroup)\n\t\t\t\t\t) {\n\t\t\t\t\t\tclassName += \" fancytree-radio\";\n\t\t\t\t\t}\n\t\t\t\t\tares.push(\n\t\t\t\t\t\t\"<span \" + role + \" class='\" + className + \"'></span>\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// Folder or doctype icon\n\t\t\t\tif (node.data.iconClass !== undefined) {\n\t\t\t\t\t// 2015-11-16\n\t\t\t\t\t// Handle / warn about backward compatibility\n\t\t\t\t\tif (node.icon) {\n\t\t\t\t\t\t$.error(\n\t\t\t\t\t\t\t\"'iconClass' node option is deprecated since v2.14.0: use 'icon' only instead\"\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnode.warn(\n\t\t\t\t\t\t\t\"'iconClass' node option is deprecated since v2.14.0: use 'icon' instead\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\tnode.icon = node.data.iconClass;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// If opts.icon is a callback and returns something other than undefined, use that\n\t\t\t\t// else if node.icon is a boolean or string, use that\n\t\t\t\t// else if opts.icon is a boolean or string, use that\n\t\t\t\t// else show standard icon (which may be different for folders or documents)\n\t\t\t\ticon = FT.evalOption(\"icon\", node, node, opts, true);\n\t\t\t\t// if( typeof icon !== \"boolean\" ) {\n\t\t\t\t// \t// icon is defined, but not true/false: must be a string\n\t\t\t\t// \ticon = \"\" + icon;\n\t\t\t\t// }\n\t\t\t\tif (icon !== false) {\n\t\t\t\t\trole = aria ? \" role='presentation'\" : \"\";\n\n\t\t\t\t\ticonTooltip = FT.evalOption(\n\t\t\t\t\t\t\"iconTooltip\",\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\topts,\n\t\t\t\t\t\tnull\n\t\t\t\t\t);\n\t\t\t\t\ticonTooltip = iconTooltip\n\t\t\t\t\t\t? \" title='\" + _escapeTooltip(iconTooltip) + \"'\"\n\t\t\t\t\t\t: \"\";\n\n\t\t\t\t\tif (typeof icon === \"string\") {\n\t\t\t\t\t\tif (TEST_IMG.test(icon)) {\n\t\t\t\t\t\t\t// node.icon is an image url. Prepend imagePath\n\t\t\t\t\t\t\ticon =\n\t\t\t\t\t\t\t\ticon.charAt(0) === \"/\"\n\t\t\t\t\t\t\t\t\t? icon\n\t\t\t\t\t\t\t\t\t: (opts.imagePath || \"\") + icon;\n\t\t\t\t\t\t\tares.push(\n\t\t\t\t\t\t\t\t\"<img src='\" +\n\t\t\t\t\t\t\t\t\ticon +\n\t\t\t\t\t\t\t\t\t\"' class='fancytree-icon'\" +\n\t\t\t\t\t\t\t\t\ticonTooltip +\n\t\t\t\t\t\t\t\t\t\" alt='' />\"\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tares.push(\n\t\t\t\t\t\t\t\t\"<span \" +\n\t\t\t\t\t\t\t\t\trole +\n\t\t\t\t\t\t\t\t\t\" class='fancytree-custom-icon \" +\n\t\t\t\t\t\t\t\t\ticon +\n\t\t\t\t\t\t\t\t\t\"'\" +\n\t\t\t\t\t\t\t\t\ticonTooltip +\n\t\t\t\t\t\t\t\t\t\"></span>\"\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (icon.text) {\n\t\t\t\t\t\tares.push(\n\t\t\t\t\t\t\t\"<span \" +\n\t\t\t\t\t\t\t\trole +\n\t\t\t\t\t\t\t\t\" class='fancytree-custom-icon \" +\n\t\t\t\t\t\t\t\t(icon.addClass || \"\") +\n\t\t\t\t\t\t\t\t\"'\" +\n\t\t\t\t\t\t\t\ticonTooltip +\n\t\t\t\t\t\t\t\t\">\" +\n\t\t\t\t\t\t\t\tFT.escapeHtml(icon.text) +\n\t\t\t\t\t\t\t\t\"</span>\"\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (icon.html) {\n\t\t\t\t\t\tares.push(\n\t\t\t\t\t\t\t\"<span \" +\n\t\t\t\t\t\t\t\trole +\n\t\t\t\t\t\t\t\t\" class='fancytree-custom-icon \" +\n\t\t\t\t\t\t\t\t(icon.addClass || \"\") +\n\t\t\t\t\t\t\t\t\"'\" +\n\t\t\t\t\t\t\t\ticonTooltip +\n\t\t\t\t\t\t\t\t\">\" +\n\t\t\t\t\t\t\t\ticon.html +\n\t\t\t\t\t\t\t\t\"</span>\"\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// standard icon: theme css will take care of this\n\t\t\t\t\t\tares.push(\n\t\t\t\t\t\t\t\"<span \" +\n\t\t\t\t\t\t\t\trole +\n\t\t\t\t\t\t\t\t\" class='fancytree-icon'\" +\n\t\t\t\t\t\t\t\ticonTooltip +\n\t\t\t\t\t\t\t\t\"></span>\"\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Node title\n\t\t\t\tnodeTitle = \"\";\n\t\t\t\tif (opts.renderTitle) {\n\t\t\t\t\tnodeTitle =\n\t\t\t\t\t\topts.renderTitle.call(\n\t\t\t\t\t\t\ttree,\n\t\t\t\t\t\t\t{ type: \"renderTitle\" },\n\t\t\t\t\t\t\tctx\n\t\t\t\t\t\t) || \"\";\n\t\t\t\t}\n\t\t\t\tif (!nodeTitle) {\n\t\t\t\t\ttooltip = FT.evalOption(\"tooltip\", node, node, opts, null);\n\t\t\t\t\tif (tooltip === true) {\n\t\t\t\t\t\ttooltip = node.title;\n\t\t\t\t\t}\n\t\t\t\t\t// if( node.tooltip ) {\n\t\t\t\t\t// \ttooltip = node.tooltip;\n\t\t\t\t\t// } else if ( opts.tooltip ) {\n\t\t\t\t\t// \ttooltip = opts.tooltip === true ? node.title : opts.tooltip.call(tree, node);\n\t\t\t\t\t// }\n\t\t\t\t\ttooltip = tooltip\n\t\t\t\t\t\t? \" title='\" + _escapeTooltip(tooltip) + \"'\"\n\t\t\t\t\t\t: \"\";\n\t\t\t\t\ttabindex = opts.titlesTabbable ? \" tabindex='0'\" : \"\";\n\n\t\t\t\t\tnodeTitle =\n\t\t\t\t\t\t\"<span class='fancytree-title'\" +\n\t\t\t\t\t\ttooltip +\n\t\t\t\t\t\ttabindex +\n\t\t\t\t\t\t\">\" +\n\t\t\t\t\t\t(opts.escapeTitles\n\t\t\t\t\t\t\t? FT.escapeHtml(node.title)\n\t\t\t\t\t\t\t: node.title) +\n\t\t\t\t\t\t\"</span>\";\n\t\t\t\t}\n\t\t\t\tares.push(nodeTitle);\n\t\t\t\t// Note: this will trigger focusout, if node had the focus\n\t\t\t\t//$(node.span).html(ares.join(\"\")); // it will cleanup the jQuery data currently associated with SPAN (if any), but it executes more slowly\n\t\t\t\tnode.span.innerHTML = ares.join(\"\");\n\t\t\t\t// Update CSS classes\n\t\t\t\tthis.nodeRenderStatus(ctx);\n\t\t\t\tif (opts.enhanceTitle) {\n\t\t\t\t\tctx.$title = $(\">span.fancytree-title\", node.span);\n\t\t\t\t\tnodeTitle =\n\t\t\t\t\t\topts.enhanceTitle.call(\n\t\t\t\t\t\t\ttree,\n\t\t\t\t\t\t\t{ type: \"enhanceTitle\" },\n\t\t\t\t\t\t\tctx\n\t\t\t\t\t\t) || \"\";\n\t\t\t\t}\n\t\t\t},\n\t\t\t/** Update element classes according to node state.\n\t\t\t * @param {EventData} ctx\n\t\t\t */\n\t\t\tnodeRenderStatus: function(ctx) {\n\t\t\t\t// Set classes for current status\n\t\t\t\tvar $ariaElem,\n\t\t\t\t\tnode = ctx.node,\n\t\t\t\t\ttree = ctx.tree,\n\t\t\t\t\topts = ctx.options,\n\t\t\t\t\t// \tnodeContainer = node[tree.nodeContainerAttrName],\n\t\t\t\t\thasChildren = node.hasChildren(),\n\t\t\t\t\tisLastSib = node.isLastSibling(),\n\t\t\t\t\taria = opts.aria,\n\t\t\t\t\tcn = opts._classNames,\n\t\t\t\t\tcnList = [],\n\t\t\t\t\tstatusElem = node[tree.statusClassPropName];\n\n\t\t\t\tif (!statusElem || tree._enableUpdate === false) {\n\t\t\t\t\t// if this function is called for an unrendered node, ignore it (will be updated on nect render anyway)\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (aria) {\n\t\t\t\t\t$ariaElem = $(node.tr || node.li);\n\t\t\t\t}\n\t\t\t\t// Build a list of class names that we will add to the node <span>\n\t\t\t\tcnList.push(cn.node);\n\t\t\t\tif (tree.activeNode === node) {\n\t\t\t\t\tcnList.push(cn.active);\n\t\t\t\t\t// \t\t$(\">span.fancytree-title\", statusElem).attr(\"tabindex\", \"0\");\n\t\t\t\t\t// \t\ttree.$container.removeAttr(\"tabindex\");\n\t\t\t\t\t// }else{\n\t\t\t\t\t// \t\t$(\">span.fancytree-title\", statusElem).removeAttr(\"tabindex\");\n\t\t\t\t\t// \t\ttree.$container.attr(\"tabindex\", \"0\");\n\t\t\t\t}\n\t\t\t\tif (tree.focusNode === node) {\n\t\t\t\t\tcnList.push(cn.focused);\n\t\t\t\t}\n\t\t\t\tif (node.expanded) {\n\t\t\t\t\tcnList.push(cn.expanded);\n\t\t\t\t}\n\t\t\t\tif (aria) {\n\t\t\t\t\tif (hasChildren === false) {\n\t\t\t\t\t\t$ariaElem.removeAttr(\"aria-expanded\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$ariaElem.attr(\"aria-expanded\", Boolean(node.expanded));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (node.folder) {\n\t\t\t\t\tcnList.push(cn.folder);\n\t\t\t\t}\n\t\t\t\tif (hasChildren !== false) {\n\t\t\t\t\tcnList.push(cn.hasChildren);\n\t\t\t\t}\n\t\t\t\t// TODO: required?\n\t\t\t\tif (isLastSib) {\n\t\t\t\t\tcnList.push(cn.lastsib);\n\t\t\t\t}\n\t\t\t\tif (node.lazy && node.children == null) {\n\t\t\t\t\tcnList.push(cn.lazy);\n\t\t\t\t}\n\t\t\t\tif (node.partload) {\n\t\t\t\t\tcnList.push(cn.partload);\n\t\t\t\t}\n\t\t\t\tif (node.partsel) {\n\t\t\t\t\tcnList.push(cn.partsel);\n\t\t\t\t}\n\t\t\t\tif (FT.evalOption(\"unselectable\", node, node, opts, false)) {\n\t\t\t\t\tcnList.push(cn.unselectable);\n\t\t\t\t}\n\t\t\t\tif (node._isLoading) {\n\t\t\t\t\tcnList.push(cn.loading);\n\t\t\t\t}\n\t\t\t\tif (node._error) {\n\t\t\t\t\tcnList.push(cn.error);\n\t\t\t\t}\n\t\t\t\tif (node.statusNodeType) {\n\t\t\t\t\tcnList.push(cn.statusNodePrefix + node.statusNodeType);\n\t\t\t\t}\n\t\t\t\tif (node.selected) {\n\t\t\t\t\tcnList.push(cn.selected);\n\t\t\t\t\tif (aria) {\n\t\t\t\t\t\t$ariaElem.attr(\"aria-selected\", true);\n\t\t\t\t\t}\n\t\t\t\t} else if (aria) {\n\t\t\t\t\t$ariaElem.attr(\"aria-selected\", false);\n\t\t\t\t}\n\t\t\t\tif (node.extraClasses) {\n\t\t\t\t\tcnList.push(node.extraClasses);\n\t\t\t\t}\n\t\t\t\t// IE6 doesn't correctly evaluate multiple class names,\n\t\t\t\t// so we create combined class names that can be used in the CSS\n\t\t\t\tif (hasChildren === false) {\n\t\t\t\t\tcnList.push(\n\t\t\t\t\t\tcn.combinedExpanderPrefix + \"n\" + (isLastSib ? \"l\" : \"\")\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tcnList.push(\n\t\t\t\t\t\tcn.combinedExpanderPrefix +\n\t\t\t\t\t\t\t(node.expanded ? \"e\" : \"c\") +\n\t\t\t\t\t\t\t(node.lazy && node.children == null ? \"d\" : \"\") +\n\t\t\t\t\t\t\t(isLastSib ? \"l\" : \"\")\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcnList.push(\n\t\t\t\t\tcn.combinedIconPrefix +\n\t\t\t\t\t\t(node.expanded ? \"e\" : \"c\") +\n\t\t\t\t\t\t(node.folder ? \"f\" : \"\")\n\t\t\t\t);\n\t\t\t\t// node.span.className = cnList.join(\" \");\n\t\t\t\tstatusElem.className = cnList.join(\" \");\n\n\t\t\t\t// TODO: we should not set this in the <span> tag also, if we set it here:\n\t\t\t\t// Maybe most (all) of the classes should be set in LI instead of SPAN?\n\t\t\t\tif (node.li) {\n\t\t\t\t\t// #719: we have to consider that there may be already other classes:\n\t\t\t\t\t$(node.li).toggleClass(cn.lastsib, isLastSib);\n\t\t\t\t}\n\t\t\t},\n\t\t\t/** Activate node.\n\t\t\t * flag defaults to true.\n\t\t\t * If flag is true, the node is activated (must be a synchronous operation)\n\t\t\t * If flag is false, the node is deactivated (must be a synchronous operation)\n\t\t\t * @param {EventData} ctx\n\t\t\t * @param {boolean} [flag=true]\n\t\t\t * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false}\n\t\t\t * @returns {$.Promise}\n\t\t\t */\n\t\t\tnodeSetActive: function(ctx, flag, callOpts) {\n\t\t\t\t// Handle user click / [space] / [enter], according to clickFolderMode.\n\t\t\t\tcallOpts = callOpts || {};\n\t\t\t\tvar subCtx,\n\t\t\t\t\tnode = ctx.node,\n\t\t\t\t\ttree = ctx.tree,\n\t\t\t\t\topts = ctx.options,\n\t\t\t\t\tnoEvents = callOpts.noEvents === true,\n\t\t\t\t\tnoFocus = callOpts.noFocus === true,\n\t\t\t\t\tscroll = callOpts.scrollIntoView !== false,\n\t\t\t\t\tisActive = node === tree.activeNode;\n\n\t\t\t\t// flag defaults to true\n\t\t\t\tflag = flag !== false;\n\t\t\t\t// node.debug(\"nodeSetActive\", flag);\n\n\t\t\t\tif (isActive === flag) {\n\t\t\t\t\t// Nothing to do\n\t\t\t\t\treturn _getResolvedPromise(node);\n\t\t\t\t} else if (\n\t\t\t\t\tflag &&\n\t\t\t\t\t!noEvents &&\n\t\t\t\t\tthis._triggerNodeEvent(\n\t\t\t\t\t\t\"beforeActivate\",\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\tctx.originalEvent\n\t\t\t\t\t) === false\n\t\t\t\t) {\n\t\t\t\t\t// Callback returned false\n\t\t\t\t\treturn _getRejectedPromise(node, [\"rejected\"]);\n\t\t\t\t}\n\t\t\t\tif (flag) {\n\t\t\t\t\tif (tree.activeNode) {\n\t\t\t\t\t\t_assert(\n\t\t\t\t\t\t\ttree.activeNode !== node,\n\t\t\t\t\t\t\t\"node was active (inconsistency)\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\tsubCtx = $.extend({}, ctx, { node: tree.activeNode });\n\t\t\t\t\t\ttree.nodeSetActive(subCtx, false);\n\t\t\t\t\t\t_assert(\n\t\t\t\t\t\t\ttree.activeNode === null,\n\t\t\t\t\t\t\t\"deactivate was out of sync?\"\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (opts.activeVisible) {\n\t\t\t\t\t\t// If no focus is set (noFocus: true) and there is no focused node, this node is made visible.\n\t\t\t\t\t\t// scroll = noFocus && tree.focusNode == null;\n\t\t\t\t\t\t// #863: scroll by default (unless `scrollIntoView: false` was passed)\n\t\t\t\t\t\tnode.makeVisible({ scrollIntoView: scroll });\n\t\t\t\t\t}\n\t\t\t\t\ttree.activeNode = node;\n\t\t\t\t\ttree.nodeRenderStatus(ctx);\n\t\t\t\t\tif (!noFocus) {\n\t\t\t\t\t\ttree.nodeSetFocus(ctx);\n\t\t\t\t\t}\n\t\t\t\t\tif (!noEvents) {\n\t\t\t\t\t\ttree._triggerNodeEvent(\n\t\t\t\t\t\t\t\"activate\",\n\t\t\t\t\t\t\tnode,\n\t\t\t\t\t\t\tctx.originalEvent\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t_assert(\n\t\t\t\t\t\ttree.activeNode === node,\n\t\t\t\t\t\t\"node was not active (inconsistency)\"\n\t\t\t\t\t);\n\t\t\t\t\ttree.activeNode = null;\n\t\t\t\t\tthis.nodeRenderStatus(ctx);\n\t\t\t\t\tif (!noEvents) {\n\t\t\t\t\t\tctx.tree._triggerNodeEvent(\n\t\t\t\t\t\t\t\"deactivate\",\n\t\t\t\t\t\t\tnode,\n\t\t\t\t\t\t\tctx.originalEvent\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn _getResolvedPromise(node);\n\t\t\t},\n\t\t\t/** Expand or collapse node, return Deferred.promise.\n\t\t\t *\n\t\t\t * @param {EventData} ctx\n\t\t\t * @param {boolean} [flag=true]\n\t\t\t * @param {object} [opts] additional options. Defaults to `{noAnimation: false, noEvents: false}`\n\t\t\t * @returns {$.Promise} The deferred will be resolved as soon as the (lazy)\n\t\t\t *     data was retrieved, rendered, and the expand animation finished.\n\t\t\t */\n\t\t\tnodeSetExpanded: function(ctx, flag, callOpts) {\n\t\t\t\tcallOpts = callOpts || {};\n\t\t\t\tvar _afterLoad,\n\t\t\t\t\tdfd,\n\t\t\t\t\ti,\n\t\t\t\t\tl,\n\t\t\t\t\tparents,\n\t\t\t\t\tprevAC,\n\t\t\t\t\tnode = ctx.node,\n\t\t\t\t\ttree = ctx.tree,\n\t\t\t\t\topts = ctx.options,\n\t\t\t\t\tnoAnimation = callOpts.noAnimation === true,\n\t\t\t\t\tnoEvents = callOpts.noEvents === true;\n\n\t\t\t\t// flag defaults to true\n\t\t\t\tflag = flag !== false;\n\n\t\t\t\t// node.debug(\"nodeSetExpanded(\" + flag + \")\");\n\n\t\t\t\tif ((node.expanded && flag) || (!node.expanded && !flag)) {\n\t\t\t\t\t// Nothing to do\n\t\t\t\t\t// node.debug(\"nodeSetExpanded(\" + flag + \"): nothing to do\");\n\t\t\t\t\treturn _getResolvedPromise(node);\n\t\t\t\t} else if (flag && !node.lazy && !node.hasChildren()) {\n\t\t\t\t\t// Prevent expanding of empty nodes\n\t\t\t\t\t// return _getRejectedPromise(node, [\"empty\"]);\n\t\t\t\t\treturn _getResolvedPromise(node);\n\t\t\t\t} else if (!flag && node.getLevel() < opts.minExpandLevel) {\n\t\t\t\t\t// Prevent collapsing locked levels\n\t\t\t\t\treturn _getRejectedPromise(node, [\"locked\"]);\n\t\t\t\t} else if (\n\t\t\t\t\t!noEvents &&\n\t\t\t\t\tthis._triggerNodeEvent(\n\t\t\t\t\t\t\"beforeExpand\",\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\tctx.originalEvent\n\t\t\t\t\t) === false\n\t\t\t\t) {\n\t\t\t\t\t// Callback returned false\n\t\t\t\t\treturn _getRejectedPromise(node, [\"rejected\"]);\n\t\t\t\t}\n\t\t\t\t// If this node inside a collpased node, no animation and scrolling is needed\n\t\t\t\tif (!noAnimation && !node.isVisible()) {\n\t\t\t\t\tnoAnimation = callOpts.noAnimation = true;\n\t\t\t\t}\n\n\t\t\t\tdfd = new $.Deferred();\n\n\t\t\t\t// Auto-collapse mode: collapse all siblings\n\t\t\t\tif (flag && !node.expanded && opts.autoCollapse) {\n\t\t\t\t\tparents = node.getParentList(false, true);\n\t\t\t\t\tprevAC = opts.autoCollapse;\n\t\t\t\t\ttry {\n\t\t\t\t\t\topts.autoCollapse = false;\n\t\t\t\t\t\tfor (i = 0, l = parents.length; i < l; i++) {\n\t\t\t\t\t\t\t// TODO: should return promise?\n\t\t\t\t\t\t\tthis._callHook(\n\t\t\t\t\t\t\t\t\"nodeCollapseSiblings\",\n\t\t\t\t\t\t\t\tparents[i],\n\t\t\t\t\t\t\t\tcallOpts\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\topts.autoCollapse = prevAC;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Trigger expand/collapse after expanding\n\t\t\t\tdfd.done(function() {\n\t\t\t\t\tvar lastChild = node.getLastChild();\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tflag &&\n\t\t\t\t\t\topts.autoScroll &&\n\t\t\t\t\t\t!noAnimation &&\n\t\t\t\t\t\tlastChild &&\n\t\t\t\t\t\ttree._enableUpdate\n\t\t\t\t\t) {\n\t\t\t\t\t\t// Scroll down to last child, but keep current node visible\n\t\t\t\t\t\tlastChild\n\t\t\t\t\t\t\t.scrollIntoView(true, { topNode: node })\n\t\t\t\t\t\t\t.always(function() {\n\t\t\t\t\t\t\t\tif (!noEvents) {\n\t\t\t\t\t\t\t\t\tctx.tree._triggerNodeEvent(\n\t\t\t\t\t\t\t\t\t\tflag ? \"expand\" : \"collapse\",\n\t\t\t\t\t\t\t\t\t\tctx\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\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!noEvents) {\n\t\t\t\t\t\t\tctx.tree._triggerNodeEvent(\n\t\t\t\t\t\t\t\tflag ? \"expand\" : \"collapse\",\n\t\t\t\t\t\t\t\tctx\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\t// vvv Code below is executed after loading finished:\n\t\t\t\t_afterLoad = function(callback) {\n\t\t\t\t\tvar cn = opts._classNames,\n\t\t\t\t\t\tisVisible,\n\t\t\t\t\t\tisExpanded,\n\t\t\t\t\t\teffect = opts.toggleEffect;\n\n\t\t\t\t\tnode.expanded = flag;\n\t\t\t\t\ttree._callHook(\n\t\t\t\t\t\t\"treeStructureChanged\",\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\tflag ? \"expand\" : \"collapse\"\n\t\t\t\t\t);\n\t\t\t\t\t// Create required markup, but make sure the top UL is hidden, so we\n\t\t\t\t\t// can animate later\n\t\t\t\t\ttree._callHook(\"nodeRender\", ctx, false, false, true);\n\n\t\t\t\t\t// Hide children, if node is collapsed\n\t\t\t\t\tif (node.ul) {\n\t\t\t\t\t\tisVisible = node.ul.style.display !== \"none\";\n\t\t\t\t\t\tisExpanded = !!node.expanded;\n\t\t\t\t\t\tif (isVisible === isExpanded) {\n\t\t\t\t\t\t\tnode.warn(\n\t\t\t\t\t\t\t\t\"nodeSetExpanded: UL.style.display already set\"\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else if (!effect || noAnimation) {\n\t\t\t\t\t\t\tnode.ul.style.display =\n\t\t\t\t\t\t\t\tnode.expanded || !parent ? \"\" : \"none\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// The UI toggle() effect works with the ext-wide extension,\n\t\t\t\t\t\t\t// while jQuery.animate() has problems when the title span\n\t\t\t\t\t\t\t// has position: absolute.\n\t\t\t\t\t\t\t// Since jQuery UI 1.12, the blind effect requires the parent\n\t\t\t\t\t\t\t// element to have 'position: relative'.\n\t\t\t\t\t\t\t// See #716, #717\n\t\t\t\t\t\t\t$(node.li).addClass(cn.animating); // #717\n\n\t\t\t\t\t\t\tif ($.isFunction($(node.ul)[effect.effect])) {\n\t\t\t\t\t\t\t\t// tree.debug( \"use jquery.\" + effect.effect + \" method\" );\n\t\t\t\t\t\t\t\t$(node.ul)[effect.effect]({\n\t\t\t\t\t\t\t\t\tduration: effect.duration,\n\t\t\t\t\t\t\t\t\talways: function() {\n\t\t\t\t\t\t\t\t\t\t// node.debug(\"fancytree-animating end: \" + node.li.className);\n\t\t\t\t\t\t\t\t\t\t$(this).removeClass(cn.animating); // #716\n\t\t\t\t\t\t\t\t\t\t$(node.li).removeClass(cn.animating); // #717\n\t\t\t\t\t\t\t\t\t\tcallback();\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} else {\n\t\t\t\t\t\t\t\t// The UI toggle() effect works with the ext-wide extension,\n\t\t\t\t\t\t\t\t// while jQuery.animate() has problems when the title span\n\t\t\t\t\t\t\t\t// has positon: absolute.\n\t\t\t\t\t\t\t\t// Since jQuery UI 1.12, the blind effect requires the parent\n\t\t\t\t\t\t\t\t// element to have 'position: relative'.\n\t\t\t\t\t\t\t\t// See #716, #717\n\t\t\t\t\t\t\t\t// tree.debug(\"use specified effect (\" + effect.effect + \") with the jqueryui.toggle method\");\n\n\t\t\t\t\t\t\t\t// try to stop an animation that might be already in progress\n\t\t\t\t\t\t\t\t$(node.ul).stop(true, true); //< does not work after resetLazy has been called for a node whose animation wasn't complete and effect was \"blind\"\n\n\t\t\t\t\t\t\t\t// dirty fix to remove a defunct animation (effect: \"blind\") after resetLazy has been called\n\t\t\t\t\t\t\t\t$(node.ul)\n\t\t\t\t\t\t\t\t\t.parent()\n\t\t\t\t\t\t\t\t\t.find(\".ui-effects-placeholder\")\n\t\t\t\t\t\t\t\t\t.remove();\n\n\t\t\t\t\t\t\t\t$(node.ul).toggle(\n\t\t\t\t\t\t\t\t\teffect.effect,\n\t\t\t\t\t\t\t\t\teffect.options,\n\t\t\t\t\t\t\t\t\teffect.duration,\n\t\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t\t// node.debug(\"fancytree-animating end: \" + node.li.className);\n\t\t\t\t\t\t\t\t\t\t$(this).removeClass(cn.animating); // #716\n\t\t\t\t\t\t\t\t\t\t$(node.li).removeClass(cn.animating); // #717\n\t\t\t\t\t\t\t\t\t\tcallback();\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\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcallback();\n\t\t\t\t};\n\t\t\t\t// ^^^ Code above is executed after loading finshed.\n\n\t\t\t\t// Load lazy nodes, if any. Then continue with _afterLoad()\n\t\t\t\tif (flag && node.lazy && node.hasChildren() === undefined) {\n\t\t\t\t\t// node.debug(\"nodeSetExpanded: load start...\");\n\t\t\t\t\tnode.load()\n\t\t\t\t\t\t.done(function() {\n\t\t\t\t\t\t\t// node.debug(\"nodeSetExpanded: load done\");\n\t\t\t\t\t\t\tif (dfd.notifyWith) {\n\t\t\t\t\t\t\t\t// requires jQuery 1.6+\n\t\t\t\t\t\t\t\tdfd.notifyWith(node, [\"loaded\"]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t_afterLoad(function() {\n\t\t\t\t\t\t\t\tdfd.resolveWith(node);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.fail(function(errMsg) {\n\t\t\t\t\t\t\t_afterLoad(function() {\n\t\t\t\t\t\t\t\tdfd.rejectWith(node, [\n\t\t\t\t\t\t\t\t\t\"load failed (\" + errMsg + \")\",\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/*\n\t\t\t\t\tvar source = tree._triggerNodeEvent(\"lazyLoad\", node, ctx.originalEvent);\n\t\t\t\t\t_assert(typeof source !== \"boolean\", \"lazyLoad event must return source in data.result\");\n\t\t\t\t\tnode.debug(\"nodeSetExpanded: load start...\");\n\t\t\t\t\tthis._callHook(\"nodeLoadChildren\", ctx, source).done(function(){\n\t\t\t\t\t\tnode.debug(\"nodeSetExpanded: load done\");\n\t\t\t\t\t\tif(dfd.notifyWith){ // requires jQuery 1.6+\n\t\t\t\t\t\t\tdfd.notifyWith(node, [\"loaded\"]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t_afterLoad.call(tree);\n\t\t\t\t\t}).fail(function(errMsg){\n\t\t\t\t\t\tdfd.rejectWith(node, [\"load failed (\" + errMsg + \")\"]);\n\t\t\t\t\t});\n\t\t\t\t\t*/\n\t\t\t\t} else {\n\t\t\t\t\t_afterLoad(function() {\n\t\t\t\t\t\tdfd.resolveWith(node);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t// node.debug(\"nodeSetExpanded: returns\");\n\t\t\t\treturn dfd.promise();\n\t\t\t},\n\t\t\t/** Focus or blur this node.\n\t\t\t * @param {EventData} ctx\n\t\t\t * @param {boolean} [flag=true]\n\t\t\t */\n\t\t\tnodeSetFocus: function(ctx, flag) {\n\t\t\t\t// ctx.node.debug(\"nodeSetFocus(\" + flag + \")\");\n\t\t\t\tvar ctx2,\n\t\t\t\t\ttree = ctx.tree,\n\t\t\t\t\tnode = ctx.node,\n\t\t\t\t\topts = tree.options,\n\t\t\t\t\t// et = ctx.originalEvent && ctx.originalEvent.type,\n\t\t\t\t\tisInput = ctx.originalEvent\n\t\t\t\t\t\t? $(ctx.originalEvent.target).is(\":input\")\n\t\t\t\t\t\t: false;\n\n\t\t\t\tflag = flag !== false;\n\n\t\t\t\t// (node || tree).debug(\"nodeSetFocus(\" + flag + \"), event: \" + et + \", isInput: \"+ isInput);\n\t\t\t\t// Blur previous node if any\n\t\t\t\tif (tree.focusNode) {\n\t\t\t\t\tif (tree.focusNode === node && flag) {\n\t\t\t\t\t\t// node.debug(\"nodeSetFocus(\" + flag + \"): nothing to do\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tctx2 = $.extend({}, ctx, { node: tree.focusNode });\n\t\t\t\t\ttree.focusNode = null;\n\t\t\t\t\tthis._triggerNodeEvent(\"blur\", ctx2);\n\t\t\t\t\tthis._callHook(\"nodeRenderStatus\", ctx2);\n\t\t\t\t}\n\t\t\t\t// Set focus to container and node\n\t\t\t\tif (flag) {\n\t\t\t\t\tif (!this.hasFocus()) {\n\t\t\t\t\t\tnode.debug(\"nodeSetFocus: forcing container focus\");\n\t\t\t\t\t\tthis._callHook(\"treeSetFocus\", ctx, true, {\n\t\t\t\t\t\t\tcalledByNode: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tnode.makeVisible({ scrollIntoView: false });\n\t\t\t\t\ttree.focusNode = node;\n\t\t\t\t\tif (opts.titlesTabbable) {\n\t\t\t\t\t\tif (!isInput) {\n\t\t\t\t\t\t\t// #621\n\t\t\t\t\t\t\t$(node.span)\n\t\t\t\t\t\t\t\t.find(\".fancytree-title\")\n\t\t\t\t\t\t\t\t.focus();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (opts.aria) {\n\t\t\t\t\t\t// Set active descendant to node's span ID (create one, if needed)\n\t\t\t\t\t\t$(tree.$container).attr(\n\t\t\t\t\t\t\t\"aria-activedescendant\",\n\t\t\t\t\t\t\t$(node.tr || node.li)\n\t\t\t\t\t\t\t\t.uniqueId()\n\t\t\t\t\t\t\t\t.attr(\"id\")\n\t\t\t\t\t\t);\n\t\t\t\t\t\t// \"ftal_\" + opts.idPrefix + node.key);\n\t\t\t\t\t}\n\t\t\t\t\t// $(node.span).find(\".fancytree-title\").focus();\n\t\t\t\t\tthis._triggerNodeEvent(\"focus\", ctx);\n\n\t\t\t\t\t// determine if we have focus on or inside tree container\n\t\t\t\t\tvar hasFancytreeFocus =\n\t\t\t\t\t\tdocument.activeElement === tree.$container.get(0) ||\n\t\t\t\t\t\t$(document.activeElement, tree.$container).length >= 1;\n\n\t\t\t\t\tif (!hasFancytreeFocus) {\n\t\t\t\t\t\t// We cannot set KB focus to a node, so use the tree container\n\t\t\t\t\t\t// #563, #570: IE scrolls on every call to .focus(), if the container\n\t\t\t\t\t\t// is partially outside the viewport. So do it only, when absolutely\n\t\t\t\t\t\t// necessary.\n\t\t\t\t\t\t$(tree.$container).focus();\n\t\t\t\t\t}\n\n\t\t\t\t\t// if( opts.autoActivate ){\n\t\t\t\t\t// \ttree.nodeSetActive(ctx, true);\n\t\t\t\t\t// }\n\t\t\t\t\tif (opts.autoScroll) {\n\t\t\t\t\t\tnode.scrollIntoView();\n\t\t\t\t\t}\n\t\t\t\t\tthis._callHook(\"nodeRenderStatus\", ctx);\n\t\t\t\t}\n\t\t\t},\n\t\t\t/** (De)Select node, return new status (sync).\n\t\t\t *\n\t\t\t * @param {EventData} ctx\n\t\t\t * @param {boolean} [flag=true]\n\t\t\t * @param {object} [opts] additional options. Defaults to {noEvents: false,\n\t\t\t *     propagateDown: null, propagateUp: null,\n\t\t\t *     callback: null,\n\t\t\t *     }\n\t\t\t * @returns {boolean} previous status\n\t\t\t */\n\t\t\tnodeSetSelected: function(ctx, flag, callOpts) {\n\t\t\t\tcallOpts = callOpts || {};\n\t\t\t\tvar node = ctx.node,\n\t\t\t\t\ttree = ctx.tree,\n\t\t\t\t\topts = ctx.options,\n\t\t\t\t\tnoEvents = callOpts.noEvents === true,\n\t\t\t\t\tparent = node.parent;\n\n\t\t\t\t// flag defaults to true\n\t\t\t\tflag = flag !== false;\n\n\t\t\t\t// node.debug(\"nodeSetSelected(\" + flag + \")\", ctx);\n\n\t\t\t\t// Cannot (de)select unselectable nodes directly (only by propagation or\n\t\t\t\t// by setting the `.selected` property)\n\t\t\t\tif (FT.evalOption(\"unselectable\", node, node, opts, false)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Remember the user's intent, in case down -> up propagation prevents\n\t\t\t\t// applying it to node.selected\n\t\t\t\tnode._lastSelectIntent = flag; // Confusing use of '!'\n\n\t\t\t\t// Nothing to do?\n\t\t\t\tif (!!node.selected === flag) {\n\t\t\t\t\tif (opts.selectMode === 3 && node.partsel && !flag) {\n\t\t\t\t\t\t// If propagation prevented selecting this node last time, we still\n\t\t\t\t\t\t// want to allow to apply setSelected(false) now\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn flag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\t!noEvents &&\n\t\t\t\t\tthis._triggerNodeEvent(\n\t\t\t\t\t\t\"beforeSelect\",\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\tctx.originalEvent\n\t\t\t\t\t) === false\n\t\t\t\t) {\n\t\t\t\t\treturn !!node.selected;\n\t\t\t\t}\n\t\t\t\tif (flag && opts.selectMode === 1) {\n\t\t\t\t\t// single selection mode (we don't uncheck all tree nodes, for performance reasons)\n\t\t\t\t\tif (tree.lastSelectedNode) {\n\t\t\t\t\t\ttree.lastSelectedNode.setSelected(false);\n\t\t\t\t\t}\n\t\t\t\t\tnode.selected = flag;\n\t\t\t\t} else if (\n\t\t\t\t\topts.selectMode === 3 &&\n\t\t\t\t\tparent &&\n\t\t\t\t\t!parent.radiogroup &&\n\t\t\t\t\t!node.radiogroup\n\t\t\t\t) {\n\t\t\t\t\t// multi-hierarchical selection mode\n\t\t\t\t\tnode.selected = flag;\n\t\t\t\t\tnode.fixSelection3AfterClick(callOpts);\n\t\t\t\t} else if (parent && parent.radiogroup) {\n\t\t\t\t\tnode.visitSiblings(function(n) {\n\t\t\t\t\t\tn._changeSelectStatusAttrs(flag && n === node);\n\t\t\t\t\t}, true);\n\t\t\t\t} else {\n\t\t\t\t\t// default: selectMode: 2, multi selection mode\n\t\t\t\t\tnode.selected = flag;\n\t\t\t\t}\n\t\t\t\tthis.nodeRenderStatus(ctx);\n\t\t\t\ttree.lastSelectedNode = flag ? node : null;\n\t\t\t\tif (!noEvents) {\n\t\t\t\t\ttree._triggerNodeEvent(\"select\", ctx);\n\t\t\t\t}\n\t\t\t},\n\t\t\t/** Show node status (ok, loading, error, nodata) using styles and a dummy child node.\n\t\t\t *\n\t\t\t * @param {EventData} ctx\n\t\t\t * @param status\n\t\t\t * @param message\n\t\t\t * @param details\n\t\t\t * @since 2.3\n\t\t\t */\n\t\t\tnodeSetStatus: function(ctx, status, message, details) {\n\t\t\t\tvar node = ctx.node,\n\t\t\t\t\ttree = ctx.tree;\n\n\t\t\t\tfunction _clearStatusNode() {\n\t\t\t\t\t// Remove dedicated dummy node, if any\n\t\t\t\t\tvar firstChild = node.children ? node.children[0] : null;\n\t\t\t\t\tif (firstChild && firstChild.isStatusNode()) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// I've seen exceptions here with loadKeyPath...\n\t\t\t\t\t\t\tif (node.ul) {\n\t\t\t\t\t\t\t\tnode.ul.removeChild(firstChild.li);\n\t\t\t\t\t\t\t\tfirstChild.li = null; // avoid leaks (DT issue 215)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\tif (node.children.length === 1) {\n\t\t\t\t\t\t\tnode.children = [];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnode.children.shift();\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttree._callHook(\n\t\t\t\t\t\t\t\"treeStructureChanged\",\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\"clearStatusNode\"\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfunction _setStatusNode(data, type) {\n\t\t\t\t\t// Create/modify the dedicated dummy node for 'loading...' or\n\t\t\t\t\t// 'error!' status. (only called for direct child of the invisible\n\t\t\t\t\t// system root)\n\t\t\t\t\tvar firstChild = node.children ? node.children[0] : null;\n\t\t\t\t\tif (firstChild && firstChild.isStatusNode()) {\n\t\t\t\t\t\t$.extend(firstChild, data);\n\t\t\t\t\t\tfirstChild.statusNodeType = type;\n\t\t\t\t\t\ttree._callHook(\"nodeRenderTitle\", firstChild);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnode._setChildren([data]);\n\t\t\t\t\t\ttree._callHook(\n\t\t\t\t\t\t\t\"treeStructureChanged\",\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\"setStatusNode\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\tnode.children[0].statusNodeType = type;\n\t\t\t\t\t\ttree.render();\n\t\t\t\t\t}\n\t\t\t\t\treturn node.children[0];\n\t\t\t\t}\n\n\t\t\t\tswitch (status) {\n\t\t\t\t\tcase \"ok\":\n\t\t\t\t\t\t_clearStatusNode();\n\t\t\t\t\t\tnode._isLoading = false;\n\t\t\t\t\t\tnode._error = null;\n\t\t\t\t\t\tnode.renderStatus();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"loading\":\n\t\t\t\t\t\tif (!node.parent) {\n\t\t\t\t\t\t\t_setStatusNode(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttitle:\n\t\t\t\t\t\t\t\t\t\ttree.options.strings.loading +\n\t\t\t\t\t\t\t\t\t\t(message ? \" (\" + message + \")\" : \"\"),\n\t\t\t\t\t\t\t\t\t// icon: true,  // needed for 'loding' icon\n\t\t\t\t\t\t\t\t\tcheckbox: false,\n\t\t\t\t\t\t\t\t\ttooltip: details,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tstatus\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnode._isLoading = true;\n\t\t\t\t\t\tnode._error = null;\n\t\t\t\t\t\tnode.renderStatus();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"error\":\n\t\t\t\t\t\t_setStatusNode(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttitle:\n\t\t\t\t\t\t\t\t\ttree.options.strings.loadError +\n\t\t\t\t\t\t\t\t\t(message ? \" (\" + message + \")\" : \"\"),\n\t\t\t\t\t\t\t\t// icon: false,\n\t\t\t\t\t\t\t\tcheckbox: false,\n\t\t\t\t\t\t\t\ttooltip: details,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tstatus\n\t\t\t\t\t\t);\n\t\t\t\t\t\tnode._isLoading = false;\n\t\t\t\t\t\tnode._error = { message: message, details: details };\n\t\t\t\t\t\tnode.renderStatus();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"nodata\":\n\t\t\t\t\t\t_setStatusNode(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttitle: message || tree.options.strings.noData,\n\t\t\t\t\t\t\t\t// icon: false,\n\t\t\t\t\t\t\t\tcheckbox: false,\n\t\t\t\t\t\t\t\ttooltip: details,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tstatus\n\t\t\t\t\t\t);\n\t\t\t\t\t\tnode._isLoading = false;\n\t\t\t\t\t\tnode._error = null;\n\t\t\t\t\t\tnode.renderStatus();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t$.error(\"invalid node status \" + status);\n\t\t\t\t}\n\t\t\t},\n\t\t\t/**\n\t\t\t *\n\t\t\t * @param {EventData} ctx\n\t\t\t */\n\t\t\tnodeToggleExpanded: function(ctx) {\n\t\t\t\treturn this.nodeSetExpanded(ctx, !ctx.node.expanded);\n\t\t\t},\n\t\t\t/**\n\t\t\t * @param {EventData} ctx\n\t\t\t */\n\t\t\tnodeToggleSelected: function(ctx) {\n\t\t\t\tvar node = ctx.node,\n\t\t\t\t\tflag = !node.selected;\n\n\t\t\t\t// In selectMode: 3 this node may be unselected+partsel, even if\n\t\t\t\t// setSelected(true) was called before, due to `unselectable` children.\n\t\t\t\t// In this case, we now toggle as `setSelected(false)`\n\t\t\t\tif (\n\t\t\t\t\tnode.partsel &&\n\t\t\t\t\t!node.selected &&\n\t\t\t\t\tnode._lastSelectIntent === true\n\t\t\t\t) {\n\t\t\t\t\tflag = false;\n\t\t\t\t\tnode.selected = true; // so it is not considered 'nothing to do'\n\t\t\t\t}\n\t\t\t\tnode._lastSelectIntent = flag;\n\t\t\t\treturn this.nodeSetSelected(ctx, flag);\n\t\t\t},\n\t\t\t/** Remove all nodes.\n\t\t\t * @param {EventData} ctx\n\t\t\t */\n\t\t\ttreeClear: function(ctx) {\n\t\t\t\tvar tree = ctx.tree;\n\t\t\t\ttree.activeNode = null;\n\t\t\t\ttree.focusNode = null;\n\t\t\t\ttree.$div.find(\">ul.fancytree-container\").empty();\n\t\t\t\t// TODO: call destructors and remove reference loops\n\t\t\t\ttree.rootNode.children = null;\n\t\t\t\ttree._callHook(\"treeStructureChanged\", ctx, \"clear\");\n\t\t\t},\n\t\t\t/** Widget was created (called only once, even it re-initialized).\n\t\t\t * @param {EventData} ctx\n\t\t\t */\n\t\t\ttreeCreate: function(ctx) {},\n\t\t\t/** Widget was destroyed.\n\t\t\t * @param {EventData} ctx\n\t\t\t */\n\t\t\ttreeDestroy: function(ctx) {\n\t\t\t\tthis.$div.find(\">ul.fancytree-container\").remove();\n\t\t\t\tif (this.$source) {\n\t\t\t\t\tthis.$source.removeClass(\"fancytree-helper-hidden\");\n\t\t\t\t}\n\t\t\t},\n\t\t\t/** Widget was (re-)initialized.\n\t\t\t * @param {EventData} ctx\n\t\t\t */\n\t\t\ttreeInit: function(ctx) {\n\t\t\t\tvar tree = ctx.tree,\n\t\t\t\t\topts = tree.options;\n\n\t\t\t\t//this.debug(\"Fancytree.treeInit()\");\n\t\t\t\t// Add container to the TAB chain\n\t\t\t\t// See http://www.w3.org/TR/wai-aria-practices/#focus_activedescendant\n\t\t\t\t// #577: Allow to set tabindex to \"0\", \"-1\" and \"\"\n\t\t\t\ttree.$container.attr(\"tabindex\", opts.tabindex);\n\n\t\t\t\t// Copy some attributes to tree.data\n\t\t\t\t$.each(TREE_ATTRS, function(i, attr) {\n\t\t\t\t\tif (opts[attr] !== undefined) {\n\t\t\t\t\t\ttree.info(\"Move option \" + attr + \" to tree\");\n\t\t\t\t\t\ttree[attr] = opts[attr];\n\t\t\t\t\t\tdelete opts[attr];\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif (opts.checkboxAutoHide) {\n\t\t\t\t\ttree.$container.addClass(\"fancytree-checkbox-auto-hide\");\n\t\t\t\t}\n\t\t\t\tif (opts.rtl) {\n\t\t\t\t\ttree.$container\n\t\t\t\t\t\t.attr(\"DIR\", \"RTL\")\n\t\t\t\t\t\t.addClass(\"fancytree-rtl\");\n\t\t\t\t} else {\n\t\t\t\t\ttree.$container\n\t\t\t\t\t\t.removeAttr(\"DIR\")\n\t\t\t\t\t\t.removeClass(\"fancytree-rtl\");\n\t\t\t\t}\n\t\t\t\tif (opts.aria) {\n\t\t\t\t\ttree.$container.attr(\"role\", \"tree\");\n\t\t\t\t\tif (opts.selectMode !== 1) {\n\t\t\t\t\t\ttree.$container.attr(\"aria-multiselectable\", true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.treeLoad(ctx);\n\t\t\t},\n\t\t\t/** Parse Fancytree from source, as configured in the options.\n\t\t\t * @param {EventData} ctx\n\t\t\t * @param {object} [source] optional new source (use last data otherwise)\n\t\t\t */\n\t\t\ttreeLoad: function(ctx, source) {\n\t\t\t\tvar metaData,\n\t\t\t\t\ttype,\n\t\t\t\t\t$ul,\n\t\t\t\t\ttree = ctx.tree,\n\t\t\t\t\t$container = ctx.widget.element,\n\t\t\t\t\tdfd,\n\t\t\t\t\t// calling context for root node\n\t\t\t\t\trootCtx = $.extend({}, ctx, { node: this.rootNode });\n\n\t\t\t\tif (tree.rootNode.children) {\n\t\t\t\t\tthis.treeClear(ctx);\n\t\t\t\t}\n\t\t\t\tsource = source || this.options.source;\n\n\t\t\t\tif (!source) {\n\t\t\t\t\ttype = $container.data(\"type\") || \"html\";\n\t\t\t\t\tswitch (type) {\n\t\t\t\t\t\tcase \"html\":\n\t\t\t\t\t\t\t// There should be an embedded `<ul>` with initial nodes,\n\t\t\t\t\t\t\t// but another `<ul class='fancytree-container'>` is appended\n\t\t\t\t\t\t\t// to the tree's <div> on startup anyway.\n\t\t\t\t\t\t\t$ul = $container\n\t\t\t\t\t\t\t\t.find(\">ul\")\n\t\t\t\t\t\t\t\t.not(\".fancytree-container\")\n\t\t\t\t\t\t\t\t.first();\n\n\t\t\t\t\t\t\tif ($ul.length) {\n\t\t\t\t\t\t\t\t$ul.addClass(\n\t\t\t\t\t\t\t\t\t\"ui-fancytree-source fancytree-helper-hidden\"\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tsource = $.ui.fancytree.parseHtml($ul);\n\t\t\t\t\t\t\t\t// allow to init tree.data.foo from <ul data-foo=''>\n\t\t\t\t\t\t\t\tthis.data = $.extend(\n\t\t\t\t\t\t\t\t\tthis.data,\n\t\t\t\t\t\t\t\t\t_getElementDataAsDict($ul)\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tFT.warn(\n\t\t\t\t\t\t\t\t\t\"No `source` option was passed and container does not contain `<ul>`: assuming `source: []`.\"\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tsource = [];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"json\":\n\t\t\t\t\t\t\tsource = $.parseJSON($container.text());\n\t\t\t\t\t\t\t// $container already contains the <ul>, but we remove the plain (json) text\n\t\t\t\t\t\t\t// $container.empty();\n\t\t\t\t\t\t\t$container\n\t\t\t\t\t\t\t\t.contents()\n\t\t\t\t\t\t\t\t.filter(function() {\n\t\t\t\t\t\t\t\t\treturn this.nodeType === 3;\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.remove();\n\t\t\t\t\t\t\tif ($.isPlainObject(source)) {\n\t\t\t\t\t\t\t\t// We got {foo: 'abc', children: [...]}\n\t\t\t\t\t\t\t\t_assert(\n\t\t\t\t\t\t\t\t\t$.isArray(source.children),\n\t\t\t\t\t\t\t\t\t\"if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')\"\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tmetaData = source;\n\t\t\t\t\t\t\t\tsource = source.children;\n\t\t\t\t\t\t\t\tdelete metaData.children;\n\t\t\t\t\t\t\t\t// Copy some attributes to tree.data\n\t\t\t\t\t\t\t\t$.each(TREE_ATTRS, function(i, attr) {\n\t\t\t\t\t\t\t\t\tif (metaData[attr] !== undefined) {\n\t\t\t\t\t\t\t\t\t\ttree[attr] = metaData[attr];\n\t\t\t\t\t\t\t\t\t\tdelete metaData[attr];\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\t// Copy extra properties to tree.data.foo\n\t\t\t\t\t\t\t\t$.extend(tree.data, metaData);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t$.error(\"Invalid data-type: \" + type);\n\t\t\t\t\t}\n\t\t\t\t} else if (typeof source === \"string\") {\n\t\t\t\t\t// TODO: source is an element ID\n\t\t\t\t\t$.error(\"Not implemented\");\n\t\t\t\t}\n\n\t\t\t\t// preInit is fired when the widget markup is created, but nodes\n\t\t\t\t// not yet loaded\n\t\t\t\ttree._triggerTreeEvent(\"preInit\", null);\n\n\t\t\t\t// Trigger fancytreeinit after nodes have been loaded\n\t\t\t\tdfd = this.nodeLoadChildren(rootCtx, source)\n\t\t\t\t\t.done(function() {\n\t\t\t\t\t\ttree._callHook(\n\t\t\t\t\t\t\t\"treeStructureChanged\",\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\"loadChildren\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\ttree.render();\n\t\t\t\t\t\tif (ctx.options.selectMode === 3) {\n\t\t\t\t\t\t\ttree.rootNode.fixSelection3FromEndNodes();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (tree.activeNode && tree.options.activeVisible) {\n\t\t\t\t\t\t\ttree.activeNode.makeVisible();\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttree._triggerTreeEvent(\"init\", null, { status: true });\n\t\t\t\t\t})\n\t\t\t\t\t.fail(function() {\n\t\t\t\t\t\ttree.render();\n\t\t\t\t\t\ttree._triggerTreeEvent(\"init\", null, { status: false });\n\t\t\t\t\t});\n\t\t\t\treturn dfd;\n\t\t\t},\n\t\t\t/** Node was inserted into or removed from the tree.\n\t\t\t * @param {EventData} ctx\n\t\t\t * @param {boolean} add\n\t\t\t * @param {FancytreeNode} node\n\t\t\t */\n\t\t\ttreeRegisterNode: function(ctx, add, node) {\n\t\t\t\tctx.tree._callHook(\n\t\t\t\t\t\"treeStructureChanged\",\n\t\t\t\t\tctx,\n\t\t\t\t\tadd ? \"addNode\" : \"removeNode\"\n\t\t\t\t);\n\t\t\t},\n\t\t\t/** Widget got focus.\n\t\t\t * @param {EventData} ctx\n\t\t\t * @param {boolean} [flag=true]\n\t\t\t */\n\t\t\ttreeSetFocus: function(ctx, flag, callOpts) {\n\t\t\t\tvar targetNode;\n\n\t\t\t\tflag = flag !== false;\n\n\t\t\t\t// this.debug(\"treeSetFocus(\" + flag + \"), callOpts: \", callOpts, this.hasFocus());\n\t\t\t\t// this.debug(\"    focusNode: \" + this.focusNode);\n\t\t\t\t// this.debug(\"    activeNode: \" + this.activeNode);\n\t\t\t\tif (flag !== this.hasFocus()) {\n\t\t\t\t\tthis._hasFocus = flag;\n\t\t\t\t\tif (!flag && this.focusNode) {\n\t\t\t\t\t\t// Node also looses focus if widget blurs\n\t\t\t\t\t\tthis.focusNode.setFocus(false);\n\t\t\t\t\t} else if (flag && (!callOpts || !callOpts.calledByNode)) {\n\t\t\t\t\t\t$(this.$container).focus();\n\t\t\t\t\t}\n\t\t\t\t\tthis.$container.toggleClass(\"fancytree-treefocus\", flag);\n\t\t\t\t\tthis._triggerTreeEvent(flag ? \"focusTree\" : \"blurTree\");\n\t\t\t\t\tif (flag && !this.activeNode) {\n\t\t\t\t\t\t// #712: Use last mousedowned node ('click' event fires after focusin)\n\t\t\t\t\t\ttargetNode =\n\t\t\t\t\t\t\tthis._lastMousedownNode || this.getFirstChild();\n\t\t\t\t\t\tif (targetNode) {\n\t\t\t\t\t\t\ttargetNode.setFocus();\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\t/** Widget option was set using `$().fancytree(\"option\", \"KEY\", VALUE)`.\n\t\t\t *\n\t\t\t * Note: `key` may reference a nested option, e.g. 'dnd5.scroll'.\n\t\t\t * In this case `value`contains the complete, modified `dnd5` option hash.\n\t\t\t * We can check for changed values like\n\t\t\t *     if( value.scroll !== tree.options.dnd5.scroll ) {...}\n\t\t\t *\n\t\t\t * @param {EventData} ctx\n\t\t\t * @param {string} key option name\n\t\t\t * @param {any} value option value\n\t\t\t */\n\t\t\ttreeSetOption: function(ctx, key, value) {\n\t\t\t\tvar tree = ctx.tree,\n\t\t\t\t\tcallDefault = true,\n\t\t\t\t\tcallCreate = false,\n\t\t\t\t\tcallRender = false;\n\n\t\t\t\tswitch (key) {\n\t\t\t\t\tcase \"aria\":\n\t\t\t\t\tcase \"checkbox\":\n\t\t\t\t\tcase \"icon\":\n\t\t\t\t\tcase \"minExpandLevel\":\n\t\t\t\t\tcase \"tabindex\":\n\t\t\t\t\t\t// tree._callHook(\"treeCreate\", tree);\n\t\t\t\t\t\tcallCreate = true;\n\t\t\t\t\t\tcallRender = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"checkboxAutoHide\":\n\t\t\t\t\t\ttree.$container.toggleClass(\n\t\t\t\t\t\t\t\"fancytree-checkbox-auto-hide\",\n\t\t\t\t\t\t\t!!value\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"escapeTitles\":\n\t\t\t\t\tcase \"tooltip\":\n\t\t\t\t\t\tcallRender = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"rtl\":\n\t\t\t\t\t\tif (value === false) {\n\t\t\t\t\t\t\ttree.$container\n\t\t\t\t\t\t\t\t.removeAttr(\"DIR\")\n\t\t\t\t\t\t\t\t.removeClass(\"fancytree-rtl\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttree.$container\n\t\t\t\t\t\t\t\t.attr(\"DIR\", \"RTL\")\n\t\t\t\t\t\t\t\t.addClass(\"fancytree-rtl\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcallRender = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"source\":\n\t\t\t\t\t\tcallDefault = false;\n\t\t\t\t\t\ttree._callHook(\"treeLoad\", tree, value);\n\t\t\t\t\t\tcallRender = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ttree.debug(\n\t\t\t\t\t\"set option \" +\n\t\t\t\t\t\tkey +\n\t\t\t\t\t\t\"=\" +\n\t\t\t\t\t\tvalue +\n\t\t\t\t\t\t\" <\" +\n\t\t\t\t\t\ttypeof value +\n\t\t\t\t\t\t\">\"\n\t\t\t\t);\n\t\t\t\tif (callDefault) {\n\t\t\t\t\tif (this.widget._super) {\n\t\t\t\t\t\t// jQuery UI 1.9+\n\t\t\t\t\t\tthis.widget._super.call(this.widget, key, value);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// jQuery UI <= 1.8, we have to manually invoke the _setOption method from the base widget\n\t\t\t\t\t\t$.Widget.prototype._setOption.call(\n\t\t\t\t\t\t\tthis.widget,\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tvalue\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (callCreate) {\n\t\t\t\t\ttree._callHook(\"treeCreate\", tree);\n\t\t\t\t}\n\t\t\t\tif (callRender) {\n\t\t\t\t\ttree.render(true, false); // force, not-deep\n\t\t\t\t}\n\t\t\t},\n\t\t\t/** A Node was added, removed, moved, or it's visibility changed.\n\t\t\t * @param {EventData} ctx\n\t\t\t */\n\t\t\ttreeStructureChanged: function(ctx, type) {},\n\t\t}\n\t);\n\n\t/*******************************************************************************\n\t * jQuery UI widget boilerplate\n\t */\n\n\t/**\n\t * The plugin (derrived from [jQuery.Widget](http://api.jqueryui.com/jQuery.widget/)).\n\t *\n\t * **Note:**\n\t * These methods implement the standard jQuery UI widget API.\n\t * It is recommended to use methods of the {Fancytree} instance instead\n\t *\n\t * @example\n\t * // DEPRECATED: Access jQuery UI widget methods and members:\n\t * var tree = $(\"#tree\").fancytree(\"getTree\", \"#myTree\");\n\t * var node = $.ui.fancytree.getTree(\"#tree\").getActiveNode();\n\t *\n\t * // RECOMMENDED: Use the Fancytree object API\n\t * var tree = $.ui.fancytree.getTree(\"#myTree\");\n\t * var node = tree.getActiveNode();\n\t *\n\t * // or you may already have stored the tree instance upon creation:\n\t * import {createTree, version} from 'jquery.fancytree'\n\t * const tree = createTree('#tree', { ... });\n\t * var node = tree.getActiveNode();\n\t *\n\t * @see {Fancytree_Static#getTree}\n\t * @deprecated Use methods of the {Fancytree} instance instead\n\t * @mixin Fancytree_Widget\n\t */\n\n\t$.widget(\n\t\t\"ui.fancytree\",\n\t\t/** @lends Fancytree_Widget# */\n\t\t{\n\t\t\t/**These options will be used as defaults\n\t\t\t * @type {FancytreeOptions}\n\t\t\t */\n\t\t\toptions: {\n\t\t\t\tactiveVisible: true,\n\t\t\t\tajax: {\n\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\tcache: false, // false: Append random '_' argument to the request url to prevent caching.\n\t\t\t\t\t// timeout: 0, // >0: Make sure we get an ajax error if server is unreachable\n\t\t\t\t\tdataType: \"json\", // Expect json format and pass json object to callbacks.\n\t\t\t\t},\n\t\t\t\taria: true,\n\t\t\t\tautoActivate: true,\n\t\t\t\tautoCollapse: false,\n\t\t\t\tautoScroll: false,\n\t\t\t\tcheckbox: false,\n\t\t\t\tclickFolderMode: 4,\n\t\t\t\tdebugLevel: null, // 0..4 (null: use global setting $.ui.fancytree.debugLevel)\n\t\t\t\tdisabled: false, // TODO: required anymore?\n\t\t\t\tenableAspx: true,\n\t\t\t\tescapeTitles: false,\n\t\t\t\textensions: [],\n\t\t\t\t// fx: { height: \"toggle\", duration: 200 },\n\t\t\t\t// toggleEffect: { effect: \"drop\", options: {direction: \"left\"}, duration: 200 },\n\t\t\t\t// toggleEffect: { effect: \"slide\", options: {direction: \"up\"}, duration: 200 },\n\t\t\t\t//toggleEffect: { effect: \"blind\", options: {direction: \"vertical\", scale: \"box\"}, duration: 200 },\n\t\t\t\ttoggleEffect: { effect: \"slideToggle\", duration: 200 }, //< \"toggle\" or \"slideToggle\" to use jQuery instead of jQueryUI for toggleEffect animation\n\t\t\t\tgenerateIds: false,\n\t\t\t\ticon: true,\n\t\t\t\tidPrefix: \"ft_\",\n\t\t\t\tfocusOnSelect: false,\n\t\t\t\tkeyboard: true,\n\t\t\t\tkeyPathSeparator: \"/\",\n\t\t\t\tminExpandLevel: 1,\n\t\t\t\tnodata: true, // (bool, string, or callback) display message, when no data available\n\t\t\t\tquicksearch: false,\n\t\t\t\trtl: false,\n\t\t\t\tscrollOfs: { top: 0, bottom: 0 },\n\t\t\t\tscrollParent: null,\n\t\t\t\tselectMode: 2,\n\t\t\t\tstrings: {\n\t\t\t\t\tloading: \"Loading...\", // &#8230; would be escaped when escapeTitles is true\n\t\t\t\t\tloadError: \"Load error!\",\n\t\t\t\t\tmoreData: \"More...\",\n\t\t\t\t\tnoData: \"No data.\",\n\t\t\t\t},\n\t\t\t\ttabindex: \"0\",\n\t\t\t\ttitlesTabbable: false,\n\t\t\t\ttooltip: false,\n\t\t\t\ttreeId: null,\n\t\t\t\t_classNames: {\n\t\t\t\t\tnode: \"fancytree-node\",\n\t\t\t\t\tfolder: \"fancytree-folder\",\n\t\t\t\t\tanimating: \"fancytree-animating\",\n\t\t\t\t\tcombinedExpanderPrefix: \"fancytree-exp-\",\n\t\t\t\t\tcombinedIconPrefix: \"fancytree-ico-\",\n\t\t\t\t\thasChildren: \"fancytree-has-children\",\n\t\t\t\t\tactive: \"fancytree-active\",\n\t\t\t\t\tselected: \"fancytree-selected\",\n\t\t\t\t\texpanded: \"fancytree-expanded\",\n\t\t\t\t\tlazy: \"fancytree-lazy\",\n\t\t\t\t\tfocused: \"fancytree-focused\",\n\t\t\t\t\tpartload: \"fancytree-partload\",\n\t\t\t\t\tpartsel: \"fancytree-partsel\",\n\t\t\t\t\tradio: \"fancytree-radio\",\n\t\t\t\t\t// radiogroup: \"fancytree-radiogroup\",\n\t\t\t\t\tunselectable: \"fancytree-unselectable\",\n\t\t\t\t\tlastsib: \"fancytree-lastsib\",\n\t\t\t\t\tloading: \"fancytree-loading\",\n\t\t\t\t\terror: \"fancytree-error\",\n\t\t\t\t\tstatusNodePrefix: \"fancytree-statusnode-\",\n\t\t\t\t},\n\t\t\t\t// events\n\t\t\t\tlazyLoad: null,\n\t\t\t\tpostProcess: null,\n\t\t\t},\n\t\t\t_deprecationWarning: function(name) {\n\t\t\t\tvar tree = this.tree;\n\n\t\t\t\tif (tree && tree.options.debugLevel >= 3) {\n\t\t\t\t\ttree.warn(\n\t\t\t\t\t\t\"$().fancytree('\" +\n\t\t\t\t\t\t\tname +\n\t\t\t\t\t\t\t\"') is deprecated (see https://wwwendt.de/tech/fancytree/doc/jsdoc/Fancytree_Widget.html\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t\t/* Set up the widget, Called on first $().fancytree() */\n\t\t\t_create: function() {\n\t\t\t\tthis.tree = new Fancytree(this);\n\n\t\t\t\tthis.$source =\n\t\t\t\t\tthis.source || this.element.data(\"type\") === \"json\"\n\t\t\t\t\t\t? this.element\n\t\t\t\t\t\t: this.element.find(\">ul\").first();\n\t\t\t\t// Subclass Fancytree instance with all enabled extensions\n\t\t\t\tvar extension,\n\t\t\t\t\textName,\n\t\t\t\t\ti,\n\t\t\t\t\topts = this.options,\n\t\t\t\t\textensions = opts.extensions,\n\t\t\t\t\tbase = this.tree;\n\n\t\t\t\tfor (i = 0; i < extensions.length; i++) {\n\t\t\t\t\textName = extensions[i];\n\t\t\t\t\textension = $.ui.fancytree._extensions[extName];\n\t\t\t\t\tif (!extension) {\n\t\t\t\t\t\t$.error(\n\t\t\t\t\t\t\t\"Could not apply extension '\" +\n\t\t\t\t\t\t\t\textName +\n\t\t\t\t\t\t\t\t\"' (it is not registered, did you forget to include it?)\"\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\t// Add extension options as tree.options.EXTENSION\n\t\t\t\t\t// \t_assert(!this.tree.options[extName], \"Extension name must not exist as option name: \" + extName);\n\n\t\t\t\t\t// console.info(\"extend \" + extName, extension.options, this.tree.options[extName])\n\t\t\t\t\t// issue #876: we want to replace custom array-options, not merge them\n\t\t\t\t\tthis.tree.options[extName] = _simpleDeepMerge(\n\t\t\t\t\t\t{},\n\t\t\t\t\t\textension.options,\n\t\t\t\t\t\tthis.tree.options[extName]\n\t\t\t\t\t);\n\t\t\t\t\t// this.tree.options[extName] = $.extend(true, {}, extension.options, this.tree.options[extName]);\n\n\t\t\t\t\t// console.info(\"extend \" + extName + \" =>\", this.tree.options[extName])\n\t\t\t\t\t// console.info(\"extend \" + extName + \" org default =>\", extension.options)\n\n\t\t\t\t\t// Add a namespace tree.ext.EXTENSION, to hold instance data\n\t\t\t\t\t_assert(\n\t\t\t\t\t\tthis.tree.ext[extName] === undefined,\n\t\t\t\t\t\t\"Extension name must not exist as Fancytree.ext attribute: '\" +\n\t\t\t\t\t\t\textName +\n\t\t\t\t\t\t\t\"'\"\n\t\t\t\t\t);\n\t\t\t\t\t// this.tree[extName] = extension;\n\t\t\t\t\tthis.tree.ext[extName] = {};\n\t\t\t\t\t// Subclass Fancytree methods using proxies.\n\t\t\t\t\t_subclassObject(this.tree, base, extension, extName);\n\t\t\t\t\t// current extension becomes base for the next extension\n\t\t\t\t\tbase = extension;\n\t\t\t\t}\n\t\t\t\t//\n\t\t\t\tif (opts.icons !== undefined) {\n\t\t\t\t\t// 2015-11-16\n\t\t\t\t\tif (opts.icon === true) {\n\t\t\t\t\t\tthis.tree.warn(\n\t\t\t\t\t\t\t\"'icons' tree option is deprecated since v2.14.0: use 'icon' instead\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\topts.icon = opts.icons;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$.error(\n\t\t\t\t\t\t\t\"'icons' tree option is deprecated since v2.14.0: use 'icon' only instead\"\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (opts.iconClass !== undefined) {\n\t\t\t\t\t// 2015-11-16\n\t\t\t\t\tif (opts.icon) {\n\t\t\t\t\t\t$.error(\n\t\t\t\t\t\t\t\"'iconClass' tree option is deprecated since v2.14.0: use 'icon' only instead\"\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.tree.warn(\n\t\t\t\t\t\t\t\"'iconClass' tree option is deprecated since v2.14.0: use 'icon' instead\"\n\t\t\t\t\t\t);\n\t\t\t\t\t\topts.icon = opts.iconClass;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (opts.tabbable !== undefined) {\n\t\t\t\t\t// 2016-04-04\n\t\t\t\t\topts.tabindex = opts.tabbable ? \"0\" : \"-1\";\n\t\t\t\t\tthis.tree.warn(\n\t\t\t\t\t\t\"'tabbable' tree option is deprecated since v2.17.0: use 'tabindex='\" +\n\t\t\t\t\t\t\topts.tabindex +\n\t\t\t\t\t\t\t\"' instead\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t//\n\t\t\t\tthis.tree._callHook(\"treeCreate\", this.tree);\n\t\t\t\t// Note: 'fancytreecreate' event is fired by widget base class\n\t\t\t\t//        this.tree._triggerTreeEvent(\"create\");\n\t\t\t},\n\n\t\t\t/* Called on every $().fancytree() */\n\t\t\t_init: function() {\n\t\t\t\tthis.tree._callHook(\"treeInit\", this.tree);\n\t\t\t\t// TODO: currently we call bind after treeInit, because treeInit\n\t\t\t\t// might change tree.$container.\n\t\t\t\t// It would be better, to move event binding into hooks altogether\n\t\t\t\tthis._bind();\n\t\t\t},\n\n\t\t\t/* Use the _setOption method to respond to changes to options. */\n\t\t\t_setOption: function(key, value) {\n\t\t\t\treturn this.tree._callHook(\n\t\t\t\t\t\"treeSetOption\",\n\t\t\t\t\tthis.tree,\n\t\t\t\t\tkey,\n\t\t\t\t\tvalue\n\t\t\t\t);\n\t\t\t},\n\n\t\t\t/** Use the destroy method to clean up any modifications your widget has made to the DOM */\n\t\t\t_destroy: function() {\n\t\t\t\tthis._unbind();\n\t\t\t\tthis.tree._callHook(\"treeDestroy\", this.tree);\n\t\t\t\t// In jQuery UI 1.8, you must invoke the destroy method from the base widget\n\t\t\t\t// $.Widget.prototype.destroy.call(this);\n\t\t\t\t// TODO: delete tree and nodes to make garbage collect easier?\n\t\t\t\t// TODO: In jQuery UI 1.9 and above, you would define _destroy instead of destroy and not call the base method\n\t\t\t},\n\n\t\t\t// -------------------------------------------------------------------------\n\n\t\t\t/* Remove all event handlers for our namespace */\n\t\t\t_unbind: function() {\n\t\t\t\tvar ns = this.tree._ns;\n\t\t\t\tthis.element.off(ns);\n\t\t\t\tthis.tree.$container.off(ns);\n\t\t\t\t$(document).off(ns);\n\t\t\t},\n\t\t\t/* Add mouse and kyboard handlers to the container */\n\t\t\t_bind: function() {\n\t\t\t\tvar self = this,\n\t\t\t\t\topts = this.options,\n\t\t\t\t\ttree = this.tree,\n\t\t\t\t\tns = tree._ns;\n\t\t\t\t// selstartEvent = ( $.support.selectstart ? \"selectstart\" : \"mousedown\" )\n\n\t\t\t\t// Remove all previuous handlers for this tree\n\t\t\t\tthis._unbind();\n\n\t\t\t\t//alert(\"keydown\" + ns + \"foc=\" + tree.hasFocus() + tree.$container);\n\t\t\t\t// tree.debug(\"bind events; container: \", tree.$container);\n\t\t\t\ttree.$container\n\t\t\t\t\t.on(\"focusin\" + ns + \" focusout\" + ns, function(event) {\n\t\t\t\t\t\tvar node = FT.getNode(event),\n\t\t\t\t\t\t\tflag = event.type === \"focusin\";\n\n\t\t\t\t\t\tif (!flag && node && $(event.target).is(\"a\")) {\n\t\t\t\t\t\t\t// #764\n\t\t\t\t\t\t\tnode.debug(\n\t\t\t\t\t\t\t\t\"Ignored focusout on embedded <a> element.\"\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// tree.treeOnFocusInOut.call(tree, event);\n\t\t\t\t\t\t// tree.debug(\"Tree container got event \" + event.type, node, event, FT.getEventTarget(event));\n\t\t\t\t\t\tif (flag) {\n\t\t\t\t\t\t\tif (tree._getExpiringValue(\"focusin\")) {\n\t\t\t\t\t\t\t\t// #789: IE 11 may send duplicate focusin events\n\t\t\t\t\t\t\t\ttree.debug(\"Ignored double focusin.\");\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttree._setExpiringValue(\"focusin\", true, 50);\n\n\t\t\t\t\t\t\tif (!node) {\n\t\t\t\t\t\t\t\t// #789: IE 11 may send focusin before mousdown(?)\n\t\t\t\t\t\t\t\tnode = tree._getExpiringValue(\"mouseDownNode\");\n\t\t\t\t\t\t\t\tif (node) {\n\t\t\t\t\t\t\t\t\ttree.debug(\n\t\t\t\t\t\t\t\t\t\t\"Reconstruct mouse target for focusin from recent event.\"\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\t\t\t\t\t\t}\n\t\t\t\t\t\tif (node) {\n\t\t\t\t\t\t\t// For example clicking into an <input> that is part of a node\n\t\t\t\t\t\t\ttree._callHook(\n\t\t\t\t\t\t\t\t\"nodeSetFocus\",\n\t\t\t\t\t\t\t\ttree._makeHookContext(node, event),\n\t\t\t\t\t\t\t\tflag\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\ttree.tbody &&\n\t\t\t\t\t\t\t\t$(event.target).parents(\n\t\t\t\t\t\t\t\t\t\"table.fancytree-container > thead\"\n\t\t\t\t\t\t\t\t).length\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t// #767: ignore events in the table's header\n\t\t\t\t\t\t\t\ttree.debug(\n\t\t\t\t\t\t\t\t\t\"Ignore focus event outside table body.\",\n\t\t\t\t\t\t\t\t\tevent\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttree._callHook(\"treeSetFocus\", tree, flag);\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\t.on(\"selectstart\" + ns, \"span.fancytree-title\", function(\n\t\t\t\t\t\tevent\n\t\t\t\t\t) {\n\t\t\t\t\t\t// prevent mouse-drags to select text ranges\n\t\t\t\t\t\t// tree.debug(\"<span title> got event \" + event.type);\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t})\n\t\t\t\t\t.on(\"keydown\" + ns, function(event) {\n\t\t\t\t\t\t// TODO: also bind keyup and keypress\n\t\t\t\t\t\t// tree.debug(\"got event \" + event.type + \", hasFocus:\" + tree.hasFocus());\n\t\t\t\t\t\t// if(opts.disabled || opts.keyboard === false || !tree.hasFocus() ){\n\t\t\t\t\t\tif (opts.disabled || opts.keyboard === false) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar res,\n\t\t\t\t\t\t\tnode = tree.focusNode, // node may be null\n\t\t\t\t\t\t\tctx = tree._makeHookContext(node || tree, event),\n\t\t\t\t\t\t\tprevPhase = tree.phase;\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\ttree.phase = \"userEvent\";\n\t\t\t\t\t\t\t// If a 'fancytreekeydown' handler returns false, skip the default\n\t\t\t\t\t\t\t// handling (implemented by tree.nodeKeydown()).\n\t\t\t\t\t\t\tif (node) {\n\t\t\t\t\t\t\t\tres = tree._triggerNodeEvent(\n\t\t\t\t\t\t\t\t\t\"keydown\",\n\t\t\t\t\t\t\t\t\tnode,\n\t\t\t\t\t\t\t\t\tevent\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tres = tree._triggerTreeEvent(\"keydown\", event);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (res === \"preventNav\") {\n\t\t\t\t\t\t\t\tres = true; // prevent keyboard navigation, but don't prevent default handling of embedded input controls\n\t\t\t\t\t\t\t} else if (res !== false) {\n\t\t\t\t\t\t\t\tres = tree._callHook(\"nodeKeydown\", ctx);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn res;\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\ttree.phase = prevPhase;\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\t.on(\"mousedown\" + ns, function(event) {\n\t\t\t\t\t\tvar et = FT.getEventTarget(event);\n\t\t\t\t\t\t// self.tree.debug(\"event(\" + event.type + \"): node: \", et.node);\n\t\t\t\t\t\t// #712: Store the clicked node, so we can use it when we get a focusin event\n\t\t\t\t\t\t//       ('click' event fires after focusin)\n\t\t\t\t\t\t// tree.debug(\"event(\" + event.type + \"): node: \", et.node);\n\t\t\t\t\t\ttree._lastMousedownNode = et ? et.node : null;\n\t\t\t\t\t\t// #789: Store the node also for a short period, so we can use it\n\t\t\t\t\t\t// in a *resulting* focusin event\n\t\t\t\t\t\ttree._setExpiringValue(\n\t\t\t\t\t\t\t\"mouseDownNode\",\n\t\t\t\t\t\t\ttree._lastMousedownNode\n\t\t\t\t\t\t);\n\t\t\t\t\t})\n\t\t\t\t\t.on(\"click\" + ns + \" dblclick\" + ns, function(event) {\n\t\t\t\t\t\tif (opts.disabled) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar ctx,\n\t\t\t\t\t\t\tet = FT.getEventTarget(event),\n\t\t\t\t\t\t\tnode = et.node,\n\t\t\t\t\t\t\ttree = self.tree,\n\t\t\t\t\t\t\tprevPhase = tree.phase;\n\n\t\t\t\t\t\t// self.tree.debug(\"event(\" + event.type + \"): node: \", node);\n\t\t\t\t\t\tif (!node) {\n\t\t\t\t\t\t\treturn true; // Allow bubbling of other events\n\t\t\t\t\t\t}\n\t\t\t\t\t\tctx = tree._makeHookContext(node, event);\n\t\t\t\t\t\t// self.tree.debug(\"event(\" + event.type + \"): node: \", node);\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\ttree.phase = \"userEvent\";\n\t\t\t\t\t\t\tswitch (event.type) {\n\t\t\t\t\t\t\t\tcase \"click\":\n\t\t\t\t\t\t\t\t\tctx.targetType = et.type;\n\t\t\t\t\t\t\t\t\tif (node.isPagingNode()) {\n\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\ttree._triggerNodeEvent(\n\t\t\t\t\t\t\t\t\t\t\t\t\"clickPaging\",\n\t\t\t\t\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\t\t\t\t\tevent\n\t\t\t\t\t\t\t\t\t\t\t) === true\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn tree._triggerNodeEvent(\n\t\t\t\t\t\t\t\t\t\t\"click\",\n\t\t\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\t\t\tevent\n\t\t\t\t\t\t\t\t\t) === false\n\t\t\t\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t\t\t\t: tree._callHook(\"nodeClick\", ctx);\n\t\t\t\t\t\t\t\tcase \"dblclick\":\n\t\t\t\t\t\t\t\t\tctx.targetType = et.type;\n\t\t\t\t\t\t\t\t\treturn tree._triggerNodeEvent(\n\t\t\t\t\t\t\t\t\t\t\"dblclick\",\n\t\t\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\t\t\tevent\n\t\t\t\t\t\t\t\t\t) === false\n\t\t\t\t\t\t\t\t\t\t? false\n\t\t\t\t\t\t\t\t\t\t: tree._callHook(\"nodeDblclick\", ctx);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\ttree.phase = prevPhase;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t},\n\t\t\t/** Return the active node or null.\n\t\t\t * @returns {FancytreeNode}\n\t\t\t * @deprecated Use methods of the Fancytree instance instead (<a href=\"Fancytree_Widget.html\">example above</a>).\n\t\t\t */\n\t\t\tgetActiveNode: function() {\n\t\t\t\tthis._deprecationWarning(\"getActiveNode\");\n\t\t\t\treturn this.tree.activeNode;\n\t\t\t},\n\t\t\t/** Return the matching node or null.\n\t\t\t * @param {string} key\n\t\t\t * @returns {FancytreeNode}\n\t\t\t * @deprecated Use methods of the Fancytree instance instead (<a href=\"Fancytree_Widget.html\">example above</a>).\n\t\t\t */\n\t\t\tgetNodeByKey: function(key) {\n\t\t\t\tthis._deprecationWarning(\"getNodeByKey\");\n\t\t\t\treturn this.tree.getNodeByKey(key);\n\t\t\t},\n\t\t\t/** Return the invisible system root node.\n\t\t\t * @returns {FancytreeNode}\n\t\t\t * @deprecated Use methods of the Fancytree instance instead (<a href=\"Fancytree_Widget.html\">example above</a>).\n\t\t\t */\n\t\t\tgetRootNode: function() {\n\t\t\t\tthis._deprecationWarning(\"getRootNode\");\n\t\t\t\treturn this.tree.rootNode;\n\t\t\t},\n\t\t\t/** Return the current tree instance.\n\t\t\t * @returns {Fancytree}\n\t\t\t * @deprecated Use `$.ui.fancytree.getTree()` instead (<a href=\"Fancytree_Widget.html\">example above</a>).\n\t\t\t */\n\t\t\tgetTree: function() {\n\t\t\t\tthis._deprecationWarning(\"getTree\");\n\t\t\t\treturn this.tree;\n\t\t\t},\n\t\t}\n\t);\n\n\t// $.ui.fancytree was created by the widget factory. Create a local shortcut:\n\tFT = $.ui.fancytree;\n\n\t/**\n\t * Static members in the `$.ui.fancytree` namespace.\n\t * This properties and methods can be accessed without instantiating a concrete\n\t * Fancytree instance.\n\t *\n\t * @example\n\t * // Access static members:\n\t * var node = $.ui.fancytree.getNode(element);\n\t * alert($.ui.fancytree.version);\n\t *\n\t * @mixin Fancytree_Static\n\t */\n\t$.extend(\n\t\t$.ui.fancytree,\n\t\t/** @lends Fancytree_Static# */\n\t\t{\n\t\t\t/** Version number `\"MAJOR.MINOR.PATCH\"`\n\t\t\t * @type {string} */\n\t\t\tversion: \"2.34.0\", // Set to semver by 'grunt release'\n\t\t\t/** @type {string}\n\t\t\t * @description `\"production\" for release builds` */\n\t\t\tbuildType: \"production\", // Set to 'production' by 'grunt build'\n\t\t\t/** @type {int}\n\t\t\t * @description 0: silent .. 5: verbose (default: 3 for release builds). */\n\t\t\tdebugLevel: 3, // Set to 3 by 'grunt build'\n\t\t\t// Used by $.ui.fancytree.debug() and as default for tree.options.debugLevel\n\n\t\t\t_nextId: 1,\n\t\t\t_nextNodeKey: 1,\n\t\t\t_extensions: {},\n\t\t\t// focusTree: null,\n\n\t\t\t/** Expose class object as `$.ui.fancytree._FancytreeClass`.\n\t\t\t * Useful to extend `$.ui.fancytree._FancytreeClass.prototype`.\n\t\t\t * @type {Fancytree}\n\t\t\t */\n\t\t\t_FancytreeClass: Fancytree,\n\t\t\t/** Expose class object as $.ui.fancytree._FancytreeNodeClass\n\t\t\t * Useful to extend `$.ui.fancytree._FancytreeNodeClass.prototype`.\n\t\t\t * @type {FancytreeNode}\n\t\t\t */\n\t\t\t_FancytreeNodeClass: FancytreeNode,\n\t\t\t/* Feature checks to provide backwards compatibility */\n\t\t\tjquerySupports: {\n\t\t\t\t// http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at\n\t\t\t\tpositionMyOfs: isVersionAtLeast($.ui.version, 1, 9),\n\t\t\t},\n\t\t\t/** Throw an error if condition fails (debug method).\n\t\t\t * @param {boolean} cond\n\t\t\t * @param {string} msg\n\t\t\t */\n\t\t\tassert: function(cond, msg) {\n\t\t\t\treturn _assert(cond, msg);\n\t\t\t},\n\t\t\t/** Create a new Fancytree instance on a target element.\n\t\t\t *\n\t\t\t * @param {Element | jQueryObject | string} el Target DOM element or selector\n\t\t\t * @param {FancytreeOptions} [opts] Fancytree options\n\t\t\t * @returns {Fancytree} new tree instance\n\t\t\t * @example\n\t\t\t * var tree = $.ui.fancytree.createTree(\"#tree\", {\n\t\t\t *     source: {url: \"my/webservice\"}\n\t\t\t * }); // Create tree for this matching element\n\t\t\t *\n\t\t\t * @since 2.25\n\t\t\t */\n\t\t\tcreateTree: function(el, opts) {\n\t\t\t\tvar $tree = $(el).fancytree(opts);\n\t\t\t\treturn FT.getTree($tree);\n\t\t\t},\n\t\t\t/** Return a function that executes *fn* at most every *timeout* ms.\n\t\t\t * @param {integer} timeout\n\t\t\t * @param {function} fn\n\t\t\t * @param {boolean} [invokeAsap=false]\n\t\t\t * @param {any} [ctx]\n\t\t\t */\n\t\t\tdebounce: function(timeout, fn, invokeAsap, ctx) {\n\t\t\t\tvar timer;\n\t\t\t\tif (arguments.length === 3 && typeof invokeAsap !== \"boolean\") {\n\t\t\t\t\tctx = invokeAsap;\n\t\t\t\t\tinvokeAsap = false;\n\t\t\t\t}\n\t\t\t\treturn function() {\n\t\t\t\t\tvar args = arguments;\n\t\t\t\t\tctx = ctx || this;\n\t\t\t\t\t// eslint-disable-next-line no-unused-expressions\n\t\t\t\t\tinvokeAsap && !timer && fn.apply(ctx, args);\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\ttimer = setTimeout(function() {\n\t\t\t\t\t\t// eslint-disable-next-line no-unused-expressions\n\t\t\t\t\t\tinvokeAsap || fn.apply(ctx, args);\n\t\t\t\t\t\ttimer = null;\n\t\t\t\t\t}, timeout);\n\t\t\t\t};\n\t\t\t},\n\t\t\t/** Write message to console if debugLevel >= 4\n\t\t\t * @param {string} msg\n\t\t\t */\n\t\t\tdebug: function(msg) {\n\t\t\t\tif ($.ui.fancytree.debugLevel >= 4) {\n\t\t\t\t\tconsoleApply(\"log\", arguments);\n\t\t\t\t}\n\t\t\t},\n\t\t\t/** Write error message to console if debugLevel >= 1.\n\t\t\t * @param {string} msg\n\t\t\t */\n\t\t\terror: function(msg) {\n\t\t\t\tif ($.ui.fancytree.debugLevel >= 1) {\n\t\t\t\t\tconsoleApply(\"error\", arguments);\n\t\t\t\t}\n\t\t\t},\n\t\t\t/** Convert `<`, `>`, `&`, `\"`, `'`, and `/` to the equivalent entities.\n\t\t\t *\n\t\t\t * @param {string} s\n\t\t\t * @returns {string}\n\t\t\t */\n\t\t\tescapeHtml: function(s) {\n\t\t\t\treturn (\"\" + s).replace(REX_HTML, function(s) {\n\t\t\t\t\treturn ENTITY_MAP[s];\n\t\t\t\t});\n\t\t\t},\n\t\t\t/** Make jQuery.position() arguments backwards compatible, i.e. if\n\t\t\t * jQuery UI version <= 1.8, convert\n\t\t\t *   { my: \"left+3 center\", at: \"left bottom\", of: $target }\n\t\t\t * to\n\t\t\t *   { my: \"left center\", at: \"left bottom\", of: $target, offset: \"3  0\" }\n\t\t\t *\n\t\t\t * See http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at\n\t\t\t * and http://jsfiddle.net/mar10/6xtu9a4e/\n\t\t\t *\n\t\t\t * @param {object} opts\n\t\t\t * @returns {object} the (potentially modified) original opts hash object\n\t\t\t */\n\t\t\tfixPositionOptions: function(opts) {\n\t\t\t\tif (opts.offset || (\"\" + opts.my + opts.at).indexOf(\"%\") >= 0) {\n\t\t\t\t\t$.error(\n\t\t\t\t\t\t\"expected new position syntax (but '%' is not supported)\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (!$.ui.fancytree.jquerySupports.positionMyOfs) {\n\t\t\t\t\tvar // parse 'left+3 center' into ['left+3 center', 'left', '+3', 'center', undefined]\n\t\t\t\t\t\tmyParts = /(\\w+)([+-]?\\d+)?\\s+(\\w+)([+-]?\\d+)?/.exec(\n\t\t\t\t\t\t\topts.my\n\t\t\t\t\t\t),\n\t\t\t\t\t\tatParts = /(\\w+)([+-]?\\d+)?\\s+(\\w+)([+-]?\\d+)?/.exec(\n\t\t\t\t\t\t\topts.at\n\t\t\t\t\t\t),\n\t\t\t\t\t\t// convert to numbers\n\t\t\t\t\t\tdx =\n\t\t\t\t\t\t\t(myParts[2] ? +myParts[2] : 0) +\n\t\t\t\t\t\t\t(atParts[2] ? +atParts[2] : 0),\n\t\t\t\t\t\tdy =\n\t\t\t\t\t\t\t(myParts[4] ? +myParts[4] : 0) +\n\t\t\t\t\t\t\t(atParts[4] ? +atParts[4] : 0);\n\n\t\t\t\t\topts = $.extend({}, opts, {\n\t\t\t\t\t\t// make a copy and overwrite\n\t\t\t\t\t\tmy: myParts[1] + \" \" + myParts[3],\n\t\t\t\t\t\tat: atParts[1] + \" \" + atParts[3],\n\t\t\t\t\t});\n\t\t\t\t\tif (dx || dy) {\n\t\t\t\t\t\topts.offset = \"\" + dx + \" \" + dy;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn opts;\n\t\t\t},\n\t\t\t/** Return a {node: FancytreeNode, type: TYPE} object for a mouse event.\n\t\t\t *\n\t\t\t * @param {Event} event Mouse event, e.g. click, ...\n\t\t\t * @returns {object} Return a {node: FancytreeNode, type: TYPE} object\n\t\t\t *     TYPE: 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined\n\t\t\t */\n\t\t\tgetEventTarget: function(event) {\n\t\t\t\tvar $target,\n\t\t\t\t\ttree,\n\t\t\t\t\ttcn = event && event.target ? event.target.className : \"\",\n\t\t\t\t\tres = { node: this.getNode(event.target), type: undefined };\n\t\t\t\t// We use a fast version of $(res.node).hasClass()\n\t\t\t\t// See http://jsperf.com/test-for-classname/2\n\t\t\t\tif (/\\bfancytree-title\\b/.test(tcn)) {\n\t\t\t\t\tres.type = \"title\";\n\t\t\t\t} else if (/\\bfancytree-expander\\b/.test(tcn)) {\n\t\t\t\t\tres.type =\n\t\t\t\t\t\tres.node.hasChildren() === false\n\t\t\t\t\t\t\t? \"prefix\"\n\t\t\t\t\t\t\t: \"expander\";\n\t\t\t\t\t// }else if( /\\bfancytree-checkbox\\b/.test(tcn) || /\\bfancytree-radio\\b/.test(tcn) ){\n\t\t\t\t} else if (/\\bfancytree-checkbox\\b/.test(tcn)) {\n\t\t\t\t\tres.type = \"checkbox\";\n\t\t\t\t} else if (/\\bfancytree(-custom)?-icon\\b/.test(tcn)) {\n\t\t\t\t\tres.type = \"icon\";\n\t\t\t\t} else if (/\\bfancytree-node\\b/.test(tcn)) {\n\t\t\t\t\t// Somewhere near the title\n\t\t\t\t\tres.type = \"title\";\n\t\t\t\t} else if (event && event.target) {\n\t\t\t\t\t$target = $(event.target);\n\t\t\t\t\tif ($target.is(\"ul[role=group]\")) {\n\t\t\t\t\t\t// #nnn: Clicking right to a node may hit the surrounding UL\n\t\t\t\t\t\ttree = res.node && res.node.tree;\n\t\t\t\t\t\t(tree || FT).debug(\"Ignoring click on outer UL.\");\n\t\t\t\t\t\tres.node = null;\n\t\t\t\t\t} else if ($target.closest(\".fancytree-title\").length) {\n\t\t\t\t\t\t// #228: clicking an embedded element inside a title\n\t\t\t\t\t\tres.type = \"title\";\n\t\t\t\t\t} else if ($target.closest(\".fancytree-checkbox\").length) {\n\t\t\t\t\t\t// E.g. <svg> inside checkbox span\n\t\t\t\t\t\tres.type = \"checkbox\";\n\t\t\t\t\t} else if ($target.closest(\".fancytree-expander\").length) {\n\t\t\t\t\t\tres.type = \"expander\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn res;\n\t\t\t},\n\t\t\t/** Return a string describing the affected node region for a mouse event.\n\t\t\t *\n\t\t\t * @param {Event} event Mouse event, e.g. click, mousemove, ...\n\t\t\t * @returns {string} 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined\n\t\t\t */\n\t\t\tgetEventTargetType: function(event) {\n\t\t\t\treturn this.getEventTarget(event).type;\n\t\t\t},\n\t\t\t/** Return a FancytreeNode instance from element, event, or jQuery object.\n\t\t\t *\n\t\t\t * @param {Element | jQueryObject | Event} el\n\t\t\t * @returns {FancytreeNode} matching node or null\n\t\t\t */\n\t\t\tgetNode: function(el) {\n\t\t\t\tif (el instanceof FancytreeNode) {\n\t\t\t\t\treturn el; // el already was a FancytreeNode\n\t\t\t\t} else if (el instanceof $) {\n\t\t\t\t\tel = el[0]; // el was a jQuery object: use the DOM element\n\t\t\t\t} else if (el.originalEvent !== undefined) {\n\t\t\t\t\tel = el.target; // el was an Event\n\t\t\t\t}\n\t\t\t\twhile (el) {\n\t\t\t\t\tif (el.ftnode) {\n\t\t\t\t\t\treturn el.ftnode;\n\t\t\t\t\t}\n\t\t\t\t\tel = el.parentNode;\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\t/** Return a Fancytree instance, from element, index, event, or jQueryObject.\n\t\t\t *\n\t\t\t * @param {Element | jQueryObject | Event | integer | string} [el]\n\t\t\t * @returns {Fancytree} matching tree or null\n\t\t\t * @example\n\t\t\t * $.ui.fancytree.getTree();  // Get first Fancytree instance on page\n\t\t\t * $.ui.fancytree.getTree(1);  // Get second Fancytree instance on page\n\t\t\t * $.ui.fancytree.getTree(event);  // Get tree for this mouse- or keyboard event\n\t\t\t * $.ui.fancytree.getTree(\"foo\");  // Get tree for this `opts.treeId`\n\t\t\t * $.ui.fancytree.getTree(\"#tree\");  // Get tree for this matching element\n\t\t\t *\n\t\t\t * @since 2.13\n\t\t\t */\n\t\t\tgetTree: function(el) {\n\t\t\t\tvar widget,\n\t\t\t\t\torgEl = el;\n\n\t\t\t\tif (el instanceof Fancytree) {\n\t\t\t\t\treturn el; // el already was a Fancytree\n\t\t\t\t}\n\t\t\t\tif (el === undefined) {\n\t\t\t\t\tel = 0; // get first tree\n\t\t\t\t}\n\t\t\t\tif (typeof el === \"number\") {\n\t\t\t\t\tel = $(\".fancytree-container\").eq(el); // el was an integer: return nth instance\n\t\t\t\t} else if (typeof el === \"string\") {\n\t\t\t\t\t// `el` may be a treeId or a selector:\n\t\t\t\t\tel = $(\"#ft-id-\" + orgEl).eq(0);\n\t\t\t\t\tif (!el.length) {\n\t\t\t\t\t\tel = $(orgEl).eq(0); // el was a selector: use first match\n\t\t\t\t\t}\n\t\t\t\t} else if (\n\t\t\t\t\tel instanceof Element ||\n\t\t\t\t\tel instanceof HTMLDocument\n\t\t\t\t) {\n\t\t\t\t\tel = $(el);\n\t\t\t\t} else if (el instanceof $) {\n\t\t\t\t\tel = el.eq(0); // el was a jQuery object: use the first\n\t\t\t\t} else if (el.originalEvent !== undefined) {\n\t\t\t\t\tel = $(el.target); // el was an Event\n\t\t\t\t}\n\t\t\t\t// el is a jQuery object wit one element here\n\t\t\t\tel = el.closest(\":ui-fancytree\");\n\t\t\t\twidget = el.data(\"ui-fancytree\") || el.data(\"fancytree\"); // the latter is required by jQuery <= 1.8\n\t\t\t\treturn widget ? widget.tree : null;\n\t\t\t},\n\t\t\t/** Return an option value that has a default, but may be overridden by a\n\t\t\t * callback or a node instance attribute.\n\t\t\t *\n\t\t\t * Evaluation sequence:\n\t\t\t *\n\t\t\t * If `tree.options.<optionName>` is a callback that returns something, use that.\n\t\t\t * Else if `node.<optionName>` is defined, use that.\n\t\t\t * Else if `tree.options.<optionName>` is a value, use that.\n\t\t\t * Else use `defaultValue`.\n\t\t\t *\n\t\t\t * @param {string} optionName name of the option property (on node and tree)\n\t\t\t * @param {FancytreeNode} node passed to the callback\n\t\t\t * @param {object} nodeObject where to look for the local option property, e.g. `node` or `node.data`\n\t\t\t * @param {object} treeOption where to look for the tree option, e.g. `tree.options` or `tree.options.dnd5`\n\t\t\t * @param {any} [defaultValue]\n\t\t\t * @returns {any}\n\t\t\t *\n\t\t\t * @example\n\t\t\t * // Check for node.foo, tree,options.foo(), and tree.options.foo:\n\t\t\t * $.ui.fancytree.evalOption(\"foo\", node, node, tree.options);\n\t\t\t * // Check for node.data.bar, tree,options.qux.bar(), and tree.options.qux.bar:\n\t\t\t * $.ui.fancytree.evalOption(\"bar\", node, node.data, tree.options.qux);\n\t\t\t *\n\t\t\t * @since 2.22\n\t\t\t */\n\t\t\tevalOption: function(\n\t\t\t\toptionName,\n\t\t\t\tnode,\n\t\t\t\tnodeObject,\n\t\t\t\ttreeOptions,\n\t\t\t\tdefaultValue\n\t\t\t) {\n\t\t\t\tvar ctx,\n\t\t\t\t\tres,\n\t\t\t\t\ttree = node.tree,\n\t\t\t\t\ttreeOpt = treeOptions[optionName],\n\t\t\t\t\tnodeOpt = nodeObject[optionName];\n\n\t\t\t\tif ($.isFunction(treeOpt)) {\n\t\t\t\t\tctx = {\n\t\t\t\t\t\tnode: node,\n\t\t\t\t\t\ttree: tree,\n\t\t\t\t\t\twidget: tree.widget,\n\t\t\t\t\t\toptions: tree.widget.options,\n\t\t\t\t\t\ttypeInfo: tree.types[node.type] || {},\n\t\t\t\t\t};\n\t\t\t\t\tres = treeOpt.call(tree, { type: optionName }, ctx);\n\t\t\t\t\tif (res == null) {\n\t\t\t\t\t\tres = nodeOpt;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tres = nodeOpt == null ? treeOpt : nodeOpt;\n\t\t\t\t}\n\t\t\t\tif (res == null) {\n\t\t\t\t\tres = defaultValue; // no option set at all: return default\n\t\t\t\t}\n\t\t\t\treturn res;\n\t\t\t},\n\t\t\t/** Set expander, checkbox, or node icon, supporting string and object format.\n\t\t\t *\n\t\t\t * @param {Element | jQueryObject} span\n\t\t\t * @param {string} baseClass\n\t\t\t * @param {string | object} icon\n\t\t\t * @since 2.27\n\t\t\t */\n\t\t\tsetSpanIcon: function(span, baseClass, icon) {\n\t\t\t\tvar $span = $(span);\n\n\t\t\t\tif (typeof icon === \"string\") {\n\t\t\t\t\t$span.attr(\"class\", baseClass + \" \" + icon);\n\t\t\t\t} else {\n\t\t\t\t\t// support object syntax: { text: ligature, addClasse: classname }\n\t\t\t\t\tif (icon.text) {\n\t\t\t\t\t\t$span.text(\"\" + icon.text);\n\t\t\t\t\t} else if (icon.html) {\n\t\t\t\t\t\tspan.innerHTML = icon.html;\n\t\t\t\t\t}\n\t\t\t\t\t$span.attr(\n\t\t\t\t\t\t\"class\",\n\t\t\t\t\t\tbaseClass + \" \" + (icon.addClass || \"\")\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t\t/** Convert a keydown or mouse event to a canonical string like 'ctrl+a',\n\t\t\t * 'ctrl+shift+f2', 'shift+leftdblclick'.\n\t\t\t *\n\t\t\t * This is especially handy for switch-statements in event handlers.\n\t\t\t *\n\t\t\t * @param {event}\n\t\t\t * @returns {string}\n\t\t\t *\n\t\t\t * @example\n\n\t\t\tswitch( $.ui.fancytree.eventToString(event) ) {\n\t\t\t\tcase \"-\":\n\t\t\t\t\ttree.nodeSetExpanded(ctx, false);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"shift+return\":\n\t\t\t\t\ttree.nodeSetActive(ctx, true);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"down\":\n\t\t\t\t\tres = node.navigate(event.which, activate);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\thandled = false;\n\t\t\t}\n\t\t\tif( handled ){\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t\t*/\n\t\t\teventToString: function(event) {\n\t\t\t\t// Poor-man's hotkeys. See here for a complete implementation:\n\t\t\t\t//   https://github.com/jeresig/jquery.hotkeys\n\t\t\t\tvar which = event.which,\n\t\t\t\t\tet = event.type,\n\t\t\t\t\ts = [];\n\n\t\t\t\tif (event.altKey) {\n\t\t\t\t\ts.push(\"alt\");\n\t\t\t\t}\n\t\t\t\tif (event.ctrlKey) {\n\t\t\t\t\ts.push(\"ctrl\");\n\t\t\t\t}\n\t\t\t\tif (event.metaKey) {\n\t\t\t\t\ts.push(\"meta\");\n\t\t\t\t}\n\t\t\t\tif (event.shiftKey) {\n\t\t\t\t\ts.push(\"shift\");\n\t\t\t\t}\n\n\t\t\t\tif (et === \"click\" || et === \"dblclick\") {\n\t\t\t\t\ts.push(MOUSE_BUTTONS[event.button] + et);\n\t\t\t\t} else if (et === \"wheel\") {\n\t\t\t\t\ts.push(et);\n\t\t\t\t} else if (!IGNORE_KEYCODES[which]) {\n\t\t\t\t\ts.push(\n\t\t\t\t\t\tSPECIAL_KEYCODES[which] ||\n\t\t\t\t\t\t\tString.fromCharCode(which).toLowerCase()\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn s.join(\"+\");\n\t\t\t},\n\t\t\t/** Write message to console if debugLevel >= 3\n\t\t\t * @param {string} msg\n\t\t\t */\n\t\t\tinfo: function(msg) {\n\t\t\t\tif ($.ui.fancytree.debugLevel >= 3) {\n\t\t\t\t\tconsoleApply(\"info\", arguments);\n\t\t\t\t}\n\t\t\t},\n\t\t\t/* @deprecated: use eventToString(event) instead.\n\t\t\t */\n\t\t\tkeyEventToString: function(event) {\n\t\t\t\tthis.warn(\n\t\t\t\t\t\"keyEventToString() is deprecated: use eventToString()\"\n\t\t\t\t);\n\t\t\t\treturn this.eventToString(event);\n\t\t\t},\n\t\t\t/** Return a wrapped handler method, that provides `this._super`.\n\t\t\t *\n\t\t\t * @example\n\t\t\t\t// Implement `opts.createNode` event to add the 'draggable' attribute\n\t\t\t\t$.ui.fancytree.overrideMethod(ctx.options, \"createNode\", function(event, data) {\n\t\t\t\t\t// Default processing if any\n\t\t\t\t\tthis._super.apply(this, arguments);\n\t\t\t\t\t// Add 'draggable' attribute\n\t\t\t\t\tdata.node.span.draggable = true;\n\t\t\t\t});\n\t\t\t *\n\t\t\t * @param {object} instance\n\t\t\t * @param {string} methodName\n\t\t\t * @param {function} handler\n\t\t\t * @param {object} [context] optional context\n\t\t\t */\n\t\t\toverrideMethod: function(instance, methodName, handler, context) {\n\t\t\t\tvar prevSuper,\n\t\t\t\t\t_super = instance[methodName] || $.noop;\n\n\t\t\t\tinstance[methodName] = function() {\n\t\t\t\t\tvar self = context || this;\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tprevSuper = self._super;\n\t\t\t\t\t\tself._super = _super;\n\t\t\t\t\t\treturn handler.apply(self, arguments);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tself._super = prevSuper;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\t\t\t/**\n\t\t\t * Parse tree data from HTML <ul> markup\n\t\t\t *\n\t\t\t * @param {jQueryObject} $ul\n\t\t\t * @returns {NodeData[]}\n\t\t\t */\n\t\t\tparseHtml: function($ul) {\n\t\t\t\tvar classes,\n\t\t\t\t\tclassName,\n\t\t\t\t\textraClasses,\n\t\t\t\t\ti,\n\t\t\t\t\tiPos,\n\t\t\t\t\tl,\n\t\t\t\t\ttmp,\n\t\t\t\t\ttmp2,\n\t\t\t\t\t$children = $ul.find(\">li\"),\n\t\t\t\t\tchildren = [];\n\n\t\t\t\t$children.each(function() {\n\t\t\t\t\tvar allData,\n\t\t\t\t\t\tlowerCaseAttr,\n\t\t\t\t\t\t$li = $(this),\n\t\t\t\t\t\t$liSpan = $li.find(\">span\", this).first(),\n\t\t\t\t\t\t$liA = $liSpan.length ? null : $li.find(\">a\").first(),\n\t\t\t\t\t\td = { tooltip: null, data: {} };\n\n\t\t\t\t\tif ($liSpan.length) {\n\t\t\t\t\t\td.title = $liSpan.html();\n\t\t\t\t\t} else if ($liA && $liA.length) {\n\t\t\t\t\t\t// If a <li><a> tag is specified, use it literally and extract href/target.\n\t\t\t\t\t\td.title = $liA.html();\n\t\t\t\t\t\td.data.href = $liA.attr(\"href\");\n\t\t\t\t\t\td.data.target = $liA.attr(\"target\");\n\t\t\t\t\t\td.tooltip = $liA.attr(\"title\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If only a <li> tag is specified, use the trimmed string up to\n\t\t\t\t\t\t// the next child <ul> tag.\n\t\t\t\t\t\td.title = $li.html();\n\t\t\t\t\t\tiPos = d.title.search(/<ul/i);\n\t\t\t\t\t\tif (iPos >= 0) {\n\t\t\t\t\t\t\td.title = d.title.substring(0, iPos);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\td.title = $.trim(d.title);\n\n\t\t\t\t\t// Make sure all fields exist\n\t\t\t\t\tfor (i = 0, l = CLASS_ATTRS.length; i < l; i++) {\n\t\t\t\t\t\td[CLASS_ATTRS[i]] = undefined;\n\t\t\t\t\t}\n\t\t\t\t\t// Initialize to `true`, if class is set and collect extraClasses\n\t\t\t\t\tclasses = this.className.split(\" \");\n\t\t\t\t\textraClasses = [];\n\t\t\t\t\tfor (i = 0, l = classes.length; i < l; i++) {\n\t\t\t\t\t\tclassName = classes[i];\n\t\t\t\t\t\tif (CLASS_ATTR_MAP[className]) {\n\t\t\t\t\t\t\td[className] = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\textraClasses.push(className);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\td.extraClasses = extraClasses.join(\" \");\n\n\t\t\t\t\t// Parse node options from ID, title and class attributes\n\t\t\t\t\ttmp = $li.attr(\"title\");\n\t\t\t\t\tif (tmp) {\n\t\t\t\t\t\td.tooltip = tmp; // overrides <a title='...'>\n\t\t\t\t\t}\n\t\t\t\t\ttmp = $li.attr(\"id\");\n\t\t\t\t\tif (tmp) {\n\t\t\t\t\t\td.key = tmp;\n\t\t\t\t\t}\n\t\t\t\t\t// Translate hideCheckbox -> checkbox:false\n\t\t\t\t\tif ($li.attr(\"hideCheckbox\")) {\n\t\t\t\t\t\td.checkbox = false;\n\t\t\t\t\t}\n\t\t\t\t\t// Add <li data-NAME='...'> as node.data.NAME\n\t\t\t\t\tallData = _getElementDataAsDict($li);\n\t\t\t\t\tif (allData && !$.isEmptyObject(allData)) {\n\t\t\t\t\t\t// #507: convert data-hidecheckbox (lower case) to hideCheckbox\n\t\t\t\t\t\tfor (lowerCaseAttr in NODE_ATTR_LOWERCASE_MAP) {\n\t\t\t\t\t\t\tif (allData.hasOwnProperty(lowerCaseAttr)) {\n\t\t\t\t\t\t\t\tallData[\n\t\t\t\t\t\t\t\t\tNODE_ATTR_LOWERCASE_MAP[lowerCaseAttr]\n\t\t\t\t\t\t\t\t] = allData[lowerCaseAttr];\n\t\t\t\t\t\t\t\tdelete allData[lowerCaseAttr];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// #56: Allow to set special node.attributes from data-...\n\t\t\t\t\t\tfor (i = 0, l = NODE_ATTRS.length; i < l; i++) {\n\t\t\t\t\t\t\ttmp = NODE_ATTRS[i];\n\t\t\t\t\t\t\ttmp2 = allData[tmp];\n\t\t\t\t\t\t\tif (tmp2 != null) {\n\t\t\t\t\t\t\t\tdelete allData[tmp];\n\t\t\t\t\t\t\t\td[tmp] = tmp2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// All other data-... goes to node.data...\n\t\t\t\t\t\t$.extend(d.data, allData);\n\t\t\t\t\t}\n\t\t\t\t\t// Recursive reading of child nodes, if LI tag contains an UL tag\n\t\t\t\t\t$ul = $li.find(\">ul\").first();\n\t\t\t\t\tif ($ul.length) {\n\t\t\t\t\t\td.children = $.ui.fancytree.parseHtml($ul);\n\t\t\t\t\t} else {\n\t\t\t\t\t\td.children = d.lazy ? undefined : null;\n\t\t\t\t\t}\n\t\t\t\t\tchildren.push(d);\n\t\t\t\t\t// FT.debug(\"parse \", d, children);\n\t\t\t\t});\n\t\t\t\treturn children;\n\t\t\t},\n\t\t\t/** Add Fancytree extension definition to the list of globally available extensions.\n\t\t\t *\n\t\t\t * @param {object} definition\n\t\t\t */\n\t\t\tregisterExtension: function(definition) {\n\t\t\t\t_assert(\n\t\t\t\t\tdefinition.name != null,\n\t\t\t\t\t\"extensions must have a `name` property.\"\n\t\t\t\t);\n\t\t\t\t_assert(\n\t\t\t\t\tdefinition.version != null,\n\t\t\t\t\t\"extensions must have a `version` property.\"\n\t\t\t\t);\n\t\t\t\t$.ui.fancytree._extensions[definition.name] = definition;\n\t\t\t},\n\t\t\t/** Inverse of escapeHtml().\n\t\t\t *\n\t\t\t * @param {string} s\n\t\t\t * @returns {string}\n\t\t\t */\n\t\t\tunescapeHtml: function(s) {\n\t\t\t\tvar e = document.createElement(\"div\");\n\t\t\t\te.innerHTML = s;\n\t\t\t\treturn e.childNodes.length === 0\n\t\t\t\t\t? \"\"\n\t\t\t\t\t: e.childNodes[0].nodeValue;\n\t\t\t},\n\t\t\t/** Write warning message to console if debugLevel >= 2.\n\t\t\t * @param {string} msg\n\t\t\t */\n\t\t\twarn: function(msg) {\n\t\t\t\tif ($.ui.fancytree.debugLevel >= 2) {\n\t\t\t\t\tconsoleApply(\"warn\", arguments);\n\t\t\t\t}\n\t\t\t},\n\t\t}\n\t);\n\n\t// Value returned by `require('jquery.fancytree')`\n\treturn $.ui.fancytree;\n}); // End of closure\n","/**\n * Admin modules\n */\n\nconst WP_Smush = WP_Smush || {};\nwindow.WP_Smush = WP_Smush;\n\n/**\n * IE polyfill for includes.\n *\n * @since 3.1.0\n * @param {string} search\n * @param {number} start\n * @return {boolean}  Returns true if searchString appears as a substring of the result of converting this\n * object to a String, at one or more positions that are\n * greater than or equal to position; otherwise, returns false.\n */\nif ( ! String.prototype.includes ) {\n\tString.prototype.includes = function( search, start ) {\n\t\tif ( typeof start !== 'number' ) {\n\t\t\tstart = 0;\n\t\t}\n\n\t\tif ( start + search.length > this.length ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn this.indexOf( search, start ) !== -1;\n\t};\n}\n\nrequire( './modules/helpers' );\nrequire( './modules/admin' );\nrequire( './modules/bulk-smush' );\nrequire( './modules/onboarding' );\nrequire( './modules/directory-smush' );\nrequire( './smush/cdn' );\nrequire( './smush/lazy-load' );\nrequire( './modules/bulk-restore' );\n\n/**\n * Notice scripts.\n *\n * Notices are used in the following functions:\n *\n * @used-by \\Smush\\Core\\Modules\\Smush::smush_updated()\n * @used-by \\Smush\\Core\\Integrations\\S3::3_support_required_notice()\n * @used-by \\Smush\\App\\Abstract_Page::installation_notice()\n *\n * TODO: should this be moved out in a separate file like common.scss?\n */\nrequire( './modules/notice' );\n","/* global WP_Smush */\n/* global ajaxurl */\n/* global wp_smush_msgs */\n/* global smush_vars */\n\n/**\n * Helpers functions.\n *\n * @since 2.9.0  Moved from admin.js\n */\n( function() {\n\t'use strict';\n\n\tWP_Smush.helpers = {\n\t\tinit: () => {},\n\n\t\t/**\n\t\t * Convert bytes to human readable form.\n\t\t *\n\t\t * @param {number} a  Bytes\n\t\t * @param {number} b  Number of digits\n\t\t * @return {*} Formatted Bytes\n\t\t */\n\t\tformatBytes: ( a, b ) => {\n\t\t\tconst thresh = 1024,\n\t\t\t\tunits = [ 'KB', 'MB', 'GB', 'TB', 'PB' ];\n\n\t\t\tif ( Math.abs( a ) < thresh ) {\n\t\t\t\treturn a + ' B';\n\t\t\t}\n\n\t\t\tlet u = -1;\n\n\t\t\tdo {\n\t\t\t\ta /= thresh;\n\t\t\t\t++u;\n\t\t\t} while ( Math.abs( a ) >= thresh && u < units.length - 1 );\n\n\t\t\treturn a.toFixed( b ) + ' ' + units[ u ];\n\t\t},\n\n\t\t/**\n\t\t * Get size from a string.\n\t\t *\n\t\t * @param {string} formattedSize  Formatter string\n\t\t * @return {*} Formatted Bytes\n\t\t */\n\t\tgetSizeFromString: ( formattedSize ) => {\n\t\t\treturn formattedSize.replace( /[a-zA-Z]/g, '' ).trim();\n\t\t},\n\n\t\t/**\n\t\t * Get type from formatted string.\n\t\t *\n\t\t * @param {string} formattedSize  Formatted string\n\t\t * @return {*} Formatted Bytes\n\t\t */\n\t\tgetFormatFromString: ( formattedSize ) => {\n\t\t\treturn formattedSize.replace( /[0-9.]/g, '' ).trim();\n\t\t},\n\n\t\t/**\n\t\t * Stackoverflow: http://stackoverflow.com/questions/1726630/formatting-a-number-with-exactly-two-decimals-in-javascript\n\t\t *\n\t\t * @param {number} num\n\t\t * @param {number} decimals\n\t\t * @return {number}  Number\n\t\t */\n\t\tprecise_round: ( num, decimals ) => {\n\t\t\tconst sign = num >= 0 ? 1 : -1;\n\t\t\t// Keep the percentage below 100.\n\t\t\tnum = num > 100 ? 100 : num;\n\t\t\treturn ( Math.round( ( num * Math.pow( 10, decimals ) ) + ( sign * 0.001 ) ) / Math.pow( 10, decimals ) );\n\t\t},\n\n\t\t/**\n\t\t * Reset settings.\n\t\t *\n\t\t * @since 3.2.0\n\t\t */\n\t\tresetSettings: () => {\n\t\t\tconst xhr = new XMLHttpRequest();\n\t\t\txhr.open( 'POST', ajaxurl + '?action=reset_settings', true );\n\t\t\txhr.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' );\n\t\t\txhr.onload = () => {\n\t\t\t\tif ( 200 === xhr.status ) {\n\t\t\t\t\tconst res = JSON.parse( xhr.response );\n\t\t\t\t\tif ( 'undefined' !== typeof res.success && res.success ) {\n\t\t\t\t\t\twindow.location.href = wp_smush_msgs.smush_url;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\twindow.console.log( 'Request failed.  Returned status of ' + xhr.status );\n\t\t\t\t}\n\t\t\t};\n\t\t\txhr.send( '_ajax_nonce=' + smush_vars.nonce.get_smush_status );\n\t\t},\n\n\t};\n\n\tWP_Smush.helpers.init();\n}() );\n","import Smush from '../smush/smush';\n\nconst remove_element = function( el, timeout ) {\n\tif ( typeof timeout === 'undefined' ) {\n\t\ttimeout = 100;\n\t}\n\tel.fadeTo( timeout, 0, function() {\n\t\tel.slideUp( timeout, function() {\n\t\t\tel.remove();\n\t\t} );\n\t} );\n};\n\njQuery( function( $ ) {\n\t'use strict';\n\n\t/** Disable the action links **/\n\tconst disable_links = function( c_element ) {\n\t\tconst parent = c_element.parent();\n\t\t//reduce parent opacity\n\t\tparent.css( { opacity: '0.5' } );\n\t\t//Disable Links\n\t\tparent.find( 'a' ).attr( 'disabled', 'disabled' );\n\t};\n\n\t/** Enable the Action Links **/\n\tconst enable_links = function( c_element ) {\n\t\tconst parent = c_element.parent();\n\n\t\t//reduce parent opacity\n\t\tparent.css( { opacity: '1' } );\n\t\t//Disable Links\n\t\tparent.find( 'a' ).removeAttr( 'disabled' );\n\t};\n\n\t/**\n\t * Restore image request with a specified action for Media Library / NextGen Gallery\n\t *\n\t * @param {Object} e\n\t * @param {string} currentButton\n\t * @param {string} smushAction\n\t * @param {string} action\n\t */\n\tconst process_smush_action = function( e, currentButton, smushAction, action ) {\n\t\t// If disabled.\n\t\tif ( 'disabled' === currentButton.attr( 'disabled' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\te.preventDefault();\n\n\t\t// Remove Error.\n\t\t$( '.wp-smush-error' ).remove();\n\n\t\t// Hide stats.\n\t\t$( '.smush-stats-wrapper' ).hide();\n\n\t\tlet mode = 'grid';\n\t\tif ( 'smush_restore_image' === smushAction ) {\n\t\t\tif ( $( document ).find( 'div.media-modal.wp-core-ui' ).length > 0 ) {\n\t\t\t\tmode = 'grid';\n\t\t\t} else {\n\t\t\t\tmode = window.location.search.indexOf( 'item' ) > -1 ? 'grid' : 'list';\n\t\t\t}\n\t\t}\n\n\t\t// Get the image ID and nonce.\n\t\tconst params = {\n\t\t\taction: smushAction,\n\t\t\tattachment_id: currentButton.data( 'id' ),\n\t\t\tmode,\n\t\t\t_nonce: currentButton.data( 'nonce' ),\n\t\t};\n\n\t\t// Reduce the opacity of stats and disable the click.\n\t\tdisable_links( currentButton );\n\n\t\tcurrentButton.html( '<span class=\"spinner wp-smush-progress\">' + wp_smush_msgs[ action ] + '</span>' );\n\n\t\t// Restore the image.\n\t\t$.post( ajaxurl, params, function( r ) {\n\t\t\t// Reset all functionality.\n\t\t\tenable_links( currentButton );\n\n\t\t\tif ( r.success && 'undefined' !== typeof r.data ) {\n\t\t\t\t// Replace in immediate parent for NextGEN.\n\t\t\t\tif ( 'undefined' !== typeof this.data && this.data.indexOf( 'nextgen' ) > -1 ) {\n\t\t\t\t\t// Show the smush button, and remove stats and restore option.\n\t\t\t\t\tcurrentButton.parents().eq(1).html( r.data.stats );\n\t\t\t\t} else if ( 'restore' === action ) { // Show the smush button, and remove stats and restore option.\n\t\t\t\t\tcurrentButton.parents().eq( 1 ).html( r.data.stats );\n\t\t\t\t} else {\n\t\t\t\t\tcurrentButton.parents().eq( 1 ).html( r.data );\n\t\t\t\t}\n\n\t\t\t\tif ( 'undefined' !== typeof r.data && 'restore' === action ) {\n\t\t\t\t\tSmush.updateImageStats( r.data.new_size );\n\t\t\t\t}\n\t\t\t} else if ( r.data.error_msg ) {\n\t\t\t\t// Show error.\n\t\t\t\tcurrentButton.parent().append( r.data.error_msg );\n\t\t\t}\n\t\t} );\n\t};\n\n\t/**\n\t * Validates the Resize Width and Height against the Largest Thumbnail Width and Height\n\t *\n\t * @param wrapper_div jQuery object for the whole setting row wrapper div\n\t * @param width_only Whether to validate only width\n\t * @param height_only Validate only Height\n\t * @return {boolean} All Good or not\n\t */\n\tconst validate_resize_settings = function( wrapper_div, width_only, height_only ) {\n\t\tconst resize_checkbox = wrapper_div.find( '#wp-smush-resize, #wp-smush-resize-quick-setup' );\n\n\t\tif ( ! height_only ) {\n\t\t\tvar width_input = wrapper_div.find( '#wp-smush-resize_width, #quick-setup-resize_width' );\n\t\t\tvar width_error_note = wrapper_div.find( '.sui-notice-info.wp-smush-update-width' );\n\t\t}\n\t\tif ( ! width_only ) {\n\t\t\tvar height_input = wrapper_div.find( '#wp-smush-resize_height, #quick-setup-resize_height' );\n\t\t\tvar height_error_note = wrapper_div.find( '.sui-notice-info.wp-smush-update-height' );\n\t\t}\n\n\t\tlet width_error = false;\n\t\tlet height_error = false;\n\n\t\t//If resize settings is not enabled, return true\n\t\tif ( ! resize_checkbox.is( ':checked' ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t//Check if we have localised width and height\n\t\tif ( 'undefined' === typeof ( wp_smushit_data.resize_sizes ) || 'undefined' === typeof ( wp_smushit_data.resize_sizes.width ) ) {\n\t\t\t//Rely on server validation\n\t\t\treturn true;\n\t\t}\n\n\t\t//Check for width\n\t\tif ( ! height_only && 'undefined' !== typeof width_input && parseInt( wp_smushit_data.resize_sizes.width ) > parseInt( width_input.val() ) ) {\n\t\t\twidth_input.parent().addClass( 'sui-form-field-error' );\n\t\t\twidth_error_note.show( 'slow' );\n\t\t\twidth_error = true;\n\t\t} else {\n\t\t\t//Remove error class\n\t\t\twidth_input.parent().removeClass( 'sui-form-field-error' );\n\t\t\twidth_error_note.hide();\n\t\t\tif ( height_input.hasClass( 'error' ) ) {\n\t\t\t\theight_error_note.show( 'slow' );\n\t\t\t}\n\t\t}\n\n\t\t//Check for height\n\t\tif ( ! width_only && 'undefined' !== typeof height_input && parseInt( wp_smushit_data.resize_sizes.height ) > parseInt( height_input.val() ) ) {\n\t\t\theight_input.parent().addClass( 'sui-form-field-error' );\n\t\t\t//If we are not showing the width error already\n\t\t\tif ( ! width_error ) {\n\t\t\t\theight_error_note.show( 'slow' );\n\t\t\t}\n\t\t\theight_error = true;\n\t\t} else {\n\t\t\t//Remove error class\n\t\t\theight_input.parent().removeClass( 'sui-form-field-error' );\n\t\t\theight_error_note.hide();\n\t\t\tif ( width_input.hasClass( 'error' ) ) {\n\t\t\t\twidth_error_note.show( 'slow' );\n\t\t\t}\n\t\t}\n\n\t\tif ( width_error || height_error ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t};\n\n\t/**\n\t * Update the progress bar width if we have images that needs to be resmushed\n  *\n\t * @param unsmushed_count\n\t * @return {boolean}\n\t */\n\tconst update_progress_bar_resmush = function( unsmushed_count ) {\n\t\tif ( 'undefined' === typeof unsmushed_count ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst smushed_count = wp_smushit_data.count_total - unsmushed_count;\n\n\t\t//Update the Progress Bar Width\n\t\t// get the progress bar\n\t\tconst $progress_bar = jQuery( '.bulk-smush-wrapper .wp-smush-progress-inner' );\n\t\tif ( $progress_bar.length < 1 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst width = ( smushed_count / wp_smushit_data.count_total ) * 100;\n\n\t\t// increase progress\n\t\t$progress_bar.css( 'width', width + '%' );\n\t};\n\n\tconst run_re_check = function( process_settings ) {\n\t\tconst button = $( '.wp-smush-scan' );\n\n\t\t// Empty the button text and add loader class.\n\t\tbutton.text( '' ).addClass( 'sui-button-onload sui-icon-loader sui-loading' ).blur();\n\n\t\t// Check if type is set in data attributes.\n\t\tlet scan_type = button.data( 'type' );\n\t\tscan_type = 'undefined' === typeof scan_type ? 'media' : scan_type;\n\n\t\t// Remove the Skip resmush attribute from button.\n\t\t$( '.wp-smush-all' ).removeAttr( 'data-smush' );\n\n\t\t// Remove notices.\n\t\tconst notices = $( '.sui-notice-top.sui-notice-success' );\n\t\tnotices.slideUp( 100, function() {\n\t\t\tnotices.remove();\n\t\t} );\n\n\t\t// Disable Bulk smush button and itself.\n\t\t$( '.wp-smush-all' ).attr( 'disabled', 'disabled' );\n\n\t\t// Hide Settings changed Notice.\n\t\t$( '.wp-smush-settings-changed' ).hide();\n\n\t\t// Ajax params.\n\t\tconst params = {\n\t\t\taction: 'scan_for_resmush',\n\t\t\ttype: scan_type,\n\t\t\tget_ui: true,\n\t\t\tprocess_settings,\n\t\t\twp_smush_options_nonce: jQuery( '#wp_smush_options_nonce' ).val(),\n\t\t};\n\n\t\t// Send ajax request and get ids if any.\n\t\t$.get( ajaxurl, params, function( r ) {\n\t\t\t// Check if we have the ids,  initialize the local variable.\n\t\t\tif ( 'undefined' !== typeof r.data ) {\n\t\t\t\t// Update Resmush id list.\n\t\t\t\tif ( 'undefined' !== typeof r.data.resmush_ids ) {\n\t\t\t\t\twp_smushit_data.resmush = r.data.resmush_ids;\n\n\t\t\t\t\t// Update wp_smushit_data ( Smushed count, Smushed Percent, Image count, Super smush count, resize savings, conversion savings ).\n\t\t\t\t\tif ( 'undefinied' !== typeof wp_smushit_data ) {\n\t\t\t\t\t\twp_smushit_data.count_smushed = 'undefined' !== typeof r.data.count_smushed ? r.data.count_smushed : wp_smushit_data.count_smushed;\n\t\t\t\t\t\twp_smushit_data.count_supersmushed = 'undefined' !== typeof r.data.count_supersmushed ? r.data.count_supersmushed : wp_smushit_data.count_supersmushed;\n\t\t\t\t\t\twp_smushit_data.count_images = 'undefined' !== typeof r.data.count_image ? r.data.count_image : wp_smushit_data.count_images;\n\t\t\t\t\t\twp_smushit_data.size_before = 'undefined' !== typeof r.data.size_before ? r.data.size_before : wp_smushit_data.size_before;\n\t\t\t\t\t\twp_smushit_data.size_after = 'undefined' !== typeof r.data.size_after ? r.data.size_after : wp_smushit_data.size_after;\n\t\t\t\t\t\twp_smushit_data.savings_resize = 'undefined' !== typeof r.data.savings_resize ? r.data.savings_resize : wp_smushit_data.savings_resize;\n\t\t\t\t\t\twp_smushit_data.savings_conversion = 'undefined' !== typeof r.data.savings_conversion ? r.data.savings_conversion : wp_smushit_data.savings_conversion;\n\t\t\t\t\t\twp_smushit_data.count_resize = 'undefined' !== typeof r.data.count_resize ? r.data.count_resize : wp_smushit_data.count_resize;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( 'nextgen' === scan_type ) {\n\t\t\t\t\t\twp_smushit_data.bytes = parseInt( wp_smushit_data.size_before ) - parseInt( wp_smushit_data.size_after );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Hide the Existing wrapper.\n\t\t\t\t\tconst notices = $( '.bulk-smush-wrapper .sui-notice' );\n\t\t\t\t\tif ( notices.length > 0 ) {\n\t\t\t\t\t\tnotices.hide();\n\t\t\t\t\t\t$( '.wp-smush-pagespeed-recommendation' ).hide();\n\t\t\t\t\t}\n\t\t\t\t\t// Remove existing Re-Smush notices.\n\t\t\t\t\t$( '.wp-smush-resmush-notice' ).remove();\n\n\t\t\t\t\t// Show Bulk wrapper.\n\t\t\t\t\t$( '.wp-smush-bulk-wrapper' ).show();\n\t\t\t\t}\n\t\t\t\t// If content is received, Prepend it.\n\t\t\t\tif ( 'undefined' !== typeof r.data.content ) {\n\t\t\t\t\t$( '.bulk-smush-wrapper .sui-box-body > p:first-of-type' ).after( r.data.content );\n\t\t\t\t}\n\t\t\t\t// If we have any notice to show.\n\t\t\t\tif ( 'undefined' !== typeof r.data.notice ) {\n\t\t\t\t\tconst notice = $( '#wp-smush-ajax-notice' );\n\t\t\t\t\tnotice.addClass( 'sui-notice-success' );\n\t\t\t\t\tnotice.html( '<p>' + r.data.notice + '</p>' );\n\t\t\t\t\tnotice.slideDown();\n\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\tnotice.slideUp();\n\t\t\t\t\t}, 5000 );\n\t\t\t\t}\n\t\t\t\t// Hide errors.\n\t\t\t\t$( 'div.smush-final-log' ).hide();\n\n\t\t\t\t// Hide Super Smush notice if it's enabled in media settings.\n\t\t\t\tif ( 'undefined' !== typeof r.data.super_smush && r.data.super_smush ) {\n\t\t\t\t\tconst enable_lossy = jQuery( '.wp-smush-enable-lossy' );\n\t\t\t\t\tif ( enable_lossy.length > 0 ) {\n\t\t\t\t\t\tenable_lossy.remove();\n\t\t\t\t\t}\n\t\t\t\t\tif ( 'undefined' !== r.data.super_smush_stats ) {\n\t\t\t\t\t\t$( '.super-smush-attachments .wp-smush-stats' ).html( r.data.super_smush_stats );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tSmush.updateStats( scan_type );\n\t\t\t}\n\t\t} ).always( function() {\n\t\t\t// Hide the progress bar.\n\t\t\tjQuery( '.bulk-smush-wrapper .wp-smush-bulk-progress-bar-wrapper' ).hide();\n\n\t\t\t// Add check complete status to button.\n\t\t\tbutton.text( wp_smush_msgs.resmush_complete )\n\t\t\t\t.removeClass( 'sui-button-onload sui-icon-loader sui-loading' )\n\t\t\t\t.addClass( 'smush-button-check-success' );\n\n\t\t\t// Remove success message from button.\n\t\t\tsetTimeout( function() {\n\t\t\t\tbutton.removeClass( 'smush-button-check-success' )\n\t\t\t\t\t.html( '<i class=\"sui-icon-update\" aria-hidden=\"true\"></i>' + wp_smush_msgs.resmush_check );\n\t\t\t}, 2000 );\n\n\t\t\t$( '.wp-smush-all' ).removeAttr( 'disabled' );\n\n\t\t\t// If wp-smush-re-check-message is there, remove it.\n\t\t\tconst reCheckMessage = $( '.wp-smush-re-check-message' );\n\t\t\tif ( reCheckMessage.length ) {\n\t\t\t\tremove_element( reCheckMessage );\n\t\t\t}\n\t\t} );\n\t};\n\n\t// Scroll the element to top of the page.\n\tconst goToByScroll = function( selector ) {\n\t\t// Scroll if element found.\n\t\tif ( $( selector ).length > 0 ) {\n\t\t\t$( 'html, body' ).animate( {\n\t\t\t\tscrollTop: $( selector ).offset().top - 100,\n\t\t\t}, 'slow'\n\t\t\t);\n\t\t}\n\t};\n\n\tconst update_cummulative_stats = function( stats ) {\n\t\t//Update Directory Smush Stats\n\t\tif ( 'undefined' !== typeof ( stats.dir_smush ) ) {\n\t\t\tconst stats_human = $( 'li.smush-dir-savings span.wp-smush-stats span.wp-smush-stats-human' );\n\t\t\tconst stats_percent = $( 'li.smush-dir-savings span.wp-smush-stats span.wp-smush-stats-percent' );\n\n\t\t\t// Do not replace if 0 savings.\n\t\t\tif ( stats.dir_smush.bytes > 0 ) {\n\t\t\t\t// Hide selector.\n\t\t\t\t$( 'li.smush-dir-savings .wp-smush-stats-label-message' ).hide();\n\t\t\t\t//Update Savings in bytes\n\t\t\t\tif ( stats_human.length > 0 ) {\n\t\t\t\t\tstats_human.html( stats.dir_smush.human );\n\t\t\t\t} else {\n\t\t\t\t\tvar span = '<span class=\"wp-smush-stats-human\">' + stats.dir_smush.bytes + '</span>';\n\t\t\t\t}\n\n\t\t\t\t//Percentage section\n\t\t\t\tif ( stats.dir_smush.percent > 0 ) {\n\t\t\t\t\t// Show size and percentage separator.\n\t\t\t\t\t$( 'li.smush-dir-savings span.wp-smush-stats span.wp-smush-stats-sep' ).removeClass( 'sui-hidden' );\n\t\t\t\t\t//Update Optimisation percentage\n\t\t\t\t\tif ( stats_percent.length > 0 ) {\n\t\t\t\t\t\tstats_percent.html( stats.dir_smush.percent + '%' );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar span = '<span class=\"wp-smush-stats-percent\">' + stats.dir_smush.percent + '%' + '</span>';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//Update Combined stats\n\t\tif ( 'undefined' !== typeof ( stats.combined_stats ) && stats.combined_stats.length > 0 ) {\n\t\t\tconst c_stats = stats.combined_stats;\n\n\t\t\tlet smush_percent = ( c_stats.smushed / c_stats.total_count ) * 100;\n\t\t\tsmush_percent = WP_Smush.helpers.precise_round( smush_percent, 1 );\n\n\t\t\t//Smushed Percent\n\t\t\tif ( smush_percent ) {\n\t\t\t\t$( 'div.wp-smush-count-total span.wp-smush-images-percent' ).html( smush_percent );\n\t\t\t}\n\t\t\t//Update Total Attachment Count\n\t\t\tif ( c_stats.total_count ) {\n\t\t\t\t$( 'span.wp-smush-count-total span.wp-smush-total-optimised' ).html( c_stats.total_count );\n\t\t\t}\n\t\t\t//Update Savings and Percent\n\t\t\tif ( c_stats.savings ) {\n\t\t\t\t$( 'span.wp-smush-savings span.wp-smush-stats-human' ).html( c_stats.savings );\n\t\t\t}\n\t\t\tif ( c_stats.percent ) {\n\t\t\t\t$( 'span.wp-smush-savings span.wp-smush-stats-percent' ).html( c_stats.percent );\n\t\t\t}\n\t\t}\n\t};\n\n\t//Remove span tag from URL\n\tfunction removeSpan( url ) {\n\t\tvar url = url.slice( url.indexOf( '?' ) + 1 ).split( '&' );\n\t\tfor ( let i = 0; i < url.length; i++ ) {\n\t\t\tconst urlparam = decodeURI( url[ i ] ).split( /=(.+)/ )[ 1 ];\n\t\t\treturn urlparam.replace( /<(?:.|\\n)*?>/gm, '' );\n\t\t}\n\t}\n\n\t/**\n\t * When 'All' is selected for the Image Sizes setting, select all available sizes.\n\t *\n\t * @since 3.2.1\n\t */\n\t$( '#all-image-sizes' ).on( 'change', function() {\n\t\t$( 'input[name^=\"wp-smush-image_sizes\"]' ).prop( 'checked', true );\n\t} );\n\n\t/**\n\t * Handle re-check api status button click (Settings)\n\t *\n\t * @since 3.2.0.2\n\t */\n\t$( '#wp-smush-update-api-status' ).on( 'click', function( e ) {\n\t\te.preventDefault();\n\n\t\t//$(this).prop('disabled', true);\n\t\t$( this ).addClass( 'sui-button-onload' );\n\n\t\t$.post( ajaxurl, { action: 'recheck_api_status' }, function() {\n\t\t\tlocation.reload();\n\t\t} );\n\t} );\n\n\t/**\n\t * Handle the Smush Stats link click\n\t */\n\t$( 'body' ).on( 'click', 'a.smush-stats-details', function( e ) {\n\t\t//If disabled\n\t\tif ( 'disabled' == $( this ).attr( 'disabled' ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// prevent the default action\n\t\te.preventDefault();\n\t\t//Replace the `+` with a `-`\n\t\tconst slide_symbol = $( this ).find( '.stats-toggle' );\n\t\t$( this ).parents().eq( 1 ).find( '.smush-stats-wrapper' ).slideToggle();\n\t\tslide_symbol.text( slide_symbol.text() == '+' ? '-' : '+' );\n\t} );\n\n\t/** Handle smush button click **/\n\t$( 'body' ).on( 'click', '.wp-smush-send:not(.wp-smush-resmush)', function( e ) {\n\t\t// prevent the default action\n\t\te.preventDefault();\n\t\tnew Smush( $( this ), false );\n\t} );\n\n\t/** Handle show in bulk smush button click **/\n\t$( 'body' ).on( 'click', '.wp-smush-remove-skipped', function( e ) {\n\t\te.preventDefault();\n\n\t\tconst self = $( this );\n\n\t\t// Send Ajax request to remove the image from the skip list.\n\t\t$.post( ajaxurl, {\n\t\t\taction: 'remove_from_skip_list',\n\t\t\tid: self.attr( 'data-id' ),\n\t\t} )\n\t\t\t.done( ( response ) => {\n\t\t\t\tif ( response.success && 'undefined' !== typeof response.data.links ) {\n\t\t\t\t\tself.parent().parent().find( '.smush-status' ).text( wp_smush_msgs.not_processed );\n\t\t\t\t\te.target.closest( '.smush-status-links' ).innerHTML = response.data.links;\n\t\t\t\t}\n\t\t\t} );\n\t} );\n\n\t/** Handle NextGen Gallery smush button click **/\n\t$( 'body' ).on( 'click', '.wp-smush-nextgen-send', function( e ) {\n\t\t// prevent the default action\n\t\te.preventDefault();\n\t\tnew Smush( $( this ), false, 'nextgen' );\n\t} );\n\n\t/** Handle NextGen Gallery Bulk smush button click **/\n\t$( 'body' ).on( 'click', '.wp-smush-nextgen-bulk', function( e ) {\n\t\t// prevent the default action\n\t\te.preventDefault();\n\n\t\t// Remove existing Re-Smush notices.\n\t\t$( '.wp-smush-resmush-notice' ).remove();\n\n\t\t//Check for ids, if there is none (Unsmushed or lossless), don't call smush function\n\t\tif ( 'undefined' === typeof wp_smushit_data ||\n\t\t\t( wp_smushit_data.unsmushed.length === 0 && wp_smushit_data.resmush.length === 0 )\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\n\t\tjQuery( '.wp-smush-all, .wp-smush-scan' ).attr( 'disabled', 'disabled' );\n\t\t$( '.wp-smush-notice.wp-smush-remaining' ).hide();\n\t\tnew Smush( $( this ), true, 'nextgen' );\n\t} );\n\n\t/** Restore: Media Library **/\n\t$( 'body' ).on( 'click', '.wp-smush-action.wp-smush-restore', function( e ) {\n\t\tconst current_button = $( this );\n\t\tprocess_smush_action( e, current_button, 'smush_restore_image', 'restore' );\n\t} );\n\n\t/** Resmush: Media Library **/\n\t$( 'body' ).on( 'click', '.wp-smush-action.wp-smush-resmush', function( e ) {\n\t\tprocess_smush_action( e, $( this ), 'smush_resmush_image', 'smushing' );\n\t} );\n\n\t/** Restore: NextGen Gallery **/\n\t$( 'body' ).on( 'click', '.wp-smush-action.wp-smush-nextgen-restore', function( e ) {\n\t\tprocess_smush_action( e, $( this ), 'smush_restore_nextgen_image', 'restore' );\n\t} );\n\n\t/** Resmush: NextGen Gallery **/\n\t$( 'body' ).on( 'click', '.wp-smush-action.wp-smush-nextgen-resmush', function( e ) {\n\t\tprocess_smush_action( e, $( this ), 'smush_resmush_nextgen_image', 'smushing' );\n\t} );\n\n\t//Scan For resmushing images\n\t$( '.wp-smush-scan' ).on( 'click', function( e ) {\n\t\te.preventDefault();\n\t\trun_re_check( false );\n\t} );\n\n\t//Dismiss Welcome notice\n\t//@todo: Use it for popup\n\t$( '#wp-smush-welcome-box .smush-dismiss-welcome' ).on( 'click', function( e ) {\n\t\te.preventDefault();\n\t\tconst $el = $( this ).parents().eq( 1 );\n\t\tremove_element( $el );\n\n\t\t//Send a ajax request to save the dismissed notice option\n\t\tconst param = {\n\t\t\taction: 'dismiss_welcome_notice',\n\t\t};\n\t\t$.post( ajaxurl, param );\n\t} );\n\n\t//Remove Notice\n\t$( 'body' ).on( 'click', '.wp-smush-notice .icon-fi-close', function( e ) {\n\t\te.preventDefault();\n\t\tconst $el = $( this ).parent();\n\t\tremove_element( $el );\n\t} );\n\n\t/**\n  * Parse remove data change.\n  */\n\t$( 'input[name=wp-smush-keep_data]' ).on( 'change', function( e ) {\n\t\tconst otherClass = 'keep_data-true' === e.target.id ? 'keep_data-false' : 'keep_data-true';\n\t\te.target.parentNode.classList.add( 'active' );\n\t\tdocument.getElementById( otherClass ).parentNode.classList.remove( 'active' );\n\t} );\n\n\t// On Click Update Settings. Check for change in settings.\n\t$( 'button#wp-smush-save-settings' ).on( 'click', function( e ) {\n\t\te.preventDefault();\n\n\t\tlet setting_type = '';\n\t\tconst setting_input = $( 'input[name=\"setting-type\"]' );\n\t\t// Check if setting type is set in the form.\n\t\tif ( setting_input.length > 0 ) {\n\t\t\tsetting_type = setting_input.val();\n\t\t}\n\n\t\t// Show the spinner.\n\t\tconst self = $( this );\n\t\tself.parent().find( 'span.sui-icon-loader.sui-loading' ).removeClass( 'sui-hidden' );\n\n\t\t// Save settings if in network admin.\n\t\tif ( '' != setting_type && 'network' == setting_type ) {\n\t\t\t// Ajax param.\n\t\t\tlet param = {\n\t\t\t\taction: 'save_settings',\n\t\t\t\twp_smush_options_nonce: $( '#wp_smush_options_nonce' ).val(),\n\t\t\t};\n\n\t\t\tparam = jQuery.param( param ) + '&' + jQuery( 'form#wp-smush-settings-form' ).serialize();\n\n\t\t\t// Send ajax, Update Settings, And Check For resmush.\n\t\t\tjQuery.post( ajaxurl, param ).done( function() {\n\t\t\t\tjQuery( 'form#wp-smush-settings-form' ).submit();\n\t\t\t\treturn true;\n\t\t\t} );\n\t\t} else {\n\t\t\t$( '.wp-smush-hex-notice' ).hide();\n\n\t\t\t// Update text.\n\t\t\tself.attr( 'disabled', 'disabled' ).addClass( 'button-grey' );\n\n\t\t\t// Update save button text.\n\t\t\tif ( 'undefined' !== typeof self.attr( 'data-msg' ) && self.attr( 'data-msg' ).length > 0 ) {\n\t\t\t\tself.html( self.attr( 'data-msg' ) );\n\t\t\t} else {\n\t\t\t\tself.html( wp_smush_msgs.checking );\n\t\t\t}\n\n\t\t\t// Check if type is set in data attributes.\n\t\t\tlet scan_type = self.data( 'type' );\n\t\t\tscan_type = 'undefined' === typeof scan_type ? 'media' : scan_type;\n\n\t\t\t// Ajax param.\n\t\t\tlet param = {\n\t\t\t\taction: 'scan_for_resmush',\n\t\t\t\twp_smush_options_nonce: jQuery( '#wp_smush_options_nonce' ).val(),\n\t\t\t\ttype: scan_type,\n\t\t\t};\n\n\t\t\tparam = jQuery.param( param ) + '&' + jQuery( 'form#wp-smush-settings-form' ).serialize();\n\n\t\t\t// Send ajax, Update Settings, And Check For resmush.\n\t\t\tjQuery.post( ajaxurl, param ).done( function() {\n\t\t\t\tjQuery( 'form#wp-smush-settings-form' ).submit();\n\t\t\t\treturn true;\n\t\t\t} );\n\t\t}\n\t} );\n\n\t// On re-Smush click.\n\t$( 'body' ).on( 'click', '.wp-smush-skip-resmush', function( e ) {\n\t\te.preventDefault();\n\n\t\tconst self = jQuery( this ),\n\t\t\t  container = self.parents().eq( 1 ),\n\t\t\t  el = self.parent();\n\n\t\t// Remove Parent div.\n\t\tremove_element( el );\n\n\t\t// Remove Settings Notice.\n\t\t$( '.sui-notice-top.sui-notice-success' ).remove();\n\n\t\t// Set button attribute to skip re-smush ids.\n\t\tcontainer.find( '.wp-smush-all' ).attr( 'data-smush', 'skip_resmush' );\n\n\t\t// Update Smushed count.\n\t\twp_smushit_data.count_smushed = parseInt( wp_smushit_data.count_smushed ) + wp_smushit_data.resmush.length;\n\t\twp_smushit_data.count_supersmushed = parseInt( wp_smushit_data.count_supersmushed ) + wp_smushit_data.resmush.length;\n\n\t\t// Update stats.\n\t\tif ( wp_smushit_data.count_smushed === wp_smushit_data.count_total ) {\n\t\t\t// Show all done notice.\n\t\t\t$( '.wp-smush-notice.wp-smush-all-done, .wp-smush-pagespeed-recommendation' ).show();\n\n\t\t\t// Hide Smush button.\n\t\t\t$( '.wp-smush-bulk-wrapper ' ).hide();\n\t\t}\n\n\t\t// Remove re-Smush notice.\n\t\t$( '.wp-smush-resmush-notice' ).remove();\n\n\t\tlet type = $( '.wp-smush-scan' ).data( 'type' );\n\t\ttype = 'undefined' === typeof type ? 'media' : type;\n\n\t\tconst smushed_count = 'undefined' !== typeof wp_smushit_data.count_smushed ? wp_smushit_data.count_smushed : 0;\n\n\t\tlet smush_percent = ( smushed_count / wp_smushit_data.count_total ) * 100;\n\t\tsmush_percent = WP_Smush.helpers.precise_round( smush_percent, 1 );\n\n\t\t$( '.wp-smush-images-percent' ).html( smush_percent );\n\n\t\t// Update the progress bar width. Get the progress bar.\n\t\tconst progress_bar = jQuery( '.bulk-smush-wrapper .wp-smush-progress-inner' );\n\t\tif ( progress_bar.length < 1 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Increase progress.\n\t\tprogress_bar.css( 'width', smush_percent + '%' );\n\n\t\t// Show the default bulk smush notice.\n\t\t$( '.wp-smush-bulk-wrapper' ).show();\n\t\t$( '.wp-smush-bulk-wrapper .sui-notice' ).show();\n\n\t\tconst params = {\n\t\t\taction: 'delete_resmush_list',\n\t\t\ttype,\n\t\t};\n\n\t\t//Delete resmush list, @todo: update stats from the ajax response\n\t\t$.post( ajaxurl, params, function( res ) {\n\t\t\t// Remove the whole li element on success\n\t\t\tif ( res.success && 'undefined' !== typeof res.data.stats ) {\n\t\t\t\tconst stats = res.data.stats;\n\t\t\t\t// Update wp_smushit_data ( Smushed count, Smushed Percent, Image count, Super smush count, resize savings, conversion savings )\n\t\t\t\tif ( 'undefinied' !== typeof wp_smushit_data ) {\n\t\t\t\t\twp_smushit_data.count_images = 'undefined' !== typeof stats.count_images ? parseInt( wp_smushit_data.count_images ) + stats.count_images : wp_smushit_data.count_images;\n\t\t\t\t\twp_smushit_data.size_before = 'undefined' !== typeof stats.size_before ? parseInt( wp_smushit_data.size_before ) + stats.size_before : wp_smushit_data.size_before;\n\t\t\t\t\twp_smushit_data.size_after = 'undefined' !== typeof stats.size_after ? parseInt( wp_smushit_data.size_after ) + stats.size_after : wp_smushit_data.size_after;\n\t\t\t\t\twp_smushit_data.savings_resize = 'undefined' !== typeof stats.savings_resize ? parseInt( wp_smushit_data.savings_resize ) + stats.savings_resize : wp_smushit_data.savings_resize;\n\t\t\t\t\twp_smushit_data.savings_conversion = 'undefined' !== typeof stats.savings_conversion ? parseInt( wp_smushit_data.savings_conversion ) + stats.savings_conversion : wp_smushit_data.savings_conversion;\n\n\t\t\t\t\t// Add directory smush stats.\n\t\t\t\t\tif ( 'undefined' !== typeof ( wp_smushit_data.savings_dir_smush ) && 'undefined' !== typeof ( wp_smushit_data.savings_dir_smush.orig_size ) ) {\n\t\t\t\t\t\twp_smushit_data.size_before = 'undefined' !== typeof wp_smushit_data.savings_dir_smush ? parseInt( wp_smushit_data.size_before ) + parseInt( wp_smushit_data.savings_dir_smush.orig_size ) : wp_smushit_data.size_before;\n\t\t\t\t\t\twp_smushit_data.size_after = 'undefined' !== typeof wp_smushit_data.savings_dir_smush ? parseInt( wp_smushit_data.size_after ) + parseInt( wp_smushit_data.savings_dir_smush.image_size ) : wp_smushit_data.size_after;\n\t\t\t\t\t}\n\n\t\t\t\t\twp_smushit_data.count_resize = 'undefined' !== typeof stats.count_resize ? parseInt( wp_smushit_data.count_resize ) + stats.count_resize : wp_smushit_data.count_resize;\n\t\t\t\t}\n\t\t\t\t// Smush notice.\n\t\t\t\tconst remainingCountDiv = $( '.bulk-smush-wrapper .wp-smush-remaining-count' );\n\t\t\t\tif ( remainingCountDiv.length && 'undefined' !== typeof wp_smushit_data.unsmushed ) {\n\t\t\t\t\tremainingCountDiv.html( wp_smushit_data.unsmushed.length );\n\t\t\t\t}\n\n\t\t\t\t// If no images left, hide the notice, show all success notice.\n\t\t\t\tif ( 'undefined' !== typeof wp_smushit_data.unsmushed || wp_smushit_data.unsmushed.length === 0 ) {\n\t\t\t\t\t$( '.wp-smush-bulk-wrapper .sui-notice' ).hide();\n\t\t\t\t\t$( '.sui-notice-success.wp-smush-all-done' ).show();\n\t\t\t\t}\n\n\t\t\t\tSmush.updateStats();\n\t\t\t}\n\t\t} );\n\t} );\n\n\t/**\n\t * Enable resize in settings and scroll.\n\t */\n\tconst scroll_and_enable_resize = function() {\n\t\t// Enable resize, show resize settings.\n\t\t$( '#wp-smush-resize' ).prop( 'checked', true ).focus();\n\t\t$( 'div.wp-smush-resize-settings-wrap' ).show();\n\n\t\t// Scroll down to settings area.\n\t\tgoToByScroll( '#column-wp-smush-resize' );\n\t};\n\n\t/**\n\t * Enable super smush in settings and scroll.\n\t */\n\tconst scroll_and_enable_lossy = function() {\n\t\t// Enable super smush.\n\t\t$( '#wp-smush-lossy' ).prop( 'checked', true ).focus();\n\n\t\t// Scroll down to settings area.\n\t\tgoToByScroll( '#column-wp-smush-lossy' );\n\t};\n\n\t// Enable super smush on clicking link from stats area.\n\t$( 'a.wp-smush-lossy-enable' ).on( 'click', function( e ) {\n\t\te.preventDefault();\n\n\t\tscroll_and_enable_lossy();\n\t} );\n\n\t// Enable resize on clicking link from stats area.\n\t$( '.wp-smush-resize-enable' ).on( 'click', function( e ) {\n\t\te.preventDefault();\n\n\t\tscroll_and_enable_resize();\n\t} );\n\n\t// If settings string is found in url, enable and scroll.\n\tif ( window.location.hash ) {\n\t\tconst setting_hash = window.location.hash.substring( 1 );\n\t\t// Enable and scroll to resize settings.\n\t\tif ( 'enable-resize' === setting_hash ) {\n\t\t\tscroll_and_enable_resize();\n\t\t} else if ( 'enable-lossy' === setting_hash ) {\n\t\t\t// Enable and scroll to lossy settings.\n\t\t\tscroll_and_enable_lossy();\n\t\t}\n\t}\n\n\t//Trigger Bulk\n\t$( 'body' ).on( 'click', '.wp-smush-trigger-bulk', function( e ) {\n\t\te.preventDefault();\n\n\t\t//Induce Setting button save click\n\t\tif ( 'undefined' !== typeof e.target.dataset.type && 'nextgen' === e.target.dataset.type ) {\n\t\t\t$( '.wp-smush-nextgen-bulk' ).click();\n\t\t} else {\n\t\t\t$( '.wp-smush-all' ).click();\n\t\t}\n\n\t\t$( 'span.sui-notice-dismiss' ).click();\n\t} );\n\n\t//Trigger Bulk\n\t$( 'body' ).on( 'click', '#bulk-smush-top-notice-close', function( e ) {\n\t\te.preventDefault();\n\t\t$( this ).parent().parent().slideUp( 'slow' );\n\t} );\n\n\t//Allow the checkboxes to be Keyboard Accessible\n\t$( '.wp-smush-setting-row .toggle-checkbox' ).focus( function() {\n\t\t//If Space is pressed\n\t\t$( this ).keypress( function( e ) {\n\t\t\tif ( e.keyCode == 32 ) {\n\t\t\t\te.preventDefault();\n\t\t\t\t$( this ).find( '.toggle-checkbox' ).click();\n\t\t\t}\n\t\t} );\n\t} );\n\n\t// Re-Validate Resize Width And Height.\n\t$( 'body' ).on( 'blur', '.wp-smush-resize-input', function() {\n\t\tconst self = $( this );\n\n\t\tconst wrapper_div = self.parents().eq( 4 );\n\n\t\t// Initiate the check.\n\t\tvalidate_resize_settings( wrapper_div, false, false ); // run the validation.\n\t} );\n\n\t// Handle Resize Checkbox toggle, to show/hide width, height settings.\n\t$( 'body' ).on( 'click', '#wp-smush-resize, #wp-smush-resize-quick-setup', function() {\n\t\tconst self = $( this );\n\t\tconst settings_wrap = $( '.wp-smush-resize-settings-wrap' );\n\n\t\tif ( self.is( ':checked' ) ) {\n\t\t\tsettings_wrap.show();\n\t\t} else {\n\t\t\tsettings_wrap.hide();\n\t\t}\n\t} );\n\n\t// Handle Automatic Smush Checkbox toggle, to show/hide image size settings.\n\t$( '#column-wp-smush-auto' ).on( 'click', '#wp-smush-auto', function() {\n\t\tconst settings_wrap = $( '#column-wp-smush-auto .auto-smush-notice' );\n\n\t\tif ( $( this ).is( ':checked' ) ) {\n\t\t\tsettings_wrap.show();\n\t\t} else {\n\t\t\tsettings_wrap.hide();\n\t\t}\n\t} );\n\n\t// Handle auto detect checkbox toggle, to show/hide highlighting notice.\n\t$( 'body' ).on( 'click', '#wp-smush-detection', function() {\n\t\tconst self = $( this );\n\t\tconst notice_wrap = $( '.smush-highlighting-notice' );\n\t\tconst warning_wrap = $( '.smush-highlighting-warning' );\n\n\t\t// Setting enabled.\n\t\tif ( self.is( ':checked' ) ) {\n\t\t\t// Highlighting is already active and setting not saved.\n\t\t\tif ( notice_wrap.length > 0 ) {\n\t\t\t\tnotice_wrap.show();\n\t\t\t} else {\n\t\t\t\twarning_wrap.show();\n\t\t\t}\n\t\t} else {\n\t\t\tnotice_wrap.hide();\n\t\t\twarning_wrap.hide();\n\t\t}\n\t} );\n\n\t// Handle PNG to JPG Checkbox toggle, to show/hide Transparent image conversion settings.\n\t$( '#wp-smush-png_to_jpg' ).click( function() {\n\t\tconst self = $( this );\n\t\tconst settings_wrap = $( '.wp-smush-png_to_jpg-wrap' );\n\n\t\tif ( self.is( ':checked' ) ) {\n\t\t\tsettings_wrap.show();\n\t\t} else {\n\t\t\tsettings_wrap.hide();\n\t\t}\n\t} );\n\n\t//Handle Re-check button functionality\n\t$( '#wp-smush-revalidate-member' ).on( 'click', function( e ) {\n\t\te.preventDefault();\n\t\t//Ajax Params\n\t\tconst params = {\n\t\t\taction: 'smush_show_warning',\n\t\t};\n\t\tconst link = $( this );\n\t\tconst parent = link.parents().eq( 1 );\n\t\tparent.addClass( 'loading-notice' );\n\t\t$.get( ajaxurl, params, function( r ) {\n\t\t\t//remove the warning\n\t\t\tparent.removeClass( 'loading-notice' ).addClass( 'loaded-notice' );\n\t\t\tif ( 0 == r ) {\n\t\t\t\tparent.attr( 'data-message', wp_smush_msgs.membership_valid );\n\t\t\t\tremove_element( parent, 1000 );\n\t\t\t} else {\n\t\t\t\tparent.attr( 'data-message', wp_smush_msgs.membership_invalid );\n\t\t\t\tsetTimeout( function remove_loader() {\n\t\t\t\t\tparent.removeClass( 'loaded-notice' );\n\t\t\t\t}, 1000 );\n\t\t\t}\n\t\t} );\n\t} );\n\n\t//Initiate Re-check if the variable is set\n\tif ( 'undefined' !== typeof ( wp_smush_run_re_check ) && 1 == wp_smush_run_re_check && $( '.wp-smush-scan' ).length > 0 ) {\n\t\trun_re_check( false );\n\t}\n\n\tif ( $( 'li.smush-dir-savings' ).length > 0 ) {\n\t\t// Update Directory Smush, as soon as the page loads.\n\t\tconst stats_param = {\n\t\t\taction: 'get_dir_smush_stats',\n\t\t};\n\t\t$.get( ajaxurl, stats_param, function( r ) {\n\t\t\t//Hide the spinner\n\t\t\t$( 'li.smush-dir-savings .sui-icon-loader' ).hide();\n\n\t\t\t//If there are no errors, and we have a message to display\n\t\t\tif ( ! r.success && 'undefined' !== typeof ( r.data.message ) ) {\n\t\t\t\t$( 'div.wp-smush-scan-result div.content' ).prepend( r.data.message );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t//If there is no value in r\n\t\t\tif ( 'undefined' === typeof ( r.data ) || 'undefined' === typeof ( r.data.dir_smush ) ) {\n\t\t\t\t//Append the text\n\t\t\t\t$( 'li.smush-dir-savings span.wp-smush-stats' ).append( wp_smush_msgs.ajax_error );\n\t\t\t\t$( 'li.smush-dir-savings span.wp-smush-stats span' ).hide();\n\t\t\t} else {\n\t\t\t\t//Update the stats\n\t\t\t\tupdate_cummulative_stats( r.data );\n\t\t\t}\n\t\t} );\n\t}\n\t//Close Directory smush modal, if pressed esc\n\t$( document ).keyup( function( e ) {\n\t\tif ( e.keyCode === 27 ) {\n\t\t\tconst modal = $( 'div.dev-overlay.wp-smush-list-dialog, div.dev-overlay.wp-smush-get-pro' );\n\t\t\t//If the Directory dialog is not visible\n\t\t\tif ( ! modal.is( ':visible' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tmodal.find( 'div.close' ).click();\n\t\t}\n\t} );\n\n\t//Dismiss Smush recommendation\n\t$( 'span.dismiss-recommendation' ).on( 'click', function( e ) {\n\t\te.preventDefault();\n\t\tconst parent = $( this ).parent();\n\t\t//remove div and save preference in db\n\t\tparent.hide( 'slow', function() {\n\t\t\tparent.remove();\n\t\t} );\n\t\t$.ajax( {\n\t\t\ttype: 'POST',\n\t\t\turl: ajaxurl,\n\t\t\tdata: {\n\t\t\t\taction: 'hide_pagespeed_suggestion',\n\t\t\t},\n\t\t} );\n\t} );\n\n\t//Remove API message\n\t$( 'div.wp-smush-api-message i.icon-fi-close' ).on( 'click', function( e ) {\n\t\te.preventDefault();\n\t\tconst parent = $( this ).parent();\n\t\t//remove div and save preference in db\n\t\tparent.hide( 'slow', function() {\n\t\t\tparent.remove();\n\t\t} );\n\t\t$.ajax( {\n\t\t\ttype: 'POST',\n\t\t\turl: ajaxurl,\n\t\t\tdata: {\n\t\t\t\taction: 'hide_api_message',\n\t\t\t},\n\t\t} );\n\t} );\n\n\t/**\n\t * Scroll to resize settings.\n\t *\n\t * @since 3.3.2\n\t */\n\t$( '#close-resize-update-dialog' ).on( 'click', function( e ) {\n\t\te.preventDefault();\n\n\t\twindow.SUI.dialogs[ 'resizing-update' ].hide();\n\n\t\tgoToByScroll( '#column-wp-smush-resize' );\n\t} );\n\n} );\n","/* global WP_Smush */\n/* global ajaxurl */\n\n/**\n * Bulk Smush functionality.\n *\n * @since 2.9.0  Moved from admin.js\n */\n\nimport Smush from '../smush/smush';\n\n( function( $ ) {\n\t'use strict';\n\n\tWP_Smush.bulk = {\n\t\tinit: () => {\n\t\t\t/**\n\t\t\t * Handle the Bulk Smush/Bulk re-Smush button click.\n\t\t\t */\n\t\t\t$( '.wp-smush-all' ).on( 'click', function( e ) {\n\t\t\t\te.preventDefault();\n\n\t\t\t\t$( '.sui-notice-top.sui-notice-success' ).remove();\n\n\t\t\t\tconst bulkWarning = document.getElementById( 'bulk_smush_warning' );\n\t\t\t\tbulkWarning.classList.add( 'sui-hidden' );\n\n\t\t\t\t// Remove limit exceeded styles.\n\t\t\t\tconst progress = $( '.wp-smush-bulk-progress-bar-wrapper' );\n\t\t\t\tprogress.removeClass( 'wp-smush-exceed-limit' );\n\t\t\t\tprogress.find( '.sui-progress-block .wp-smush-all' ).addClass( 'sui-hidden' );\n\t\t\t\tprogress.find( '.sui-progress-block .wp-smush-cancel-bulk' ).removeClass( 'sui-hidden' );\n\t\t\t\tif ( bulkWarning ) {\n\t\t\t\t\tdocument.getElementById( 'bulk-smush-resume-button' ).classList.add( 'sui-hidden' );\n\t\t\t\t}\n\n\t\t\t\t// Disable re-Smush and scan button.\n\t\t\t\t// TODO: refine what is disabled.\n\t\t\t\t$( '.wp-resmush.wp-smush-action, .wp-smush-scan, .wp-smush-all:not(.sui-progress-close), a.wp-smush-lossy-enable, button.wp-smush-resize-enable, button#wp-smush-save-settings' ).attr( 'disabled', 'disabled' );\n\n\t\t\t\t// Check for IDs, if there is none (unsmushed or lossless), don't call Smush function.\n\t\t\t\t/** @param {Array} wp_smushit_data.unsmushed */\n\t\t\t\tif ( 'undefined' === typeof window.wp_smushit_data ||\n\t\t\t\t\t( 0 === window.wp_smushit_data.unsmushed.length && 0 === window.wp_smushit_data.resmush.length )\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t$( '.wp-smush-remaining' ).hide();\n\n\t\t\t\t// Show loader.\n\t\t\t\tprogress.find( 'i.sui-icon-info' ).removeClass( 'sui-icon-info' )\n\t\t\t\t\t.addClass( 'sui-loading' )\n\t\t\t\t\t.addClass( 'sui-icon-loader' );\n\n\t\t\t\tnew Smush( $( this ), true );\n\t\t\t} );\n\n\t\t\t/**\n\t\t\t * Ignore file from bulk Smush.\n\t\t\t *\n\t\t\t * @since 2.9.0\n\t\t\t */\n\t\t\t$( 'body' ).on( 'click', '.smush-ignore-image', function( e ) {\n\t\t\t\te.preventDefault();\n\n\t\t\t\tconst self = $( this );\n\n\t\t\t\tself.attr( 'disabled', true );\n\t\t\t\tself.attr( 'data-tooltip' );\n\t\t\t\tself.removeClass( 'sui-tooltip' );\n\t\t\t\t$.post( ajaxurl, {\n\t\t\t\t\taction: 'ignore_bulk_image',\n\t\t\t\t\tid: self.attr( 'data-id' ),\n\t\t\t\t} )\n\t\t\t\t\t.done( ( response ) => {\n\t\t\t\t\t\tif ( self.is( 'a' ) && response.success && 'undefined' !== typeof response.data.links ) {\n\t\t\t\t\t\t\tself.parent().parent().find( '.smush-status' ).text( wp_smush_msgs.ignored );\n\t\t\t\t\t\t\te.target.closest( '.smush-status-links' ).innerHTML = response.data.links;\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t} );\n\t\t},\n\n\t};\n\n\tWP_Smush.bulk.init();\n}( jQuery ) );\n","/* global WP_Smush */\n/* global ajaxurl */\n\n/**\n * Modals JavaScript code.\n */\n( function() {\n\t'use strict';\n\n\t/**\n\t * Onboarding modal.\n\t *\n\t * @since 3.1\n\t */\n\tWP_Smush.onboarding = {\n\t\tmembership: 'free', // Assume free by default.\n\t\tonboardingModal: document.getElementById( 'smush-onboarding-dialog' ),\n\t\tscanFilesModal: document.getElementById( 'checking-files-dialog' ),\n\t\tsettings: {\n\t\t\tfirst: true,\n\t\t\tlast: false,\n\t\t\tslide: 'start',\n\t\t\tvalue: false,\n\t\t},\n\t\tselection: {\n\t\t\tauto: true,\n\t\t\tlossy: true,\n\t\t\tstrip_exif: true,\n\t\t\toriginal: false,\n\t\t\tlazy_load: true,\n\t\t\tusage: false,\n\t\t},\n\t\tcontentContainer: document.getElementById( 'smush-onboarding-content' ),\n\t\tonboardingSlides: [ 'start', 'auto', 'lossy', 'strip_exif', 'original', 'lazy_load', 'usage' ],\n\t\ttouchX: null,\n\t\ttouchY: null,\n\n\t\t/**\n\t\t * Init module.\n\t\t */\n\t\tinit() {\n\t\t\tif ( ! this.onboardingModal ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.membership = document.getElementById( 'smush-onboarding' ).dataset.type;\n\n\t\t\tif ( 'pro' !== this.membership ) {\n\t\t\t\tthis.onboardingSlides = [ 'start', 'auto', 'strip_exif', 'lazy_load', 'usage' ];\n\t\t\t\tthis.selection.lossy = false;\n\t\t\t}\n\n\t\t\tthis.renderTemplate();\n\n\t\t\t// Skip setup.\n\t\t\tconst skipButton = this.onboardingModal.querySelector( '.smush-onboarding-skip-link' );\n\t\t\tif ( skipButton ) {\n\t\t\t\tskipButton.addEventListener( 'click', this.skipSetup );\n\t\t\t}\n\n\t\t\t// Show the modal.\n\t\t\twindow.SUI.openModal( 'smush-onboarding-dialog', 'checking-files-dialog', undefined, false );\n\t\t},\n\n\t\t/**\n\t\t * Get swipe coordinates.\n\t\t *\n\t\t * @param {Object} e\n\t\t */\n\t\thandleTouchStart( e ) {\n\t\t\tconst firstTouch = e.touches[ 0 ];\n\t\t\tthis.touchX = firstTouch.clientX;\n\t\t\tthis.touchY = firstTouch.clientY;\n\t\t},\n\n\t\t/**\n\t\t * Process swipe left/right.\n\t\t *\n\t\t * @param {Object} e\n\t\t */\n\t\thandleTouchMove( e ) {\n\t\t\tif ( ! this.touchX || ! this.touchY ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst xUp = e.touches[ 0 ].clientX,\n\t\t\t\tyUp = e.touches[ 0 ].clientY,\n\t\t\t\txDiff = this.touchX - xUp,\n\t\t\t\tyDiff = this.touchY - yUp;\n\n\t\t\tif ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {\n\t\t\t\tif ( xDiff > 0 ) {\n\t\t\t\t\tif ( false === WP_Smush.onboarding.settings.last ) {\n\t\t\t\t\t\tWP_Smush.onboarding.next( null, 'next' );\n\t\t\t\t\t}\n\t\t\t\t} else if ( false === WP_Smush.onboarding.settings.first ) {\n\t\t\t\t\tWP_Smush.onboarding.next( null, 'prev' );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.touchX = null;\n\t\t\tthis.touchY = null;\n\t\t},\n\n\t\t/**\n\t\t * Update the template, register new listeners.\n\t\t *\n\t\t * @param {string} directionClass  Accepts: fadeInRight, fadeInLeft, none.\n\t\t */\n\t\trenderTemplate( directionClass = 'none' ) {\n\t\t\t// Grab the selected value.\n\t\t\tconst input = this.onboardingModal.querySelector( 'input[type=\"checkbox\"]' );\n\t\t\tif ( input ) {\n\t\t\t\tthis.selection[ input.id ] = input.checked;\n\t\t\t}\n\n\t\t\tconst template = WP_Smush.onboarding.template( 'smush-onboarding' );\n\t\t\tconst content = template( this.settings );\n\n\t\t\tif ( content ) {\n\t\t\t\tthis.contentContainer.innerHTML = content;\n\n\t\t\t\tif ( 'none' === directionClass ) {\n\t\t\t\t\tthis.contentContainer.classList.add( 'loaded' );\n\t\t\t\t} else {\n\t\t\t\t\tthis.contentContainer.classList.remove( 'loaded' );\n\t\t\t\t\tthis.contentContainer.classList.add( directionClass );\n\t\t\t\t\tsetTimeout( () => {\n\t\t\t\t\t\tthis.contentContainer.classList.add( 'loaded' );\n\t\t\t\t\t\tthis.contentContainer.classList.remove( directionClass );\n\t\t\t\t\t}, 600 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.onboardingModal.addEventListener( 'touchstart', this.handleTouchStart, false );\n\t\t\tthis.onboardingModal.addEventListener( 'touchmove', this.handleTouchMove, false );\n\n\t\t\tthis.bindSubmit();\n\t\t},\n\n\t\t/**\n\t\t * Catch \"Finish setup wizard\" button click.\n\t\t */\n\t\tbindSubmit() {\n\t\t\tconst submitButton = this.onboardingModal.querySelector( 'button[type=\"submit\"]' );\n\t\t\tconst self = this;\n\n\t\t\tif ( submitButton ) {\n\t\t\t\tsubmitButton.addEventListener( 'click', function( e ) {\n\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t// Because we are not rendering the template, we need to update the last element value.\n\t\t\t\t\tconst input = self.onboardingModal.querySelector( 'input[type=\"checkbox\"]' );\n\t\t\t\t\tif ( input ) {\n\t\t\t\t\t\tself.selection[ input.id ] = input.checked;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst _nonce = document.getElementById( '_wpnonce' );\n\n\t\t\t\t\tconst xhr = new XMLHttpRequest();\n\t\t\t\t\txhr.open( 'POST', ajaxurl + '?action=smush_setup', true );\n\t\t\t\t\txhr.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' );\n\t\t\t\t\txhr.onload = () => {\n\t\t\t\t\t\tif ( 200 === xhr.status ) {\n\t\t\t\t\t\t\tWP_Smush.onboarding.showScanDialog();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\twindow.console.log( 'Request failed.  Returned status of ' + xhr.status );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\txhr.send( 'smush_settings=' + JSON.stringify( self.selection ) + '&_ajax_nonce=' + _nonce.value );\n\t\t\t\t} );\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Handle navigation.\n\t\t *\n\t\t * @param {Object} e\n\t\t * @param {null|string} whereTo\n\t\t */\n\t\tnext( e, whereTo = null ) {\n\t\t\tconst index = this.onboardingSlides.indexOf( this.settings.slide );\n\t\t\tlet newIndex = 0;\n\n\t\t\tif ( ! whereTo ) {\n\t\t\t\tnewIndex = null !== e && e.classList.contains( 'next' ) ? index + 1 : index - 1;\n\t\t\t} else {\n\t\t\t\tnewIndex = 'next' === whereTo ? index + 1 : index - 1;\n\t\t\t}\n\n\t\t\tconst directionClass = null !== e && e.classList.contains( 'next' ) ? 'fadeInRight' : 'fadeInLeft';\n\n\t\t\tthis.settings = {\n\t\t\t\tfirst: 0 === newIndex,\n\t\t\t\tlast: newIndex + 1 === this.onboardingSlides.length, // length !== index\n\t\t\t\tslide: this.onboardingSlides[ newIndex ],\n\t\t\t\tvalue: this.selection[ this.onboardingSlides[ newIndex ] ],\n\t\t\t};\n\n\t\t\tthis.renderTemplate( directionClass );\n\t\t},\n\n\t\t/**\n\t\t * Handle circle navigation.\n\t\t *\n\t\t * @param {string} target\n\t\t */\n\t\tgoTo( target ) {\n\t\t\tconst newIndex = this.onboardingSlides.indexOf( target );\n\n\t\t\tthis.settings = {\n\t\t\t\tfirst: 0 === newIndex,\n\t\t\t\tlast: newIndex + 1 === this.onboardingSlides.length, // length !== index\n\t\t\t\tslide: target,\n\t\t\t\tvalue: this.selection[ target ],\n\t\t\t};\n\n\t\t\tthis.renderTemplate();\n\t\t},\n\n\t\t/**\n\t\t * Skip onboarding experience.\n\t\t */\n\t\tskipSetup: () => {\n\t\t\tconst _nonce = document.getElementById( '_wpnonce' );\n\n\t\t\tconst xhr = new XMLHttpRequest();\n\t\t\txhr.open( 'POST', ajaxurl + '?action=skip_smush_setup&_ajax_nonce=' + _nonce.value );\n\t\t\txhr.onload = () => {\n\t\t\t\tif ( 200 === xhr.status ) {\n\t\t\t\t\tWP_Smush.onboarding.showScanDialog();\n\t\t\t\t} else {\n\t\t\t\t\twindow.console.log( 'Request failed.  Returned status of ' + xhr.status );\n\t\t\t\t}\n\t\t\t};\n\t\t\txhr.send();\n\t\t},\n\n\t\t/**\n\t\t * Show checking files dialog.\n\t\t */\n\t\tshowScanDialog() {\n\t\t\twindow.SUI.closeModal();\n\t\t\twindow.SUI.openModal( 'checking-files-dialog', 'wpbody-content', undefined, false );\n\n\t\t\tconst nonce = document.getElementById( 'wp_smush_options_nonce' );\n\n\t\t\tsetTimeout( () => {\n\t\t\t\tconst xhr = new XMLHttpRequest();\n\t\t\t\txhr.open( 'POST', ajaxurl + '?action=scan_for_resmush', true );\n\t\t\t\txhr.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' );\n\t\t\t\txhr.onload = () => {\n\t\t\t\t\tconst elem = document.querySelector( '#smush-onboarding-dialog' );\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t\twindow.SUI.closeModal();\n\n\t\t\t\t\tif ( 200 === xhr.status ) {\n\t\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\t\tlocation.reload();\n\t\t\t\t\t\t}, 1000 );\n\t\t\t\t\t} else {\n\t\t\t\t\t\twindow.console.log( 'Request failed.  Returned status of ' + xhr.status );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\txhr.send( 'type=media&get_ui=false&process_settings=false&wp_smush_options_nonce=' + nonce.value );\n\t\t\t}, 3000 );\n\t\t},\n\t};\n\n\t/**\n\t * Template function (underscores based).\n\t *\n\t * @type {Function}\n\t */\n\tWP_Smush.onboarding.template = _.memoize( ( id ) => {\n\t\tlet compiled;\n\t\tconst options = {\n\t\t\tevaluate: /<#([\\s\\S]+?)#>/g,\n\t\t\tinterpolate: /{{{([\\s\\S]+?)}}}/g,\n\t\t\tescape: /{{([^}]+?)}}(?!})/g,\n\t\t\tvariable: 'data',\n\t\t};\n\n\t\treturn ( data ) => {\n\t\t\t_.templateSettings = options;\n\t\t\tcompiled = compiled || _.template( document.getElementById( id ).innerHTML );\n\t\t\treturn compiled( data );\n\t\t};\n\t} );\n\n\twindow.addEventListener( 'load', () => WP_Smush.onboarding.init() );\n}() );\n","/*! jQuery UI - v1.12.1 - 2018-05-20\n* http://jqueryui.com\n* Includes: widget.js, position.js, keycode.js, scroll-parent.js, unique-id.js\n* Copyright jQuery Foundation and other contributors; Licensed MIT */\n\n;(function( factory ) {\n\tif ( typeof define === \"function\" && define.amd ) {\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine( [ \"jquery\" ], factory );\n\t} else if ( typeof module === \"object\" && module.exports ) {\n\t\t// Node/CommonJS\n\t\tmodule.exports = factory(require(\"jquery\"));\n\t} else {\n\t\t// Browser globals\n\t\tfactory( jQuery );\n\t}\n}(function( $ ) {\n\n$.ui = $.ui || {};\n\nvar version = $.ui.version = \"1.12.1\";\n\n\n/*!\n * jQuery UI Widget 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Widget\n//>>group: Core\n//>>description: Provides a factory for creating stateful widgets with a common API.\n//>>docs: http://api.jqueryui.com/jQuery.widget/\n//>>demos: http://jqueryui.com/widget/\n\n\n\nvar widgetUuid = 0;\nvar widgetSlice = Array.prototype.slice;\n\n$.cleanData = $.cleanData || ( function( orig ) {\n\treturn function( elems ) {\n\t\tvar events, elem, i;\n\t\tfor ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {\n\t\t\ttry {\n\n\t\t\t\t// Only trigger remove when necessary to save time\n\t\t\t\tevents = $._data( elem, \"events\" );\n\t\t\t\tif ( events && events.remove ) {\n\t\t\t\t\t$( elem ).triggerHandler( \"remove\" );\n\t\t\t\t}\n\n\t\t\t// Http://bugs.jquery.com/ticket/8235\n\t\t\t} catch ( e ) {}\n\t\t}\n\t\torig( elems );\n\t};\n} )( $.cleanData );\n\n$.widget = $.widget || function( name, base, prototype ) {\n\tvar existingConstructor, constructor, basePrototype;\n\n\t// ProxiedPrototype allows the provided prototype to remain unmodified\n\t// so that it can be used as a mixin for multiple widgets (#8876)\n\tvar proxiedPrototype = {};\n\n\tvar namespace = name.split( \".\" )[ 0 ];\n\tname = name.split( \".\" )[ 1 ];\n\tvar fullName = namespace + \"-\" + name;\n\n\tif ( !prototype ) {\n\t\tprototype = base;\n\t\tbase = $.Widget;\n\t}\n\n\tif ( $.isArray( prototype ) ) {\n\t\tprototype = $.extend.apply( null, [ {} ].concat( prototype ) );\n\t}\n\n\t// Create selector for plugin\n\t$.expr[ \":\" ][ fullName.toLowerCase() ] = function( elem ) {\n\t\treturn !!$.data( elem, fullName );\n\t};\n\n\t$[ namespace ] = $[ namespace ] || {};\n\texistingConstructor = $[ namespace ][ name ];\n\tconstructor = $[ namespace ][ name ] = function( options, element ) {\n\n\t\t// Allow instantiation without \"new\" keyword\n\t\tif ( !this._createWidget ) {\n\t\t\treturn new constructor( options, element );\n\t\t}\n\n\t\t// Allow instantiation without initializing for simple inheritance\n\t\t// must use \"new\" keyword (the code above always passes args)\n\t\tif ( arguments.length ) {\n\t\t\tthis._createWidget( options, element );\n\t\t}\n\t};\n\n\t// Extend with the existing constructor to carry over any static properties\n\t$.extend( constructor, existingConstructor, {\n\t\tversion: prototype.version,\n\n\t\t// Copy the object used to create the prototype in case we need to\n\t\t// redefine the widget later\n\t\t_proto: $.extend( {}, prototype ),\n\n\t\t// Track widgets that inherit from this widget in case this widget is\n\t\t// redefined after a widget inherits from it\n\t\t_childConstructors: []\n\t} );\n\n\tbasePrototype = new base();\n\n\t// We need to make the options hash a property directly on the new instance\n\t// otherwise we'll modify the options hash on the prototype that we're\n\t// inheriting from\n\tbasePrototype.options = $.widget.extend( {}, basePrototype.options );\n\t$.each( prototype, function( prop, value ) {\n\t\tif ( !$.isFunction( value ) ) {\n\t\t\tproxiedPrototype[ prop ] = value;\n\t\t\treturn;\n\t\t}\n\t\tproxiedPrototype[ prop ] = ( function() {\n\t\t\tfunction _super() {\n\t\t\t\treturn base.prototype[ prop ].apply( this, arguments );\n\t\t\t}\n\n\t\t\tfunction _superApply( args ) {\n\t\t\t\treturn base.prototype[ prop ].apply( this, args );\n\t\t\t}\n\n\t\t\treturn function() {\n\t\t\t\tvar __super = this._super;\n\t\t\t\tvar __superApply = this._superApply;\n\t\t\t\tvar returnValue;\n\n\t\t\t\tthis._super = _super;\n\t\t\t\tthis._superApply = _superApply;\n\n\t\t\t\treturnValue = value.apply( this, arguments );\n\n\t\t\t\tthis._super = __super;\n\t\t\t\tthis._superApply = __superApply;\n\n\t\t\t\treturn returnValue;\n\t\t\t};\n\t\t} )();\n\t} );\n\tconstructor.prototype = $.widget.extend( basePrototype, {\n\n\t\t// TODO: remove support for widgetEventPrefix\n\t\t// always use the name + a colon as the prefix, e.g., draggable:start\n\t\t// don't prefix for widgets that aren't DOM-based\n\t\twidgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name\n\t}, proxiedPrototype, {\n\t\tconstructor: constructor,\n\t\tnamespace: namespace,\n\t\twidgetName: name,\n\t\twidgetFullName: fullName\n\t} );\n\n\t// If this widget is being redefined then we need to find all widgets that\n\t// are inheriting from it and redefine all of them so that they inherit from\n\t// the new version of this widget. We're essentially trying to replace one\n\t// level in the prototype chain.\n\tif ( existingConstructor ) {\n\t\t$.each( existingConstructor._childConstructors, function( i, child ) {\n\t\t\tvar childPrototype = child.prototype;\n\n\t\t\t// Redefine the child widget using the same prototype that was\n\t\t\t// originally used, but inherit from the new version of the base\n\t\t\t$.widget( childPrototype.namespace + \".\" + childPrototype.widgetName, constructor,\n\t\t\t\tchild._proto );\n\t\t} );\n\n\t\t// Remove the list of existing child constructors from the old constructor\n\t\t// so the old child constructors can be garbage collected\n\t\tdelete existingConstructor._childConstructors;\n\t} else {\n\t\tbase._childConstructors.push( constructor );\n\t}\n\n\t$.widget.bridge( name, constructor );\n\n\treturn constructor;\n};\n\n$.widget.extend = function( target ) {\n\tvar input = widgetSlice.call( arguments, 1 );\n\tvar inputIndex = 0;\n\tvar inputLength = input.length;\n\tvar key;\n\tvar value;\n\n\tfor ( ; inputIndex < inputLength; inputIndex++ ) {\n\t\tfor ( key in input[ inputIndex ] ) {\n\t\t\tvalue = input[ inputIndex ][ key ];\n\t\t\tif ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {\n\n\t\t\t\t// Clone objects\n\t\t\t\tif ( $.isPlainObject( value ) ) {\n\t\t\t\t\ttarget[ key ] = $.isPlainObject( target[ key ] ) ?\n\t\t\t\t\t\t$.widget.extend( {}, target[ key ], value ) :\n\n\t\t\t\t\t\t// Don't extend strings, arrays, etc. with objects\n\t\t\t\t\t\t$.widget.extend( {}, value );\n\n\t\t\t\t// Copy everything else by reference\n\t\t\t\t} else {\n\t\t\t\t\ttarget[ key ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn target;\n};\n\n$.widget.bridge = function( name, object ) {\n\tvar fullName = object.prototype.widgetFullName || name;\n\t$.fn[ name ] = function( options ) {\n\t\tvar isMethodCall = typeof options === \"string\";\n\t\tvar args = widgetSlice.call( arguments, 1 );\n\t\tvar returnValue = this;\n\n\t\tif ( isMethodCall ) {\n\n\t\t\t// If this is an empty collection, we need to have the instance method\n\t\t\t// return undefined instead of the jQuery instance\n\t\t\tif ( !this.length && options === \"instance\" ) {\n\t\t\t\treturnValue = undefined;\n\t\t\t} else {\n\t\t\t\tthis.each( function() {\n\t\t\t\t\tvar methodValue;\n\t\t\t\t\tvar instance = $.data( this, fullName );\n\n\t\t\t\t\tif ( options === \"instance\" ) {\n\t\t\t\t\t\treturnValue = instance;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !instance ) {\n\t\t\t\t\t\treturn $.error( \"cannot call methods on \" + name +\n\t\t\t\t\t\t\t\" prior to initialization; \" +\n\t\t\t\t\t\t\t\"attempted to call method '\" + options + \"'\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === \"_\" ) {\n\t\t\t\t\t\treturn $.error( \"no such method '\" + options + \"' for \" + name +\n\t\t\t\t\t\t\t\" widget instance\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tmethodValue = instance[ options ].apply( instance, args );\n\n\t\t\t\t\tif ( methodValue !== instance && methodValue !== undefined ) {\n\t\t\t\t\t\treturnValue = methodValue && methodValue.jquery ?\n\t\t\t\t\t\t\treturnValue.pushStack( methodValue.get() ) :\n\t\t\t\t\t\t\tmethodValue;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Allow multiple hashes to be passed on init\n\t\t\tif ( args.length ) {\n\t\t\t\toptions = $.widget.extend.apply( null, [ options ].concat( args ) );\n\t\t\t}\n\n\t\t\tthis.each( function() {\n\t\t\t\tvar instance = $.data( this, fullName );\n\t\t\t\tif ( instance ) {\n\t\t\t\t\tinstance.option( options || {} );\n\t\t\t\t\tif ( instance._init ) {\n\t\t\t\t\t\tinstance._init();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$.data( this, fullName, new object( options, this ) );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\treturn returnValue;\n\t};\n};\n\n$.Widget = $.Widget || function( /* options, element */ ) {};\n$.Widget._childConstructors = [];\n\n$.Widget.prototype = {\n\twidgetName: \"widget\",\n\twidgetEventPrefix: \"\",\n\tdefaultElement: \"<div>\",\n\n\toptions: {\n\t\tclasses: {},\n\t\tdisabled: false,\n\n\t\t// Callbacks\n\t\tcreate: null\n\t},\n\n\t_createWidget: function( options, element ) {\n\t\telement = $( element || this.defaultElement || this )[ 0 ];\n\t\tthis.element = $( element );\n\t\tthis.uuid = widgetUuid++;\n\t\tthis.eventNamespace = \".\" + this.widgetName + this.uuid;\n\n\t\tthis.bindings = $();\n\t\tthis.hoverable = $();\n\t\tthis.focusable = $();\n\t\tthis.classesElementLookup = {};\n\n\t\tif ( element !== this ) {\n\t\t\t$.data( element, this.widgetFullName, this );\n\t\t\tthis._on( true, this.element, {\n\t\t\t\tremove: function( event ) {\n\t\t\t\t\tif ( event.target === element ) {\n\t\t\t\t\t\tthis.destroy();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t\tthis.document = $( element.style ?\n\n\t\t\t\t// Element within the document\n\t\t\t\telement.ownerDocument :\n\n\t\t\t\t// Element is window or document\n\t\t\t\telement.document || element );\n\t\t\tthis.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );\n\t\t}\n\n\t\tthis.options = $.widget.extend( {},\n\t\t\tthis.options,\n\t\t\tthis._getCreateOptions(),\n\t\t\toptions );\n\n\t\tthis._create();\n\n\t\tif ( this.options.disabled ) {\n\t\t\tthis._setOptionDisabled( this.options.disabled );\n\t\t}\n\n\t\tthis._trigger( \"create\", null, this._getCreateEventData() );\n\t\tthis._init();\n\t},\n\n\t_getCreateOptions: function() {\n\t\treturn {};\n\t},\n\n\t_getCreateEventData: $.noop,\n\n\t_create: $.noop,\n\n\t_init: $.noop,\n\n\tdestroy: function() {\n\t\tvar that = this;\n\n\t\tthis._destroy();\n\t\t$.each( this.classesElementLookup, function( key, value ) {\n\t\t\tthat._removeClass( value, key );\n\t\t} );\n\n\t\t// We can probably remove the unbind calls in 2.0\n\t\t// all event bindings should go through this._on()\n\t\tthis.element\n\t\t\t.off( this.eventNamespace )\n\t\t\t.removeData( this.widgetFullName );\n\t\tthis.widget()\n\t\t\t.off( this.eventNamespace )\n\t\t\t.removeAttr( \"aria-disabled\" );\n\n\t\t// Clean up events and states\n\t\tthis.bindings.off( this.eventNamespace );\n\t},\n\n\t_destroy: $.noop,\n\n\twidget: function() {\n\t\treturn this.element;\n\t},\n\n\toption: function( key, value ) {\n\t\tvar options = key;\n\t\tvar parts;\n\t\tvar curOption;\n\t\tvar i;\n\n\t\tif ( arguments.length === 0 ) {\n\n\t\t\t// Don't return a reference to the internal hash\n\t\t\treturn $.widget.extend( {}, this.options );\n\t\t}\n\n\t\tif ( typeof key === \"string\" ) {\n\n\t\t\t// Handle nested keys, e.g., \"foo.bar\" => { foo: { bar: ___ } }\n\t\t\toptions = {};\n\t\t\tparts = key.split( \".\" );\n\t\t\tkey = parts.shift();\n\t\t\tif ( parts.length ) {\n\t\t\t\tcurOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );\n\t\t\t\tfor ( i = 0; i < parts.length - 1; i++ ) {\n\t\t\t\t\tcurOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};\n\t\t\t\t\tcurOption = curOption[ parts[ i ] ];\n\t\t\t\t}\n\t\t\t\tkey = parts.pop();\n\t\t\t\tif ( arguments.length === 1 ) {\n\t\t\t\t\treturn curOption[ key ] === undefined ? null : curOption[ key ];\n\t\t\t\t}\n\t\t\t\tcurOption[ key ] = value;\n\t\t\t} else {\n\t\t\t\tif ( arguments.length === 1 ) {\n\t\t\t\t\treturn this.options[ key ] === undefined ? null : this.options[ key ];\n\t\t\t\t}\n\t\t\t\toptions[ key ] = value;\n\t\t\t}\n\t\t}\n\n\t\tthis._setOptions( options );\n\n\t\treturn this;\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar key;\n\n\t\tfor ( key in options ) {\n\t\t\tthis._setOption( key, options[ key ] );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"classes\" ) {\n\t\t\tthis._setOptionClasses( value );\n\t\t}\n\n\t\tthis.options[ key ] = value;\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis._setOptionDisabled( value );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_setOptionClasses: function( value ) {\n\t\tvar classKey, elements, currentElements;\n\n\t\tfor ( classKey in value ) {\n\t\t\tcurrentElements = this.classesElementLookup[ classKey ];\n\t\t\tif ( value[ classKey ] === this.options.classes[ classKey ] ||\n\t\t\t\t\t!currentElements ||\n\t\t\t\t\t!currentElements.length ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// We are doing this to create a new jQuery object because the _removeClass() call\n\t\t\t// on the next line is going to destroy the reference to the current elements being\n\t\t\t// tracked. We need to save a copy of this collection so that we can add the new classes\n\t\t\t// below.\n\t\t\telements = $( currentElements.get() );\n\t\t\tthis._removeClass( currentElements, classKey );\n\n\t\t\t// We don't use _addClass() here, because that uses this.options.classes\n\t\t\t// for generating the string of classes. We want to use the value passed in from\n\t\t\t// _setOption(), this is the new value of the classes option which was passed to\n\t\t\t// _setOption(). We pass this value directly to _classes().\n\t\t\telements.addClass( this._classes( {\n\t\t\t\telement: elements,\n\t\t\t\tkeys: classKey,\n\t\t\t\tclasses: value,\n\t\t\t\tadd: true\n\t\t\t} ) );\n\t\t}\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._toggleClass( this.widget(), this.widgetFullName + \"-disabled\", null, !!value );\n\n\t\t// If the widget is becoming disabled, then nothing is interactive\n\t\tif ( value ) {\n\t\t\tthis._removeClass( this.hoverable, null, \"ui-state-hover\" );\n\t\t\tthis._removeClass( this.focusable, null, \"ui-state-focus\" );\n\t\t}\n\t},\n\n\tenable: function() {\n\t\treturn this._setOptions( { disabled: false } );\n\t},\n\n\tdisable: function() {\n\t\treturn this._setOptions( { disabled: true } );\n\t},\n\n\t_classes: function( options ) {\n\t\tvar full = [];\n\t\tvar that = this;\n\n\t\toptions = $.extend( {\n\t\t\telement: this.element,\n\t\t\tclasses: this.options.classes || {}\n\t\t}, options );\n\n\t\tfunction processClassString( classes, checkOption ) {\n\t\t\tvar current, i;\n\t\t\tfor ( i = 0; i < classes.length; i++ ) {\n\t\t\t\tcurrent = that.classesElementLookup[ classes[ i ] ] || $();\n\t\t\t\tif ( options.add ) {\n\t\t\t\t\tcurrent = $( $.unique( current.get().concat( options.element.get() ) ) );\n\t\t\t\t} else {\n\t\t\t\t\tcurrent = $( current.not( options.element ).get() );\n\t\t\t\t}\n\t\t\t\tthat.classesElementLookup[ classes[ i ] ] = current;\n\t\t\t\tfull.push( classes[ i ] );\n\t\t\t\tif ( checkOption && options.classes[ classes[ i ] ] ) {\n\t\t\t\t\tfull.push( options.classes[ classes[ i ] ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._on( options.element, {\n\t\t\t\"remove\": \"_untrackClassesElement\"\n\t\t} );\n\n\t\tif ( options.keys ) {\n\t\t\tprocessClassString( options.keys.match( /\\S+/g ) || [], true );\n\t\t}\n\t\tif ( options.extra ) {\n\t\t\tprocessClassString( options.extra.match( /\\S+/g ) || [] );\n\t\t}\n\n\t\treturn full.join( \" \" );\n\t},\n\n\t_untrackClassesElement: function( event ) {\n\t\tvar that = this;\n\t\t$.each( that.classesElementLookup, function( key, value ) {\n\t\t\tif ( $.inArray( event.target, value ) !== -1 ) {\n\t\t\t\tthat.classesElementLookup[ key ] = $( value.not( event.target ).get() );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_removeClass: function( element, keys, extra ) {\n\t\treturn this._toggleClass( element, keys, extra, false );\n\t},\n\n\t_addClass: function( element, keys, extra ) {\n\t\treturn this._toggleClass( element, keys, extra, true );\n\t},\n\n\t_toggleClass: function( element, keys, extra, add ) {\n\t\tadd = ( typeof add === \"boolean\" ) ? add : extra;\n\t\tvar shift = ( typeof element === \"string\" || element === null ),\n\t\t\toptions = {\n\t\t\t\textra: shift ? keys : extra,\n\t\t\t\tkeys: shift ? element : keys,\n\t\t\t\telement: shift ? this.element : element,\n\t\t\t\tadd: add\n\t\t\t};\n\t\toptions.element.toggleClass( this._classes( options ), add );\n\t\treturn this;\n\t},\n\n\t_on: function( suppressDisabledCheck, element, handlers ) {\n\t\tvar delegateElement;\n\t\tvar instance = this;\n\n\t\t// No suppressDisabledCheck flag, shuffle arguments\n\t\tif ( typeof suppressDisabledCheck !== \"boolean\" ) {\n\t\t\thandlers = element;\n\t\t\telement = suppressDisabledCheck;\n\t\t\tsuppressDisabledCheck = false;\n\t\t}\n\n\t\t// No element argument, shuffle and use this.element\n\t\tif ( !handlers ) {\n\t\t\thandlers = element;\n\t\t\telement = this.element;\n\t\t\tdelegateElement = this.widget();\n\t\t} else {\n\t\t\telement = delegateElement = $( element );\n\t\t\tthis.bindings = this.bindings.add( element );\n\t\t}\n\n\t\t$.each( handlers, function( event, handler ) {\n\t\t\tfunction handlerProxy() {\n\n\t\t\t\t// Allow widgets to customize the disabled handling\n\t\t\t\t// - disabled as an array instead of boolean\n\t\t\t\t// - disabled class as method for disabling individual parts\n\t\t\t\tif ( !suppressDisabledCheck &&\n\t\t\t\t\t\t( instance.options.disabled === true ||\n\t\t\t\t\t\t$( this ).hasClass( \"ui-state-disabled\" ) ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t\t.apply( instance, arguments );\n\t\t\t}\n\n\t\t\t// Copy the guid so direct unbinding works\n\t\t\tif ( typeof handler !== \"string\" ) {\n\t\t\t\thandlerProxy.guid = handler.guid =\n\t\t\t\t\thandler.guid || handlerProxy.guid || $.guid++;\n\t\t\t}\n\n\t\t\tvar match = event.match( /^([\\w:-]*)\\s*(.*)$/ );\n\t\t\tvar eventName = match[ 1 ] + instance.eventNamespace;\n\t\t\tvar selector = match[ 2 ];\n\n\t\t\tif ( selector ) {\n\t\t\t\tdelegateElement.on( eventName, selector, handlerProxy );\n\t\t\t} else {\n\t\t\t\telement.on( eventName, handlerProxy );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_off: function( element, eventName ) {\n\t\teventName = ( eventName || \"\" ).split( \" \" ).join( this.eventNamespace + \" \" ) +\n\t\t\tthis.eventNamespace;\n\t\telement.off( eventName ).off( eventName );\n\n\t\t// Clear the stack to avoid memory leaks (#10056)\n\t\tthis.bindings = $( this.bindings.not( element ).get() );\n\t\tthis.focusable = $( this.focusable.not( element ).get() );\n\t\tthis.hoverable = $( this.hoverable.not( element ).get() );\n\t},\n\n\t_delay: function( handler, delay ) {\n\t\tfunction handlerProxy() {\n\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t.apply( instance, arguments );\n\t\t}\n\t\tvar instance = this;\n\t\treturn setTimeout( handlerProxy, delay || 0 );\n\t},\n\n\t_hoverable: function( element ) {\n\t\tthis.hoverable = this.hoverable.add( element );\n\t\tthis._on( element, {\n\t\t\tmouseenter: function( event ) {\n\t\t\t\tthis._addClass( $( event.currentTarget ), null, \"ui-state-hover\" );\n\t\t\t},\n\t\t\tmouseleave: function( event ) {\n\t\t\t\tthis._removeClass( $( event.currentTarget ), null, \"ui-state-hover\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_focusable: function( element ) {\n\t\tthis.focusable = this.focusable.add( element );\n\t\tthis._on( element, {\n\t\t\tfocusin: function( event ) {\n\t\t\t\tthis._addClass( $( event.currentTarget ), null, \"ui-state-focus\" );\n\t\t\t},\n\t\t\tfocusout: function( event ) {\n\t\t\t\tthis._removeClass( $( event.currentTarget ), null, \"ui-state-focus\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_trigger: function( type, event, data ) {\n\t\tvar prop, orig;\n\t\tvar callback = this.options[ type ];\n\n\t\tdata = data || {};\n\t\tevent = $.Event( event );\n\t\tevent.type = ( type === this.widgetEventPrefix ?\n\t\t\ttype :\n\t\t\tthis.widgetEventPrefix + type ).toLowerCase();\n\n\t\t// The original event may come from any element\n\t\t// so we need to reset the target on the new event\n\t\tevent.target = this.element[ 0 ];\n\n\t\t// Copy original event properties over to the new event\n\t\torig = event.originalEvent;\n\t\tif ( orig ) {\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tif ( !( prop in event ) ) {\n\t\t\t\t\tevent[ prop ] = orig[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.element.trigger( event, data );\n\t\treturn !( $.isFunction( callback ) &&\n\t\t\tcallback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||\n\t\t\tevent.isDefaultPrevented() );\n\t}\n};\n\n$.each( { show: \"fadeIn\", hide: \"fadeOut\" }, function( method, defaultEffect ) {\n\t$.Widget.prototype[ \"_\" + method ] = function( element, options, callback ) {\n\t\tif ( typeof options === \"string\" ) {\n\t\t\toptions = { effect: options };\n\t\t}\n\n\t\tvar hasOptions;\n\t\tvar effectName = !options ?\n\t\t\tmethod :\n\t\t\toptions === true || typeof options === \"number\" ?\n\t\t\t\tdefaultEffect :\n\t\t\t\toptions.effect || defaultEffect;\n\n\t\toptions = options || {};\n\t\tif ( typeof options === \"number\" ) {\n\t\t\toptions = { duration: options };\n\t\t}\n\n\t\thasOptions = !$.isEmptyObject( options );\n\t\toptions.complete = callback;\n\n\t\tif ( options.delay ) {\n\t\t\telement.delay( options.delay );\n\t\t}\n\n\t\tif ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {\n\t\t\telement[ method ]( options );\n\t\t} else if ( effectName !== method && element[ effectName ] ) {\n\t\t\telement[ effectName ]( options.duration, options.easing, callback );\n\t\t} else {\n\t\t\telement.queue( function( next ) {\n\t\t\t\t$( this )[ method ]();\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback.call( element[ 0 ] );\n\t\t\t\t}\n\t\t\t\tnext();\n\t\t\t} );\n\t\t}\n\t};\n} );\n\nvar widget = $.widget;\n\n\n/*!\n * jQuery UI Position 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n * http://api.jqueryui.com/position/\n */\n\n//>>label: Position\n//>>group: Core\n//>>description: Positions elements relative to other elements.\n//>>docs: http://api.jqueryui.com/position/\n//>>demos: http://jqueryui.com/position/\n\n\n( function() {\nvar cachedScrollbarWidth,\n\tmax = Math.max,\n\tabs = Math.abs,\n\trhorizontal = /left|center|right/,\n\trvertical = /top|center|bottom/,\n\troffset = /[\\+\\-]\\d+(\\.[\\d]+)?%?/,\n\trposition = /^\\w+/,\n\trpercent = /%$/,\n\t_position = $.fn.position;\n\nfunction getOffsets( offsets, width, height ) {\n\treturn [\n\t\tparseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),\n\t\tparseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )\n\t];\n}\n\nfunction parseCss( element, property ) {\n\treturn parseInt( $.css( element, property ), 10 ) || 0;\n}\n\nfunction getDimensions( elem ) {\n\tvar raw = elem[ 0 ];\n\tif ( raw.nodeType === 9 ) {\n\t\treturn {\n\t\t\twidth: elem.width(),\n\t\t\theight: elem.height(),\n\t\t\toffset: { top: 0, left: 0 }\n\t\t};\n\t}\n\tif ( $.isWindow( raw ) ) {\n\t\treturn {\n\t\t\twidth: elem.width(),\n\t\t\theight: elem.height(),\n\t\t\toffset: { top: elem.scrollTop(), left: elem.scrollLeft() }\n\t\t};\n\t}\n\tif ( raw.preventDefault ) {\n\t\treturn {\n\t\t\twidth: 0,\n\t\t\theight: 0,\n\t\t\toffset: { top: raw.pageY, left: raw.pageX }\n\t\t};\n\t}\n\treturn {\n\t\twidth: elem.outerWidth(),\n\t\theight: elem.outerHeight(),\n\t\toffset: elem.offset()\n\t};\n}\n\n$.position = $.position || {\n\tscrollbarWidth: function() {\n\t\tif ( cachedScrollbarWidth !== undefined ) {\n\t\t\treturn cachedScrollbarWidth;\n\t\t}\n\t\tvar w1, w2,\n\t\t\tdiv = $( \"<div \" +\n\t\t\t\t\"style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>\" +\n\t\t\t\t\"<div style='height:100px;width:auto;'></div></div>\" ),\n\t\t\tinnerDiv = div.children()[ 0 ];\n\n\t\t$( \"body\" ).append( div );\n\t\tw1 = innerDiv.offsetWidth;\n\t\tdiv.css( \"overflow\", \"scroll\" );\n\n\t\tw2 = innerDiv.offsetWidth;\n\n\t\tif ( w1 === w2 ) {\n\t\t\tw2 = div[ 0 ].clientWidth;\n\t\t}\n\n\t\tdiv.remove();\n\n\t\treturn ( cachedScrollbarWidth = w1 - w2 );\n\t},\n\tgetScrollInfo: function( within ) {\n\t\tvar overflowX = within.isWindow || within.isDocument ? \"\" :\n\t\t\t\twithin.element.css( \"overflow-x\" ),\n\t\t\toverflowY = within.isWindow || within.isDocument ? \"\" :\n\t\t\t\twithin.element.css( \"overflow-y\" ),\n\t\t\thasOverflowX = overflowX === \"scroll\" ||\n\t\t\t\t( overflowX === \"auto\" && within.width < within.element[ 0 ].scrollWidth ),\n\t\t\thasOverflowY = overflowY === \"scroll\" ||\n\t\t\t\t( overflowY === \"auto\" && within.height < within.element[ 0 ].scrollHeight );\n\t\treturn {\n\t\t\twidth: hasOverflowY ? $.position.scrollbarWidth() : 0,\n\t\t\theight: hasOverflowX ? $.position.scrollbarWidth() : 0\n\t\t};\n\t},\n\tgetWithinInfo: function( element ) {\n\t\tvar withinElement = $( element || window ),\n\t\t\tisWindow = $.isWindow( withinElement[ 0 ] ),\n\t\t\tisDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,\n\t\t\thasOffset = !isWindow && !isDocument;\n\t\treturn {\n\t\t\telement: withinElement,\n\t\t\tisWindow: isWindow,\n\t\t\tisDocument: isDocument,\n\t\t\toffset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },\n\t\t\tscrollLeft: withinElement.scrollLeft(),\n\t\t\tscrollTop: withinElement.scrollTop(),\n\t\t\twidth: withinElement.outerWidth(),\n\t\t\theight: withinElement.outerHeight()\n\t\t};\n\t}\n};\n\n$.fn.position = function( options ) {\n\tif ( !options || !options.of ) {\n\t\treturn _position.apply( this, arguments );\n\t}\n\n\t// Make a copy, we don't want to modify arguments\n\toptions = $.extend( {}, options );\n\n\tvar atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,\n\t\ttarget = $( options.of ),\n\t\twithin = $.position.getWithinInfo( options.within ),\n\t\tscrollInfo = $.position.getScrollInfo( within ),\n\t\tcollision = ( options.collision || \"flip\" ).split( \" \" ),\n\t\toffsets = {};\n\n\tdimensions = getDimensions( target );\n\tif ( target[ 0 ].preventDefault ) {\n\n\t\t// Force left top to allow flipping\n\t\toptions.at = \"left top\";\n\t}\n\ttargetWidth = dimensions.width;\n\ttargetHeight = dimensions.height;\n\ttargetOffset = dimensions.offset;\n\n\t// Clone to reuse original targetOffset later\n\tbasePosition = $.extend( {}, targetOffset );\n\n\t// Force my and at to have valid horizontal and vertical positions\n\t// if a value is missing or invalid, it will be converted to center\n\t$.each( [ \"my\", \"at\" ], function() {\n\t\tvar pos = ( options[ this ] || \"\" ).split( \" \" ),\n\t\t\thorizontalOffset,\n\t\t\tverticalOffset;\n\n\t\tif ( pos.length === 1 ) {\n\t\t\tpos = rhorizontal.test( pos[ 0 ] ) ?\n\t\t\t\tpos.concat( [ \"center\" ] ) :\n\t\t\t\trvertical.test( pos[ 0 ] ) ?\n\t\t\t\t\t[ \"center\" ].concat( pos ) :\n\t\t\t\t\t[ \"center\", \"center\" ];\n\t\t}\n\t\tpos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : \"center\";\n\t\tpos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : \"center\";\n\n\t\t// Calculate offsets\n\t\thorizontalOffset = roffset.exec( pos[ 0 ] );\n\t\tverticalOffset = roffset.exec( pos[ 1 ] );\n\t\toffsets[ this ] = [\n\t\t\thorizontalOffset ? horizontalOffset[ 0 ] : 0,\n\t\t\tverticalOffset ? verticalOffset[ 0 ] : 0\n\t\t];\n\n\t\t// Reduce to just the positions without the offsets\n\t\toptions[ this ] = [\n\t\t\trposition.exec( pos[ 0 ] )[ 0 ],\n\t\t\trposition.exec( pos[ 1 ] )[ 0 ]\n\t\t];\n\t} );\n\n\t// Normalize collision option\n\tif ( collision.length === 1 ) {\n\t\tcollision[ 1 ] = collision[ 0 ];\n\t}\n\n\tif ( options.at[ 0 ] === \"right\" ) {\n\t\tbasePosition.left += targetWidth;\n\t} else if ( options.at[ 0 ] === \"center\" ) {\n\t\tbasePosition.left += targetWidth / 2;\n\t}\n\n\tif ( options.at[ 1 ] === \"bottom\" ) {\n\t\tbasePosition.top += targetHeight;\n\t} else if ( options.at[ 1 ] === \"center\" ) {\n\t\tbasePosition.top += targetHeight / 2;\n\t}\n\n\tatOffset = getOffsets( offsets.at, targetWidth, targetHeight );\n\tbasePosition.left += atOffset[ 0 ];\n\tbasePosition.top += atOffset[ 1 ];\n\n\treturn this.each( function() {\n\t\tvar collisionPosition, using,\n\t\t\telem = $( this ),\n\t\t\telemWidth = elem.outerWidth(),\n\t\t\telemHeight = elem.outerHeight(),\n\t\t\tmarginLeft = parseCss( this, \"marginLeft\" ),\n\t\t\tmarginTop = parseCss( this, \"marginTop\" ),\n\t\t\tcollisionWidth = elemWidth + marginLeft + parseCss( this, \"marginRight\" ) +\n\t\t\t\tscrollInfo.width,\n\t\t\tcollisionHeight = elemHeight + marginTop + parseCss( this, \"marginBottom\" ) +\n\t\t\t\tscrollInfo.height,\n\t\t\tposition = $.extend( {}, basePosition ),\n\t\t\tmyOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );\n\n\t\tif ( options.my[ 0 ] === \"right\" ) {\n\t\t\tposition.left -= elemWidth;\n\t\t} else if ( options.my[ 0 ] === \"center\" ) {\n\t\t\tposition.left -= elemWidth / 2;\n\t\t}\n\n\t\tif ( options.my[ 1 ] === \"bottom\" ) {\n\t\t\tposition.top -= elemHeight;\n\t\t} else if ( options.my[ 1 ] === \"center\" ) {\n\t\t\tposition.top -= elemHeight / 2;\n\t\t}\n\n\t\tposition.left += myOffset[ 0 ];\n\t\tposition.top += myOffset[ 1 ];\n\n\t\tcollisionPosition = {\n\t\t\tmarginLeft: marginLeft,\n\t\t\tmarginTop: marginTop\n\t\t};\n\n\t\t$.each( [ \"left\", \"top\" ], function( i, dir ) {\n\t\t\tif ( $.ui.position[ collision[ i ] ] ) {\n\t\t\t\t$.ui.position[ collision[ i ] ][ dir ]( position, {\n\t\t\t\t\ttargetWidth: targetWidth,\n\t\t\t\t\ttargetHeight: targetHeight,\n\t\t\t\t\telemWidth: elemWidth,\n\t\t\t\t\telemHeight: elemHeight,\n\t\t\t\t\tcollisionPosition: collisionPosition,\n\t\t\t\t\tcollisionWidth: collisionWidth,\n\t\t\t\t\tcollisionHeight: collisionHeight,\n\t\t\t\t\toffset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],\n\t\t\t\t\tmy: options.my,\n\t\t\t\t\tat: options.at,\n\t\t\t\t\twithin: within,\n\t\t\t\t\telem: elem\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\n\t\tif ( options.using ) {\n\n\t\t\t// Adds feedback as second argument to using callback, if present\n\t\t\tusing = function( props ) {\n\t\t\t\tvar left = targetOffset.left - position.left,\n\t\t\t\t\tright = left + targetWidth - elemWidth,\n\t\t\t\t\ttop = targetOffset.top - position.top,\n\t\t\t\t\tbottom = top + targetHeight - elemHeight,\n\t\t\t\t\tfeedback = {\n\t\t\t\t\t\ttarget: {\n\t\t\t\t\t\t\telement: target,\n\t\t\t\t\t\t\tleft: targetOffset.left,\n\t\t\t\t\t\t\ttop: targetOffset.top,\n\t\t\t\t\t\t\twidth: targetWidth,\n\t\t\t\t\t\t\theight: targetHeight\n\t\t\t\t\t\t},\n\t\t\t\t\t\telement: {\n\t\t\t\t\t\t\telement: elem,\n\t\t\t\t\t\t\tleft: position.left,\n\t\t\t\t\t\t\ttop: position.top,\n\t\t\t\t\t\t\twidth: elemWidth,\n\t\t\t\t\t\t\theight: elemHeight\n\t\t\t\t\t\t},\n\t\t\t\t\t\thorizontal: right < 0 ? \"left\" : left > 0 ? \"right\" : \"center\",\n\t\t\t\t\t\tvertical: bottom < 0 ? \"top\" : top > 0 ? \"bottom\" : \"middle\"\n\t\t\t\t\t};\n\t\t\t\tif ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {\n\t\t\t\t\tfeedback.horizontal = \"center\";\n\t\t\t\t}\n\t\t\t\tif ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {\n\t\t\t\t\tfeedback.vertical = \"middle\";\n\t\t\t\t}\n\t\t\t\tif ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {\n\t\t\t\t\tfeedback.important = \"horizontal\";\n\t\t\t\t} else {\n\t\t\t\t\tfeedback.important = \"vertical\";\n\t\t\t\t}\n\t\t\t\toptions.using.call( this, props, feedback );\n\t\t\t};\n\t\t}\n\n\t\telem.offset( $.extend( position, { using: using } ) );\n\t} );\n};\n\n$.ui.position = {\n\tfit: {\n\t\tleft: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.isWindow ? within.scrollLeft : within.offset.left,\n\t\t\t\touterWidth = within.width,\n\t\t\t\tcollisionPosLeft = position.left - data.collisionPosition.marginLeft,\n\t\t\t\toverLeft = withinOffset - collisionPosLeft,\n\t\t\t\toverRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,\n\t\t\t\tnewOverRight;\n\n\t\t\t// Element is wider than within\n\t\t\tif ( data.collisionWidth > outerWidth ) {\n\n\t\t\t\t// Element is initially over the left side of within\n\t\t\t\tif ( overLeft > 0 && overRight <= 0 ) {\n\t\t\t\t\tnewOverRight = position.left + overLeft + data.collisionWidth - outerWidth -\n\t\t\t\t\t\twithinOffset;\n\t\t\t\t\tposition.left += overLeft - newOverRight;\n\n\t\t\t\t// Element is initially over right side of within\n\t\t\t\t} else if ( overRight > 0 && overLeft <= 0 ) {\n\t\t\t\t\tposition.left = withinOffset;\n\n\t\t\t\t// Element is initially over both left and right sides of within\n\t\t\t\t} else {\n\t\t\t\t\tif ( overLeft > overRight ) {\n\t\t\t\t\t\tposition.left = withinOffset + outerWidth - data.collisionWidth;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tposition.left = withinOffset;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Too far left -> align with left edge\n\t\t\t} else if ( overLeft > 0 ) {\n\t\t\t\tposition.left += overLeft;\n\n\t\t\t// Too far right -> align with right edge\n\t\t\t} else if ( overRight > 0 ) {\n\t\t\t\tposition.left -= overRight;\n\n\t\t\t// Adjust based on position and margin\n\t\t\t} else {\n\t\t\t\tposition.left = max( position.left - collisionPosLeft, position.left );\n\t\t\t}\n\t\t},\n\t\ttop: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.isWindow ? within.scrollTop : within.offset.top,\n\t\t\t\touterHeight = data.within.height,\n\t\t\t\tcollisionPosTop = position.top - data.collisionPosition.marginTop,\n\t\t\t\toverTop = withinOffset - collisionPosTop,\n\t\t\t\toverBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,\n\t\t\t\tnewOverBottom;\n\n\t\t\t// Element is taller than within\n\t\t\tif ( data.collisionHeight > outerHeight ) {\n\n\t\t\t\t// Element is initially over the top of within\n\t\t\t\tif ( overTop > 0 && overBottom <= 0 ) {\n\t\t\t\t\tnewOverBottom = position.top + overTop + data.collisionHeight - outerHeight -\n\t\t\t\t\t\twithinOffset;\n\t\t\t\t\tposition.top += overTop - newOverBottom;\n\n\t\t\t\t// Element is initially over bottom of within\n\t\t\t\t} else if ( overBottom > 0 && overTop <= 0 ) {\n\t\t\t\t\tposition.top = withinOffset;\n\n\t\t\t\t// Element is initially over both top and bottom of within\n\t\t\t\t} else {\n\t\t\t\t\tif ( overTop > overBottom ) {\n\t\t\t\t\t\tposition.top = withinOffset + outerHeight - data.collisionHeight;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tposition.top = withinOffset;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Too far up -> align with top\n\t\t\t} else if ( overTop > 0 ) {\n\t\t\t\tposition.top += overTop;\n\n\t\t\t// Too far down -> align with bottom edge\n\t\t\t} else if ( overBottom > 0 ) {\n\t\t\t\tposition.top -= overBottom;\n\n\t\t\t// Adjust based on position and margin\n\t\t\t} else {\n\t\t\t\tposition.top = max( position.top - collisionPosTop, position.top );\n\t\t\t}\n\t\t}\n\t},\n\tflip: {\n\t\tleft: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.offset.left + within.scrollLeft,\n\t\t\t\touterWidth = within.width,\n\t\t\t\toffsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,\n\t\t\t\tcollisionPosLeft = position.left - data.collisionPosition.marginLeft,\n\t\t\t\toverLeft = collisionPosLeft - offsetLeft,\n\t\t\t\toverRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,\n\t\t\t\tmyOffset = data.my[ 0 ] === \"left\" ?\n\t\t\t\t\t-data.elemWidth :\n\t\t\t\t\tdata.my[ 0 ] === \"right\" ?\n\t\t\t\t\t\tdata.elemWidth :\n\t\t\t\t\t\t0,\n\t\t\t\tatOffset = data.at[ 0 ] === \"left\" ?\n\t\t\t\t\tdata.targetWidth :\n\t\t\t\t\tdata.at[ 0 ] === \"right\" ?\n\t\t\t\t\t\t-data.targetWidth :\n\t\t\t\t\t\t0,\n\t\t\t\toffset = -2 * data.offset[ 0 ],\n\t\t\t\tnewOverRight,\n\t\t\t\tnewOverLeft;\n\n\t\t\tif ( overLeft < 0 ) {\n\t\t\t\tnewOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -\n\t\t\t\t\touterWidth - withinOffset;\n\t\t\t\tif ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {\n\t\t\t\t\tposition.left += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t} else if ( overRight > 0 ) {\n\t\t\t\tnewOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +\n\t\t\t\t\tatOffset + offset - offsetLeft;\n\t\t\t\tif ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {\n\t\t\t\t\tposition.left += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\ttop: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.offset.top + within.scrollTop,\n\t\t\t\touterHeight = within.height,\n\t\t\t\toffsetTop = within.isWindow ? within.scrollTop : within.offset.top,\n\t\t\t\tcollisionPosTop = position.top - data.collisionPosition.marginTop,\n\t\t\t\toverTop = collisionPosTop - offsetTop,\n\t\t\t\toverBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,\n\t\t\t\ttop = data.my[ 1 ] === \"top\",\n\t\t\t\tmyOffset = top ?\n\t\t\t\t\t-data.elemHeight :\n\t\t\t\t\tdata.my[ 1 ] === \"bottom\" ?\n\t\t\t\t\t\tdata.elemHeight :\n\t\t\t\t\t\t0,\n\t\t\t\tatOffset = data.at[ 1 ] === \"top\" ?\n\t\t\t\t\tdata.targetHeight :\n\t\t\t\t\tdata.at[ 1 ] === \"bottom\" ?\n\t\t\t\t\t\t-data.targetHeight :\n\t\t\t\t\t\t0,\n\t\t\t\toffset = -2 * data.offset[ 1 ],\n\t\t\t\tnewOverTop,\n\t\t\t\tnewOverBottom;\n\t\t\tif ( overTop < 0 ) {\n\t\t\t\tnewOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -\n\t\t\t\t\touterHeight - withinOffset;\n\t\t\t\tif ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {\n\t\t\t\t\tposition.top += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t} else if ( overBottom > 0 ) {\n\t\t\t\tnewOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +\n\t\t\t\t\toffset - offsetTop;\n\t\t\t\tif ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {\n\t\t\t\t\tposition.top += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tflipfit: {\n\t\tleft: function() {\n\t\t\t$.ui.position.flip.left.apply( this, arguments );\n\t\t\t$.ui.position.fit.left.apply( this, arguments );\n\t\t},\n\t\ttop: function() {\n\t\t\t$.ui.position.flip.top.apply( this, arguments );\n\t\t\t$.ui.position.fit.top.apply( this, arguments );\n\t\t}\n\t}\n};\n\n} )();\n\nvar position = $.ui.position;\n\n\n/*!\n * jQuery UI Keycode 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Keycode\n//>>group: Core\n//>>description: Provide keycodes as keynames\n//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/\n\n\nvar keycode = $.ui.keyCode = {\n\tBACKSPACE: 8,\n\tCOMMA: 188,\n\tDELETE: 46,\n\tDOWN: 40,\n\tEND: 35,\n\tENTER: 13,\n\tESCAPE: 27,\n\tHOME: 36,\n\tLEFT: 37,\n\tPAGE_DOWN: 34,\n\tPAGE_UP: 33,\n\tPERIOD: 190,\n\tRIGHT: 39,\n\tSPACE: 32,\n\tTAB: 9,\n\tUP: 38\n};\n\n\n/*!\n * jQuery UI Scroll Parent 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: scrollParent\n//>>group: Core\n//>>description: Get the closest ancestor element that is scrollable.\n//>>docs: http://api.jqueryui.com/scrollParent/\n\n\n\nvar scrollParent = $.fn.scrollParent = function( includeHidden ) {\n\tvar position = this.css( \"position\" ),\n\t\texcludeStaticParent = position === \"absolute\",\n\t\toverflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,\n\t\tscrollParent = this.parents().filter( function() {\n\t\t\tvar parent = $( this );\n\t\t\tif ( excludeStaticParent && parent.css( \"position\" ) === \"static\" ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn overflowRegex.test( parent.css( \"overflow\" ) + parent.css( \"overflow-y\" ) +\n\t\t\t\tparent.css( \"overflow-x\" ) );\n\t\t} ).eq( 0 );\n\n\treturn position === \"fixed\" || !scrollParent.length ?\n\t\t$( this[ 0 ].ownerDocument || document ) :\n\t\tscrollParent;\n};\n\n\n/*!\n * jQuery UI Unique ID 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: uniqueId\n//>>group: Core\n//>>description: Functions to generate and remove uniqueId's\n//>>docs: http://api.jqueryui.com/uniqueId/\n\n\n\nvar uniqueId = $.fn.extend( {\n\tuniqueId: ( function() {\n\t\tvar uuid = 0;\n\n\t\treturn function() {\n\t\t\treturn this.each( function() {\n\t\t\t\tif ( !this.id ) {\n\t\t\t\t\tthis.id = \"ui-id-\" + ( ++uuid );\n\t\t\t\t}\n\t\t\t} );\n\t\t};\n\t} )(),\n\n\tremoveUniqueId: function() {\n\t\treturn this.each( function() {\n\t\t\tif ( /^ui-id-\\d+$/.test( this.id ) ) {\n\t\t\t\t$( this ).removeAttr( \"id\" );\n\t\t\t}\n\t\t} );\n\t}\n} );\n\n\n}));\n","/* global WP_Smush */\n/* global ajaxurl */\n\n/**\n * CDN functionality.\n *\n * @since 3.0\n */\n( function() {\n\t'use strict';\n\n\tWP_Smush.CDN = {\n\t\tcdnEnableButton: document.getElementById( 'smush-enable-cdn' ),\n\t\tcdnDisableButton: document.getElementById( 'smush-cancel-cdn' ),\n\t\tcdnStatsBox: document.querySelector( '.smush-cdn-stats' ),\n\n\t\tinit() {\n\t\t\t/**\n\t\t\t * Handle \"Get Started\" button click on disabled CDN page.\n\t\t\t */\n\t\t\tif ( this.cdnEnableButton ) {\n\t\t\t\tthis.cdnEnableButton.addEventListener( 'click', ( e ) => {\n\t\t\t\t\te.currentTarget.classList.add( 'sui-button-onload' );\n\n\t\t\t\t\t// Force repaint of the spinner.\n\t\t\t\t\tconst loader = e.currentTarget.querySelector( '.sui-icon-loader' );\n\t\t\t\t\tloader.style.display = 'none';\n\t\t\t\t\tloader.style.display = 'flex';\n\n\t\t\t\t\tthis.toggle_cdn( true );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Handle \"Deactivate' button click on CDN page.\n\t\t\t */\n\t\t\tif ( this.cdnDisableButton ) {\n\t\t\t\tthis.cdnDisableButton.addEventListener( 'click', ( e ) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tthis.toggle_cdn( false );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tthis.updateStatsBox();\n\t\t},\n\n\t\t/**\n\t\t * Toggle CDN.\n\t\t *\n\t\t * @since 3.0\n\t\t *\n\t\t * @param {boolean} enable\n\t\t */\n\t\ttoggle_cdn( enable ) {\n\t\t\tconst nonceField = document.getElementsByName( 'wp_smush_options_nonce' );\n\n\t\t\tconst xhr = new XMLHttpRequest();\n\t\t\txhr.open( 'POST', ajaxurl + '?action=smush_toggle_cdn', true );\n\t\t\txhr.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' );\n\t\t\txhr.onload = () => {\n\t\t\t\tif ( 200 === xhr.status ) {\n\t\t\t\t\tconst res = JSON.parse( xhr.response );\n\t\t\t\t\tif ( 'undefined' !== typeof res.success && res.success ) {\n\t\t\t\t\t\tlocation.reload();\n\t\t\t\t\t} else if ( 'undefined' !== typeof res.data.message ) {\n\t\t\t\t\t\tthis.showNotice( res.data.message );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.showNotice( 'Request failed. Returned status of ' + xhr.status );\n\t\t\t\t}\n\t\t\t};\n\t\t\txhr.send( 'param=' + enable + '&_ajax_nonce=' + nonceField[ 0 ].value );\n\t\t},\n\n\t\t/**\n\t\t * Show message (notice).\n\t\t *\n\t\t * @since 3.0\n\t\t *\n\t\t * @param {string} message\n\t\t */\n\t\tshowNotice( message ) {\n\t\t\tif ( 'undefined' === typeof message ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst notice = document.getElementById( 'wp-smush-ajax-notice' );\n\n\t\t\tnotice.classList.add( 'sui-notice-error' );\n\t\t\tnotice.innerHTML = `<p>${ message }</p>`;\n\n\t\t\tif ( this.cdnEnableButton ) {\n\t\t\t\tthis.cdnEnableButton.classList.remove( 'sui-button-onload' );\n\t\t\t}\n\n\t\t\tnotice.style.display = 'block';\n\t\t\tsetTimeout( () => {\n\t\t\t\tnotice.style.display = 'none';\n\t\t\t}, 5000 );\n\t\t},\n\n\t\t/**\n\t\t * Update the CDN stats box in summary meta box. Only fetch new data when on CDN page.\n\t\t *\n\t\t * @since 3.0\n\t\t */\n\t\tupdateStatsBox() {\n\t\t\tif ( 'undefined' === typeof this.cdnStatsBox || ! this.cdnStatsBox ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Only fetch the new stats, when user is on CDN page.\n\t\t\tif ( ! window.location.search.includes( 'view=cdn' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.toggleElements();\n\n\t\t\tconst xhr = new XMLHttpRequest();\n\t\t\txhr.open( 'POST', ajaxurl + '?action=get_cdn_stats', true );\n\t\t\txhr.onload = () => {\n\t\t\t\tif ( 200 === xhr.status ) {\n\t\t\t\t\tconst res = JSON.parse( xhr.response );\n\t\t\t\t\tif ( 'undefined' !== typeof res.success && res.success ) {\n\t\t\t\t\t\tthis.toggleElements();\n\t\t\t\t\t} else if ( 'undefined' !== typeof res.data.message ) {\n\t\t\t\t\t\tthis.showNotice( res.data.message );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.showNotice( 'Request failed. Returned status of ' + xhr.status );\n\t\t\t\t}\n\t\t\t};\n\t\t\txhr.send();\n\t\t},\n\n\t\t/**\n\t\t * Show/hide elements during status update in the updateStatsBox()\n\t\t *\n\t\t * @since 3.1  Moved out from updateStatsBox()\n\t\t */\n\t\ttoggleElements() {\n\t\t\tconst spinner = this.cdnStatsBox.querySelector( '.sui-icon-loader' );\n\t\t\tconst elements = this.cdnStatsBox.querySelectorAll( '.wp-smush-stats > :not(.sui-icon-loader)' );\n\n\t\t\tfor ( let i = 0; i < elements.length; i++ ) {\n\t\t\t\telements[ i ].classList.toggle( 'sui-hidden' );\n\t\t\t}\n\n\t\t\tspinner.classList.toggle( 'sui-hidden' );\n\t\t},\n\n\t};\n\n\tWP_Smush.CDN.init();\n}() );\n","/* global WP_Smush */\n/* global ajaxurl */\n\n/**\n * Lazy loading functionality.\n *\n * @since 3.0\n */\n( function() {\n\t'use strict';\n\n\tWP_Smush.Lazyload = {\n\t\tlazyloadEnableButton: document.getElementById( 'smush-enable-lazyload' ),\n\t\tlazyloadDisableButton: document.getElementById( 'smush-cancel-lazyload' ),\n\n\t\tinit() {\n\t\t\tconst self = this;\n\n\t\t\t/**\n\t\t\t * Handle \"Activate\" button click on disabled Lazy load page.\n\t\t\t */\n\t\t\tif ( this.lazyloadEnableButton ) {\n\t\t\t\tthis.lazyloadEnableButton.addEventListener( 'click', ( e ) => {\n\t\t\t\t\te.currentTarget.classList.add( 'sui-button-onload' );\n\n\t\t\t\t\t// Force repaint of the spinner.\n\t\t\t\t\tconst loader = e.currentTarget.querySelector( '.sui-icon-loader' );\n\t\t\t\t\tloader.style.display = 'none';\n\t\t\t\t\tloader.offsetHeight;\n\t\t\t\t\tloader.style.display = 'flex';\n\n\t\t\t\t\tthis.toggle_lazy_load( true );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Handle \"Deactivate' button click on Lazy load page.\n\t\t\t */\n\t\t\tif ( this.lazyloadDisableButton ) {\n\t\t\t\tthis.lazyloadDisableButton.addEventListener( 'click', ( e ) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tthis.toggle_lazy_load( false );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Handle \"Remove icon\" button click on Lazy load page.\n\t\t\t *\n\t\t\t * This removes the image from the upload placeholder.\n\t\t\t *\n\t\t\t * @since 3.2.2\n\t\t\t */\n\t\t\tconst removeSpinner = document.getElementById( 'smush-remove-spinner' );\n\t\t\tif ( removeSpinner ) {\n\t\t\t\tremoveSpinner.addEventListener( 'click', ( e ) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tthis.removeLoaderIcon();\n\t\t\t\t} );\n\t\t\t}\n\t\t\tconst removePlaceholder = document.getElementById( 'smush-remove-placeholder' );\n\t\t\tif ( removePlaceholder ) {\n\t\t\t\tremovePlaceholder.addEventListener( 'click', ( e ) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tthis.removeLoaderIcon( 'placeholder' );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Handle \"Remove\" icon click.\n\t\t\t *\n\t\t\t * This removes the select icon from the list (not same as above functions).\n\t\t\t *\n\t\t\t * @since 3.2.2\n\t\t\t */\n\t\t\tconst items = document.querySelectorAll( '.smush-ll-remove' );\n\t\t\tif ( items && 0 < items.length ) {\n\t\t\t\titems.forEach( function( el ) {\n\t\t\t\t\tel.addEventListener( 'click', ( e ) => {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\te.target.closest( 'li' ).style.display = 'none';\n\t\t\t\t\t\tself.remove( e.target.dataset.id, e.target.dataset.type );\n\t\t\t\t\t} );\n\t\t\t\t} );\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Toggle lazy loading.\n\t\t *\n\t\t * @since 3.2.0\n\t\t *\n\t\t * @param {string} enable\n\t\t */\n\t\ttoggle_lazy_load( enable ) {\n\t\t\tconst nonceField = document.getElementsByName( 'wp_smush_options_nonce' );\n\n\t\t\tconst xhr = new XMLHttpRequest();\n\t\t\txhr.open( 'POST', ajaxurl + '?action=smush_toggle_lazy_load', true );\n\t\t\txhr.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' );\n\t\t\txhr.onload = () => {\n\t\t\t\tif ( 200 === xhr.status ) {\n\t\t\t\t\tconst res = JSON.parse( xhr.response );\n\t\t\t\t\tif ( 'undefined' !== typeof res.success && res.success ) {\n\t\t\t\t\t\tlocation.reload();\n\t\t\t\t\t} else if ( 'undefined' !== typeof res.data.message ) {\n\t\t\t\t\t\tthis.showNotice( res.data.message );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\twindow.console.log( 'Request failed.  Returned status of ' + xhr.status );\n\t\t\t\t}\n\t\t\t};\n\t\t\txhr.send( 'param=' + enable + '&_ajax_nonce=' + nonceField[ 0 ].value );\n\t\t},\n\n\t\t/**\n\t\t * Show message (notice).\n\t\t *\n\t\t * @since 3.0\n\t\t *\n\t\t * @param {string} message\n\t\t */\n\t\tshowNotice( message ) {\n\t\t\tif ( 'undefined' === typeof message ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst notice = document.getElementById( 'wp-smush-ajax-notice' );\n\n\t\t\tnotice.classList.add( 'sui-notice-error' );\n\t\t\tnotice.innerHTML = `<p>${ message }</p>`;\n\n\t\t\tif ( this.cdnEnableButton ) {\n\t\t\t\tthis.cdnEnableButton.classList.remove( 'sui-button-onload' );\n\t\t\t}\n\n\t\t\tnotice.style.display = 'block';\n\t\t\tsetTimeout( () => {\n\t\t\t\tnotice.style.display = 'none';\n\t\t\t}, 5000 );\n\t\t},\n\n\t\t/**\n\t\t * Add lazy load spinner icon.\n\t\t *\n\t\t * @since 3.2.2\n\t\t * @param {string} type  Accepts: spinner, placeholder.\n\t\t */\n\t\taddLoaderIcon( type = 'spinner' ) {\n\t\t\tlet frame;\n\n\t\t\t// If the media frame already exists, reopen it.\n\t\t\tif ( frame ) {\n\t\t\t\tframe.open();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Create a new media frame\n\t\t\tframe = wp.media( {\n\t\t\t\ttitle: 'Select or upload an icon',\n\t\t\t\tbutton: {\n\t\t\t\t\ttext: 'Select icon',\n\t\t\t\t},\n\t\t\t\tmultiple: false, // Set to true to allow multiple files to be selected\n\t\t\t} );\n\n\t\t\t// When an image is selected in the media frame...\n\t\t\tframe.on( 'select', function() {\n\t\t\t\t// Get media attachment details from the frame state\n\t\t\t\tconst attachment = frame.state().get( 'selection' ).first().toJSON();\n\n\t\t\t\t// Send the attachment URL to our custom image input field.\n\t\t\t\tconst imageIcon = document.getElementById( 'smush-' + type + '-icon-preview' );\n\t\t\t\timageIcon.style.backgroundImage = 'url(\"' + attachment.url + '\")';\n\t\t\t\timageIcon.style.display = 'block';\n\n\t\t\t\t// Send the attachment id to our hidden input\n\t\t\t\tdocument.getElementById( 'smush-' + type + '-icon-file' ).setAttribute( 'value', attachment.id );\n\n\t\t\t\t// Hide the add image link\n\t\t\t\tdocument.getElementById( 'smush-upload-' + type ).style.display = 'none';\n\n\t\t\t\t// Unhide the remove image link\n\t\t\t\tconst removeDiv = document.getElementById( 'smush-remove-' + type );\n\t\t\t\tremoveDiv.querySelector( 'span' ).innerHTML = attachment.filename;\n\t\t\t\tremoveDiv.style.display = 'block';\n\t\t\t} );\n\n\t\t\t// Finally, open the modal on click\n\t\t\tframe.open();\n\t\t},\n\n\t\t/**\n\t\t * Remove lazy load spinner icon.\n\t\t *\n\t\t * @since 3.2.2\n\t\t * @param {string} type  Accepts: spinner, placeholder.\n\t\t */\n\t\tremoveLoaderIcon: ( type = 'spinner' ) => {\n\t\t\t// Clear out the preview image\n\t\t\tconst imageIcon = document.getElementById( 'smush-' + type + '-icon-preview' );\n\t\t\timageIcon.style.backgroundImage = '';\n\t\t\timageIcon.style.display = 'none';\n\n\t\t\t// Un-hide the add image link\n\t\t\tdocument.getElementById( 'smush-upload-' + type ).style.display = 'block';\n\n\t\t\t// Hide the delete image link\n\t\t\tdocument.getElementById( 'smush-remove-' + type ).style.display = 'none';\n\n\t\t\t// Delete the image id from the hidden input\n\t\t\tdocument.getElementById( 'smush-' + type + '-icon-file' ).setAttribute( 'value', '' );\n\t\t},\n\n\t\t/**\n\t\t * Remove item.\n\t\t *\n\t\t * @param {number} id    Image ID.\n\t\t * @param {string} type  Accepts: spinner, placeholder.\n\t\t */\n\t\tremove: ( id, type = 'spinner' ) => {\n\t\t\tconst nonceField = document.getElementsByName( 'wp_smush_options_nonce' );\n\t\t\tconst xhr = new XMLHttpRequest();\n\t\t\txhr.open( 'POST', ajaxurl + '?action=smush_remove_icon', true );\n\t\t\txhr.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' );\n\t\t\txhr.send( 'id=' + id + '&type=' + type + '&_ajax_nonce=' + nonceField[ 0 ].value );\n\t\t},\n\t};\n\n\tWP_Smush.Lazyload.init();\n}() );\n","/* global WP_Smush */\n/* global ajaxurl */\n\n/**\n * Bulk restore JavaScript code.\n *\n * @since 3.2.2\n */\n( function() {\n\t'use strict';\n\n\t/**\n\t * Bulk restore modal.\n\t *\n\t * @since 3.2.2\n\t */\n\tWP_Smush.restore = {\n\t\tmodal: document.getElementById( 'smush-restore-images-dialog' ),\n\t\tcontentContainer: document.getElementById( 'smush-bulk-restore-content' ),\n\t\tsettings: {\n\t\t\tslide: 'start', // start, progress or finish.\n\t\t\tsuccess: 0,\n\t\t\terrors: [],\n\t\t},\n\t\titems: [], // total items, 1 item = 1 step.\n\t\tsuccess: [], // successful items restored.\n\t\terrors: [], // failed items.\n\t\tcurrentStep: 0,\n\t\ttotalSteps: 0,\n\n\t\t/**\n\t\t * Init module.\n\t\t */\n\t\tinit() {\n\t\t\tif ( ! this.modal ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.settings = {\n\t\t\t\tslide: 'start',\n\t\t\t\tsuccess: 0,\n\t\t\t\terrors: [],\n\t\t\t};\n\n\t\t\tthis.resetModalWidth();\n\t\t\tthis.renderTemplate();\n\n\t\t\t// Show the modal.\n\n\t\t\twindow.SUI.openModal( 'smush-restore-images-dialog', 'wpbody-content', undefined, false );\n\t\t},\n\n\t\t/**\n\t\t * Update the template, register new listeners.\n\t\t */\n\t\trenderTemplate() {\n\t\t\tconst template = WP_Smush.onboarding.template( 'smush-bulk-restore' );\n\t\t\tconst content = template( this.settings );\n\n\t\t\tif ( content ) {\n\t\t\t\tthis.contentContainer.innerHTML = content;\n\t\t\t}\n\n\t\t\tthis.bindSubmit();\n\t\t},\n\n\t\t/**\n\t\t * Reset modal width.\n\t\t * @since 3.6.0\n\t\t */\n\t\tresetModalWidth() {\n\t\t\tthis.modal.style.maxWidth = '460px';\n\t\t\tthis.modal.querySelector( '.sui-box' ).style.maxWidth = '460px';\n\t\t},\n\n\t\t/**\n\t\t * Catch \"Finish setup wizard\" button click.\n\t\t */\n\t\tbindSubmit() {\n\t\t\tconst confirmButton = this.modal.querySelector( 'button[id=\"smush-bulk-restore-button\"]' );\n\t\t\tconst self = this;\n\n\t\t\tif ( confirmButton ) {\n\t\t\t\tconfirmButton.addEventListener( 'click', function( e ) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tself.resetModalWidth();\n\n\t\t\t\t\tself.settings = { slide: 'progress' };\n\t\t\t\t\tself.errors = [];\n\n\t\t\t\t\tself.renderTemplate();\n\t\t\t\t\tself.initScan();\n\t\t\t\t} );\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Cancel the bulk restore.\n\t\t */\n\t\tcancel() {\n\t\t\tif ( 'start' === this.settings.slide || 'finish' === this.settings.slide ) {\n\t\t\t\t// Hide the modal.\n\t\t\t\twindow.SUI.closeModal();\n\t\t\t} else {\n\t\t\t\tthis.updateProgressBar( true );\n\t\t\t\twindow.location.reload();\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Update progress bar during directory smush.\n\t\t *\n\t\t * @param {boolean} cancel  Cancel status.\n\t\t */\n\t\tupdateProgressBar( cancel = false ) {\n\t\t\tlet progress = 0;\n\t\t\tif ( 0 < this.currentStep ) {\n\t\t\t\tprogress = Math.min( Math.round( this.currentStep * 100 / this.totalSteps ), 99 );\n\t\t\t}\n\n\t\t\tif ( progress > 100 ) {\n\t\t\t\tprogress = 100;\n\t\t\t}\n\n\t\t\t// Update progress bar\n\t\t\tthis.modal.querySelector( '.sui-progress-text span' ).innerHTML = progress + '%';\n\t\t\tthis.modal.querySelector( '.sui-progress-bar span' ).style.width = progress + '%';\n\n\t\t\tconst statusDiv = this.modal.querySelector( '.sui-progress-state-text' );\n\t\t\tif ( progress >= 90 ) {\n\t\t\t\tstatusDiv.innerHTML = 'Finalizing...';\n\t\t\t} else if ( cancel ) {\n\t\t\t\tstatusDiv.innerHTML = 'Cancelling...';\n\t\t\t} else {\n\t\t\t\tstatusDiv.innerHTML = this.currentStep + '/' + this.totalSteps + ' ' + 'images restored';\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * First step in bulk restore - get the bulk attachment count.\n\t\t */\n\t\tinitScan() {\n\t\t\tconst self = this;\n\t\t\tconst _nonce = document.getElementById( '_wpnonce' );\n\n\t\t\tconst xhr = new XMLHttpRequest();\n\t\t\txhr.open( 'POST', ajaxurl + '?action=get_image_count', true );\n\t\t\txhr.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' );\n\t\t\txhr.onload = () => {\n\t\t\t\tif ( 200 === xhr.status ) {\n\t\t\t\t\tconst res = JSON.parse( xhr.response );\n\t\t\t\t\tif ( 'undefined' !== typeof res.data.items ) {\n\t\t\t\t\t\tself.items = res.data.items;\n\t\t\t\t\t\tself.totalSteps = res.data.items.length;\n\t\t\t\t\t\tself.step();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\twindow.console.log( 'Request failed.  Returned status of ' + xhr.status );\n\t\t\t\t}\n\t\t\t};\n\t\t\txhr.send( '_ajax_nonce=' + _nonce.value );\n\t\t},\n\n\t\t/**\n\t\t * Execute a scan step recursively\n\t\t */\n\t\tstep() {\n\t\t\tconst self = this;\n\t\t\tconst _nonce = document.getElementById( '_wpnonce' );\n\n\t\t\tif ( 0 < this.items.length ) {\n\t\t\t\tconst item = this.items.pop();\n\t\t\t\tconst xhr = new XMLHttpRequest();\n\t\t\t\txhr.open( 'POST', ajaxurl + '?action=restore_step', true );\n\t\t\t\txhr.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' );\n\t\t\t\txhr.onload = () => {\n\t\t\t\t\tthis.currentStep++;\n\n\t\t\t\t\tif ( 200 === xhr.status ) {\n\t\t\t\t\t\tconst res = JSON.parse( xhr.response );\n\t\t\t\t\t\tif ( 'undefined' !== typeof res.data.success && res.data.success ) {\n\t\t\t\t\t\t\tself.success.push( item );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.errors.push( {\n\t\t\t\t\t\t\t\tid: item,\n\t\t\t\t\t\t\t\tsrc: res.data.src,\n\t\t\t\t\t\t\t\tthumb: res.data.thumb,\n\t\t\t\t\t\t\t\tlink: res.data.link,\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\tself.updateProgressBar();\n\t\t\t\t\tself.step();\n\t\t\t\t};\n\t\t\t\txhr.send( 'item=' + item + '&_ajax_nonce=' + _nonce.value );\n\t\t\t} else {\n\t\t\t\t// Finish.\n\t\t\t\tthis.settings = {\n\t\t\t\t\tslide: 'finish',\n\t\t\t\t\tsuccess: this.success.length,\n\t\t\t\t\terrors: this.errors,\n\t\t\t\t\ttotal: this.totalSteps,\n\t\t\t\t};\n\n\t\t\t\tself.renderTemplate();\n\t\t\t\tif ( 0 < this.errors.length ) {\n\t\t\t\t\tthis.modal.style.maxWidth = '660px';\n\t\t\t\t\tthis.modal.querySelector( '.sui-box' ).style.maxWidth = '660px';\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n\n\t/**\n\t * Template function (underscores based).\n\t *\n\t * @type {Function}\n\t */\n\tWP_Smush.restore.template = _.memoize( ( id ) => {\n\t\tlet compiled;\n\t\tconst options = {\n\t\t\tevaluate: /<#([\\s\\S]+?)#>/g,\n\t\t\tinterpolate: /{{{([\\s\\S]+?)}}}/g,\n\t\t\tescape: /{{([^}]+?)}}(?!})/g,\n\t\t\tvariable: 'data',\n\t\t};\n\n\t\treturn ( data ) => {\n\t\t\t_.templateSettings = options;\n\t\t\tcompiled = compiled || _.template( document.getElementById( id ).innerHTML );\n\t\t\treturn compiled( data );\n\t\t};\n\t} );\n}() );\n","/* global ajaxurl */\n\n/**\n * @typedef {Object} jQuery\n */\n( function( $ ) {\n\tlet elNotice = $( '.smush-notice' );\n\tconst btnAct = elNotice.find( '.smush-notice-act' );\n\n\telNotice.fadeIn( 500 );\n\n\t// Hide the notice after a CTA button was clicked\n\tfunction removeNotice() {\n\t\telNotice.fadeTo( 100, 0, () => elNotice.slideUp( 100, () => elNotice.remove() ) );\n\t}\n\n\tbtnAct.on( 'click', () => {\n\t\tremoveNotice();\n\t\tnotifyWordpress( btnAct.data( 'msg' ) );\n\t} );\n\n\telNotice.find( '.smush-notice-dismiss' ).on( 'click', () => {\n\t\tremoveNotice();\n\t\tnotifyWordpress( btnAct.data( 'msg' ) );\n\t} );\n\n\t// Notify WordPress about the users choice and close the message.\n\tfunction notifyWordpress( message ) {\n\t\telNotice.attr( 'data-message', message );\n\t\telNotice.addClass( 'loading' );\n\n\t\t//Send a ajax request to save the dismissed notice option\n\t\t$.post( ajaxurl, { action: 'dismiss_upgrade_notice' } );\n\t}\n\n\t// Dismiss the update notice.\n\t$( '.wp-smush-update-info' ).on( 'click', '.notice-dismiss', ( e ) => {\n\t\te.preventDefault();\n\t\telNotice = $( this );\n\t\tremoveNotice();\n\t\t$.post( ajaxurl, { action: 'dismiss_update_info' } );\n\t} );\n\n\t// Dismiss S3 support alert.\n\t$( 'div.wp-smush-s3support-alert' ).on( 'click', '.sui-notice-dismiss > a', () => {\n\t\telNotice = $( this );\n\t\tremoveNotice();\n\t\t$.post( ajaxurl, { action: 'dismiss_s3support_alert' } );\n\t} );\n}( jQuery ) );\n","/* global WP_Smush */\n/* global ajaxurl */\n\n/**\n * Directory Smush module JavaScript code.\n *\n * @since 2.8.1  Separated from admin.js into dedicated file.\n */\n\nimport { createTree } from 'jquery.fancytree';\nimport Scanner from '../smush/directory-scanner';\n\n( function( $ ) {\n\t'use strict';\n\n\tWP_Smush.directory = {\n\t\tselected: [],\n\t\ttree: [],\n\t\twp_smush_msgs: [],\n\n\t\tinit() {\n\t\t\tconst self = this,\n\t\t\t\tprogressDialog = $( '#wp-smush-progress-dialog' );\n\n\t\t\tlet totalSteps = 0,\n\t\t\t\tcurrentScanStep = 0;\n\n\t\t\t// Make sure directory smush vars are set.\n\t\t\tif ( typeof window.wp_smushit_data.dir_smush !== 'undefined' ) {\n\t\t\t\ttotalSteps = window.wp_smushit_data.dir_smush.totalSteps;\n\t\t\t\tcurrentScanStep = window.wp_smushit_data.dir_smush.currentScanStep;\n\t\t\t}\n\n\t\t\t// Init image scanner.\n\t\t\tthis.scanner = new Scanner( totalSteps, currentScanStep );\n\n\t\t\t/**\n\t\t\t * Smush translation strings.\n\t\t\t *\n\t\t\t * @param {Array} wp_smush_msgs\n\t\t\t */\n\t\t\tthis.wp_smush_msgs = window.wp_smush_msgs || {};\n\n\t\t\t/**\n\t\t\t * Folder select: Choose Folder in Directory Smush tab clicked.\n\t\t\t */\n\t\t\t$( 'div.sui-wrap' ).on( 'click', 'button.wp-smush-browse', function( e ) {\n\t\t\t\te.preventDefault();\n\n\t\t\t\t// Hide all the notices.\n\t\t\t\t$( 'div.wp-smush-scan-result div.wp-smush-notice' ).hide();\n\n\t\t\t\t// Remove notice.\n\t\t\t\t$( 'div.wp-smush-info' ).remove();\n\n\t\t\t\t// Display file tree for directory Smush.\n\t\t\t\tself.initFileTree();\n\t\t\t} );\n\n\t\t\t/**\n\t\t\t * Stats section: Directory Link\n\t\t\t */\n\t\t\t$( 'body' ).on( 'click', 'a.wp-smush-dir-link', function( e ) {\n\t\t\t\tif ( $( 'div.sui-wrap button.wp-smush-browse' ).length > 0 ) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\twindow.SUI.openModal( 'wp-smush-list-dialog', 'dialog-close-div', undefined, false );\n\t\t\t\t\t//Display File tree for Directory Smush\n\t\t\t\t\tself.initFileTree();\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t/**\n\t\t\t * Smush images: Smush in Choose Directory modal clicked\n\t\t\t */\n\t\t\t$( '.wp-smush-select-dir' ).on( 'click', function( e ) {\n\t\t\t\te.preventDefault();\n\n\t\t\t\t// If disabled, do not process\n\t\t\t\tif ( $( this ).attr( 'disabled' ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst button = $( this );\n\n\t\t\t\t$( 'div.wp-smush-list-dialog div.sui-box-body' ).css( { opacity: '0.8' } );\n\t\t\t\t$( 'div.wp-smush-list-dialog div.sui-box-body a' ).unbind( 'click' );\n\n\t\t\t\t// Disable button\n\t\t\t\tbutton.attr( 'disabled', 'disabled' );\n\n\t\t\t\tconst spinner = button.parent().find( '.add-dir-loader' );\n\t\t\t\t// Display the spinner\n\t\t\t\tspinner.addClass( 'sui-icon-loader sui-loading' );\n\n\t\t\t\tconst selectedFolders = self.tree.getSelectedNodes(),\n\t\t\t\t\tabsPath = $( 'input[name=\"wp-smush-base-path\"]' ).val(); // Absolute path.\n\n\t\t\t\tconst paths = [];\n\t\t\t\tselectedFolders.forEach( function( folder ) {\n\t\t\t\t\tpaths.push( absPath + '/' + folder.key );\n\t\t\t\t} );\n\n\t\t\t\t// Send a ajax request to get a list of all the image files\n\t\t\t\tconst param = {\n\t\t\t\t\taction: 'image_list',\n\t\t\t\t\tsmush_path: paths,\n\t\t\t\t\timage_list_nonce: $( 'input[name=\"image_list_nonce\"]' ).val(),\n\t\t\t\t};\n\n\t\t\t\t$.get( ajaxurl, param, function( response ) {\n\t\t\t\t\twindow.SUI.closeModal();\n\n\t\t\t\t\t// TODO: check for errors.\n\t\t\t\t\tself.scanner = new Scanner( response.data, 0 );\n\t\t\t\t\tself.showProgressDialog( response.data );\n\t\t\t\t\tself.scanner.scan();\n\t\t\t\t} );\n\t\t\t} );\n\n\t\t\t/**\n\t\t\t * On dialog close make browse button active.\n\t\t\t */\n\t\t\t$( '#wp-smush-list-dialog' ).on( 'click', '.sui-dialog-close', function() {\n\t\t\t\t$( '.wp-smush-browse' ).removeAttr( 'disabled' );\n\n\t\t\t\t// Close the dialog.\n\t\t\t\twindow.SUI.closeModal();\n\n\t\t\t\t$( '.wp-smush-select-dir, button.wp-smush-browse, a.wp-smush-dir-link' ).removeAttr( 'disabled' );\n\n\t\t\t\t// Reset the opacity for content and scan button\n\t\t\t\t$( '.wp-smush-select-dir, .wp-smush-list-dialog .sui-box-body' ).css( { opacity: '1' } );\n\t\t\t} );\n\n\t\t\t/**\n\t\t\t * Cancel scan.\n\t\t\t */\n\t\t\tprogressDialog.on( 'click', '#cancel-directory-smush, .sui-dialog-close, .wp-smush-cancel-dir', function( e ) {\n\t\t\t\te.preventDefault();\n\t\t\t\t// Display the spinner\n\t\t\t\t$( this ).parent().find( '.add-dir-loader' ).addClass( 'sui-icon-loader sui-loading' );\n\t\t\t\tself.scanner.cancel().done( () => window.location.href = self.wp_smush_msgs.directory_url );\n\t\t\t} );\n\n\t\t\t/**\n\t\t\t * Continue scan.\n\t\t\t */\n\t\t\tprogressDialog.on( 'click', '.sui-icon-play, .wp-smush-resume-scan', function( e ) {\n\t\t\t\te.preventDefault();\n\t\t\t\tself.scanner.resume();\n\t\t\t} );\n\t\t},\n\n\t\t/**\n\t\t * Init fileTree.\n\t\t */\n\t\tinitFileTree() {\n\t\t\tconst self = this,\n\t\t\t\tsmushButton = $( 'button.wp-smush-select-dir' ),\n\t\t\t\tajaxSettings = {\n\t\t\t\t\ttype: 'GET',\n\t\t\t\t\turl: ajaxurl,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taction: 'smush_get_directory_list',\n\t\t\t\t\t\tlist_nonce: $( 'input[name=\"list_nonce\"]' ).val(),\n\t\t\t\t\t},\n\t\t\t\t\tcache: false,\n\t\t\t\t};\n\n\t\t\t// Object already defined.\n\t\t\tif ( Object.entries( self.tree ).length > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tself.tree = createTree( '.wp-smush-list-dialog .content', {\n\t\t\t\tautoCollapse: true, // Automatically collapse all siblings, when a node is expanded\n\t\t\t\tclickFolderMode: 3, // 1:activate, 2:expand, 3:activate and expand, 4:activate (dblclick expands)\n\t\t\t\tcheckbox: true, // Show checkboxes\n\t\t\t\tdebugLevel: 0, // 0:quiet, 1:errors, 2:warnings, 3:infos, 4:debug\n\t\t\t\tselectMode: 3, // 1:single, 2:multi, 3:multi-hier\n\t\t\t\ttabindex: '0', // Whole tree behaves as one single control\n\t\t\t\tkeyboard: true, // Support keyboard navigation\n\t\t\t\tquicksearch: true, // Navigate to next node by typing the first letters\n\t\t\t\tsource: ajaxSettings,\n\t\t\t\tlazyLoad: ( event, data ) => {\n\t\t\t\t\tdata.result = new Promise( function( resolve, reject ) {\n\t\t\t\t\t\tajaxSettings.data.dir = data.node.key;\n\t\t\t\t\t\t$.ajax( ajaxSettings )\n\t\t\t\t\t\t\t.done( ( response ) => resolve( response ) )\n\t\t\t\t\t\t\t.fail( reject );\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Update the button text.\n\t\t\t\t\tdata.result.then( smushButton.html( self.wp_smush_msgs.add_dir ) );\n\t\t\t\t},\n\t\t\t\tloadChildren: ( event, data ) => data.node.fixSelection3AfterClick(), // Apply parent's state to new child nodes:\n\t\t\t\tselect: () => smushButton.attr( 'disabled', ! +self.tree.getSelectedNodes().length ),\n\t\t\t\tinit: () => smushButton.attr( 'disabled', true ),\n\t\t\t} );\n\t\t},\n\n\t\t/**\n\t\t * Show progress dialog.\n\t\t *\n\t\t * @param {number} items  Number of items in the scan.\n\t\t */\n\t\tshowProgressDialog( items ) {\n\t\t\t// Update items status and show the progress dialog..\n\t\t\t$( '.wp-smush-progress-dialog .sui-progress-state-text' ).html( '0/' + items + ' ' + self.wp_smush_msgs.progress_smushed );\n\n\t\t\twindow.SUI.openModal( 'wp-smush-progress-dialog', 'dialog-close-div', undefined, false );\n\t\t},\n\n\t\t/**\n\t\t * Update progress bar during directory smush.\n\t\t *\n\t\t * @param {number}  progress  Current progress in percent.\n\t\t * @param {boolean} cancel    Cancel status.\n\t\t */\n\t\tupdateProgressBar( progress, cancel = false ) {\n\t\t\tif ( progress > 100 ) {\n\t\t\t\tprogress = 100;\n\t\t\t}\n\n\t\t\t// Update progress bar\n\t\t\t$( '.sui-progress-block .sui-progress-text span' ).text( progress + '%' );\n\t\t\t$( '.sui-progress-block .sui-progress-bar span' ).width( progress + '%' );\n\n\t\t\tif ( progress >= 90 ) {\n\t\t\t\t$( '.sui-progress-state .sui-progress-state-text' ).text( 'Finalizing...' );\n\t\t\t}\n\n\t\t\tif ( cancel ) {\n\t\t\t\t$( '.sui-progress-state .sui-progress-state-text' ).text( 'Cancelling...' );\n\t\t\t}\n\t\t},\n\n\t};\n\n\tWP_Smush.directory.init();\n}( jQuery ) );\n","/* global WP_Smush */\n/* global ajaxurl */\n\n/**\n * Directory scanner module that will Smush images in the Directory Smush modal.\n *\n * @since 2.8.1\n *\n * @param {string|number} totalSteps\n * @param {string|number} currentStep\n * @return {Object}  Scan object.\n * @class\n */\nconst DirectoryScanner = ( totalSteps, currentStep ) => {\n\ttotalSteps = parseInt( totalSteps );\n\tcurrentStep = parseInt( currentStep );\n\n\tlet cancelling = false,\n\t\tfailedItems = 0;\n\n\tconst obj = {\n\t\tscan() {\n\t\t\tconst remainingSteps = totalSteps - currentStep;\n\t\t\tif ( currentStep !== 0 ) {\n\t\t\t\t// Scan started on a previous page load.\n\t\t\t\tstep( remainingSteps );\n\t\t\t} else {\n\t\t\t\tjQuery.post( ajaxurl, { action: 'directory_smush_start' },\n\t\t\t\t\t() => step( remainingSteps ) );\n\t\t\t}\n\t\t},\n\n\t\tcancel() {\n\t\t\tcancelling = true;\n\t\t\treturn jQuery.post( ajaxurl, { action: 'directory_smush_cancel' } );\n\t\t},\n\n\t\tgetProgress() {\n\t\t\tif ( cancelling ) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\t// O M G ... Logic at it's finest!\n\t\t\tconst remainingSteps = totalSteps - currentStep;\n\t\t\treturn Math.min( Math.round( ( parseInt( ( totalSteps - remainingSteps ) ) * 100 ) / totalSteps ), 99 );\n\t\t},\n\n\t\tonFinishStep( progress ) {\n\t\t\tjQuery( '.wp-smush-progress-dialog .sui-progress-state-text' ).html( ( currentStep - failedItems ) + '/' + totalSteps + ' ' + window.wp_smush_msgs.progress_smushed );\n\t\t\tWP_Smush.directory.updateProgressBar( progress );\n\t\t},\n\n\t\tonFinish() {\n\t\t\tWP_Smush.directory.updateProgressBar( 100 );\n\t\t\twindow.location.href = window.wp_smush_msgs.directory_url + '&scan=done';\n\t\t},\n\n\t\tlimitReached() {\n\t\t\tconst dialog = jQuery( '#wp-smush-progress-dialog' );\n\n\t\t\tdialog.addClass( 'wp-smush-exceed-limit' );\n\t\t\tdialog.find( '#cancel-directory-smush' ).attr( 'data-tooltip', window.wp_smush_msgs.bulk_resume );\n\t\t\tdialog.find( '.sui-icon-close' ).removeClass( 'sui-icon-close' ).addClass( 'sui-icon-play' );\n\t\t\tdialog.find( '#cancel-directory-smush' ).attr( 'id', 'cancel-directory-smush-disabled' );\n\t\t},\n\n\t\tresume() {\n\t\t\tconst dialog = jQuery( '#wp-smush-progress-dialog' );\n\t\t\tconst resume = dialog.find( '#cancel-directory-smush-disabled' );\n\n\t\t\tdialog.removeClass( 'wp-smush-exceed-limit' );\n\t\t\tdialog.find( '.sui-icon-play' ).removeClass( 'sui-icon-play' ).addClass( 'sui-icon-close' );\n\t\t\tresume.attr( 'data-tooltip', 'Cancel' );\n\t\t\tresume.attr( 'id', 'cancel-directory-smush' );\n\n\t\t\tobj.scan();\n\t\t},\n\t};\n\n\t/**\n\t * Execute a scan step recursively\n\t *\n\t * Private to avoid overriding\n\t *\n\t * @param {number} remainingSteps\n\t */\n\tconst step = function( remainingSteps ) {\n\t\tif ( remainingSteps >= 0 ) {\n\t\t\tcurrentStep = totalSteps - remainingSteps;\n\t\t\tjQuery.post( ajaxurl, {\n\t\t\t\taction: 'directory_smush_check_step',\n\t\t\t\tstep: currentStep,\n\t\t\t}, ( response ) => {\n\t\t\t\t// We're good - continue on.\n\t\t\t\tif ( 'undefined' !== typeof response.success && response.success ) {\n\t\t\t\t\tcurrentStep++;\n\t\t\t\t\tremainingSteps = remainingSteps - 1;\n\t\t\t\t\tobj.onFinishStep( obj.getProgress() );\n\t\t\t\t\tstep( remainingSteps );\n\t\t\t\t} else if ( 'undefined' !== typeof response.data.error && 'dir_smush_limit_exceeded' === response.data.error ) {\n\t\t\t\t\t// Limit reached. Stop.\n\t\t\t\t\tobj.limitReached();\n\t\t\t\t} else {\n\t\t\t\t\t// Error? never mind, continue, but count them.\n\t\t\t\t\tfailedItems++;\n\t\t\t\t\tcurrentStep++;\n\t\t\t\t\tremainingSteps = remainingSteps - 1;\n\t\t\t\t\tobj.onFinishStep( obj.getProgress() );\n\t\t\t\t\tstep( remainingSteps );\n\t\t\t\t}\n\t\t\t} );\n\t\t} else {\n\t\t\tjQuery.post( ajaxurl, {\n\t\t\t\taction: 'directory_smush_finish',\n\t\t\t\titems: ( totalSteps - failedItems ),\n\t\t\t\tfailed: failedItems,\n\t\t\t}, ( response ) => obj.onFinish( response ) );\n\t\t}\n\t};\n\n\treturn obj;\n};\n\nexport default DirectoryScanner;\n"],"sourceRoot":""}