| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284232852328623287232882328923290232912329223293232942329523296232972329823299233002330123302233032330423305233062330723308233092331023311233122331323314233152331623317233182331923320233212332223323233242332523326233272332823329233302333123332233332333423335233362333723338233392334023341233422334323344233452334623347233482334923350233512335223353233542335523356233572335823359233602336123362233632336423365233662336723368233692337023371233722337323374233752337623377233782337923380233812338223383233842338523386233872338823389233902339123392233932339423395233962339723398233992340023401234022340323404234052340623407234082340923410234112341223413234142341523416234172341823419234202342123422234232342423425234262342723428234292343023431234322343323434234352343623437234382343923440234412344223443234442344523446234472344823449234502345123452234532345423455234562345723458234592346023461234622346323464234652346623467234682346923470234712347223473234742347523476234772347823479234802348123482234832348423485234862348723488234892349023491234922349323494234952349623497234982349923500235012350223503235042350523506235072350823509235102351123512235132351423515235162351723518235192352023521235222352323524235252352623527235282352923530235312353223533235342353523536235372353823539235402354123542235432354423545235462354723548235492355023551235522355323554235552355623557235582355923560235612356223563235642356523566235672356823569235702357123572235732357423575235762357723578235792358023581235822358323584235852358623587235882358923590235912359223593235942359523596235972359823599236002360123602236032360423605236062360723608236092361023611236122361323614236152361623617236182361923620236212362223623236242362523626236272362823629236302363123632236332363423635236362363723638236392364023641236422364323644236452364623647236482364923650236512365223653236542365523656236572365823659236602366123662236632366423665236662366723668236692367023671236722367323674236752367623677236782367923680236812368223683236842368523686236872368823689236902369123692236932369423695236962369723698236992370023701237022370323704237052370623707237082370923710237112371223713237142371523716237172371823719237202372123722237232372423725237262372723728237292373023731237322373323734237352373623737237382373923740237412374223743237442374523746237472374823749237502375123752237532375423755237562375723758237592376023761237622376323764237652376623767237682376923770237712377223773237742377523776237772377823779237802378123782237832378423785237862378723788237892379023791237922379323794237952379623797237982379923800238012380223803238042380523806238072380823809238102381123812238132381423815238162381723818238192382023821238222382323824238252382623827238282382923830238312383223833238342383523836238372383823839238402384123842238432384423845238462384723848238492385023851238522385323854238552385623857238582385923860238612386223863238642386523866238672386823869238702387123872238732387423875238762387723878238792388023881238822388323884238852388623887238882388923890238912389223893238942389523896238972389823899239002390123902239032390423905239062390723908239092391023911239122391323914239152391623917239182391923920239212392223923239242392523926239272392823929239302393123932239332393423935239362393723938239392394023941239422394323944239452394623947239482394923950239512395223953239542395523956239572395823959239602396123962239632396423965239662396723968239692397023971239722397323974239752397623977239782397923980239812398223983239842398523986239872398823989239902399123992239932399423995239962399723998239992400024001240022400324004240052400624007240082400924010240112401224013240142401524016240172401824019240202402124022240232402424025240262402724028240292403024031240322403324034240352403624037240382403924040240412404224043240442404524046240472404824049240502405124052240532405424055240562405724058240592406024061240622406324064240652406624067240682406924070240712407224073240742407524076240772407824079240802408124082240832408424085240862408724088240892409024091240922409324094240952409624097240982409924100241012410224103241042410524106241072410824109241102411124112241132411424115241162411724118241192412024121241222412324124241252412624127241282412924130241312413224133241342413524136241372413824139241402414124142241432414424145241462414724148241492415024151241522415324154241552415624157241582415924160241612416224163241642416524166241672416824169241702417124172241732417424175241762417724178241792418024181241822418324184241852418624187241882418924190241912419224193241942419524196241972419824199242002420124202242032420424205242062420724208242092421024211242122421324214242152421624217242182421924220242212422224223242242422524226242272422824229242302423124232242332423424235242362423724238242392424024241242422424324244242452424624247242482424924250242512425224253242542425524256242572425824259242602426124262242632426424265242662426724268242692427024271242722427324274242752427624277242782427924280242812428224283242842428524286242872428824289242902429124292242932429424295242962429724298242992430024301243022430324304243052430624307243082430924310243112431224313243142431524316243172431824319243202432124322243232432424325243262432724328243292433024331243322433324334243352433624337243382433924340243412434224343243442434524346243472434824349243502435124352243532435424355243562435724358243592436024361243622436324364243652436624367243682436924370243712437224373243742437524376243772437824379243802438124382243832438424385243862438724388243892439024391243922439324394243952439624397243982439924400244012440224403244042440524406244072440824409244102441124412244132441424415244162441724418244192442024421244222442324424244252442624427244282442924430244312443224433244342443524436244372443824439244402444124442244432444424445244462444724448244492445024451244522445324454244552445624457244582445924460244612446224463244642446524466244672446824469244702447124472244732447424475244762447724478244792448024481244822448324484244852448624487244882448924490244912449224493244942449524496244972449824499245002450124502245032450424505245062450724508245092451024511245122451324514245152451624517245182451924520245212452224523245242452524526245272452824529245302453124532245332453424535245362453724538245392454024541245422454324544245452454624547245482454924550245512455224553245542455524556245572455824559245602456124562245632456424565245662456724568245692457024571245722457324574245752457624577245782457924580245812458224583245842458524586245872458824589245902459124592245932459424595245962459724598245992460024601246022460324604246052460624607246082460924610246112461224613246142461524616246172461824619246202462124622246232462424625246262462724628246292463024631246322463324634246352463624637246382463924640246412464224643246442464524646246472464824649246502465124652246532465424655246562465724658246592466024661246622466324664246652466624667246682466924670246712467224673246742467524676246772467824679246802468124682246832468424685246862468724688246892469024691246922469324694246952469624697246982469924700247012470224703247042470524706247072470824709247102471124712247132471424715247162471724718247192472024721247222472324724247252472624727247282472924730247312473224733247342473524736247372473824739247402474124742247432474424745247462474724748247492475024751247522475324754247552475624757247582475924760247612476224763247642476524766247672476824769247702477124772247732477424775247762477724778247792478024781247822478324784247852478624787247882478924790247912479224793247942479524796247972479824799248002480124802248032480424805248062480724808248092481024811248122481324814248152481624817248182481924820248212482224823248242482524826248272482824829248302483124832248332483424835248362483724838248392484024841248422484324844248452484624847248482484924850248512485224853248542485524856248572485824859248602486124862248632486424865248662486724868248692487024871248722487324874248752487624877248782487924880248812488224883248842488524886248872488824889248902489124892248932489424895248962489724898248992490024901249022490324904249052490624907249082490924910249112491224913249142491524916249172491824919249202492124922249232492424925249262492724928249292493024931249322493324934249352493624937249382493924940249412494224943249442494524946249472494824949249502495124952249532495424955249562495724958249592496024961249622496324964249652496624967249682496924970249712497224973249742497524976249772497824979249802498124982249832498424985249862498724988249892499024991249922499324994249952499624997249982499925000250012500225003250042500525006250072500825009250102501125012250132501425015250162501725018250192502025021250222502325024250252502625027250282502925030250312503225033250342503525036250372503825039250402504125042250432504425045250462504725048250492505025051250522505325054250552505625057250582505925060250612506225063250642506525066250672506825069250702507125072250732507425075250762507725078250792508025081250822508325084250852508625087250882508925090250912509225093250942509525096250972509825099251002510125102251032510425105251062510725108251092511025111251122511325114251152511625117251182511925120251212512225123251242512525126251272512825129251302513125132251332513425135251362513725138251392514025141251422514325144251452514625147251482514925150251512515225153251542515525156251572515825159251602516125162251632516425165251662516725168251692517025171251722517325174251752517625177251782517925180251812518225183251842518525186251872518825189251902519125192251932519425195251962519725198251992520025201252022520325204252052520625207252082520925210252112521225213252142521525216252172521825219252202522125222252232522425225252262522725228252292523025231252322523325234252352523625237252382523925240252412524225243252442524525246252472524825249252502525125252252532525425255252562525725258252592526025261252622526325264252652526625267252682526925270252712527225273252742527525276252772527825279252802528125282252832528425285252862528725288252892529025291252922529325294252952529625297252982529925300253012530225303253042530525306253072530825309253102531125312253132531425315253162531725318253192532025321253222532325324253252532625327253282532925330253312533225333253342533525336253372533825339253402534125342253432534425345253462534725348253492535025351253522535325354253552535625357253582535925360253612536225363253642536525366253672536825369253702537125372253732537425375253762537725378253792538025381253822538325384253852538625387253882538925390253912539225393253942539525396253972539825399254002540125402254032540425405254062540725408254092541025411254122541325414254152541625417254182541925420254212542225423254242542525426254272542825429254302543125432254332543425435254362543725438254392544025441254422544325444254452544625447254482544925450254512545225453254542545525456254572545825459254602546125462254632546425465254662546725468254692547025471254722547325474254752547625477254782547925480254812548225483254842548525486254872548825489254902549125492254932549425495254962549725498254992550025501255022550325504255052550625507255082550925510255112551225513255142551525516255172551825519255202552125522255232552425525255262552725528255292553025531255322553325534255352553625537255382553925540255412554225543255442554525546255472554825549255502555125552255532555425555255562555725558255592556025561255622556325564255652556625567255682556925570255712557225573255742557525576255772557825579255802558125582255832558425585255862558725588255892559025591255922559325594255952559625597255982559925600256012560225603256042560525606256072560825609256102561125612256132561425615256162561725618256192562025621256222562325624256252562625627256282562925630256312563225633256342563525636256372563825639256402564125642256432564425645256462564725648256492565025651256522565325654256552565625657256582565925660256612566225663256642566525666256672566825669256702567125672256732567425675256762567725678256792568025681256822568325684256852568625687256882568925690256912569225693256942569525696256972569825699257002570125702257032570425705257062570725708257092571025711257122571325714257152571625717257182571925720257212572225723257242572525726257272572825729257302573125732257332573425735257362573725738257392574025741257422574325744257452574625747257482574925750257512575225753257542575525756257572575825759257602576125762257632576425765257662576725768257692577025771257722577325774257752577625777257782577925780257812578225783257842578525786257872578825789257902579125792257932579425795257962579725798257992580025801258022580325804258052580625807258082580925810258112581225813258142581525816258172581825819258202582125822258232582425825258262582725828258292583025831258322583325834258352583625837258382583925840258412584225843258442584525846258472584825849258502585125852258532585425855258562585725858258592586025861258622586325864258652586625867258682586925870258712587225873258742587525876258772587825879258802588125882258832588425885258862588725888258892589025891258922589325894258952589625897258982589925900259012590225903259042590525906259072590825909259102591125912259132591425915259162591725918259192592025921259222592325924259252592625927259282592925930259312593225933259342593525936259372593825939259402594125942259432594425945259462594725948259492595025951259522595325954259552595625957259582595925960259612596225963259642596525966259672596825969259702597125972259732597425975259762597725978259792598025981259822598325984259852598625987259882598925990259912599225993259942599525996259972599825999260002600126002260032600426005260062600726008260092601026011260122601326014260152601626017260182601926020260212602226023260242602526026260272602826029260302603126032260332603426035260362603726038260392604026041260422604326044260452604626047260482604926050260512605226053260542605526056260572605826059260602606126062260632606426065260662606726068260692607026071260722607326074260752607626077260782607926080260812608226083260842608526086260872608826089260902609126092260932609426095260962609726098260992610026101261022610326104261052610626107261082610926110261112611226113261142611526116261172611826119261202612126122261232612426125261262612726128261292613026131261322613326134261352613626137261382613926140261412614226143261442614526146261472614826149261502615126152261532615426155261562615726158261592616026161261622616326164261652616626167261682616926170261712617226173261742617526176261772617826179261802618126182261832618426185261862618726188261892619026191261922619326194261952619626197261982619926200262012620226203262042620526206262072620826209262102621126212262132621426215262162621726218262192622026221262222622326224262252622626227262282622926230262312623226233262342623526236262372623826239262402624126242262432624426245262462624726248262492625026251262522625326254262552625626257262582625926260262612626226263262642626526266262672626826269262702627126272262732627426275262762627726278262792628026281262822628326284262852628626287262882628926290262912629226293262942629526296262972629826299263002630126302263032630426305263062630726308263092631026311263122631326314263152631626317263182631926320263212632226323263242632526326263272632826329263302633126332263332633426335263362633726338263392634026341263422634326344263452634626347263482634926350263512635226353263542635526356263572635826359263602636126362263632636426365263662636726368263692637026371263722637326374263752637626377263782637926380263812638226383263842638526386263872638826389263902639126392263932639426395263962639726398263992640026401264022640326404264052640626407264082640926410264112641226413264142641526416264172641826419264202642126422264232642426425264262642726428264292643026431264322643326434264352643626437264382643926440264412644226443264442644526446264472644826449264502645126452264532645426455264562645726458264592646026461264622646326464264652646626467264682646926470264712647226473264742647526476264772647826479264802648126482264832648426485264862648726488264892649026491264922649326494264952649626497264982649926500265012650226503265042650526506265072650826509265102651126512265132651426515265162651726518265192652026521265222652326524265252652626527265282652926530265312653226533265342653526536265372653826539265402654126542265432654426545265462654726548265492655026551265522655326554265552655626557265582655926560265612656226563265642656526566265672656826569265702657126572265732657426575265762657726578265792658026581265822658326584265852658626587265882658926590265912659226593265942659526596265972659826599266002660126602266032660426605266062660726608266092661026611266122661326614266152661626617266182661926620266212662226623266242662526626266272662826629266302663126632266332663426635266362663726638266392664026641266422664326644266452664626647266482664926650266512665226653266542665526656266572665826659266602666126662266632666426665266662666726668266692667026671266722667326674266752667626677266782667926680266812668226683266842668526686266872668826689266902669126692266932669426695266962669726698266992670026701267022670326704267052670626707267082670926710267112671226713267142671526716267172671826719267202672126722267232672426725267262672726728267292673026731267322673326734267352673626737267382673926740267412674226743267442674526746267472674826749267502675126752267532675426755267562675726758267592676026761267622676326764267652676626767267682676926770267712677226773267742677526776267772677826779267802678126782267832678426785267862678726788267892679026791267922679326794267952679626797267982679926800268012680226803268042680526806268072680826809268102681126812268132681426815268162681726818268192682026821268222682326824268252682626827268282682926830268312683226833268342683526836268372683826839268402684126842268432684426845268462684726848268492685026851268522685326854268552685626857268582685926860268612686226863268642686526866268672686826869268702687126872268732687426875268762687726878268792688026881268822688326884268852688626887268882688926890268912689226893268942689526896268972689826899269002690126902269032690426905269062690726908269092691026911269122691326914269152691626917269182691926920269212692226923269242692526926269272692826929269302693126932269332693426935269362693726938269392694026941269422694326944269452694626947269482694926950269512695226953269542695526956269572695826959269602696126962269632696426965269662696726968269692697026971269722697326974269752697626977269782697926980269812698226983269842698526986269872698826989269902699126992269932699426995269962699726998269992700027001270022700327004270052700627007270082700927010270112701227013270142701527016270172701827019270202702127022270232702427025270262702727028270292703027031270322703327034270352703627037270382703927040270412704227043270442704527046270472704827049270502705127052270532705427055270562705727058270592706027061270622706327064270652706627067270682706927070270712707227073270742707527076270772707827079270802708127082270832708427085270862708727088270892709027091270922709327094270952709627097270982709927100271012710227103271042710527106271072710827109271102711127112271132711427115271162711727118271192712027121271222712327124271252712627127271282712927130271312713227133271342713527136271372713827139271402714127142271432714427145271462714727148271492715027151271522715327154271552715627157271582715927160271612716227163271642716527166271672716827169271702717127172271732717427175271762717727178271792718027181271822718327184271852718627187271882718927190271912719227193271942719527196271972719827199272002720127202272032720427205272062720727208272092721027211272122721327214272152721627217272182721927220272212722227223272242722527226272272722827229272302723127232272332723427235272362723727238272392724027241272422724327244272452724627247272482724927250272512725227253272542725527256272572725827259272602726127262272632726427265272662726727268272692727027271272722727327274272752727627277272782727927280272812728227283272842728527286272872728827289272902729127292272932729427295272962729727298272992730027301273022730327304273052730627307273082730927310273112731227313273142731527316273172731827319273202732127322273232732427325273262732727328273292733027331273322733327334273352733627337273382733927340273412734227343273442734527346273472734827349273502735127352273532735427355273562735727358273592736027361273622736327364273652736627367273682736927370273712737227373273742737527376273772737827379273802738127382273832738427385273862738727388273892739027391273922739327394273952739627397273982739927400274012740227403274042740527406274072740827409274102741127412274132741427415274162741727418274192742027421274222742327424274252742627427274282742927430274312743227433274342743527436274372743827439274402744127442274432744427445274462744727448274492745027451274522745327454274552745627457274582745927460274612746227463274642746527466274672746827469274702747127472274732747427475274762747727478274792748027481274822748327484274852748627487274882748927490274912749227493274942749527496274972749827499275002750127502275032750427505275062750727508275092751027511275122751327514275152751627517275182751927520275212752227523275242752527526275272752827529275302753127532275332753427535275362753727538275392754027541275422754327544275452754627547275482754927550275512755227553275542755527556275572755827559275602756127562275632756427565275662756727568275692757027571275722757327574275752757627577275782757927580275812758227583275842758527586275872758827589275902759127592275932759427595275962759727598275992760027601276022760327604276052760627607276082760927610276112761227613276142761527616276172761827619276202762127622276232762427625276262762727628276292763027631276322763327634276352763627637276382763927640276412764227643276442764527646276472764827649276502765127652276532765427655276562765727658276592766027661276622766327664276652766627667276682766927670276712767227673276742767527676276772767827679276802768127682276832768427685276862768727688276892769027691276922769327694276952769627697276982769927700277012770227703277042770527706277072770827709277102771127712277132771427715277162771727718277192772027721277222772327724277252772627727277282772927730277312773227733277342773527736277372773827739277402774127742277432774427745277462774727748277492775027751277522775327754277552775627757277582775927760277612776227763277642776527766277672776827769277702777127772277732777427775277762777727778277792778027781277822778327784277852778627787277882778927790277912779227793277942779527796277972779827799278002780127802278032780427805278062780727808278092781027811278122781327814278152781627817278182781927820278212782227823278242782527826278272782827829278302783127832278332783427835278362783727838278392784027841278422784327844278452784627847278482784927850278512785227853278542785527856278572785827859278602786127862278632786427865278662786727868278692787027871278722787327874278752787627877278782787927880278812788227883278842788527886278872788827889278902789127892278932789427895278962789727898278992790027901279022790327904279052790627907279082790927910279112791227913279142791527916279172791827919279202792127922279232792427925279262792727928279292793027931279322793327934279352793627937279382793927940279412794227943279442794527946279472794827949279502795127952279532795427955279562795727958279592796027961279622796327964279652796627967279682796927970279712797227973279742797527976279772797827979279802798127982279832798427985279862798727988279892799027991279922799327994279952799627997279982799928000280012800228003280042800528006280072800828009280102801128012280132801428015280162801728018280192802028021280222802328024280252802628027280282802928030280312803228033280342803528036280372803828039280402804128042280432804428045280462804728048280492805028051280522805328054280552805628057280582805928060280612806228063280642806528066280672806828069280702807128072280732807428075280762807728078280792808028081280822808328084280852808628087280882808928090280912809228093280942809528096280972809828099281002810128102281032810428105281062810728108281092811028111281122811328114281152811628117281182811928120281212812228123281242812528126281272812828129281302813128132281332813428135281362813728138281392814028141281422814328144281452814628147281482814928150281512815228153281542815528156281572815828159281602816128162281632816428165281662816728168281692817028171281722817328174281752817628177281782817928180281812818228183281842818528186281872818828189281902819128192281932819428195281962819728198281992820028201282022820328204282052820628207282082820928210282112821228213282142821528216282172821828219282202822128222282232822428225282262822728228282292823028231282322823328234282352823628237282382823928240282412824228243282442824528246282472824828249282502825128252282532825428255282562825728258282592826028261282622826328264282652826628267282682826928270282712827228273282742827528276282772827828279282802828128282282832828428285282862828728288282892829028291282922829328294282952829628297282982829928300283012830228303283042830528306283072830828309283102831128312283132831428315283162831728318283192832028321283222832328324283252832628327283282832928330283312833228333283342833528336283372833828339283402834128342283432834428345283462834728348283492835028351283522835328354283552835628357283582835928360283612836228363283642836528366283672836828369283702837128372283732837428375283762837728378283792838028381283822838328384283852838628387283882838928390283912839228393283942839528396283972839828399284002840128402284032840428405284062840728408284092841028411284122841328414284152841628417284182841928420284212842228423284242842528426284272842828429284302843128432284332843428435284362843728438284392844028441284422844328444284452844628447284482844928450284512845228453284542845528456284572845828459284602846128462284632846428465284662846728468284692847028471284722847328474284752847628477284782847928480284812848228483284842848528486284872848828489284902849128492284932849428495284962849728498284992850028501285022850328504285052850628507285082850928510285112851228513285142851528516285172851828519285202852128522285232852428525285262852728528285292853028531285322853328534285352853628537285382853928540285412854228543285442854528546285472854828549285502855128552285532855428555285562855728558285592856028561285622856328564285652856628567285682856928570285712857228573285742857528576285772857828579285802858128582285832858428585285862858728588285892859028591285922859328594285952859628597285982859928600286012860228603286042860528606286072860828609286102861128612286132861428615286162861728618286192862028621286222862328624286252862628627286282862928630286312863228633286342863528636286372863828639286402864128642286432864428645286462864728648286492865028651286522865328654286552865628657286582865928660286612866228663286642866528666286672866828669286702867128672286732867428675286762867728678286792868028681286822868328684286852868628687286882868928690286912869228693286942869528696286972869828699287002870128702287032870428705287062870728708287092871028711287122871328714287152871628717287182871928720287212872228723287242872528726287272872828729287302873128732287332873428735287362873728738287392874028741287422874328744287452874628747287482874928750287512875228753287542875528756287572875828759287602876128762287632876428765287662876728768287692877028771287722877328774287752877628777287782877928780287812878228783287842878528786287872878828789287902879128792287932879428795287962879728798287992880028801288022880328804288052880628807288082880928810288112881228813288142881528816288172881828819288202882128822288232882428825288262882728828288292883028831288322883328834288352883628837288382883928840288412884228843288442884528846288472884828849288502885128852288532885428855288562885728858288592886028861288622886328864288652886628867288682886928870288712887228873288742887528876288772887828879288802888128882288832888428885288862888728888288892889028891288922889328894288952889628897288982889928900289012890228903289042890528906289072890828909289102891128912289132891428915289162891728918289192892028921289222892328924289252892628927289282892928930289312893228933289342893528936289372893828939289402894128942289432894428945289462894728948289492895028951289522895328954289552895628957289582895928960289612896228963289642896528966289672896828969289702897128972289732897428975289762897728978289792898028981289822898328984289852898628987289882898928990289912899228993289942899528996289972899828999290002900129002290032900429005290062900729008290092901029011290122901329014290152901629017290182901929020290212902229023290242902529026290272902829029290302903129032290332903429035290362903729038290392904029041290422904329044290452904629047290482904929050290512905229053290542905529056290572905829059290602906129062290632906429065290662906729068290692907029071290722907329074290752907629077290782907929080290812908229083290842908529086290872908829089290902909129092290932909429095290962909729098290992910029101291022910329104291052910629107291082910929110291112911229113291142911529116291172911829119291202912129122291232912429125291262912729128291292913029131291322913329134291352913629137291382913929140291412914229143291442914529146291472914829149291502915129152291532915429155291562915729158291592916029161291622916329164291652916629167291682916929170291712917229173291742917529176291772917829179291802918129182291832918429185291862918729188291892919029191291922919329194291952919629197291982919929200292012920229203292042920529206292072920829209292102921129212292132921429215292162921729218292192922029221292222922329224292252922629227292282922929230292312923229233292342923529236292372923829239292402924129242292432924429245292462924729248292492925029251292522925329254292552925629257292582925929260292612926229263292642926529266292672926829269292702927129272292732927429275292762927729278292792928029281292822928329284292852928629287292882928929290292912929229293292942929529296292972929829299293002930129302293032930429305293062930729308293092931029311293122931329314293152931629317293182931929320293212932229323293242932529326293272932829329293302933129332293332933429335293362933729338293392934029341293422934329344293452934629347293482934929350293512935229353293542935529356293572935829359293602936129362293632936429365293662936729368293692937029371293722937329374293752937629377293782937929380293812938229383293842938529386293872938829389293902939129392293932939429395293962939729398293992940029401294022940329404294052940629407294082940929410294112941229413294142941529416294172941829419294202942129422294232942429425294262942729428294292943029431294322943329434294352943629437294382943929440294412944229443294442944529446294472944829449294502945129452294532945429455294562945729458294592946029461294622946329464294652946629467294682946929470294712947229473294742947529476294772947829479294802948129482294832948429485294862948729488294892949029491294922949329494294952949629497294982949929500295012950229503295042950529506295072950829509295102951129512295132951429515295162951729518295192952029521295222952329524295252952629527295282952929530295312953229533295342953529536295372953829539295402954129542295432954429545295462954729548295492955029551295522955329554295552955629557295582955929560295612956229563295642956529566295672956829569295702957129572295732957429575295762957729578295792958029581295822958329584295852958629587295882958929590295912959229593295942959529596295972959829599296002960129602296032960429605296062960729608296092961029611296122961329614296152961629617296182961929620296212962229623296242962529626296272962829629296302963129632296332963429635296362963729638296392964029641296422964329644296452964629647296482964929650296512965229653296542965529656296572965829659296602966129662296632966429665296662966729668296692967029671296722967329674296752967629677296782967929680296812968229683296842968529686296872968829689296902969129692296932969429695296962969729698296992970029701297022970329704297052970629707297082970929710297112971229713297142971529716297172971829719297202972129722297232972429725297262972729728297292973029731297322973329734297352973629737297382973929740297412974229743297442974529746297472974829749297502975129752297532975429755297562975729758297592976029761297622976329764297652976629767297682976929770297712977229773297742977529776297772977829779297802978129782297832978429785297862978729788297892979029791297922979329794297952979629797297982979929800298012980229803298042980529806298072980829809298102981129812298132981429815298162981729818298192982029821298222982329824298252982629827298282982929830298312983229833298342983529836298372983829839298402984129842298432984429845298462984729848298492985029851298522985329854298552985629857298582985929860298612986229863298642986529866298672986829869298702987129872298732987429875298762987729878298792988029881298822988329884298852988629887298882988929890298912989229893298942989529896298972989829899299002990129902299032990429905299062990729908299092991029911299122991329914299152991629917299182991929920299212992229923299242992529926299272992829929299302993129932299332993429935299362993729938299392994029941299422994329944299452994629947299482994929950299512995229953299542995529956299572995829959299602996129962299632996429965299662996729968299692997029971299722997329974299752997629977299782997929980299812998229983299842998529986299872998829989299902999129992299932999429995299962999729998299993000030001300023000330004300053000630007300083000930010300113001230013300143001530016300173001830019300203002130022300233002430025300263002730028300293003030031300323003330034300353003630037300383003930040300413004230043300443004530046300473004830049300503005130052300533005430055300563005730058300593006030061300623006330064300653006630067300683006930070300713007230073300743007530076300773007830079300803008130082300833008430085300863008730088300893009030091300923009330094300953009630097300983009930100301013010230103301043010530106301073010830109301103011130112301133011430115301163011730118301193012030121301223012330124301253012630127301283012930130301313013230133301343013530136301373013830139301403014130142301433014430145301463014730148301493015030151301523015330154301553015630157301583015930160301613016230163301643016530166301673016830169301703017130172301733017430175301763017730178301793018030181301823018330184301853018630187301883018930190301913019230193301943019530196301973019830199302003020130202302033020430205302063020730208302093021030211302123021330214302153021630217302183021930220302213022230223302243022530226302273022830229302303023130232302333023430235302363023730238302393024030241302423024330244302453024630247302483024930250302513025230253302543025530256302573025830259302603026130262302633026430265302663026730268302693027030271302723027330274302753027630277302783027930280302813028230283302843028530286302873028830289302903029130292302933029430295302963029730298302993030030301303023030330304303053030630307303083030930310303113031230313303143031530316303173031830319303203032130322303233032430325303263032730328303293033030331303323033330334303353033630337303383033930340303413034230343303443034530346303473034830349303503035130352303533035430355303563035730358303593036030361303623036330364303653036630367303683036930370303713037230373303743037530376303773037830379303803038130382303833038430385303863038730388303893039030391303923039330394303953039630397303983039930400304013040230403304043040530406304073040830409304103041130412304133041430415304163041730418304193042030421304223042330424304253042630427304283042930430304313043230433304343043530436304373043830439304403044130442304433044430445304463044730448304493045030451304523045330454304553045630457304583045930460304613046230463304643046530466304673046830469304703047130472304733047430475304763047730478304793048030481304823048330484304853048630487304883048930490304913049230493304943049530496304973049830499305003050130502305033050430505305063050730508305093051030511305123051330514305153051630517305183051930520305213052230523305243052530526305273052830529305303053130532305333053430535305363053730538305393054030541305423054330544305453054630547305483054930550305513055230553305543055530556305573055830559305603056130562305633056430565305663056730568305693057030571305723057330574305753057630577305783057930580305813058230583305843058530586305873058830589305903059130592305933059430595305963059730598305993060030601306023060330604306053060630607306083060930610306113061230613306143061530616306173061830619306203062130622306233062430625306263062730628306293063030631306323063330634306353063630637306383063930640306413064230643306443064530646306473064830649306503065130652306533065430655306563065730658306593066030661306623066330664306653066630667306683066930670306713067230673306743067530676306773067830679306803068130682306833068430685306863068730688306893069030691306923069330694306953069630697306983069930700307013070230703307043070530706307073070830709307103071130712307133071430715307163071730718307193072030721307223072330724307253072630727307283072930730307313073230733307343073530736307373073830739307403074130742307433074430745307463074730748307493075030751307523075330754307553075630757307583075930760307613076230763307643076530766307673076830769307703077130772307733077430775307763077730778307793078030781307823078330784307853078630787307883078930790307913079230793307943079530796307973079830799308003080130802308033080430805308063080730808308093081030811308123081330814308153081630817308183081930820308213082230823308243082530826308273082830829308303083130832308333083430835308363083730838308393084030841308423084330844308453084630847308483084930850308513085230853308543085530856308573085830859308603086130862308633086430865308663086730868308693087030871308723087330874308753087630877308783087930880308813088230883308843088530886308873088830889308903089130892308933089430895308963089730898308993090030901309023090330904309053090630907309083090930910309113091230913309143091530916309173091830919309203092130922309233092430925309263092730928309293093030931309323093330934309353093630937309383093930940309413094230943309443094530946309473094830949309503095130952309533095430955309563095730958309593096030961309623096330964309653096630967309683096930970309713097230973309743097530976309773097830979309803098130982309833098430985309863098730988309893099030991309923099330994309953099630997309983099931000310013100231003310043100531006310073100831009310103101131012310133101431015310163101731018310193102031021310223102331024310253102631027310283102931030310313103231033310343103531036310373103831039310403104131042310433104431045310463104731048310493105031051310523105331054310553105631057310583105931060310613106231063310643106531066310673106831069310703107131072310733107431075310763107731078310793108031081310823108331084310853108631087310883108931090310913109231093310943109531096310973109831099311003110131102311033110431105311063110731108311093111031111311123111331114311153111631117311183111931120311213112231123311243112531126311273112831129311303113131132311333113431135311363113731138311393114031141311423114331144311453114631147311483114931150311513115231153311543115531156311573115831159311603116131162311633116431165311663116731168311693117031171311723117331174311753117631177311783117931180311813118231183311843118531186311873118831189311903119131192311933119431195311963119731198311993120031201312023120331204312053120631207312083120931210312113121231213312143121531216312173121831219312203122131222312233122431225312263122731228312293123031231312323123331234312353123631237312383123931240312413124231243312443124531246312473124831249312503125131252312533125431255312563125731258312593126031261312623126331264312653126631267312683126931270312713127231273312743127531276312773127831279312803128131282312833128431285312863128731288312893129031291312923129331294312953129631297312983129931300313013130231303313043130531306313073130831309313103131131312313133131431315313163131731318313193132031321313223132331324313253132631327313283132931330313313133231333313343133531336313373133831339313403134131342313433134431345313463134731348313493135031351313523135331354313553135631357313583135931360313613136231363313643136531366313673136831369313703137131372313733137431375313763137731378313793138031381313823138331384313853138631387313883138931390313913139231393313943139531396313973139831399314003140131402314033140431405314063140731408314093141031411314123141331414314153141631417314183141931420314213142231423314243142531426314273142831429314303143131432314333143431435314363143731438314393144031441314423144331444314453144631447314483144931450314513145231453314543145531456314573145831459314603146131462314633146431465314663146731468314693147031471314723147331474314753147631477314783147931480314813148231483314843148531486314873148831489314903149131492314933149431495314963149731498314993150031501315023150331504315053150631507315083150931510315113151231513315143151531516315173151831519315203152131522315233152431525315263152731528315293153031531315323153331534315353153631537315383153931540315413154231543315443154531546315473154831549315503155131552315533155431555315563155731558315593156031561315623156331564315653156631567315683156931570315713157231573315743157531576315773157831579315803158131582315833158431585315863158731588315893159031591315923159331594315953159631597315983159931600316013160231603316043160531606316073160831609316103161131612316133161431615316163161731618316193162031621316223162331624316253162631627316283162931630316313163231633316343163531636316373163831639316403164131642316433164431645316463164731648316493165031651316523165331654316553165631657316583165931660316613166231663316643166531666316673166831669316703167131672316733167431675316763167731678316793168031681316823168331684316853168631687316883168931690316913169231693316943169531696316973169831699317003170131702317033170431705317063170731708317093171031711317123171331714317153171631717317183171931720317213172231723317243172531726317273172831729317303173131732317333173431735317363173731738317393174031741317423174331744317453174631747317483174931750317513175231753317543175531756317573175831759317603176131762317633176431765317663176731768317693177031771317723177331774317753177631777317783177931780317813178231783317843178531786317873178831789317903179131792317933179431795317963179731798317993180031801318023180331804318053180631807318083180931810318113181231813318143181531816318173181831819318203182131822318233182431825318263182731828318293183031831318323183331834318353183631837318383183931840318413184231843318443184531846318473184831849318503185131852318533185431855318563185731858318593186031861318623186331864318653186631867318683186931870318713187231873318743187531876318773187831879318803188131882318833188431885318863188731888318893189031891318923189331894318953189631897318983189931900319013190231903319043190531906319073190831909319103191131912319133191431915319163191731918319193192031921319223192331924319253192631927319283192931930319313193231933319343193531936319373193831939319403194131942319433194431945319463194731948319493195031951319523195331954319553195631957319583195931960319613196231963319643196531966319673196831969319703197131972319733197431975319763197731978319793198031981319823198331984319853198631987319883198931990319913199231993319943199531996319973199831999320003200132002320033200432005320063200732008320093201032011320123201332014320153201632017320183201932020320213202232023320243202532026320273202832029320303203132032320333203432035320363203732038320393204032041320423204332044320453204632047320483204932050320513205232053320543205532056320573205832059320603206132062320633206432065320663206732068320693207032071320723207332074320753207632077320783207932080320813208232083320843208532086320873208832089320903209132092320933209432095320963209732098320993210032101321023210332104321053210632107321083210932110321113211232113321143211532116321173211832119321203212132122321233212432125321263212732128321293213032131321323213332134321353213632137321383213932140321413214232143321443214532146321473214832149321503215132152321533215432155321563215732158321593216032161321623216332164321653216632167321683216932170321713217232173321743217532176321773217832179321803218132182321833218432185321863218732188321893219032191321923219332194321953219632197321983219932200322013220232203322043220532206322073220832209322103221132212322133221432215322163221732218322193222032221322223222332224322253222632227322283222932230322313223232233322343223532236322373223832239322403224132242322433224432245322463224732248322493225032251322523225332254322553225632257322583225932260322613226232263322643226532266322673226832269322703227132272322733227432275322763227732278322793228032281322823228332284322853228632287322883228932290322913229232293322943229532296322973229832299323003230132302323033230432305323063230732308323093231032311323123231332314323153231632317323183231932320323213232232323323243232532326323273232832329323303233132332323333233432335323363233732338323393234032341323423234332344323453234632347323483234932350323513235232353323543235532356323573235832359323603236132362323633236432365323663236732368323693237032371323723237332374323753237632377323783237932380323813238232383323843238532386323873238832389323903239132392323933239432395323963239732398323993240032401324023240332404324053240632407324083240932410324113241232413324143241532416324173241832419324203242132422324233242432425324263242732428324293243032431324323243332434324353243632437324383243932440324413244232443324443244532446324473244832449324503245132452324533245432455324563245732458324593246032461324623246332464324653246632467324683246932470324713247232473324743247532476324773247832479324803248132482324833248432485324863248732488324893249032491324923249332494324953249632497324983249932500325013250232503325043250532506325073250832509325103251132512325133251432515325163251732518325193252032521325223252332524325253252632527325283252932530325313253232533325343253532536325373253832539325403254132542325433254432545325463254732548325493255032551325523255332554325553255632557325583255932560325613256232563325643256532566325673256832569325703257132572325733257432575325763257732578325793258032581325823258332584325853258632587325883258932590325913259232593325943259532596325973259832599326003260132602326033260432605326063260732608326093261032611326123261332614326153261632617326183261932620326213262232623326243262532626326273262832629326303263132632326333263432635326363263732638326393264032641326423264332644326453264632647326483264932650326513265232653326543265532656326573265832659326603266132662326633266432665326663266732668326693267032671326723267332674326753267632677326783267932680326813268232683326843268532686326873268832689326903269132692326933269432695326963269732698326993270032701327023270332704327053270632707327083270932710327113271232713327143271532716327173271832719327203272132722327233272432725327263272732728327293273032731327323273332734327353273632737327383273932740327413274232743327443274532746327473274832749327503275132752327533275432755327563275732758327593276032761327623276332764327653276632767327683276932770327713277232773327743277532776327773277832779327803278132782327833278432785327863278732788327893279032791327923279332794327953279632797327983279932800328013280232803328043280532806328073280832809328103281132812328133281432815328163281732818328193282032821328223282332824328253282632827328283282932830328313283232833328343283532836328373283832839328403284132842328433284432845328463284732848328493285032851328523285332854328553285632857328583285932860328613286232863328643286532866328673286832869328703287132872328733287432875328763287732878328793288032881328823288332884328853288632887328883288932890328913289232893328943289532896328973289832899329003290132902329033290432905329063290732908329093291032911329123291332914329153291632917329183291932920329213292232923329243292532926329273292832929329303293132932329333293432935329363293732938329393294032941329423294332944329453294632947329483294932950329513295232953329543295532956329573295832959329603296132962329633296432965329663296732968329693297032971329723297332974329753297632977329783297932980329813298232983329843298532986329873298832989329903299132992329933299432995329963299732998329993300033001330023300333004330053300633007330083300933010330113301233013330143301533016330173301833019330203302133022330233302433025330263302733028330293303033031330323303333034330353303633037330383303933040330413304233043330443304533046330473304833049330503305133052330533305433055330563305733058330593306033061330623306333064330653306633067330683306933070330713307233073330743307533076330773307833079330803308133082330833308433085330863308733088330893309033091330923309333094330953309633097330983309933100331013310233103331043310533106331073310833109331103311133112331133311433115331163311733118331193312033121331223312333124331253312633127331283312933130331313313233133331343313533136331373313833139331403314133142331433314433145331463314733148331493315033151331523315333154331553315633157331583315933160331613316233163331643316533166331673316833169331703317133172331733317433175331763317733178331793318033181331823318333184331853318633187331883318933190331913319233193331943319533196331973319833199332003320133202332033320433205332063320733208332093321033211332123321333214332153321633217332183321933220332213322233223332243322533226332273322833229332303323133232332333323433235332363323733238332393324033241332423324333244332453324633247332483324933250332513325233253332543325533256332573325833259332603326133262332633326433265332663326733268332693327033271332723327333274332753327633277332783327933280332813328233283332843328533286332873328833289332903329133292332933329433295332963329733298332993330033301333023330333304333053330633307333083330933310333113331233313333143331533316333173331833319333203332133322333233332433325333263332733328333293333033331333323333333334333353333633337333383333933340333413334233343333443334533346333473334833349333503335133352333533335433355333563335733358333593336033361333623336333364333653336633367333683336933370333713337233373333743337533376333773337833379333803338133382333833338433385333863338733388333893339033391333923339333394333953339633397333983339933400334013340233403334043340533406334073340833409334103341133412334133341433415334163341733418334193342033421334223342333424334253342633427334283342933430334313343233433334343343533436334373343833439334403344133442334433344433445334463344733448334493345033451334523345333454334553345633457334583345933460334613346233463334643346533466334673346833469334703347133472334733347433475334763347733478334793348033481334823348333484334853348633487334883348933490334913349233493334943349533496334973349833499335003350133502335033350433505335063350733508335093351033511335123351333514335153351633517335183351933520335213352233523335243352533526335273352833529335303353133532335333353433535335363353733538335393354033541335423354333544335453354633547335483354933550335513355233553335543355533556335573355833559335603356133562335633356433565335663356733568335693357033571335723357333574335753357633577335783357933580335813358233583335843358533586335873358833589335903359133592335933359433595335963359733598335993360033601336023360333604336053360633607336083360933610336113361233613336143361533616336173361833619336203362133622336233362433625336263362733628336293363033631336323363333634336353363633637336383363933640336413364233643336443364533646336473364833649336503365133652336533365433655336563365733658336593366033661336623366333664336653366633667336683366933670336713367233673336743367533676336773367833679336803368133682336833368433685336863368733688336893369033691336923369333694336953369633697336983369933700337013370233703337043370533706337073370833709337103371133712337133371433715337163371733718337193372033721337223372333724337253372633727337283372933730337313373233733337343373533736337373373833739337403374133742337433374433745337463374733748337493375033751337523375333754337553375633757337583375933760337613376233763337643376533766337673376833769337703377133772337733377433775337763377733778337793378033781337823378333784337853378633787337883378933790337913379233793337943379533796337973379833799338003380133802338033380433805338063380733808338093381033811338123381333814338153381633817338183381933820338213382233823338243382533826338273382833829338303383133832338333383433835338363383733838338393384033841338423384333844338453384633847338483384933850338513385233853338543385533856338573385833859338603386133862338633386433865338663386733868338693387033871338723387333874338753387633877338783387933880338813388233883338843388533886338873388833889338903389133892338933389433895338963389733898338993390033901339023390333904339053390633907339083390933910339113391233913339143391533916339173391833919339203392133922339233392433925339263392733928339293393033931339323393333934339353393633937339383393933940339413394233943339443394533946339473394833949339503395133952339533395433955339563395733958339593396033961339623396333964339653396633967339683396933970339713397233973339743397533976339773397833979339803398133982339833398433985339863398733988339893399033991339923399333994339953399633997339983399934000340013400234003340043400534006340073400834009340103401134012340133401434015340163401734018340193402034021340223402334024340253402634027340283402934030340313403234033340343403534036340373403834039340403404134042340433404434045340463404734048340493405034051340523405334054340553405634057340583405934060340613406234063340643406534066340673406834069340703407134072340733407434075340763407734078340793408034081340823408334084340853408634087340883408934090340913409234093340943409534096340973409834099341003410134102341033410434105341063410734108341093411034111341123411334114341153411634117341183411934120341213412234123341243412534126341273412834129341303413134132341333413434135341363413734138341393414034141341423414334144341453414634147341483414934150341513415234153341543415534156341573415834159341603416134162341633416434165341663416734168341693417034171341723417334174341753417634177341783417934180341813418234183341843418534186341873418834189341903419134192341933419434195341963419734198341993420034201342023420334204342053420634207342083420934210342113421234213342143421534216342173421834219342203422134222342233422434225342263422734228342293423034231342323423334234342353423634237342383423934240342413424234243342443424534246342473424834249342503425134252342533425434255342563425734258342593426034261342623426334264342653426634267342683426934270 | 
							- /*!
 
-  * elFinder - file manager for web
 
-  * Version 2.1.43 (2018-11-24)
 
-  * http://elfinder.org
 
-  * 
 
-  * Copyright 2009-2018, Studio 42
 
-  * Licensed under a 3-clauses BSD license
 
-  */
 
- (function(root, factory) {
 
- 	if (typeof define === 'function' && define.amd) {
 
- 		// AMD
 
- 		define(['jquery','jquery-ui'], factory);
 
- 	} else if (typeof exports !== 'undefined') {
 
- 		// CommonJS
 
- 		var $, ui;
 
- 		try {
 
- 			$ = require('jquery');
 
- 			ui = require('jquery-ui');
 
- 		} catch (e) {}
 
- 		module.exports = factory($, ui);
 
- 	} else {
 
- 		// Browser globals (Note: root is window)
 
- 		factory(root.jQuery, root.jQuery.ui, true);
 
- 	}
 
- }(this, function($, _ui, toGlobal) {
 
- toGlobal = toGlobal || false;
 
- /*
 
-  * File: /js/elFinder.js
 
-  */
 
- /**
 
-  * @class elFinder - file manager for web
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- var elFinder = function(elm, opts, bootCallback) {
 
- 		//this.time('load');
 
- 	var self = this,
 
- 		
 
- 		/**
 
- 		 * Objects array of jQuery.Deferred that calls before elFinder boot up
 
- 		 * 
 
- 		 * @type Array
 
- 		 */
 
- 		dfrdsBeforeBootup = [],
 
- 		
 
- 		/**
 
- 		 * Plugin name to check for conflicts with bootstrap etc
 
- 		 *
 
- 		 * @type Array
 
- 		 **/
 
- 		conflictChecks = ['button', 'tooltip'],
 
- 		
 
- 		/**
 
- 		 * Node on which elfinder creating
 
- 		 *
 
- 		 * @type jQuery
 
- 		 **/
 
- 		node = $(elm),
 
- 		
 
- 		/**
 
- 		 * Object of events originally registered in this node
 
- 		 * 
 
- 		 * @type Object
 
- 		 */
 
- 		prevEvents = $.extend(true, {}, $._data(node.get(0), 'events')),
 
- 		
 
- 		/**
 
- 		 * Store node contents.
 
- 		 *
 
- 		 * @see this.destroy
 
- 		 * @type jQuery
 
- 		 **/
 
- 		prevContent = $('<div/>').append(node.contents()).attr('class', node.attr('class') || '').attr('style', node.attr('style') || ''),
 
- 		
 
- 		/**
 
- 		 * Instance ID. Required to get/set cookie
 
- 		 *
 
- 		 * @type String
 
- 		 **/
 
- 		id = node.attr('id') || '',
 
- 		
 
- 		/**
 
- 		 * Events namespace
 
- 		 *
 
- 		 * @type String
 
- 		 **/
 
- 		namespace = 'elfinder-' + (id ? id : Math.random().toString().substr(2, 7)),
 
- 		
 
- 		/**
 
- 		 * Mousedown event
 
- 		 *
 
- 		 * @type String
 
- 		 **/
 
- 		mousedown = 'mousedown.'+namespace,
 
- 		
 
- 		/**
 
- 		 * Keydown event
 
- 		 *
 
- 		 * @type String
 
- 		 **/
 
- 		keydown = 'keydown.'+namespace,
 
- 		
 
- 		/**
 
- 		 * Keypress event
 
- 		 *
 
- 		 * @type String
 
- 		 **/
 
- 		keypress = 'keypress.'+namespace,
 
- 		
 
- 		/**
 
- 		 * Keypup event
 
- 		 *
 
- 		 * @type String
 
- 		 **/
 
- 		keyup    = 'keyup.'+namespace,
 
- 		/**
 
- 		 * Is shortcuts/commands enabled
 
- 		 *
 
- 		 * @type Boolean
 
- 		 **/
 
- 		enabled = false,
 
- 		
 
- 		/**
 
- 		 * Store enabled value before ajax request
 
- 		 *
 
- 		 * @type Boolean
 
- 		 **/
 
- 		prevEnabled = false,
 
- 		
 
- 		/**
 
- 		 * List of build-in events which mapped into methods with same names
 
- 		 *
 
- 		 * @type Array
 
- 		 **/
 
- 		events = ['enable', 'disable', 'load', 'open', 'reload', 'select',  'add', 'remove', 'change', 'dblclick', 'getfile', 'lockfiles', 'unlockfiles', 'selectfiles', 'unselectfiles', 'dragstart', 'dragstop', 'search', 'searchend', 'viewchange'],
 
- 		
 
- 		/**
 
- 		 * Rules to validate data from backend
 
- 		 *
 
- 		 * @type Object
 
- 		 **/
 
- 		rules = {},
 
- 		
 
- 		/**
 
- 		 * Current working directory hash
 
- 		 *
 
- 		 * @type String
 
- 		 **/
 
- 		cwd = '',
 
- 		
 
- 		/**
 
- 		 * Current working directory options default
 
- 		 *
 
- 		 * @type Object
 
- 		 **/
 
- 		cwdOptionsDefault = {
 
- 			path          : '',
 
- 			url           : '',
 
- 			tmbUrl        : '',
 
- 			disabled      : [],
 
- 			separator     : '/',
 
- 			archives      : [],
 
- 			extract       : [],
 
- 			copyOverwrite : true,
 
- 			uploadOverwrite : true,
 
- 			uploadMaxSize : 0,
 
- 			jpgQuality    : 100,
 
- 			tmbCrop       : false,
 
- 			tmb           : false // old API
 
- 		},
 
- 		
 
- 		/**
 
- 		 * Current working directory options
 
- 		 *
 
- 		 * @type Object
 
- 		 **/
 
- 		cwdOptions = {},
 
- 		
 
- 		/**
 
- 		 * Files/dirs cache
 
- 		 *
 
- 		 * @type Object
 
- 		 **/
 
- 		files = {},
 
- 		
 
- 		/**
 
- 		 * Hidden Files/dirs cache
 
- 		 *
 
- 		 * @type Object
 
- 		 **/
 
- 		hiddenFiles = {},
 
- 		/**
 
- 		 * Files/dirs hash cache of each dirs
 
- 		 *
 
- 		 * @type Object
 
- 		 **/
 
- 		ownFiles = {},
 
- 		
 
- 		/**
 
- 		 * Selected files hashes
 
- 		 *
 
- 		 * @type Array
 
- 		 **/
 
- 		selected = [],
 
- 		
 
- 		/**
 
- 		 * Events listeners
 
- 		 *
 
- 		 * @type Object
 
- 		 **/
 
- 		listeners = {},
 
- 		
 
- 		/**
 
- 		 * Shortcuts
 
- 		 *
 
- 		 * @type Object
 
- 		 **/
 
- 		shortcuts = {},
 
- 		
 
- 		/**
 
- 		 * Buffer for copied files
 
- 		 *
 
- 		 * @type Array
 
- 		 **/
 
- 		clipboard = [],
 
- 		
 
- 		/**
 
- 		 * Copied/cuted files hashes
 
- 		 * Prevent from remove its from cache.
 
- 		 * Required for dispaly correct files names in error messages
 
- 		 *
 
- 		 * @type Object
 
- 		 **/
 
- 		remember = {},
 
- 		
 
- 		/**
 
- 		 * Queue for 'open' requests
 
- 		 *
 
- 		 * @type Array
 
- 		 **/
 
- 		queue = [],
 
- 		
 
- 		/**
 
- 		 * Queue for only cwd requests e.g. `tmb`
 
- 		 *
 
- 		 * @type Array
 
- 		 **/
 
- 		cwdQueue = [],
 
- 		
 
- 		/**
 
- 		 * Commands prototype
 
- 		 *
 
- 		 * @type Object
 
- 		 **/
 
- 		base = new self.command(self),
 
- 		
 
- 		/**
 
- 		 * elFinder node width
 
- 		 *
 
- 		 * @type String
 
- 		 * @default "auto"
 
- 		 **/
 
- 		width  = 'auto',
 
- 		
 
- 		/**
 
- 		 * elFinder node height
 
- 		 * Number: pixcel or String: Number + "%"
 
- 		 *
 
- 		 * @type Number | String
 
- 		 * @default 400
 
- 		 **/
 
- 		height = 400,
 
- 		
 
- 		/**
 
- 		 * Base node object or selector
 
- 		 * Element which is the reference of the height percentage
 
- 		 *
 
- 		 * @type Object|String
 
- 		 * @default null | $(window) (if height is percentage)
 
- 		 **/
 
- 		heightBase = null,
 
- 		
 
- 		/**
 
- 		 * MIME type list(Associative array) handled as a text file
 
- 		 * 
 
- 		 * @type Object|null
 
- 		 */
 
- 		textMimes = null,
 
- 		
 
- 		/**
 
- 		 * elfinder path for sound played on remove
 
- 		 * @type String
 
- 		 * @default ./sounds/
 
- 		 **/
 
- 		soundPath = 'sounds/',
 
- 		
 
- 		/**
 
- 		 * JSON.stringify of previous fm.sorters
 
- 		 * @type String
 
- 		 */
 
- 		prevSorterStr = '',
 
- 		/**
 
- 		 * Map table of file extention to MIME-Type
 
- 		 * @type Object
 
- 		 */
 
- 		extToMimeTable,
 
- 		beeper = $(document.createElement('audio')).hide().appendTo('body')[0],
 
- 			
 
- 		syncInterval,
 
- 		autoSyncStop = 0,
 
- 		
 
- 		uiCmdMapPrev = '',
 
- 		
 
- 		gcJobRes = null,
 
- 		
 
- 		open = function(data) {
 
- 			// NOTES: Do not touch data object
 
- 		
 
- 			var volumeid, contextmenu, emptyDirs = {}, stayDirs = {},
 
- 				rmClass, hashes, calc, gc, collapsed, prevcwd, sorterStr;
 
- 			
 
- 			if (self.api >= 2.1) {
 
- 				// support volume driver option `uiCmdMap`
 
- 				self.commandMap = (data.options.uiCmdMap && Object.keys(data.options.uiCmdMap).length)? data.options.uiCmdMap : {};
 
- 				if (uiCmdMapPrev !== JSON.stringify(self.commandMap)) {
 
- 					uiCmdMapPrev = JSON.stringify(self.commandMap);
 
- 				}
 
- 			} else {
 
- 				self.options.sync = 0;
 
- 			}
 
- 			
 
- 			if (data.init) {
 
- 				// init - reset cache
 
- 				files = {};
 
- 				ownFiles = {};
 
- 			} else {
 
- 				// remove only files from prev cwd
 
- 				// and collapsed directory (included 100+ directories) to empty for perfomance tune in DnD
 
- 				prevcwd = cwd;
 
- 				rmClass = 'elfinder-subtree-loaded ' + self.res('class', 'navexpand');
 
- 				collapsed = self.res('class', 'navcollapse');
 
- 				hashes = Object.keys(files);
 
- 				calc = function(i) {
 
- 					if (!files[i]) {
 
- 						return true;
 
- 					}
 
- 					
 
- 					var isDir = (files[i].mime === 'directory'),
 
- 						phash = files[i].phash,
 
- 						pnav;
 
- 					
 
- 					if (
 
- 						(!isDir
 
- 							|| emptyDirs[phash]
 
- 							|| (!stayDirs[phash]
 
- 								&& $('#'+self.navHash2Id(files[i].hash)).is(':hidden')
 
- 								&& $('#'+self.navHash2Id(phash)).next('.elfinder-navbar-subtree').children().length > 100
 
- 							)
 
- 						)
 
- 						&& (isDir || phash !== cwd)
 
- 						&& ! remember[i]
 
- 					) {
 
- 						if (isDir && !emptyDirs[phash]) {
 
- 							emptyDirs[phash] = true;
 
- 							$('#'+self.navHash2Id(phash))
 
- 							 .removeClass(rmClass)
 
- 							 .next('.elfinder-navbar-subtree').empty();
 
- 						}
 
- 						deleteCache(files[i]);
 
- 					} else if (isDir) {
 
- 						stayDirs[phash] = true;
 
- 					}
 
- 				};
 
- 				gc = function() {
 
- 					if (hashes.length) {
 
- 						gcJobRes && gcJobRes._abort();
 
- 						gcJobRes = self.asyncJob(calc, hashes, {
 
- 							interval : 20,
 
- 							numPerOnce : 100
 
- 						}).done(function() {
 
- 							var hd = self.storage('hide') || {items: {}};
 
- 							if (Object.keys(hiddenFiles).length) {
 
- 								$.each(hiddenFiles, function(h) {
 
- 									if (!hd.items[h]) {
 
- 										delete hiddenFiles[h];
 
- 									}
 
- 								});
 
- 							}
 
- 						});
 
- 					}
 
- 				};
 
- 				
 
- 				self.trigger('filesgc').one('filesgc', function() {
 
- 					hashes = [];
 
- 				});
 
- 				
 
- 				self.one('opendone', function() {
 
- 					if (prevcwd !== cwd) {
 
- 						if (! node.data('lazycnt')) {
 
- 							gc();
 
- 						} else {
 
- 							self.one('lazydone', gc);
 
- 						}
 
- 					}
 
- 				});
 
- 			}
 
- 			self.sorters = {};
 
- 			cwd = data.cwd.hash;
 
- 			cache(data.files);
 
- 			if (!files[cwd]) {
 
- 				cache([data.cwd]);
 
- 			}
 
- 			// trigger event 'sorterupdate'
 
- 			sorterStr = JSON.stringify(self.sorters);
 
- 			if (prevSorterStr !== sorterStr) {
 
- 				self.trigger('sorterupdate');
 
- 				prevSorterStr = sorterStr;
 
- 			}
 
- 			self.lastDir(cwd);
 
- 			
 
- 			self.autoSync();
 
- 		},
 
- 		
 
- 		/**
 
- 		 * Store info about files/dirs in "files" object.
 
- 		 *
 
- 		 * @param  Array  files
 
- 		 * @param  String data type
 
- 		 * @return void
 
- 		 **/
 
- 		cache = function(data, type) {
 
- 			var defsorter = { name: true, perm: true, date: true,  size: true, kind: true },
 
- 				sorterChk = !self.sorters._checked,
 
- 				l         = data.length,
 
- 				setSorter = function(file) {
 
- 					var f = file || {},
 
- 						sorters = [];
 
- 					$.each(self.sortRules, function(key) {
 
- 						if (defsorter[key] || typeof f[key] !== 'undefined' || (key === 'mode' && typeof f.perm !== 'undefined')) {
 
- 							sorters.push(key);
 
- 						}
 
- 					});
 
- 					self.sorters = self.arrayFlip(sorters, true);
 
- 					self.sorters._checked = true;
 
- 				},
 
- 				keeps = ['sizeInfo'],
 
- 				changedParents = {},
 
- 				hideData = self.storage('hide') || {},
 
- 				hides = hideData.items || {},
 
- 				f, i, keepProp, parents, hidden;
 
- 			for (i = 0; i < l; i++) {
 
- 				f = Object.assign({}, data[i]);
 
- 				hidden = (!hideData.show && hides[f.hash])? true : false;
 
- 				if (f.name && f.hash && f.mime) {
 
- 					if (!hidden) {
 
- 						if (sorterChk && f.phash === cwd) {
 
- 							setSorter(f);
 
- 							sorterChk = false;
 
- 						}
 
- 						
 
- 						if (f.phash && (type === 'add' || type === 'change')) {
 
- 							if (parents = self.parents(f.phash)) {
 
- 								$.each(parents, function() {
 
- 									changedParents[this] = true;
 
- 								});
 
- 							}
 
- 						}
 
- 					}
 
- 					if (files[f.hash]) {
 
- 						$.each(keeps, function() {
 
- 							if(files[f.hash][this] && ! f[this]) {
 
- 								f[this] = files[f.hash][this];
 
- 							}
 
- 						});
 
- 						if (f.sizeInfo && !f.size) {
 
- 							f.size = f.sizeInfo.size;
 
- 						}
 
- 						deleteCache(files[f.hash], true);
 
- 					}
 
- 					if (hides[f.hash]) {
 
- 						hiddenFiles[f.hash] = f;
 
- 					}
 
- 					if (hidden) {
 
- 						l--;
 
- 						data.splice(i--, 1);
 
- 					} else {
 
- 						files[f.hash] = f;
 
- 						if (f.mime === 'directory' && !ownFiles[f.hash]) {
 
- 							ownFiles[f.hash] = {};
 
- 						}
 
- 						if (f.phash) {
 
- 							if (!ownFiles[f.phash]) {
 
- 								ownFiles[f.phash] = {};
 
- 							}
 
- 							ownFiles[f.phash][f.hash] = true;
 
- 						}
 
- 					}
 
- 				}
 
- 			}
 
- 			// delete sizeInfo cache
 
- 			$.each(Object.keys(changedParents), function() {
 
- 				var target = files[this];
 
- 				if (target && target.sizeInfo) {
 
- 					delete target.sizeInfo;
 
- 				}
 
- 			});
 
- 			
 
- 			// for empty folder
 
- 			sorterChk && setSorter();
 
- 		},
 
- 		
 
- 		/**
 
- 		 * Delete file object from files caches
 
- 		 * 
 
- 		 * @param  Array  removed hashes
 
- 		 * @return void
 
- 		 */
 
- 		remove = function(removed) {
 
- 			var l       = removed.length,
 
- 				roots   = {},
 
- 				rm      = function(hash) {
 
- 					var file = files[hash], i;
 
- 					if (file) {
 
- 						if (file.mime === 'directory') {
 
- 							if (roots[hash]) {
 
- 								delete self.roots[roots[hash]];
 
- 							}
 
- 							// restore stats of deleted root parent directory
 
- 							$.each(self.leafRoots, function(phash, roots) {
 
- 								var idx, pdir;
 
- 								if ((idx = $.inArray(hash, roots))!== -1) {
 
- 									if (roots.length === 1) {
 
- 										if ((pdir = Object.assign({}, files[phash])) && pdir._realStats) {
 
- 											$.each(pdir._realStats, function(k, v) {
 
- 												pdir[k] = v;
 
- 											});
 
- 											remove(files[phash]._realStats);
 
- 											self.change({ changed: [pdir] });
 
- 										}
 
- 										delete self.leafRoots[phash];
 
- 									} else {
 
- 										self.leafRoots[phash].splice(idx, 1);
 
- 									}
 
- 								}
 
- 							});
 
- 							if (self.searchStatus.state < 2) {
 
- 								$.each(files, function(h, f) {
 
- 									f.phash == hash && rm(h);
 
- 								});
 
- 							}
 
- 						}
 
- 						if (file.phash) {
 
- 							if (parents = self.parents(file.phash)) {
 
- 								$.each(parents, function() {
 
- 									changedParents[this] = true;
 
- 								});
 
- 							}
 
- 						}
 
- 						deleteCache(files[hash]);
 
- 					}
 
- 				},
 
- 				changedParents = {},
 
- 				parents;
 
- 		
 
- 			$.each(self.roots, function(k, v) {
 
- 				roots[v] = k;
 
- 			});
 
- 			while (l--) {
 
- 				rm(removed[l]);
 
- 			}
 
- 			// delete sizeInfo cache
 
- 			$.each(Object.keys(changedParents), function() {
 
- 				var target = files[this];
 
- 				if (target && target.sizeInfo) {
 
- 					delete target.sizeInfo;
 
- 				}
 
- 			});
 
- 		},
 
- 		
 
- 		/**
 
- 		 * Update file object in files caches
 
- 		 * 
 
- 		 * @param  Array  changed file objects
 
- 		 * @return void
 
- 		 */
 
- 		change = function(changed) {
 
- 			$.each(changed, function(i, file) {
 
- 				var hash = file.hash;
 
- 				if (files[hash]) {
 
- 					$.each(Object.keys(files[hash]), function(i, v){
 
- 						if (typeof file[v] === 'undefined') {
 
- 							delete files[hash][v];
 
- 						}
 
- 					});
 
- 				}
 
- 				files[hash] = files[hash] ? Object.assign(files[hash], file) : file;
 
- 			});
 
- 		},
 
- 		
 
- 		/**
 
- 		 * Delete cache data of files, ownFiles and self.optionsByHashes
 
- 		 * 
 
- 		 * @param  Object  file
 
- 		 * @param  Boolean update
 
- 		 * @return void
 
- 		 */
 
- 		deleteCache = function(file, update) {
 
- 			var hash = file.hash,
 
- 				phash = file.phash;
 
- 			
 
- 			if (phash && ownFiles[phash]) {
 
- 				 delete ownFiles[phash][hash];
 
- 			}
 
- 			if (!update) {
 
- 				ownFiles[hash] && delete ownFiles[hash];
 
- 				self.optionsByHashes[hash] && delete self.optionsByHashes[hash];
 
- 			}
 
- 			delete files[hash];
 
- 		},
 
- 		
 
- 		/**
 
- 		 * Maximum number of concurrent connections on request
 
- 		 * 
 
- 		 * @type Number
 
- 		 */
 
- 		requestMaxConn,
 
- 		
 
- 		/**
 
- 		 * Current number of connections
 
- 		 * 
 
- 		 * @type Number
 
- 		 */
 
- 		requestCnt = 0,
 
- 		
 
- 		/**
 
- 		 * Queue waiting for connection
 
- 		 * 
 
- 		 * @type Array
 
- 		 */
 
- 		requestQueue = [],
 
- 		
 
- 		/**
 
- 		 * Flag to cancel the `open` command waiting for connection
 
- 		 * 
 
- 		 * @type Boolean
 
- 		 */
 
- 		requestQueueSkipOpen = false,
 
- 		
 
- 		/**
 
- 		 * Exec shortcut
 
- 		 *
 
- 		 * @param  jQuery.Event  keydown/keypress event
 
- 		 * @return void
 
- 		 */
 
- 		execShortcut = function(e) {
 
- 			var code    = e.keyCode,
 
- 				ctrlKey = !!(e.ctrlKey || e.metaKey),
 
- 				isMousedown = e.type === 'mousedown',
 
- 				ddm;
 
- 			!isMousedown && (self.keyState.keyCode = code);
 
- 			self.keyState.ctrlKey  = ctrlKey;
 
- 			self.keyState.shiftKey = e.shiftKey;
 
- 			self.keyState.metaKey  = e.metaKey;
 
- 			self.keyState.altKey   = e.altKey;
 
- 			if (isMousedown) {
 
- 				return;
 
- 			} else if (e.type === 'keyup') {
 
- 				self.keyState.keyCode = null;
 
- 				return;
 
- 			}
 
- 			if (enabled) {
 
- 				$.each(shortcuts, function(i, shortcut) {
 
- 					if (shortcut.type    == e.type 
 
- 					&& shortcut.keyCode  == code 
 
- 					&& shortcut.shiftKey == e.shiftKey 
 
- 					&& shortcut.ctrlKey  == ctrlKey 
 
- 					&& shortcut.altKey   == e.altKey) {
 
- 						e.preventDefault();
 
- 						e.stopPropagation();
 
- 						shortcut.callback(e, self);
 
- 						self.debug('shortcut-exec', i+' : '+shortcut.description);
 
- 					}
 
- 				});
 
- 				
 
- 				// prevent tab out of elfinder
 
- 				if (code == $.ui.keyCode.TAB && !$(e.target).is(':input')) {
 
- 					e.preventDefault();
 
- 				}
 
- 				
 
- 				// cancel any actions by [Esc] key
 
- 				if (e.type === 'keydown' && code == $.ui.keyCode.ESCAPE) {
 
- 					// copy or cut 
 
- 					if (! node.find('.ui-widget:visible').length) {
 
- 						self.clipboard().length && self.clipboard([]);
 
- 					}
 
- 					// dragging
 
- 					if ($.ui.ddmanager) {
 
- 						ddm = $.ui.ddmanager.current;
 
- 						ddm && ddm.helper && ddm.cancel();
 
- 					}
 
- 					// button menus
 
- 					self.toHide(node.find('.ui-widget.elfinder-button-menu.elfinder-frontmost:visible'));
 
- 					// trigger keydownEsc
 
- 					self.trigger('keydownEsc', e);
 
- 				}
 
- 			}
 
- 		},
 
- 		date = new Date(),
 
- 		utc,
 
- 		i18n,
 
- 		inFrame = (window.parent !== window),
 
- 		parentIframe = (function() {
 
- 			var pifm, ifms;
 
- 			if (inFrame) {
 
- 				try {
 
- 					ifms = $('iframe', window.parent.document);
 
- 					if (ifms.length) {
 
- 						$.each(ifms, function(i, ifm) {
 
- 							if (ifm.contentWindow === window) {
 
- 								pifm = $(ifm);
 
- 								return false;
 
- 							}
 
- 						});
 
- 					}
 
- 				} catch(e) {}
 
- 			}
 
- 			return pifm;
 
- 		})(),
 
- 		/**
 
- 		 * elFinder boot up function
 
- 		 * 
 
- 		 * @type Function
 
- 		 */
 
- 		bootUp,
 
- 		/**
 
- 		 * Original function of XMLHttpRequest.prototype.send
 
- 		 * 
 
- 		 * @type Function
 
- 		 */
 
- 		savedXhrSend;
 
- 	
 
- 	// opts must be an object
 
- 	if (!opts) {
 
- 		opts = {};
 
- 	}
 
- 	
 
- 	// set UA.Angle, UA.Rotated for mobile devices
 
- 	if (self.UA.Mobile) {
 
- 		$(window).on('orientationchange.'+namespace, function() {
 
- 			var a = ((screen && screen.orientation && screen.orientation.angle) || window.orientation || 0) + 0;
 
- 			if (a === -90) {
 
- 				a = 270;
 
- 			}
 
- 			self.UA.Angle = a;
 
- 			self.UA.Rotated = a % 180 === 0? false : true;
 
- 		}).trigger('orientationchange.'+namespace);
 
- 	}
 
- 	
 
- 	// check opt.bootCallback
 
- 	if (opts.bootCallback && typeof opts.bootCallback === 'function') {
 
- 		(function() {
 
- 			var func = bootCallback,
 
- 				opFunc = opts.bootCallback;
 
- 			bootCallback = function(fm, extraObj) {
 
- 				func && typeof func === 'function' && func.call(this, fm, extraObj);
 
- 				opFunc.call(this, fm, extraObj);
 
- 			};
 
- 		})();
 
- 	}
 
- 	delete opts.bootCallback;
 
- 	/**
 
- 	 * Protocol version
 
- 	 *
 
- 	 * @type String
 
- 	 **/
 
- 	this.api = null;
 
- 	
 
- 	/**
 
- 	 * elFinder use new api
 
- 	 *
 
- 	 * @type Boolean
 
- 	 **/
 
- 	this.newAPI = false;
 
- 	
 
- 	/**
 
- 	 * elFinder use old api
 
- 	 *
 
- 	 * @type Boolean
 
- 	 **/
 
- 	this.oldAPI = false;
 
- 	
 
- 	/**
 
- 	 * Net drivers names
 
- 	 *
 
- 	 * @type Array
 
- 	 **/
 
- 	this.netDrivers = [];
 
- 	
 
- 	/**
 
- 	 * Base URL of elfFinder library starting from Manager HTML
 
- 	 * 
 
- 	 * @type String
 
- 	 */
 
- 	this.baseUrl = '';
 
- 	
 
- 	/**
 
- 	 * Base URL of i18n js files
 
- 	 * baseUrl + "js/i18n/" when empty value
 
- 	 * 
 
- 	 * @type String
 
- 	 */
 
- 	this.i18nBaseUrl = '';
 
- 	/**
 
- 	 * Is elFinder CSS loaded
 
- 	 * 
 
- 	 * @type Boolean
 
- 	 */
 
- 	this.cssloaded = false;
 
- 	
 
- 	/**
 
- 	 * Current theme object
 
- 	 * 
 
- 	 * @type Object|Null
 
- 	 */
 
- 	this.theme = null;
 
- 	this.mimesCanMakeEmpty = {};
 
- 	/**
 
- 	 * Callback function at boot up that option specified at elFinder starting
 
- 	 * 
 
- 	 * @type Function
 
- 	 */
 
- 	this.bootCallback;
 
- 	/**
 
- 	 * ID. Required to create unique cookie name
 
- 	 *
 
- 	 * @type String
 
- 	 **/
 
- 	this.id = id;
 
- 	/**
 
- 	 * Method to store/fetch data
 
- 	 *
 
- 	 * @type Function
 
- 	 **/
 
- 	this.storage = (function() {
 
- 		try {
 
- 			if ('localStorage' in window && window['localStorage'] !== null) {
 
- 				if (self.UA.Safari) {
 
- 					// check for Mac/iOS safari private browsing mode
 
- 					window.localStorage.setItem('elfstoragecheck', 1);
 
- 					window.localStorage.removeItem('elfstoragecheck');
 
- 				}
 
- 				return self.localStorage;
 
- 			} else {
 
- 				return self.cookie;
 
- 			}
 
- 		} catch (e) {
 
- 			return self.cookie;
 
- 		}
 
- 	})();
 
- 	/**
 
- 	 * Configuration options
 
- 	 *
 
- 	 * @type Object
 
- 	 **/
 
- 	//this.options = $.extend(true, {}, this._options, opts);
 
- 	this.options = Object.assign({}, this._options);
 
- 	
 
- 	// for old type configuration
 
- 	if (opts.uiOptions) {
 
- 		if (opts.uiOptions.toolbar && Array.isArray(opts.uiOptions.toolbar)) {
 
- 			if ($.isPlainObject(opts.uiOptions.toolbar[opts.uiOptions.toolbar.length - 1])) {
 
- 				self.options.uiOptions.toolbarExtra = Object.assign(self.options.uiOptions.toolbarExtra || {}, opts.uiOptions.toolbar.pop());
 
- 			}
 
- 		}
 
- 	}
 
- 	
 
- 	// Overwrite if opts value is an array
 
- 	(function() {
 
- 		var arrOv = function(obj, base) {
 
- 			if ($.isPlainObject(obj)) {
 
- 				$.each(obj, function(k, v) {
 
- 					if ($.isPlainObject(v)) {
 
- 						if (!base[k]) {
 
- 							base[k] = {};
 
- 						}
 
- 						arrOv(v, base[k]);
 
- 					} else {
 
- 						base[k] = v;
 
- 					}
 
- 				});
 
- 			}
 
- 		};
 
- 		arrOv(opts, self.options);
 
- 	})();
 
- 	
 
- 	// join toolbarExtra to toolbar
 
- 	this.options.uiOptions.toolbar.push(this.options.uiOptions.toolbarExtra);
 
- 	delete this.options.uiOptions.toolbarExtra;
 
- 	
 
- 	// set fm.baseUrl
 
- 	this.baseUrl = (function() {
 
- 		var myTag, myCss, base, baseUrl;
 
- 		
 
- 		if (self.options.baseUrl) {
 
- 			return self.options.baseUrl;
 
- 		} else {
 
- 			baseUrl = '';
 
- 			//myTag = $('head > script[src$="js/elfinder.min.js"],script[src$="js/elfinder.full.js"]:first');
 
- 			myTag = null;
 
- 			$('head > script').each(function() {
 
- 				if (this.src && this.src.match(/js\/elfinder(?:-[a-z0-9_-]+)?\.(?:min|full)\.js$/i)) {
 
- 					myTag = $(this);
 
- 					return false;
 
- 				}
 
- 			});
 
- 			if (myTag) {
 
- 				myCss = $('head > link[href$="css/elfinder.min.css"],link[href$="css/elfinder.full.css"]:first').length;
 
- 				if (! myCss) {
 
- 					// to request CSS auto loading
 
- 					self.cssloaded = null;
 
- 				}
 
- 				baseUrl = myTag.attr('src').replace(/js\/[^\/]+$/, '');
 
- 				if (! baseUrl.match(/^(https?\/\/|\/)/)) {
 
- 					// check <base> tag
 
- 					if (base = $('head > base[href]').attr('href')) {
 
- 						baseUrl = base.replace(/\/$/, '') + '/' + baseUrl; 
 
- 					}
 
- 				}
 
- 			}
 
- 			if (baseUrl !== '') {
 
- 				self.options.baseUrl = baseUrl;
 
- 			} else {
 
- 				if (! self.options.baseUrl) {
 
- 					self.options.baseUrl = './';
 
- 				}
 
- 				baseUrl = self.options.baseUrl;
 
- 			}
 
- 			return baseUrl;
 
- 		}
 
- 	})();
 
- 	
 
- 	this.i18nBaseUrl = (this.options.i18nBaseUrl || this.baseUrl + 'js/i18n').replace(/\/$/, '') + '/';
 
- 	// set dispInlineRegex
 
- 	cwdOptionsDefault['dispInlineRegex'] = this.options.dispInlineRegex;
 
- 	
 
- 	// auto load required CSS
 
- 	if (this.options.cssAutoLoad) {
 
- 		(function() {
 
- 			var baseUrl = self.baseUrl;
 
- 			
 
- 			if (self.cssloaded === null) {
 
- 				// hide elFinder node while css loading
 
- 				node.data('cssautoloadHide', $('<style>.elfinder{visibility:hidden;overflow:hidden}</style>'));
 
- 				$('head').append(node.data('cssautoloadHide'));
 
- 				
 
- 				// load CSS
 
- 				self.loadCss([baseUrl+'css/elfinder.min.css', baseUrl+'css/theme.css'], {
 
- 					dfd: $.Deferred().always(function() {
 
- 						if (node.data('cssautoloadHide')) {
 
- 							node.data('cssautoloadHide').remove();
 
- 							node.removeData('cssautoloadHide');
 
- 						}
 
- 					}).done(function() {
 
- 						if (!self.cssloaded) {
 
- 							self.cssloaded = true;
 
- 							self.trigger('cssloaded');
 
- 						}
 
- 					}).fail(function() {
 
- 						self.cssloaded = false;
 
- 						self.error(['errRead', 'CSS (elfinder or theme)']);
 
- 					})
 
- 				});
 
- 				
 
- 				// additional CSS files
 
- 				if (Array.isArray(self.options.cssAutoLoad)) {
 
- 					self.loadCss(self.options.cssAutoLoad);
 
- 				}
 
- 			}
 
- 			self.options.cssAutoLoad = false;
 
- 		})();
 
- 	}
 
- 	// load theme if exists
 
- 	self.changeTheme(self.storage('theme') || self.options.theme);
 
- 	
 
- 	/**
 
- 	 * Volume option to set the properties of the root Stat
 
- 	 * 
 
- 	 * @type Object
 
- 	 */
 
- 	this.optionProperties = {
 
- 		icon: void(0),
 
- 		csscls: void(0),
 
- 		tmbUrl: void(0),
 
- 		uiCmdMap: {},
 
- 		netkey: void(0),
 
- 		disabled: []
 
- 	};
 
- 	
 
- 	if (! inFrame && ! this.options.enableAlways && $('body').children().length === 2) { // only node and beeper
 
- 		this.options.enableAlways = true;
 
- 	}
 
- 	
 
- 	// make options.debug
 
- 	if (this.options.debug === true) {
 
- 		this.options.debug = 'all';
 
- 	} else if (Array.isArray(this.options.debug)) {
 
- 		(function() {
 
- 			var d = {};
 
- 			$.each(self.options.debug, function() {
 
- 				d[this] = true;
 
- 			});
 
- 			self.options.debug = d;
 
- 		})();
 
- 	} else {
 
- 		this.options.debug = false;
 
- 	}
 
- 	
 
- 	/**
 
- 	 * Original functions evacuated by conflict check
 
- 	 * 
 
- 	 * @type Object
 
- 	 */
 
- 	this.noConflicts = {};
 
- 	
 
- 	/**
 
- 	 * Check and save conflicts with bootstrap etc
 
- 	 * 
 
- 	 * @type Function
 
- 	 */
 
- 	this.noConflict = function() {
 
- 		$.each(conflictChecks, function(i, p) {
 
- 			if ($.fn[p] && typeof $.fn[p].noConflict === 'function') {
 
- 				self.noConflicts[p] = $.fn[p].noConflict();
 
- 			}
 
- 		});
 
- 	};
 
- 	// do check conflict
 
- 	this.noConflict();
 
- 	
 
- 	/**
 
- 	 * Is elFinder over CORS
 
- 	 *
 
- 	 * @type Boolean
 
- 	 **/
 
- 	this.isCORS = false;
 
- 	
 
- 	// configure for CORS
 
- 	(function(){
 
- 		if (typeof self.options.cors !== 'undefined' && self.options.cors !== null) {
 
- 			self.isCORS = self.options.cors? true : false;
 
- 		} else {
 
- 			var parseUrl = document.createElement('a'),
 
- 				parseUploadUrl,
 
- 				selfProtocol = window.location.protocol,
 
- 				portReg = function(protocol) {
 
- 					protocol = (!protocol || protocol === ':')? selfProtocol : protocol;
 
- 					return protocol === 'https:'? /\:443$/ : /\:80$/;
 
- 				},
 
- 				selfHost = window.location.host.replace(portReg(selfProtocol), '');
 
- 			parseUrl.href = opts.url;
 
- 			if (opts.urlUpload && (opts.urlUpload !== opts.url)) {
 
- 				parseUploadUrl = document.createElement('a');
 
- 				parseUploadUrl.href = opts.urlUpload;
 
- 			}
 
- 			if (selfHost !== parseUrl.host.replace(portReg(parseUrl.protocol), '')
 
- 				|| (parseUrl.protocol !== ':'&& parseUrl.protocol !== '' && (selfProtocol !== parseUrl.protocol))
 
- 				|| (parseUploadUrl && 
 
- 					(selfHost !== parseUploadUrl.host.replace(portReg(parseUploadUrl.protocol), '')
 
- 					|| (parseUploadUrl.protocol !== ':' && parseUploadUrl.protocol !== '' && (selfProtocol !== parseUploadUrl.protocol))
 
- 					)
 
- 				)
 
- 			) {
 
- 				self.isCORS = true;
 
- 			}
 
- 		}
 
- 		if (self.isCORS) {
 
- 			if (!$.isPlainObject(self.options.customHeaders)) {
 
- 				self.options.customHeaders = {};
 
- 			}
 
- 			if (!$.isPlainObject(self.options.xhrFields)) {
 
- 				self.options.xhrFields = {};
 
- 			}
 
- 			self.options.requestType = 'post';
 
- 			self.options.customHeaders['X-Requested-With'] = 'XMLHttpRequest';
 
- 			self.options.xhrFields['withCredentials'] = true;
 
- 		}
 
- 	})();
 
- 	/**
 
- 	 * Ajax request type
 
- 	 *
 
- 	 * @type String
 
- 	 * @default "get"
 
- 	 **/
 
- 	this.requestType = /^(get|post)$/i.test(this.options.requestType) ? this.options.requestType.toLowerCase() : 'get';
 
- 	
 
- 	// set `requestMaxConn` by option
 
- 	requestMaxConn = Math.max(parseInt(this.options.requestMaxConn), 1);
 
- 	
 
- 	/**
 
- 	 * Custom data that given as options
 
- 	 * 
 
- 	 * @type Object
 
- 	 * @default {}
 
- 	 */
 
- 	this.optsCustomData = $.isPlainObject(this.options.customData) ? this.options.customData : {};
 
- 	/**
 
- 	 * Any data to send across every ajax request
 
- 	 *
 
- 	 * @type Object
 
- 	 * @default {}
 
- 	 **/
 
- 	this.customData = Object.assign({}, this.optsCustomData);
 
- 	/**
 
- 	 * Previous custom data from connector
 
- 	 * 
 
- 	 * @type Object|null
 
- 	 */
 
- 	this.prevCustomData = null;
 
- 	/**
 
- 	 * Any custom headers to send across every ajax request
 
- 	 *
 
- 	 * @type Object
 
- 	 * @default {}
 
- 	*/
 
- 	this.customHeaders = $.isPlainObject(this.options.customHeaders) ? this.options.customHeaders : {};
 
- 	/**
 
- 	 * Any custom xhrFields to send across every ajax request
 
- 	 *
 
- 	 * @type Object
 
- 	 * @default {}
 
- 	 */
 
- 	this.xhrFields = $.isPlainObject(this.options.xhrFields) ? this.options.xhrFields : {};
 
- 	/**
 
- 	 * Replace XMLHttpRequest.prototype.send to extended function for 3rd party libs XHR request etc.
 
- 	 * 
 
- 	 * @type Function
 
- 	 */
 
- 	this.replaceXhrSend = function() {
 
- 		if (! savedXhrSend) {
 
- 			savedXhrSend = XMLHttpRequest.prototype.send;
 
- 		}
 
- 		XMLHttpRequest.prototype.send = function() {
 
- 			var xhr = this;
 
- 			// set request headers
 
- 			if (self.customHeaders) {
 
- 				$.each(self.customHeaders, function(key) {
 
- 					xhr.setRequestHeader(key, this);
 
- 				});
 
- 			}
 
- 			// set xhrFields
 
- 			if (self.xhrFields) {
 
- 				$.each(self.xhrFields, function(key) {
 
- 					if (key in xhr) {
 
- 						xhr[key] = this;
 
- 					}
 
- 				});
 
- 			}
 
- 			return savedXhrSend.apply(this, arguments);
 
- 		};
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Restore saved original XMLHttpRequest.prototype.send
 
- 	 * 
 
- 	 * @type Function
 
- 	 */
 
- 	this.restoreXhrSend = function() {
 
- 		savedXhrSend && (XMLHttpRequest.prototype.send = savedXhrSend);
 
- 	};
 
- 	/**
 
- 	 * command names for into queue for only cwd requests
 
- 	 * these commands aborts before `open` request
 
- 	 *
 
- 	 * @type Array
 
- 	 * @default ['tmb', 'parents']
 
- 	 */
 
- 	this.abortCmdsOnOpen = this.options.abortCmdsOnOpen || ['tmb', 'parents'];
 
- 	/**
 
- 	 * ui.nav id prefix
 
- 	 * 
 
- 	 * @type String
 
- 	 */
 
- 	this.navPrefix = 'nav' + (elFinder.prototype.uniqueid? elFinder.prototype.uniqueid : '') + '-';
 
- 	
 
- 	/**
 
- 	 * ui.cwd id prefix
 
- 	 * 
 
- 	 * @type String
 
- 	 */
 
- 	this.cwdPrefix = elFinder.prototype.uniqueid? ('cwd' + elFinder.prototype.uniqueid + '-') : '';
 
- 	
 
- 	// Increment elFinder.prototype.uniqueid
 
- 	++elFinder.prototype.uniqueid;
 
- 	
 
- 	/**
 
- 	 * URL to upload files
 
- 	 *
 
- 	 * @type String
 
- 	 **/
 
- 	this.uploadURL = opts.urlUpload || opts.url;
 
- 	
 
- 	/**
 
- 	 * Events namespace
 
- 	 *
 
- 	 * @type String
 
- 	 **/
 
- 	this.namespace = namespace;
 
- 	/**
 
- 	 * Today timestamp
 
- 	 *
 
- 	 * @type Number
 
- 	 **/
 
- 	this.today = (new Date(date.getFullYear(), date.getMonth(), date.getDate())).getTime()/1000;
 
- 	
 
- 	/**
 
- 	 * Yesterday timestamp
 
- 	 *
 
- 	 * @type Number
 
- 	 **/
 
- 	this.yesterday = this.today - 86400;
 
- 	
 
- 	utc = this.options.UTCDate ? 'UTC' : '';
 
- 	
 
- 	this.getHours    = 'get'+utc+'Hours';
 
- 	this.getMinutes  = 'get'+utc+'Minutes';
 
- 	this.getSeconds  = 'get'+utc+'Seconds';
 
- 	this.getDate     = 'get'+utc+'Date';
 
- 	this.getDay      = 'get'+utc+'Day';
 
- 	this.getMonth    = 'get'+utc+'Month';
 
- 	this.getFullYear = 'get'+utc+'FullYear';
 
- 	
 
- 	/**
 
- 	 * elFinder node z-index (auto detect on elFinder load)
 
- 	 *
 
- 	 * @type null | Number
 
- 	 **/
 
- 	this.zIndex;
 
- 	/**
 
- 	 * Current search status
 
- 	 * 
 
- 	 * @type Object
 
- 	 */
 
- 	this.searchStatus = {
 
- 		state  : 0, // 0: search ended, 1: search started, 2: in search result
 
- 		query  : '',
 
- 		target : '',
 
- 		mime   : '',
 
- 		mixed  : false, // in multi volumes search: false or Array that target volume ids
 
- 		ininc  : false // in incremental search
 
- 	};
 
- 	/**
 
- 	 * Interface language
 
- 	 *
 
- 	 * @type String
 
- 	 * @default "en"
 
- 	 **/
 
- 	this.lang = this.storage('lang') || this.options.lang;
 
- 	if (this.lang === 'jp') {
 
- 		this.lang = this.options.lang = 'ja';
 
- 	}
 
- 	this.viewType = this.storage('view') || this.options.defaultView || 'icons';
 
- 	this.sortType = this.storage('sortType') || this.options.sortType || 'name';
 
- 	
 
- 	this.sortOrder = this.storage('sortOrder') || this.options.sortOrder || 'asc';
 
- 	this.sortStickFolders = this.storage('sortStickFolders');
 
- 	if (this.sortStickFolders === null) {
 
- 		this.sortStickFolders = !!this.options.sortStickFolders;
 
- 	} else {
 
- 		this.sortStickFolders = !!this.sortStickFolders;
 
- 	}
 
- 	this.sortAlsoTreeview = this.storage('sortAlsoTreeview');
 
- 	if (this.sortAlsoTreeview === null) {
 
- 		this.sortAlsoTreeview = !!this.options.sortAlsoTreeview;
 
- 	} else {
 
- 		this.sortAlsoTreeview = !!this.sortAlsoTreeview;
 
- 	}
 
- 	this.sortRules = $.extend(true, {}, this._sortRules, this.options.sortRules);
 
- 	
 
- 	$.each(this.sortRules, function(name, method) {
 
- 		if (typeof method != 'function') {
 
- 			delete self.sortRules[name];
 
- 		} 
 
- 	});
 
- 	
 
- 	this.compare = $.proxy(this.compare, this);
 
- 	
 
- 	/**
 
- 	 * Delay in ms before open notification dialog
 
- 	 *
 
- 	 * @type Number
 
- 	 * @default 500
 
- 	 **/
 
- 	this.notifyDelay = this.options.notifyDelay > 0 ? parseInt(this.options.notifyDelay) : 500;
 
- 	
 
- 	/**
 
- 	 * Dragging UI Helper object
 
- 	 *
 
- 	 * @type jQuery | null
 
- 	 **/
 
- 	this.draggingUiHelper = null;
 
- 	
 
- 	/**
 
- 	 * Base droppable options
 
- 	 *
 
- 	 * @type Object
 
- 	 **/
 
- 	this.droppable = {
 
- 		greedy     : true,
 
- 		tolerance  : 'pointer',
 
- 		accept     : '.elfinder-cwd-file-wrapper,.elfinder-navbar-dir,.elfinder-cwd-file,.elfinder-cwd-filename',
 
- 		hoverClass : this.res('class', 'adroppable'),
 
- 		classes    : { // Deprecated hoverClass jQueryUI>=1.12.0
 
- 			'ui-droppable-hover': this.res('class', 'adroppable')
 
- 		},
 
- 		autoDisable: true, // elFinder original, see jquery.elfinder.js
 
- 		drop : function(e, ui) {
 
- 			var dst     = $(this),
 
- 				targets = $.grep(ui.helper.data('files')||[], function(h) { return h? true : false; }),
 
- 				result  = [],
 
- 				dups    = [],
 
- 				faults  = [],
 
- 				isCopy  = ui.helper.hasClass('elfinder-drag-helper-plus'),
 
- 				c       = 'class',
 
- 				cnt, hash, i, h;
 
- 			
 
- 			if (typeof e.button === 'undefined' || ui.helper.data('namespace') !== namespace || ! self.insideWorkzone(e.pageX, e.pageY)) {
 
- 				return false;
 
- 			}
 
- 			if (dst.hasClass(self.res(c, 'cwdfile'))) {
 
- 				hash = self.cwdId2Hash(dst.attr('id'));
 
- 			} else if (dst.hasClass(self.res(c, 'navdir'))) {
 
- 				hash = self.navId2Hash(dst.attr('id'));
 
- 			} else {
 
- 				hash = cwd;
 
- 			}
 
- 			cnt = targets.length;
 
- 			
 
- 			while (cnt--) {
 
- 				h = targets[cnt];
 
- 				// ignore drop into itself or in own location
 
- 				if (h != hash && files[h].phash != hash) {
 
- 					result.push(h);
 
- 				} else {
 
- 					((isCopy && h !== hash && files[hash].write)? dups : faults).push(h);
 
- 				}
 
- 			}
 
- 			
 
- 			if (faults.length) {
 
- 				return false;
 
- 			}
 
- 			
 
- 			ui.helper.data('droped', true);
 
- 			
 
- 			if (dups.length) {
 
- 				ui.helper.hide();
 
- 				self.exec('duplicate', dups, {_userAction: true});
 
- 			}
 
- 			
 
- 			if (result.length) {
 
- 				ui.helper.hide();
 
- 				self.clipboard(result, !isCopy);
 
- 				self.exec('paste', hash, {_userAction: true}, hash).always(function(){
 
- 					self.clipboard([]);
 
- 					self.trigger('unlockfiles', {files : targets});
 
- 				});
 
- 				self.trigger('drop', {files : targets});
 
- 			}
 
- 		}
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return true if filemanager is active
 
- 	 *
 
- 	 * @return Boolean
 
- 	 **/
 
- 	this.enabled = function() {
 
- 		return enabled && this.visible();
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return true if filemanager is visible
 
- 	 *
 
- 	 * @return Boolean
 
- 	 **/
 
- 	this.visible = function() {
 
- 		return node[0].elfinder && node.is(':visible');
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return file is root?
 
- 	 * 
 
- 	 * @param  Object  target file object
 
- 	 * @return Boolean
 
- 	 */
 
- 	this.isRoot = function(file) {
 
- 		return (file.isroot || ! file.phash)? true : false;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return root dir hash for current working directory
 
- 	 * 
 
- 	 * @param  String   target hash
 
- 	 * @param  Boolean  include fake parent (optional)
 
- 	 * @return String
 
- 	 */
 
- 	this.root = function(hash, fake) {
 
- 		hash = hash || cwd;
 
- 		var dir, i;
 
- 		
 
- 		if (! fake) {
 
- 			$.each(self.roots, function(id, rhash) {
 
- 				if (hash.indexOf(id) === 0) {
 
- 					dir = rhash;
 
- 					return false;
 
- 				}
 
- 			});
 
- 			if (dir) {
 
- 				return dir;
 
- 			}
 
- 		}
 
- 		
 
- 		dir = files[hash];
 
- 		while (dir && dir.phash && (fake || ! dir.isroot)) {
 
- 			dir = files[dir.phash];
 
- 		}
 
- 		if (dir) {
 
- 			return dir.hash;
 
- 		}
 
- 		
 
- 		while (i in files && files.hasOwnProperty(i)) {
 
- 			dir = files[i];
 
- 			if (dir.mime === 'directory' && !dir.phash && dir.read) {
 
- 				return dir.hash;
 
- 			}
 
- 		}
 
- 		
 
- 		return '';
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return current working directory info
 
- 	 * 
 
- 	 * @return Object
 
- 	 */
 
- 	this.cwd = function() {
 
- 		return files[cwd] || {};
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return required cwd option
 
- 	 * 
 
- 	 * @param  String  option name
 
- 	 * @param  String  target hash (optional)
 
- 	 * @return mixed
 
- 	 */
 
- 	this.option = function(name, target) {
 
- 		var res, item;
 
- 		target = target || cwd;
 
- 		if (self.optionsByHashes[target] && typeof self.optionsByHashes[target][name] !== 'undefined') {
 
- 			return self.optionsByHashes[target][name];
 
- 		}
 
- 		if (self.hasVolOptions && cwd !== target && (!(item = self.file(target)) || item.phash !== cwd)) {
 
- 			res = '';
 
- 			$.each(self.volOptions, function(id, opt) {
 
- 				if (target.indexOf(id) === 0) {
 
- 					res = opt[name] || '';
 
- 					return false;
 
- 				}
 
- 			});
 
- 			return res;
 
- 		} else {
 
- 			return cwdOptions[name] || '';
 
- 		}
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return disabled commands by each folder
 
- 	 * 
 
- 	 * @param  Array  target hashes
 
- 	 * @return Array
 
- 	 */
 
- 	this.getDisabledCmds = function(targets, flip) {
 
- 		var disabled = {'hidden': true};
 
- 		if (! Array.isArray(targets)) {
 
- 			targets = [ targets ];
 
- 		}
 
- 		$.each(targets, function(i, h) {
 
- 			var disCmds = self.option('disabledFlip', h);
 
- 			if (disCmds) {
 
- 				Object.assign(disabled, disCmds);
 
- 			}
 
- 		});
 
- 		return flip? disabled : Object.keys(disabled);
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return file data from current dir or tree by it's hash
 
- 	 * 
 
- 	 * @param  String  file hash
 
- 	 * @return Object
 
- 	 */
 
- 	this.file = function(hash, alsoHidden) { 
 
- 		return hash? (files[hash] || (alsoHidden? hiddenFiles[hash] : void(0))) : void(0); 
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return all cached files
 
- 	 * 
 
- 	 * @param  String  parent hash
 
- 	 * @return Object
 
- 	 */
 
- 	this.files = function(phash) {
 
- 		var items = {};
 
- 		if (phash) {
 
- 			if (!ownFiles[phash]) {
 
- 				return {};
 
- 			}
 
- 			$.each(ownFiles[phash], function(h) {
 
- 				if (files[h]) {
 
- 					items[h] = files[h];
 
- 				} else {
 
- 					delete ownFiles[phash][h];
 
- 				}
 
- 			});
 
- 			return Object.assign({}, items);
 
- 		}
 
- 		return Object.assign({}, files);
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return list of file parents hashes include file hash
 
- 	 * 
 
- 	 * @param  String  file hash
 
- 	 * @return Array
 
- 	 */
 
- 	this.parents = function(hash) {
 
- 		var parents = [],
 
- 			dir;
 
- 		
 
- 		while (hash && (dir = this.file(hash))) {
 
- 			parents.unshift(dir.hash);
 
- 			hash = dir.phash;
 
- 		}
 
- 		return parents;
 
- 	};
 
- 	
 
- 	this.path2array = function(hash, i18) {
 
- 		var file, 
 
- 			path = [];
 
- 			
 
- 		while (hash) {
 
- 			if ((file = files[hash]) && file.hash) {
 
- 				path.unshift(i18 && file.i18 ? file.i18 : file.name);
 
- 				hash = file.isroot? null : file.phash;
 
- 			} else {
 
- 				path = [];
 
- 				break;
 
- 			}
 
- 		}
 
- 			
 
- 		return path;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return file path or Get path async with jQuery.Deferred
 
- 	 * 
 
- 	 * @param  Object  file
 
- 	 * @param  Boolean i18
 
- 	 * @param  Object  asyncOpt
 
- 	 * @return String|jQuery.Deferred
 
- 	 */
 
- 	this.path = function(hash, i18, asyncOpt) { 
 
- 		var path = files[hash] && files[hash].path
 
- 			? files[hash].path
 
- 			: this.path2array(hash, i18).join(cwdOptions.separator);
 
- 		if (! asyncOpt || ! files[hash]) {
 
- 			return path;
 
- 		} else {
 
- 			asyncOpt = Object.assign({notify: {type : 'parents', cnt : 1, hideCnt : true}}, asyncOpt);
 
- 			
 
- 			var dfd    = $.Deferred(),
 
- 				notify = asyncOpt.notify,
 
- 				noreq  = false,
 
- 				req    = function() {
 
- 					self.request({
 
- 						data : {cmd : 'parents', target : files[hash].phash},
 
- 						notify : notify,
 
- 						preventFail : true
 
- 					})
 
- 					.done(done)
 
- 					.fail(function() {
 
- 						dfd.reject();
 
- 					});
 
- 				},
 
- 				done   = function() {
 
- 					self.one('parentsdone', function() {
 
- 						path = self.path(hash, i18);
 
- 						if (path === '' && noreq) {
 
- 							//retry with request
 
- 							noreq = false;
 
- 							req();
 
- 						} else {
 
- 							if (notify) {
 
- 								clearTimeout(ntftm);
 
- 								notify.cnt = -(parseInt(notify.cnt || 0));
 
- 								self.notify(notify);
 
- 							}
 
- 							dfd.resolve(path);
 
- 						}
 
- 					});
 
- 				},
 
- 				ntftm;
 
- 		
 
- 			if (path) {
 
- 				return dfd.resolve(path);
 
- 			} else {
 
- 				if (self.ui['tree']) {
 
- 					// try as no request
 
- 					if (notify) {
 
- 						ntftm = setTimeout(function() {
 
- 							self.notify(notify);
 
- 						}, self.notifyDelay);
 
- 					}
 
- 					noreq = true;
 
- 					done(true);
 
- 				} else {
 
- 					req();
 
- 				}
 
- 				return dfd;
 
- 			}
 
- 		}
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return file url if set
 
- 	 * 
 
- 	 * @param  String  file hash
 
- 	 * @param  Object  Options
 
- 	 * @return String
 
- 	 */
 
- 	this.url = function(hash, o) {
 
- 		var file   = files[hash],
 
- 			opts   = o || {},
 
- 			async  = opts.async || false,
 
- 			temp   = opts.temporary || false,
 
- 			dfrd   = async? $.Deferred() : null,
 
- 			getUrl = function(url) {
 
- 				if (url) {
 
- 					return url;
 
- 				}
 
- 				if (file.url) {
 
- 					return file.url;
 
- 				}
 
- 				
 
- 				if (typeof baseUrl === 'undefined') {
 
- 					baseUrl = self.option('url', (!self.isRoot(file) && file.phash) || file.hash);
 
- 				}
 
- 				
 
- 				if (baseUrl) {
 
- 					return baseUrl + $.map(self.path2array(hash), function(n) { return encodeURIComponent(n); }).slice(1).join('/');
 
- 				}
 
- 				var params = Object.assign({}, self.customData, {
 
- 					cmd: 'file',
 
- 					target: file.hash
 
- 				});
 
- 				if (self.oldAPI) {
 
- 					params.cmd = 'open';
 
- 					params.current = file.phash;
 
- 				}
 
- 				return self.options.url + (self.options.url.indexOf('?') === -1 ? '?' : '&') + $.param(params, true);
 
- 			}, 
 
- 			baseUrl, res;
 
- 		
 
- 		if (!file || !file.read) {
 
- 			return async? dfrd.resolve('') : '';
 
- 		}
 
- 		
 
- 		if (file.url == '1' || (temp && !file.url && !(baseUrl = self.option('url', (!self.isRoot(file) && file.phash) || file.hash)))) {
 
- 			this.request({
 
- 				data : { cmd : 'url', target : hash, options : { temporary: temp? 1 : 0 } },
 
- 				preventDefault : true,
 
- 				options: {async: async},
 
- 				notify: async? {type : temp? 'file' : 'url', cnt : 1, hideCnt : true} : {}
 
- 			})
 
- 			.done(function(data) {
 
- 				file.url = data.url || '';
 
- 			})
 
- 			.fail(function() {
 
- 				file.url = '';
 
- 			})
 
- 			.always(function() {
 
- 				var url;
 
- 				if (file.url && temp) {
 
- 					url = file.url;
 
- 					file.url = '1'; // restore
 
- 				}
 
- 				if (async) {
 
- 					dfrd.resolve(getUrl(url));
 
- 				} else {
 
- 					return getUrl(url);
 
- 				}
 
- 			});
 
- 		} else {
 
- 			if (async) {
 
- 				dfrd.resolve(getUrl());
 
- 			} else {
 
- 				return getUrl();
 
- 			}
 
- 		}
 
- 		
 
- 		if (async) {
 
- 			return dfrd;
 
- 		}
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return file url for open in elFinder
 
- 	 * 
 
- 	 * @param  String  file hash
 
- 	 * @param  Boolean for download link
 
- 	 * @return String
 
- 	 */
 
- 	this.openUrl = function(hash, download) {
 
- 		var file = files[hash],
 
- 			url  = '';
 
- 		
 
- 		if (!file || !file.read) {
 
- 			return '';
 
- 		}
 
- 		
 
- 		if (!download) {
 
- 			if (file.url) {
 
- 				if (file.url != 1) {
 
- 					url = file.url;
 
- 				}
 
- 			} else if (cwdOptions.url && file.hash.indexOf(self.cwd().volumeid) === 0) {
 
- 				url = cwdOptions.url + $.map(this.path2array(hash), function(n) { return encodeURIComponent(n); }).slice(1).join('/');
 
- 			}
 
- 			if (url) {
 
- 				url += (url.match(/\?/)? '&' : '?') + '_'.repeat((url.match(/[\?&](_+)t=/g) || ['&t=']).sort().shift().match(/[\?&](_*)t=/)[1].length + 1) + 't=' + (file.ts || parseInt(+new Date()/1000));
 
- 				return url;
 
- 			}
 
- 		}
 
- 		
 
- 		url = this.options.url;
 
- 		url = url + (url.indexOf('?') === -1 ? '?' : '&')
 
- 			+ (this.oldAPI ? 'cmd=open¤t='+file.phash : 'cmd=file')
 
- 			+ '&target=' + file.hash
 
- 			+ '&_t=' + (file.ts || parseInt(+new Date()/1000));
 
- 		
 
- 		if (download) {
 
- 			url += '&download=1';
 
- 		}
 
- 		
 
- 		$.each(this.customData, function(key, val) {
 
- 			url += '&' + encodeURIComponent(key) + '=' + encodeURIComponent(val);
 
- 		});
 
- 		
 
- 		return url;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return thumbnail url
 
- 	 * 
 
- 	 * @param  Object  file object
 
- 	 * @return String
 
- 	 */
 
- 	this.tmb = function(file) {
 
- 		var tmbUrl, tmbCrop,
 
- 			cls    = 'elfinder-cwd-bgurl',
 
- 			url    = '';
 
- 		if ($.isPlainObject(file)) {
 
- 			if (self.searchStatus.state && file.hash.indexOf(self.cwd().volumeid) !== 0) {
 
- 				tmbUrl = self.option('tmbUrl', file.hash);
 
- 				tmbCrop = self.option('tmbCrop', file.hash);
 
- 			} else {
 
- 				tmbUrl = cwdOptions['tmbUrl'];
 
- 				tmbCrop = cwdOptions['tmbCrop'];
 
- 			}
 
- 			if (tmbCrop) {
 
- 				cls += ' elfinder-cwd-bgurl-crop';
 
- 			}
 
- 			if (tmbUrl === 'self' && file.mime.indexOf('image/') === 0) {
 
- 				url = self.openUrl(file.hash);
 
- 				cls += ' elfinder-cwd-bgself';
 
- 			} else if ((self.oldAPI || tmbUrl) && file && file.tmb && file.tmb != 1) {
 
- 				url = tmbUrl + file.tmb;
 
- 			} else if (self.newAPI && file && file.tmb && file.tmb != 1) {
 
- 				url = file.tmb;
 
- 			}
 
- 			if (url) {
 
- 				if (file.ts && tmbUrl !== 'self') {
 
- 					url += (url.match(/\?/)? '&' : '?') + '_t=' + file.ts;
 
- 				}
 
- 				return { url: url, className: cls };
 
- 			}
 
- 		}
 
- 		
 
- 		return false;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return selected files hashes
 
- 	 *
 
- 	 * @return Array
 
- 	 **/
 
- 	this.selected = function() {
 
- 		return selected.slice(0);
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return selected files info
 
- 	 * 
 
- 	 * @return Array
 
- 	 */
 
- 	this.selectedFiles = function() {
 
- 		return $.map(selected, function(hash) { return files[hash] ? Object.assign({}, files[hash]) : null; });
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return true if file with required name existsin required folder
 
- 	 * 
 
- 	 * @param  String  file name
 
- 	 * @param  String  parent folder hash
 
- 	 * @return Boolean
 
- 	 */
 
- 	this.fileByName = function(name, phash) {
 
- 		var hash;
 
- 	
 
- 		for (hash in files) {
 
- 			if (files.hasOwnProperty(hash) && files[hash].phash == phash && files[hash].name == name) {
 
- 				return files[hash];
 
- 			}
 
- 		}
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Valid data for required command based on rules
 
- 	 * 
 
- 	 * @param  String  command name
 
- 	 * @param  Object  cammand's data
 
- 	 * @return Boolean
 
- 	 */
 
- 	this.validResponse = function(cmd, data) {
 
- 		return data.error || this.rules[this.rules[cmd] ? cmd : 'defaults'](data);
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return bytes from ini formated size
 
- 	 * 
 
- 	 * @param  String  ini formated size
 
- 	 * @return Integer
 
- 	 */
 
- 	this.returnBytes = function(val) {
 
- 		var last;
 
- 		if (isNaN(val)) {
 
- 			if (! val) {
 
- 				val = '';
 
- 			}
 
- 			// for ex. 1mb, 1KB
 
- 			val = val.replace(/b$/i, '');
 
- 			last = val.charAt(val.length - 1).toLowerCase();
 
- 			val = val.replace(/[tgmk]$/i, '');
 
- 			if (last == 't') {
 
- 				val = val * 1024 * 1024 * 1024 * 1024;
 
- 			} else if (last == 'g') {
 
- 				val = val * 1024 * 1024 * 1024;
 
- 			} else if (last == 'm') {
 
- 				val = val * 1024 * 1024;
 
- 			} else if (last == 'k') {
 
- 				val = val * 1024;
 
- 			}
 
- 			val = isNaN(val)? 0 : parseInt(val);
 
- 		} else {
 
- 			val = parseInt(val);
 
- 			if (val < 1) val = 0;
 
- 		}
 
- 		return val;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Process ajax request.
 
- 	 * Fired events :
 
- 	 * @todo
 
- 	 * @example
 
- 	 * @todo
 
- 	 * @return $.Deferred
 
- 	 */
 
- 	this.request = function(opts) { 
 
- 		var self     = this,
 
- 			o        = this.options,
 
- 			dfrd     = $.Deferred(),
 
- 			// request ID
 
- 			reqId    = (+ new Date()).toString(16) + Math.floor(1000 * Math.random()).toString(16), 
 
- 			// request data
 
- 			data     = Object.assign({}, self.customData, {mimes : o.onlyMimes}, opts.data || opts),
 
- 			// command name
 
- 			cmd      = data.cmd,
 
- 			// request type is binary
 
- 			isBinary = (opts.options || {}).dataType === 'binary',
 
- 			// current cmd is "open"
 
- 			isOpen   = (!opts.asNotOpen && cmd === 'open'),
 
- 			// call default fail callback (display error dialog) ?
 
- 			deffail  = !(isBinary || opts.preventDefault || opts.preventFail),
 
- 			// call default success callback ?
 
- 			defdone  = !(isBinary || opts.preventDefault || opts.preventDone),
 
- 			// options for notify dialog
 
- 			notify   = Object.assign({}, opts.notify),
 
- 			// make cancel button
 
- 			cancel   = !!opts.cancel,
 
- 			// do not normalize data - return as is
 
- 			raw      = isBinary || !!opts.raw,
 
- 			// sync files on request fail
 
- 			syncOnFail = opts.syncOnFail,
 
- 			// use lazy()
 
- 			lazy     = !!opts.lazy,
 
- 			// prepare function before done()
 
- 			prepare  = opts.prepare,
 
- 			// navigate option object when cmd done
 
- 			navigate = opts.navigate,
 
- 			// open notify dialog timeout
 
- 			timeout,
 
- 			// use browser cache
 
- 			useCache = (opts.options || {}).cache,
 
- 			// request options
 
- 			options = Object.assign({
 
- 				url      : o.url,
 
- 				async    : true,
 
- 				type     : this.requestType,
 
- 				dataType : 'json',
 
- 				cache    : (self.api >= 2.1029), // api >= 2.1029 has unique request ID
 
- 				data     : data,
 
- 				headers  : this.customHeaders,
 
- 				xhrFields: this.xhrFields
 
- 			}, opts.options || {}),
 
- 			/**
 
- 			 * Default success handler. 
 
- 			 * Call default data handlers and fire event with command name.
 
- 			 *
 
- 			 * @param Object  normalized response data
 
- 			 * @return void
 
- 			 **/
 
- 			done = function(data) {
 
- 				data.warning && self.error(data.warning);
 
- 				
 
- 				if (isOpen) {
 
- 					open(data);
 
- 				} else {
 
- 					self.updateCache(data);
 
- 				}
 
- 				
 
- 				data.changed && data.changed.length && change(data.changed);
 
- 				
 
- 				self.lazy(function() {
 
- 					// fire some event to update cache/ui
 
- 					data.removed && data.removed.length && self.remove(data);
 
- 					data.added   && data.added.length   && self.add(data);
 
- 					data.changed && data.changed.length && self.change(data);
 
- 				}).then(function() {
 
- 					// fire event with command name
 
- 					return self.lazy(function() {
 
- 						self.trigger(cmd, data, false);
 
- 					});
 
- 				}).then(function() {
 
- 					// fire event with command name + 'done'
 
- 					return self.lazy(function() {
 
- 						self.trigger(cmd + 'done');
 
- 					});
 
- 				}).then(function() {
 
- 					// make toast message
 
- 					if (data.toasts && Array.isArray(data.toasts)) {
 
- 						$.each(data.toasts, function() {
 
- 							this.msg && self.toast(this);
 
- 						});
 
- 					}
 
- 					// force update content
 
- 					data.sync && self.sync();
 
- 				});
 
- 			},
 
- 			/**
 
- 			 * Request error handler. Reject dfrd with correct error message.
 
- 			 *
 
- 			 * @param jqxhr  request object
 
- 			 * @param String request status
 
- 			 * @return void
 
- 			 **/
 
- 			error = function(xhr, status) {
 
- 				var error, data, 
 
- 					d = self.options.debug;
 
- 				
 
- 				switch (status) {
 
- 					case 'abort':
 
- 						error = xhr.quiet ? '' : ['errConnect', 'errAbort'];
 
- 						break;
 
- 					case 'timeout':	    
 
- 						error = ['errConnect', 'errTimeout'];
 
- 						break;
 
- 					case 'parsererror': 
 
- 						error = ['errResponse', 'errDataNotJSON'];
 
- 						if (xhr.responseText) {
 
- 							if (! cwd || (d && (d === 'all' || d['backend-error']))) {
 
- 								error.push(xhr.responseText);
 
- 							}
 
- 						}
 
- 						break;
 
- 					default:
 
- 						if (xhr.responseText) {
 
- 							// check responseText, Is that JSON?
 
- 							try {
 
- 								data = JSON.parse(xhr.responseText);
 
- 								if (data && data.error) {
 
- 									error = data.error;
 
- 								}
 
- 							} catch(e) {}
 
- 						}
 
- 						if (! error) {
 
- 							if (xhr.status == 403) {
 
- 								error = ['errConnect', 'errAccess', 'HTTP error ' + xhr.status];
 
- 							} else if (xhr.status == 404) {
 
- 								error = ['errConnect', 'errNotFound', 'HTTP error ' + xhr.status];
 
- 							} else if (xhr.status >= 500) {
 
- 								error = ['errResponse', 'errServerError', 'HTTP error ' + xhr.status];
 
- 							} else {
 
- 								if (xhr.status == 414 && options.type === 'get') {
 
- 									// retry by POST method
 
- 									options.type = 'post';
 
- 									self.abortXHR(xhr);
 
- 									dfrd.xhr = xhr = self.transport.send(options).fail(error).done(success);
 
- 									return;
 
- 								}
 
- 								error = xhr.quiet ? '' : ['errConnect', 'HTTP error ' + xhr.status];
 
- 							} 
 
- 						}
 
- 				}
 
- 				
 
- 				self.trigger(cmd + 'done');
 
- 				dfrd.reject({error: error}, xhr, status);
 
- 			},
 
- 			/**
 
- 			 * Request success handler. Valid response data and reject/resolve dfrd.
 
- 			 *
 
- 			 * @param Object  response data
 
- 			 * @param String request status
 
- 			 * @return void
 
- 			 **/
 
- 			success = function(response) {
 
- 				var d = self.options.debug;
 
- 				
 
- 				// Set currrent request command name
 
- 				self.currentReqCmd = cmd;
 
- 				
 
- 				if (response.debug && (!d || d !== 'all')) {
 
- 					if (!d) {
 
- 						d = self.options.debug = {};
 
- 					}
 
- 					d['backend-error'] = true;
 
- 					d['warning'] = true;
 
- 				}
 
- 				
 
- 				if (raw) {
 
- 					self.abortXHR(xhr);
 
- 					response && response.debug && self.debug('backend-debug', response);
 
- 					return dfrd.resolve(response);
 
- 				}
 
- 				
 
- 				if (!response) {
 
- 					return dfrd.reject({error :['errResponse', 'errDataEmpty']}, xhr, response);
 
- 				} else if (!$.isPlainObject(response)) {
 
- 					return dfrd.reject({error :['errResponse', 'errDataNotJSON']}, xhr, response);
 
- 				} else if (response.error) {
 
- 					if (isOpen) {
 
- 						// check leafRoots
 
- 						$.each(self.leafRoots, function(phash, roots) {
 
- 							self.leafRoots[phash] = $.grep(roots, function(h) { return h !== data.target; });
 
- 						});
 
- 					}
 
- 					return dfrd.reject({error :response.error}, xhr, response);
 
- 				}
 
- 				
 
- 				var resolve = function() {
 
- 					var pushLeafRoots = function(name) {
 
- 						if (self.leafRoots[data.target] && response[name]) {
 
- 							$.each(self.leafRoots[data.target], function(i, h) {
 
- 								var root;
 
- 								if (root = self.file(h)) {
 
- 									response[name].push(root);
 
- 								}
 
- 							});
 
- 						}
 
- 					},
 
- 					setTextMimes = function() {
 
- 						self.textMimes = {};
 
- 						$.each(self.res('mimes', 'text'), function() {
 
- 							self.textMimes[this.toLowerCase()] = true;
 
- 						});
 
- 					},
 
- 					actionTarget;
 
- 					
 
- 					if (isOpen) {
 
- 						pushLeafRoots('files');
 
- 					} else if (cmd === 'tree') {
 
- 						pushLeafRoots('tree');
 
- 					}
 
- 					
 
- 					response = self.normalize(response);
 
- 					
 
- 					if (!self.validResponse(cmd, response)) {
 
- 						return dfrd.reject({error :(response.norError || 'errResponse')}, xhr, response);
 
- 					}
 
- 					
 
- 					if (isOpen) {
 
- 						if (!self.api) {
 
- 							self.api    = response.api || 1;
 
- 							if (self.api == '2.0' && typeof response.options.uploadMaxSize !== 'undefined') {
 
- 								self.api = '2.1';
 
- 							}
 
- 							self.newAPI = self.api >= 2;
 
- 							self.oldAPI = !self.newAPI;
 
- 						}
 
- 						
 
- 						if (response.textMimes && Array.isArray(response.textMimes)) {
 
- 							self.resources.mimes.text = response.textMimes;
 
- 							setTextMimes();
 
- 						}
 
- 						!self.textMimes && setTextMimes();
 
- 						
 
- 						if (response.options) {
 
- 							cwdOptions = Object.assign({}, cwdOptionsDefault, response.options);
 
- 						}
 
- 						if (response.netDrivers) {
 
- 							self.netDrivers = response.netDrivers;
 
- 						}
 
- 						if (response.maxTargets) {
 
- 							self.maxTargets = response.maxTargets;
 
- 						}
 
- 						if (!!data.init) {
 
- 							self.uplMaxSize = self.returnBytes(response.uplMaxSize);
 
- 							self.uplMaxFile = !!response.uplMaxFile? Math.max(parseInt(response.uplMaxFile), 50) : 20;
 
- 						}
 
- 					}
 
- 					if (typeof prepare === 'function') {
 
- 						prepare(response);
 
- 					}
 
- 					
 
- 					if (navigate) {
 
- 						actionTarget = navigate.target || 'added';
 
- 						if (response[actionTarget] && response[actionTarget].length) {
 
- 							self.one(cmd + 'done', function() {
 
- 								var targets  = response[actionTarget],
 
- 									newItems = self.findCwdNodes(targets),
 
- 									inCwdHashes = function() {
 
- 										var cwdHash = self.cwd().hash;
 
- 										return $.map(targets, function(f) { return (f.phash && cwdHash === f.phash)? f.hash : null; });
 
- 									},
 
- 									hashes   = inCwdHashes(),
 
- 									makeToast  = function(t) {
 
- 										var node = void(0),
 
- 											data = t.action? t.action.data : void(0),
 
- 											cmd, msg, done;
 
- 										if ((data || hashes.length) && t.action && (msg = t.action.msg) && (cmd = t.action.cmd) && (!t.action.cwdNot || t.action.cwdNot !== self.cwd().hash)) {
 
- 											done = t.action.done;
 
- 											data = t.action.data;
 
- 											node = $('<div/>')
 
- 												.append(
 
- 													$('<button type="button" class="ui-button ui-widget ui-state-default ui-corner-all elfinder-tabstop"><span class="ui-button-text">'
 
- 														+self.i18n(msg)
 
- 														+'</span></button>')
 
- 													.on('mouseenter mouseleave', function(e) { 
 
- 														$(this).toggleClass('ui-state-hover', e.type == 'mouseenter');
 
- 													})
 
- 													.on('click', function() {
 
- 														self.exec(cmd, data || hashes, {_userAction: true, _currentType: 'toast', _currentNode: $(this) });
 
- 														if (done) {
 
- 															self.one(cmd+'done', function() {
 
- 																if (typeof done === 'function') {
 
- 																	done();
 
- 																} else if (done === 'select') {
 
- 																	self.trigger('selectfiles', {files : inCwdHashes()});
 
- 																}
 
- 															});
 
- 														}
 
- 													})
 
- 												);
 
- 										}
 
- 										delete t.action;
 
- 										t.extNode = node;
 
- 										return t;
 
- 									};
 
- 								
 
- 								if (! navigate.toast) {
 
- 									navigate.toast = {};
 
- 								}
 
- 								
 
- 								!navigate.noselect && self.trigger('selectfiles', {files : self.searchStatus.state > 1 ? $.map(targets, function(f) { return f.hash; }) : hashes});
 
- 								
 
- 								if (newItems.length) {
 
- 									if (!navigate.noscroll) {
 
- 										newItems.first().trigger('scrolltoview', {blink : false});
 
- 										self.resources.blink(newItems, 'lookme');
 
- 									}
 
- 									if ($.isPlainObject(navigate.toast.incwd)) {
 
- 										self.toast(makeToast(navigate.toast.incwd));
 
- 									}
 
- 								} else {
 
- 									if ($.isPlainObject(navigate.toast.inbuffer)) {
 
- 										self.toast(makeToast(navigate.toast.inbuffer));
 
- 									}
 
- 								}
 
- 							});
 
- 						}
 
- 					}
 
- 					
 
- 					dfrd.resolve(response);
 
- 					
 
- 					response.debug && self.debug('backend-debug', response);
 
- 				};
 
- 				self.abortXHR(xhr);
 
- 				lazy? self.lazy(resolve) : resolve();
 
- 			},
 
- 			xhr, _xhr,
 
- 			xhrAbort = function(e) {
 
- 				if (xhr && xhr.state() === 'pending') {
 
- 					self.abortXHR(xhr, { quiet: true , abort: true });
 
- 					if (!e || (e.type !== 'unload' && e.type !== 'destroy')) {
 
- 						self.autoSync();
 
- 					}
 
- 				}
 
- 			},
 
- 			abort = function(e){
 
- 				self.trigger(cmd + 'done');
 
- 				if (e.type == 'autosync') {
 
- 					if (e.data.action != 'stop') return;
 
- 				} else if (e.type != 'unload' && e.type != 'destroy' && e.type != 'openxhrabort') {
 
- 					if (!e.data.added || !e.data.added.length) {
 
- 						return;
 
- 					}
 
- 				}
 
- 				xhrAbort(e);
 
- 			},
 
- 			request = function(mode) {
 
- 				var queueAbort = function() {
 
- 					syncOnFail = false;
 
- 					dfrd.reject();
 
- 				};
 
- 				
 
- 				if (mode) {
 
- 					if (mode === 'cmd') {
 
- 						return cmd;
 
- 					}
 
- 				}
 
- 				
 
- 				if (isOpen) {
 
- 					if (requestQueueSkipOpen) {
 
- 						return dfrd.reject();
 
- 					}
 
- 					requestQueueSkipOpen = true;
 
- 				}
 
- 				
 
- 				dfrd.always(function() {
 
- 					delete options.headers['X-elFinderReqid'];
 
- 				}).fail(function(error, xhr, response) {
 
- 					var errData = {
 
- 						cmd: cmd,
 
- 						err: error,
 
- 						xhr: xhr,
 
- 						rc: response
 
- 					};
 
- 					// unset this cmd queue when user canceling
 
- 					// see notify : function - `cancel.reject(0);`
 
- 					if (error === 0) {
 
- 						if (requestQueue.length) {
 
- 							requestQueue = $.grep(requestQueue, function(req) {
 
- 								return (req('cmd') === cmd) ? false : true;
 
- 							});
 
- 						}
 
- 					}
 
- 					// trigger "requestError" event
 
- 					self.trigger('requestError', errData);
 
- 					if (errData._event && errData._event.isDefaultPrevented()) {
 
- 						deffail = false;
 
- 						syncOnFail = false;
 
- 						if (error) {
 
- 							error.error = '';
 
- 						}
 
- 					}
 
- 					// abort xhr
 
- 					xhrAbort();
 
- 					if (isOpen) {
 
- 						openDir = self.file(data.target);
 
- 						openDir && openDir.volumeid && self.isRoot(openDir) && delete self.volumeExpires[openDir.volumeid];
 
- 					}
 
- 					self.trigger(cmd + 'fail', response);
 
- 					if (error) {
 
- 						deffail ? self.error(error) : self.debug('error', self.i18n(error));
 
- 					}
 
- 					syncOnFail && self.sync();
 
- 				});
 
- 				if (!cmd) {
 
- 					syncOnFail = false;
 
- 					return dfrd.reject({error :'errCmdReq'});
 
- 				}
 
- 				
 
- 				if (self.maxTargets && data.targets && data.targets.length > self.maxTargets) {
 
- 					syncOnFail = false;
 
- 					return dfrd.reject({error :['errMaxTargets', self.maxTargets]});
 
- 				}
 
- 				defdone && dfrd.done(done);
 
- 				
 
- 				// quiet abort not completed "open" requests
 
- 				if (isOpen) {
 
- 					while ((_xhr = queue.pop())) {
 
- 						_xhr.queueAbort();
 
- 					}
 
- 					if (cwd !== data.target) {
 
- 						while ((_xhr = cwdQueue.pop())) {
 
- 							_xhr.queueAbort();
 
- 						}
 
- 					}
 
- 				}
 
- 				// trigger abort autoSync for commands to add the item
 
- 				if ($.inArray(cmd, (self.cmdsToAdd + ' autosync').split(' ')) !== -1) {
 
- 					if (cmd !== 'autosync') {
 
- 						self.autoSync('stop');
 
- 						dfrd.always(function() {
 
- 							self.autoSync();
 
- 						});
 
- 					}
 
- 					self.trigger('openxhrabort');
 
- 				}
 
- 				delete options.preventFail;
 
- 				if (self.api >= 2.1029) {
 
- 					if (useCache) {
 
- 						options.headers['X-elFinderReqid'] = reqId;
 
- 					} else {
 
- 						Object.assign(options.data, { reqid : reqId });
 
- 					}
 
- 				}
 
- 				
 
- 				// function for set value of this syncOnFail
 
- 				dfrd.syncOnFail = function(state) {
 
- 					syncOnFail = !!state;
 
- 				};
 
- 				requestCnt++;
 
- 				dfrd.xhr = xhr = self.transport.send(options).always(function() {
 
- 					// set responseURL from native xhr object
 
- 					if (options._xhr && typeof options._xhr.responseURL !== 'undefined') {
 
- 						xhr.responseURL = options._xhr.responseURL || '';
 
- 					}
 
- 					--requestCnt;
 
- 					if (requestQueue.length) {
 
- 						requestQueue.shift()();
 
- 					} else {
 
- 						requestQueueSkipOpen = false;
 
- 					}
 
- 				}).fail(error).done(success);
 
- 				
 
- 				if (self.api >= 2.1029) {
 
- 					xhr._requestId = reqId;
 
- 				}
 
- 				
 
- 				if (isOpen || (data.compare && cmd === 'info')) {
 
- 					// regist function queueAbort
 
- 					xhr.queueAbort = queueAbort;
 
- 					// add autoSync xhr into queue
 
- 					queue.unshift(xhr);
 
- 					// bind abort()
 
- 					data.compare && self.bind(self.cmdsToAdd + ' autosync openxhrabort', abort);
 
- 					dfrd.always(function() {
 
- 						var ndx = $.inArray(xhr, queue);
 
- 						data.compare && self.unbind(self.cmdsToAdd + ' autosync openxhrabort', abort);
 
- 						ndx !== -1 && queue.splice(ndx, 1);
 
- 					});
 
- 				} else if ($.inArray(cmd, self.abortCmdsOnOpen) !== -1) {
 
- 					// regist function queueAbort
 
- 					xhr.queueAbort = queueAbort;
 
- 					// add "open" xhr, only cwd xhr into queue
 
- 					cwdQueue.unshift(xhr);
 
- 					dfrd.always(function() {
 
- 						var ndx = $.inArray(xhr, cwdQueue);
 
- 						ndx !== -1 && cwdQueue.splice(ndx, 1);
 
- 					});
 
- 				}
 
- 				
 
- 				// abort pending xhr on window unload or elFinder destroy
 
- 				self.bind('unload destroy', abort);
 
- 				dfrd.always(function() {
 
- 					self.unbind('unload destroy', abort);
 
- 				});
 
- 				
 
- 				return dfrd;
 
- 			},
 
- 			queueingRequest = function() {
 
- 				// show notify
 
- 				if (notify.type && notify.cnt) {
 
- 					if (cancel) {
 
- 						notify.cancel = dfrd;
 
- 						opts.eachCancel && (notify.id = +new Date());
 
- 					}
 
- 					timeout = setTimeout(function() {
 
- 						self.notify(notify);
 
- 						dfrd.always(function() {
 
- 							notify.cnt = -(parseInt(notify.cnt)||0);
 
- 							self.notify(notify);
 
- 						});
 
- 					}, self.notifyDelay);
 
- 					
 
- 					dfrd.always(function() {
 
- 						clearTimeout(timeout);
 
- 					});
 
- 				}
 
- 				// queueing
 
- 				if (isOpen) {
 
- 					requestQueueSkipOpen = false;
 
- 				}
 
- 				if (requestCnt < requestMaxConn) {
 
- 					// do request
 
- 					return request();
 
- 				} else {
 
- 					if (isOpen) {
 
- 						requestQueue.unshift(request);
 
- 					} else {
 
- 						requestQueue.push(request);
 
- 					}
 
- 					return dfrd;
 
- 				}
 
- 			},
 
- 			bindData = {opts: opts, result: true},
 
- 			openDir;
 
- 		
 
- 		// prevent request initial request is completed
 
- 		if (!self.api && !data.init) {
 
- 			syncOnFail = false;
 
- 			return dfrd.reject();
 
- 		}
 
- 		// trigger "request.cmd" that callback be able to cancel request by substituting "false" for "event.data.result"
 
- 		self.trigger('request.' + cmd, bindData, true);
 
- 		
 
- 		if (! bindData.result) {
 
- 			self.trigger(cmd + 'done');
 
- 			return dfrd.reject();
 
- 		} else if (typeof bindData.result === 'object' && bindData.result.promise) {
 
- 			bindData.result
 
- 				.done(queueingRequest)
 
- 				.fail(function() {
 
- 					self.trigger(cmd + 'done');
 
- 					dfrd.reject();
 
- 				});
 
- 			return dfrd;
 
- 		}
 
- 		
 
- 		return queueingRequest();
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Call cache()
 
- 	 * Store info about files/dirs in "files" object.
 
- 	 *
 
- 	 * @param  Array  files
 
- 	 * @return void
 
- 	 */
 
- 	this.cache = function(dataArray) {
 
- 		if (! Array.isArray(dataArray)) {
 
- 			dataArray = [ dataArray ];
 
- 		}
 
- 		cache(dataArray);
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Update file object caches by respose data object
 
- 	 * 
 
- 	 * @param  Object  respose data object
 
- 	 * @return void
 
- 	 */
 
- 	this.updateCache = function(data) {
 
- 		if ($.isPlainObject(data)) {
 
- 			data.files && data.files.length && cache(data.files, 'files');
 
- 			data.tree && data.tree.length && cache(data.tree, 'tree');
 
- 			data.removed && data.removed.length && remove(data.removed);
 
- 			data.added && data.added.length && cache(data.added, 'add');
 
- 			data.changed && data.changed.length && change(data.changed, 'change');
 
- 		}
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Compare current files cache with new files and return diff
 
- 	 * 
 
- 	 * @param  Array   new files
 
- 	 * @param  String  target folder hash
 
- 	 * @param  Array   exclude properties to compare
 
- 	 * @return Object
 
- 	 */
 
- 	this.diff = function(incoming, onlydir, excludeProps) {
 
- 		var raw       = {},
 
- 			added     = [],
 
- 			removed   = [],
 
- 			changed   = [],
 
- 			excludes  = null,
 
- 			isChanged = function(hash) {
 
- 				var l = changed.length;
 
- 				while (l--) {
 
- 					if (changed[l].hash == hash) {
 
- 						return true;
 
- 					}
 
- 				}
 
- 			};
 
- 		
 
- 		$.each(incoming, function(i, f) {
 
- 			raw[f.hash] = f;
 
- 		});
 
- 		
 
- 		// make excludes object
 
- 		if (excludeProps && excludeProps.length) {
 
- 			excludes = {};
 
- 			$.each(excludeProps, function() {
 
- 				excludes[this] = true;
 
- 			});
 
- 		}
 
- 		
 
- 		// find removed
 
- 		$.each(files, function(hash, f) {
 
- 			if (! raw[hash] && (! onlydir || f.phash === onlydir)) {
 
- 				removed.push(hash);
 
- 			}
 
- 		});
 
- 		
 
- 		// compare files
 
- 		$.each(raw, function(hash, file) {
 
- 			var origin  = files[hash],
 
- 				orgKeys = {},
 
- 				chkKeyLen;
 
- 			if (!origin) {
 
- 				added.push(file);
 
- 			} else {
 
- 				// make orgKeys object
 
- 				$.each(Object.keys(origin), function() {
 
- 					orgKeys[this] = true;
 
- 				});
 
- 				$.each(file, function(prop) {
 
- 					delete orgKeys[prop];
 
- 					if (! excludes || ! excludes[prop]) {
 
- 						if (file[prop] !== origin[prop]) {
 
- 							changed.push(file);
 
- 							orgKeys = {};
 
- 							return false;
 
- 						}
 
- 					}
 
- 				});
 
- 				chkKeyLen = Object.keys(orgKeys).length;
 
- 				if (chkKeyLen !== 0) {
 
- 					if (excludes) {
 
- 						$.each(orgKeys, function(prop) {
 
- 							if (excludes[prop]) {
 
- 								--chkKeyLen;
 
- 							}
 
- 						});
 
- 					}
 
- 					(chkKeyLen !== 0) && changed.push(file);
 
- 				}
 
- 			}
 
- 		});
 
- 		
 
- 		// parents of removed dirs mark as changed (required for tree correct work)
 
- 		$.each(removed, function(i, hash) {
 
- 			var file  = files[hash], 
 
- 				phash = file.phash;
 
- 			if (phash 
 
- 			&& file.mime == 'directory' 
 
- 			&& $.inArray(phash, removed) === -1 
 
- 			&& raw[phash] 
 
- 			&& !isChanged(phash)) {
 
- 				changed.push(raw[phash]);
 
- 			}
 
- 		});
 
- 		
 
- 		return {
 
- 			added   : added,
 
- 			removed : removed,
 
- 			changed : changed
 
- 		};
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Sync content
 
- 	 * 
 
- 	 * @return jQuery.Deferred
 
- 	 */
 
- 	this.sync = function(onlydir, polling) {
 
- 		this.autoSync('stop');
 
- 		var self  = this,
 
- 			compare = function(){
 
- 				var c = '', cnt = 0, mtime = 0;
 
- 				if (onlydir && polling) {
 
- 					$.each(files, function(h, f) {
 
- 						if (f.phash && f.phash === onlydir) {
 
- 							++cnt;
 
- 							mtime = Math.max(mtime, f.ts);
 
- 						}
 
- 						c = cnt+':'+mtime;
 
- 					});
 
- 				}
 
- 				return c;
 
- 			},
 
- 			comp  = compare(),
 
- 			dfrd  = $.Deferred().done(function() { self.trigger('sync'); }),
 
- 			opts = [this.request({
 
- 				data           : {cmd : 'open', reload : 1, target : cwd, tree : (! onlydir && this.ui.tree) ? 1 : 0, compare : comp},
 
- 				preventDefault : true
 
- 			})],
 
- 			exParents = function() {
 
- 				var parents = [],
 
- 					curRoot = self.file(self.root(cwd)),
 
- 					curId = curRoot? curRoot.volumeid : null,
 
- 					phash = self.cwd().phash,
 
- 					isroot,pdir;
 
- 				
 
- 				while(phash) {
 
- 					if (pdir = self.file(phash)) {
 
- 						if (phash.indexOf(curId) !== 0) {
 
- 							parents.push( {target: phash, cmd: 'tree'} );
 
- 							if (! self.isRoot(pdir)) {
 
- 								parents.push( {target: phash, cmd: 'parents'} );
 
- 							}
 
- 							curRoot = self.file(self.root(phash));
 
- 							curId = curRoot? curRoot.volumeid : null;
 
- 						}
 
- 						phash = pdir.phash;
 
- 					} else {
 
- 						phash = null;
 
- 					}
 
- 				}
 
- 				return parents;
 
- 			};
 
- 		
 
- 		if (! onlydir && self.api >= 2) {
 
- 			(cwd !== this.root()) && opts.push(this.request({
 
- 				data           : {cmd : 'parents', target : cwd},
 
- 				preventDefault : true
 
- 			}));
 
- 			$.each(exParents(), function(i, data) {
 
- 				opts.push(self.request({
 
- 					data           : {cmd : data.cmd, target : data.target},
 
- 					preventDefault : true
 
- 				}));
 
- 			});
 
- 		}
 
- 		$.when.apply($, opts)
 
- 		.fail(function(error, xhr) {
 
- 			if (! polling || $.inArray('errOpen', error) !== -1) {
 
- 				dfrd.reject(error);
 
- 				self.parseError(error) && self.request({
 
- 					data   : {cmd : 'open', target : (self.lastDir('') || self.root()), tree : 1, init : 1},
 
- 					notify : {type : 'open', cnt : 1, hideCnt : true}
 
- 				});
 
- 			} else {
 
- 				dfrd.reject((error && xhr.status != 0)? error : void 0);
 
- 			}
 
- 		})
 
- 		.done(function(odata) {
 
- 			var pdata, argLen, i;
 
- 			
 
- 			if (odata.cwd.compare) {
 
- 				if (comp === odata.cwd.compare) {
 
- 					return dfrd.reject();
 
- 				}
 
- 			}
 
- 			
 
- 			// for 2nd and more requests
 
- 			pdata = {tree : []};
 
- 			
 
- 			// results marge of 2nd and more requests
 
- 			argLen = arguments.length;
 
- 			if (argLen > 1) {
 
- 				for(i = 1; i < argLen; i++) {
 
- 					if (arguments[i].tree && arguments[i].tree.length) {
 
- 						pdata.tree.push.apply(pdata.tree, arguments[i].tree);
 
- 					}
 
- 				}
 
- 			}
 
- 			
 
- 			if (self.api < 2.1) {
 
- 				if (! pdata.tree) {
 
- 					pdata.tree = [];
 
- 				}
 
- 				pdata.tree.push(odata.cwd);
 
- 			}
 
- 			
 
- 			// data normalize
 
- 			odata = self.normalize(odata);
 
- 			if (!self.validResponse('open', odata)) {
 
- 				return dfrd.reject((odata.norError || 'errResponse'));
 
- 			}
 
- 			pdata = self.normalize(pdata);
 
- 			if (!self.validResponse('tree', pdata)) {
 
- 				return dfrd.reject((pdata.norError || 'errResponse'));
 
- 			}
 
- 			
 
- 			var diff = self.diff(odata.files.concat(pdata && pdata.tree ? pdata.tree : []), onlydir);
 
- 			diff.added.push(odata.cwd);
 
- 			
 
- 			self.updateCache(diff);
 
- 			
 
- 			// trigger events
 
- 			diff.removed.length && self.remove(diff);
 
- 			diff.added.length   && self.add(diff);
 
- 			diff.changed.length && self.change(diff);
 
- 			return dfrd.resolve(diff);
 
- 		})
 
- 		.always(function() {
 
- 			self.autoSync();
 
- 		});
 
- 		
 
- 		return dfrd;
 
- 	};
 
- 	
 
- 	this.upload = function(files) {
 
- 		return this.transport.upload(files, this);
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Arrays that has to unbind events
 
- 	 * 
 
- 	 * @type Object
 
- 	 */
 
- 	this.toUnbindEvents = {};
 
- 	
 
- 	/**
 
- 	 * Attach listener to events
 
- 	 * To bind to multiply events at once, separate events names by space
 
- 	 * 
 
- 	 * @param  String  event(s) name(s)
 
- 	 * @param  Object  event handler or {done: handler}
 
- 	 * @param  Boolean priority first
 
- 	 * @return elFinder
 
- 	 */
 
- 	this.bind = function(event, callback, priorityFirst) {
 
- 		var i, len;
 
- 		
 
- 		if (callback && (typeof callback === 'function' || typeof callback.done === 'function')) {
 
- 			event = ('' + event).toLowerCase().replace(/^\s+|\s+$/g, '').split(/\s+/);
 
- 			
 
- 			len = event.length;
 
- 			for (i = 0; i < len; i++) {
 
- 				if (listeners[event[i]] === void(0)) {
 
- 					listeners[event[i]] = [];
 
- 				}
 
- 				listeners[event[i]][priorityFirst? 'unshift' : 'push'](callback);
 
- 			}
 
- 		}
 
- 		return this;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Remove event listener if exists
 
- 	 * To un-bind to multiply events at once, separate events names by space
 
- 	 *
 
- 	 * @param  String    event(s) name(s)
 
- 	 * @param  Function  callback
 
- 	 * @return elFinder
 
- 	 */
 
- 	this.unbind = function(event, callback) {
 
- 		var i, len, l, ci;
 
- 		
 
- 		event = ('' + event).toLowerCase().split(/\s+/);
 
- 		
 
- 		len = event.length;
 
- 		for (i = 0; i < len; i++) {
 
- 			if (l = listeners[event[i]]) {
 
- 				ci = $.inArray(callback, l);
 
- 				ci > -1 && l.splice(ci, 1);
 
- 			}
 
- 		}
 
- 		
 
- 		callback = null;
 
- 		return this;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Fire event - send notification to all event listeners
 
- 	 * In the callback `this` becames an event object
 
- 	 *
 
- 	 * @param  String   event type
 
- 	 * @param  Object   data to send across event
 
- 	 * @param  Boolean  allow modify data (call by reference of data) default: true
 
- 	 * @return elFinder
 
- 	 */
 
- 	this.trigger = function(evType, data, allowModify) {
 
- 		var type      = evType.toLowerCase(),
 
- 			isopen    = (type === 'open'),
 
- 			dataIsObj = (typeof data === 'object'),
 
- 			handlers  = listeners[type] || [],
 
- 			dones     = [],
 
- 			i, l, jst, event;
 
- 		
 
- 		this.debug('event-'+type, data);
 
- 		
 
- 		if (! dataIsObj || typeof allowModify === 'undefined') {
 
- 			allowModify = true;
 
- 		}
 
- 		if (l = handlers.length) {
 
- 			event = $.Event(type);
 
- 			if (data) {
 
- 				data._event = event;
 
- 			}
 
- 			if (allowModify) {
 
- 				event.data = data;
 
- 			}
 
- 			for (i = 0; i < l; i++) {
 
- 				if (! handlers[i]) {
 
- 					// probably un-binded this handler
 
- 					continue;
 
- 				}
 
- 				// handler is $.Deferred(), call all functions upon completion
 
- 				if (handlers[i].done) {
 
- 					dones.push(handlers[i].done);
 
- 					continue;
 
- 				}
 
- 				
 
- 				// set `event.data` only callback has argument
 
- 				if (handlers[i].length) {
 
- 					if (!allowModify) {
 
- 						// to avoid data modifications. remember about "sharing" passing arguments in js :) 
 
- 						if (typeof jst === 'undefined') {
 
- 							try {
 
- 								jst = JSON.stringify(data);
 
- 							} catch(e) {
 
- 								jst = false;
 
- 							}
 
- 						}
 
- 						event.data = jst? JSON.parse(jst) : data;
 
- 					}
 
- 				}
 
- 				try {
 
- 					if (handlers[i].call(event, event, this) === false || event.isDefaultPrevented()) {
 
- 						this.debug('event-stoped', event.type);
 
- 						break;
 
- 					}
 
- 				} catch (ex) {
 
- 					window.console && window.console.log && window.console.log(ex);
 
- 				}
 
- 				
 
- 			}
 
- 			
 
- 			// call done functions
 
- 			if (l = dones.length) {
 
- 				for (i = 0; i < l; i++) {
 
- 					try {
 
- 						if (dones[i].call(event, event, this) === false || event.isDefaultPrevented()) {
 
- 							this.debug('event-stoped', event.type + '(done)');
 
- 							break;
 
- 						}
 
- 					} catch (ex) {
 
- 						window.console && window.console.log && window.console.log(ex);
 
- 					}
 
- 				}
 
- 			}
 
- 			if (this.toUnbindEvents[type] && this.toUnbindEvents[type].length) {
 
- 				$.each(this.toUnbindEvents[type], function(i, v) {
 
- 					self.unbind(v.type, v.callback);
 
- 				});
 
- 				delete this.toUnbindEvents[type];
 
- 			}
 
- 		}
 
- 		return this;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Get event listeners
 
- 	 *
 
- 	 * @param  String   event type
 
- 	 * @return Array    listed event functions
 
- 	 */
 
- 	this.getListeners = function(event) {
 
- 		return event? listeners[event.toLowerCase()] : listeners;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Bind keybord shortcut to keydown event
 
- 	 *
 
- 	 * @example
 
- 	 *    elfinder.shortcut({ 
 
- 	 *       pattern : 'ctrl+a', 
 
- 	 *       description : 'Select all files', 
 
- 	 *       callback : function(e) { ... }, 
 
- 	 *       keypress : true|false (bind to keypress instead of keydown) 
 
- 	 *    })
 
- 	 *
 
- 	 * @param  Object  shortcut config
 
- 	 * @return elFinder
 
- 	 */
 
- 	this.shortcut = function(s) {
 
- 		var patterns, pattern, code, i, parts;
 
- 		
 
- 		if (this.options.allowShortcuts && s.pattern && $.isFunction(s.callback)) {
 
- 			patterns = s.pattern.toUpperCase().split(/\s+/);
 
- 			
 
- 			for (i= 0; i < patterns.length; i++) {
 
- 				pattern = patterns[i];
 
- 				parts   = pattern.split('+');
 
- 				code    = (code = parts.pop()).length == 1 
 
- 					? (code > 0 ? code : code.charCodeAt(0))
 
- 					: (code > 0 ? code : $.ui.keyCode[code]);
 
- 				if (code && !shortcuts[pattern]) {
 
- 					shortcuts[pattern] = {
 
- 						keyCode     : code,
 
- 						altKey      : $.inArray('ALT', parts)   != -1,
 
- 						ctrlKey     : $.inArray('CTRL', parts)  != -1,
 
- 						shiftKey    : $.inArray('SHIFT', parts) != -1,
 
- 						type        : s.type || 'keydown',
 
- 						callback    : s.callback,
 
- 						description : s.description,
 
- 						pattern     : pattern
 
- 					};
 
- 				}
 
- 			}
 
- 		}
 
- 		return this;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Registered shortcuts
 
- 	 *
 
- 	 * @type Object
 
- 	 **/
 
- 	this.shortcuts = function() {
 
- 		var ret = [];
 
- 		
 
- 		$.each(shortcuts, function(i, s) {
 
- 			ret.push([s.pattern, self.i18n(s.description)]);
 
- 		});
 
- 		return ret;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Get/set clipboard content.
 
- 	 * Return new clipboard content.
 
- 	 *
 
- 	 * @example
 
- 	 *   this.clipboard([]) - clean clipboard
 
- 	 *   this.clipboard([{...}, {...}], true) - put 2 files in clipboard and mark it as cutted
 
- 	 * 
 
- 	 * @param  Array    new files hashes
 
- 	 * @param  Boolean  cut files?
 
- 	 * @return Array
 
- 	 */
 
- 	this.clipboard = function(hashes, cut) {
 
- 		var map = function() { return $.map(clipboard, function(f) { return f.hash; }); };
 
- 		if (hashes !== void(0)) {
 
- 			clipboard.length && this.trigger('unlockfiles', {files : map()});
 
- 			remember = {};
 
- 			
 
- 			clipboard = $.map(hashes||[], function(hash) {
 
- 				var file = files[hash];
 
- 				if (file) {
 
- 					
 
- 					remember[hash] = true;
 
- 					
 
- 					return {
 
- 						hash   : hash,
 
- 						phash  : file.phash,
 
- 						name   : file.name,
 
- 						mime   : file.mime,
 
- 						read   : file.read,
 
- 						locked : file.locked,
 
- 						cut    : !!cut
 
- 					};
 
- 				}
 
- 				return null;
 
- 			});
 
- 			this.trigger('changeclipboard', {clipboard : clipboard.slice(0, clipboard.length)});
 
- 			cut && this.trigger('lockfiles', {files : map()});
 
- 		}
 
- 		// return copy of clipboard instead of refrence
 
- 		return clipboard.slice(0, clipboard.length);
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return true if command enabled
 
- 	 * 
 
- 	 * @param  String       command name
 
- 	 * @param  String|void  hash for check of own volume's disabled cmds
 
- 	 * @return Boolean
 
- 	 */
 
- 	this.isCommandEnabled = function(name, dstHash) {
 
- 		var disabled, cmd,
 
- 			cvid = self.cwd().volumeid || '';
 
- 		
 
- 		// In serach results use selected item hash to check
 
- 		if (!dstHash && self.searchStatus.state > 1 && self.selected().length) {
 
- 			dstHash = self.selected()[0];
 
- 		}
 
- 		if (dstHash && (! cvid || dstHash.indexOf(cvid) !== 0)) {
 
- 			disabled = self.option('disabledFlip', dstHash);
 
- 			//if (! disabled) {
 
- 			//	disabled = {};
 
- 			//}
 
- 		} else {
 
- 			disabled = cwdOptions.disabledFlip/* || {}*/;
 
- 		}
 
- 		cmd = this._commands[name];
 
- 		return cmd ? (cmd.alwaysEnabled || !disabled[name]) : false;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Exec command and return result;
 
- 	 *
 
- 	 * @param  String         command name
 
- 	 * @param  String|Array   usualy files hashes
 
- 	 * @param  String|Array   command options
 
- 	 * @param  String|void    hash for enabled check of own volume's disabled cmds
 
- 	 * @return $.Deferred
 
- 	 */		
 
- 	this.exec = function(cmd, files, opts, dstHash) {
 
- 		var dfrd, resType;
 
- 		
 
- 		// apply commandMap for keyboard shortcut
 
- 		if (!dstHash && this.commandMap[cmd] && this.commandMap[cmd] !== 'hidden') {
 
- 			cmd = this.commandMap[cmd];
 
- 		}
 
- 		if (cmd === 'open') {
 
- 			if (this.searchStatus.state || this.searchStatus.ininc) {
 
- 				this.trigger('searchend', { noupdate: true });
 
- 			}
 
- 			this.autoSync('stop');
 
- 		}
 
- 		if (!dstHash && files) {
 
- 			if ($.isArray(files)) {
 
- 				if (files.length) {
 
- 					dstHash = files[0];
 
- 				}
 
- 			} else {
 
- 				dstHash = files;
 
- 			}
 
- 		}
 
- 		dfrd = this._commands[cmd] && this.isCommandEnabled(cmd, dstHash) 
 
- 			? this._commands[cmd].exec(files, opts) 
 
- 			: $.Deferred().reject('No such command');
 
- 		
 
- 		resType = typeof dfrd;
 
- 		if (!(resType === 'object' && dfrd.promise)) {
 
- 			self.debug('warning', '"cmd.exec()" should be returned "$.Deferred" but cmd "' + cmd + '" returned "' + resType + '"');
 
- 			dfrd = $.Deferred().resolve();
 
- 		}
 
- 		
 
- 		this.trigger('exec', { dfrd : dfrd, cmd : cmd, files : files, opts : opts, dstHash : dstHash });
 
- 		return dfrd;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Create and return dialog.
 
- 	 *
 
- 	 * @param  String|DOMElement  dialog content
 
- 	 * @param  Object             dialog options
 
- 	 * @return jQuery
 
- 	 */
 
- 	this.dialog = function(content, options) {
 
- 		var dialog = $('<div/>').append(content).appendTo(node).elfinderdialog(options, self),
 
- 			dnode  = dialog.closest('.ui-dialog'),
 
- 			resize = function(){
 
- 				! dialog.data('draged') && dialog.is(':visible') && dialog.elfinderdialog('posInit');
 
- 			};
 
- 		if (dnode.length) {
 
- 			self.bind('resize', resize);
 
- 			dnode.on('remove', function() {
 
- 				self.unbind('resize', resize);
 
- 			});
 
- 		}
 
- 		return dialog;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Create and return toast.
 
- 	 *
 
- 	 * @param  Object  toast options - see ui/toast.js
 
- 	 * @return jQuery
 
- 	 */
 
- 	this.toast = function(options) {
 
- 		return $('<div class="ui-front"/>').appendTo(this.ui.toast).elfindertoast(options || {}, this);
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return UI widget or node
 
- 	 *
 
- 	 * @param  String  ui name
 
- 	 * @return jQuery
 
- 	 */
 
- 	this.getUI = function(ui) {
 
- 		return this.ui[ui] || (ui? $() : node);
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return elFinder.command instance or instances array
 
- 	 *
 
- 	 * @param  String  command name
 
- 	 * @return Object | Array
 
- 	 */
 
- 	this.getCommand = function(name) {
 
- 		return name === void(0) ? this._commands : this._commands[name];
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Resize elfinder node
 
- 	 * 
 
- 	 * @param  String|Number  width
 
- 	 * @param  String|Number  height
 
- 	 * @return void
 
- 	 */
 
- 	this.resize = function(w, h) {
 
- 		var getMargin = function() {
 
- 				var m = node.outerHeight(true) - node.innerHeight(),
 
- 					p = node;
 
- 				
 
- 				while(p.get(0) !== heightBase.get(0)) {
 
- 					p = p.parent();
 
- 					m += p.outerHeight(true) - p.innerHeight();
 
- 					if (! p.parent().length) {
 
- 						// reached the document
 
- 						break;
 
- 					}
 
- 				}
 
- 				return m;
 
- 			},
 
- 			fit = ! node.hasClass('ui-resizable'),
 
- 			prv = node.data('resizeSize') || {w: 0, h: 0},
 
- 			mt, size = {};
 
- 		if (heightBase && heightBase.data('resizeTm')) {
 
- 			clearTimeout(heightBase.data('resizeTm'));
 
- 		}
 
- 		
 
- 		if (typeof h === 'string') {
 
- 			if (mt = h.match(/^([0-9.]+)%$/)) {
 
- 				// setup heightBase
 
- 				if (! heightBase || ! heightBase.length) {
 
- 					heightBase = $(window);
 
- 				}
 
- 				if (! heightBase.data('marginToMyNode')) {
 
- 					heightBase.data('marginToMyNode', getMargin());
 
- 				}
 
- 				if (! heightBase.data('fitToBaseFunc')) {
 
- 					heightBase.data('fitToBaseFunc', function(e) {
 
- 						var tm = heightBase.data('resizeTm');
 
- 						e.preventDefault();
 
- 						e.stopPropagation();
 
- 						tm && cancelAnimationFrame(tm);
 
- 						if (! node.hasClass('elfinder-fullscreen') && (!self.UA.Mobile || heightBase.data('rotated') !== self.UA.Rotated)) {
 
- 							heightBase.data('rotated', self.UA.Rotated);
 
- 							heightBase.data('resizeTm', requestAnimationFrame(function() {
 
- 								self.restoreSize();
 
- 							}));
 
- 						}
 
- 					});
 
- 				}
 
- 				if (typeof heightBase.data('rotated') === 'undefined') {
 
- 					heightBase.data('rotated', self.UA.Rotated);
 
- 				}
 
- 				h = heightBase.height() * (mt[1] / 100) - heightBase.data('marginToMyNode');
 
- 				
 
- 				heightBase.off('resize.' + self.namespace, heightBase.data('fitToBaseFunc'));
 
- 				fit && heightBase.on('resize.' + self.namespace, heightBase.data('fitToBaseFunc'));
 
- 			}
 
- 		}
 
- 		
 
- 		node.css({ width : w, height : parseInt(h) });
 
- 		size.w = Math.round(node.width());
 
- 		size.h = Math.round(node.height());
 
- 		node.data('resizeSize', size);
 
- 		if (size.w !== prv.w || size.h !== prv.h) {
 
- 			node.trigger('resize');
 
- 			this.trigger('resize', {width : size.w, height : size.h});
 
- 		}
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Restore elfinder node size
 
- 	 * 
 
- 	 * @return elFinder
 
- 	 */
 
- 	this.restoreSize = function() {
 
- 		this.resize(width, height);
 
- 	};
 
- 	
 
- 	this.show = function() {
 
- 		node.show();
 
- 		this.enable().trigger('show');
 
- 	};
 
- 	
 
- 	this.hide = function() {
 
- 		if (this.options.enableAlways) {
 
- 			prevEnabled = enabled;
 
- 			enabled = false;
 
- 		}
 
- 		this.disable();
 
- 		this.trigger('hide');
 
- 		node.hide();
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Lazy execution function
 
- 	 * 
 
- 	 * @param  Object  function
 
- 	 * @param  Number  delay
 
- 	 * @param  Object  options
 
- 	 * @return Object  jQuery.Deferred
 
- 	 */
 
- 	this.lazy = function(func, delay, opts) {
 
- 		var busy = function(state) {
 
- 				var cnt = node.data('lazycnt'),
 
- 					repaint;
 
- 				
 
- 				if (state) {
 
- 					repaint = node.data('lazyrepaint')? false : opts.repaint;
 
- 					if (! cnt) {
 
- 						node.data('lazycnt', 1)
 
- 							.addClass('elfinder-processing');
 
- 					} else {
 
- 						node.data('lazycnt', ++cnt);
 
- 					}
 
- 					if (repaint) {
 
- 						node.data('lazyrepaint', true).css('display'); // force repaint
 
- 					}
 
- 				} else {
 
- 					if (cnt && cnt > 1) {
 
- 						node.data('lazycnt', --cnt);
 
- 					} else {
 
- 						repaint = node.data('lazyrepaint');
 
- 						node.data('lazycnt', 0)
 
- 							.removeData('lazyrepaint')
 
- 							.removeClass('elfinder-processing');
 
- 						repaint && node.css('display'); // force repaint;
 
- 						self.trigger('lazydone');
 
- 					}
 
- 				}
 
- 			},
 
- 			dfd  = $.Deferred(),
 
- 			callFunc = function() {
 
- 				dfd.resolve(func.call(dfd));
 
- 				busy(false);
 
- 			};
 
- 		
 
- 		delay = delay || 0;
 
- 		opts = opts || {};
 
- 		busy(true);
 
- 		
 
- 		if (delay) {
 
- 			setTimeout(callFunc, delay);
 
- 		} else {
 
- 			requestAnimationFrame(callFunc);
 
- 		}
 
- 		
 
- 		return dfd;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Destroy this elFinder instance
 
- 	 *
 
- 	 * @return void
 
- 	 **/
 
- 	this.destroy = function() {
 
- 		if (node && node[0].elfinder) {
 
- 			node.hasClass('elfinder-fullscreen') && self.toggleFullscreen(node);
 
- 			this.options.syncStart = false;
 
- 			this.autoSync('forcestop');
 
- 			this.trigger('destroy').disable();
 
- 			clipboard = [];
 
- 			selected = [];
 
- 			listeners = {};
 
- 			shortcuts = {};
 
- 			$(window).off('.' + namespace);
 
- 			$(document).off('.' + namespace);
 
- 			self.trigger = function(){};
 
- 			$(beeper).remove();
 
- 			node.off()
 
- 				.removeData()
 
- 				.empty()
 
- 				.append(prevContent.contents())
 
- 				.attr('class', prevContent.attr('class'))
 
- 				.attr('style', prevContent.attr('style'));
 
- 			delete node[0].elfinder;
 
- 			// restore kept events
 
- 			$.each(prevEvents, function(n, arr) {
 
- 				$.each(arr, function(i, o) {
 
- 					node.on(o.type + (o.namespace? '.'+o.namespace : ''), o.selector, o.handler);
 
- 				});
 
- 			});
 
- 		}
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Start or stop auto sync
 
- 	 * 
 
- 	 * @param  String|Bool  stop
 
- 	 * @return void
 
- 	 */
 
- 	this.autoSync = function(mode) {
 
- 		var sync;
 
- 		if (self.options.sync >= 1000) {
 
- 			if (syncInterval) {
 
- 				clearTimeout(syncInterval);
 
- 				syncInterval = null;
 
- 				self.trigger('autosync', {action : 'stop'});
 
- 			}
 
- 			
 
- 			if (mode === 'stop') {
 
- 				++autoSyncStop;
 
- 			} else {
 
- 				autoSyncStop = Math.max(0, --autoSyncStop);
 
- 			}
 
- 			
 
- 			if (autoSyncStop || mode === 'forcestop' || ! self.options.syncStart) {
 
- 				return;
 
- 			} 
 
- 			
 
- 			// run interval sync
 
- 			sync = function(start){
 
- 				var timeout;
 
- 				if (cwdOptions.syncMinMs && (start || syncInterval)) {
 
- 					start && self.trigger('autosync', {action : 'start'});
 
- 					timeout = Math.max(self.options.sync, cwdOptions.syncMinMs);
 
- 					syncInterval && clearTimeout(syncInterval);
 
- 					syncInterval = setTimeout(function() {
 
- 						var dosync = true, hash = cwd, cts;
 
- 						if (cwdOptions.syncChkAsTs && files[hash] && (cts = files[hash].ts)) {
 
- 							self.request({
 
- 								data : {cmd : 'info', targets : [hash], compare : cts, reload : 1},
 
- 								preventDefault : true
 
- 							})
 
- 							.done(function(data){
 
- 								var ts;
 
- 								dosync = true;
 
- 								if (data.compare) {
 
- 									ts = data.compare;
 
- 									if (ts == cts) {
 
- 										dosync = false;
 
- 									}
 
- 								}
 
- 								if (dosync) {
 
- 									self.sync(hash).always(function(){
 
- 										if (ts) {
 
- 											// update ts for cache clear etc.
 
- 											files[hash].ts = ts;
 
- 										}
 
- 										sync();
 
- 									});
 
- 								} else {
 
- 									sync();
 
- 								}
 
- 							})
 
- 							.fail(function(error, xhr){
 
- 								var err = self.parseError(error);
 
- 								if (err && xhr.status != 0) {
 
- 									self.error(err);
 
- 									if (Array.isArray(err) && $.inArray('errOpen', err) !== -1) {
 
- 										self.request({
 
- 											data   : {cmd : 'open', target : (self.lastDir('') || self.root()), tree : 1, init : 1},
 
- 											notify : {type : 'open', cnt : 1, hideCnt : true}
 
- 										});
 
- 									}
 
- 								} else {
 
- 									syncInterval = setTimeout(function() {
 
- 										sync();
 
- 									}, timeout);
 
- 								}
 
- 							});
 
- 						} else {
 
- 							self.sync(cwd, true).always(function(){
 
- 								sync();
 
- 							});
 
- 						}
 
- 					}, timeout);
 
- 				}
 
- 			};
 
- 			sync(true);
 
- 		}
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return bool is inside work zone of specific point
 
- 	 * 
 
- 	 * @param  Number event.pageX
 
- 	 * @param  Number event.pageY
 
- 	 * @return Bool
 
- 	 */
 
- 	this.insideWorkzone = function(x, y, margin) {
 
- 		var rectangle = this.getUI('workzone').data('rectangle');
 
- 		
 
- 		margin = margin || 1;
 
- 		if (x < rectangle.left + margin
 
- 		|| x > rectangle.left + rectangle.width + margin
 
- 		|| y < rectangle.top + margin
 
- 		|| y > rectangle.top + rectangle.height + margin) {
 
- 			return false;
 
- 		}
 
- 		return true;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Target ui node move to last of children of elFinder node fot to show front
 
- 	 * 
 
- 	 * @param  Object  target    Target jQuery node object
 
- 	 */
 
- 	this.toFront = function(target) {
 
- 		var nodes = node.children('.ui-front').removeClass('elfinder-frontmost'),
 
- 			lastnode = nodes.last();
 
- 		nodes.css('z-index', '');
 
- 		$(target).addClass('ui-front elfinder-frontmost').css('z-index', lastnode.css('z-index') + 1);
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Remove class 'elfinder-frontmost' and hide() to target ui node
 
- 	 *
 
- 	 * @param      Object   target  Target jQuery node object
 
- 	 * @param      Boolean  nohide  Do not hide
 
- 	 */
 
- 	this.toHide =function(target, nohide) {
 
- 		var tgt = $(target),
 
- 			last;
 
- 		!nohide && tgt.hide();
 
- 		if (tgt.hasClass('elfinder-frontmost')) {
 
- 			tgt.removeClass('elfinder-frontmost');
 
- 			last = node.children('.ui-front:visible:not(.elfinder-frontmost)').last();
 
- 			if (last.length) {
 
- 				requestAnimationFrame(function() {
 
- 					if (!node.children('.elfinder-frontmost:visible').length) {
 
- 						self.toFront(last);
 
- 						last.trigger('frontmost');
 
- 					}
 
- 				});
 
- 			}
 
- 		}
 
- 	};
 
- 	/**
 
- 	 * Return css object for maximize
 
- 	 * 
 
- 	 * @return Object
 
- 	 */
 
- 	this.getMaximizeCss = function() {
 
- 		return {
 
- 			width   : '100%',
 
- 			height  : '100%',
 
- 			margin  : 0,
 
- 			top     : 0,
 
- 			left    : 0,
 
- 			display : 'block',
 
- 			position: 'fixed',
 
- 			zIndex  : Math.max(self.zIndex? (self.zIndex + 1) : 0 , 1000),
 
- 			maxWidth : '',
 
- 			maxHeight: ''
 
- 		};
 
- 	};
 
- 	
 
- 	// Closure for togglefullscreen
 
- 	(function() {
 
- 		// check is in iframe
 
- 		if (inFrame && self.UA.Fullscreen) {
 
- 			self.UA.Fullscreen = false;
 
- 			if (parentIframe && typeof parentIframe.attr('allowfullscreen') !== 'undefined') {
 
- 				self.UA.Fullscreen = true;
 
- 			}
 
- 		}
 
- 		var orgStyle, bodyOvf, resizeTm, fullElm, exitFull, toFull,
 
- 			cls = 'elfinder-fullscreen',
 
- 			clsN = 'elfinder-fullscreen-native',
 
- 			checkDialog = function() {
 
- 				var t = 0,
 
- 					l = 0;
 
- 				$.each(node.children('.ui-dialog,.ui-draggable'), function(i, d) {
 
- 					var $d = $(d),
 
- 						pos = $d.position();
 
- 					
 
- 					if (pos.top < 0) {
 
- 						$d.css('top', t);
 
- 						t += 20;
 
- 					}
 
- 					if (pos.left < 0) {
 
- 						$d.css('left', l);
 
- 						l += 20;
 
- 					}
 
- 				});
 
- 			},
 
- 			funcObj = self.UA.Fullscreen? {
 
- 				// native full screen mode
 
- 				
 
- 				fullElm: function() {
 
- 					return document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement || null;
 
- 				},
 
- 				
 
- 				exitFull: function() {
 
- 					if (document.exitFullscreen) {
 
- 						return document.exitFullscreen();
 
- 					} else if (document.webkitExitFullscreen) {
 
- 						return document.webkitExitFullscreen();
 
- 					} else if (document.mozCancelFullScreen) {
 
- 						return document.mozCancelFullScreen();
 
- 					} else if (document.msExitFullscreen) {
 
- 						return document.msExitFullscreen();
 
- 					}
 
- 				},
 
- 				
 
- 				toFull: function(elem) {
 
- 					if (elem.requestFullscreen) {
 
- 						return elem.requestFullscreen();
 
- 					} else if (elem.webkitRequestFullscreen) {
 
- 						return elem.webkitRequestFullscreen();
 
- 					} else if (elem.mozRequestFullScreen) {
 
- 						return elem.mozRequestFullScreen();
 
- 					} else if (elem.msRequestFullscreen) {
 
- 						return elem.msRequestFullscreen();
 
- 					}
 
- 					return false;
 
- 				}
 
- 			} : {
 
- 				// node element maximize mode
 
- 				
 
- 				fullElm: function() {
 
- 					var full;
 
- 					if (node.hasClass(cls)) {
 
- 						return node.get(0);
 
- 					} else {
 
- 						full = node.find('.' + cls);
 
- 						if (full.length) {
 
- 							return full.get(0);
 
- 						}
 
- 					}
 
- 					return null;
 
- 				},
 
- 				
 
- 				exitFull: function() {
 
- 					var elm;
 
- 					
 
- 					$(window).off('resize.' + namespace, resize);
 
- 					if (bodyOvf !== void(0)) {
 
- 						$('body').css('overflow', bodyOvf);
 
- 					}
 
- 					bodyOvf = void(0);
 
- 					
 
- 					if (orgStyle) {
 
- 						elm = orgStyle.elm;
 
- 						restoreStyle(elm);
 
- 						$(elm).trigger('resize', {fullscreen: 'off'});
 
- 					}
 
- 					
 
- 					$(window).trigger('resize');
 
- 				},
 
- 				
 
- 				toFull: function(elem) {
 
- 					bodyOvf = $('body').css('overflow') || '';
 
- 					$('body').css('overflow', 'hidden');
 
- 					
 
- 					$(elem).css(self.getMaximizeCss())
 
- 						.addClass(cls)
 
- 						.trigger('resize', {fullscreen: 'on'});
 
- 					
 
- 					checkDialog();
 
- 					
 
- 					$(window).on('resize.' + namespace, resize).trigger('resize');
 
- 					
 
- 					return true;
 
- 				}
 
- 			},
 
- 			restoreStyle = function(elem) {
 
- 				if (orgStyle && orgStyle.elm == elem) {
 
- 					$(elem).removeClass(cls + ' ' + clsN).attr('style', orgStyle.style);
 
- 					orgStyle = null;
 
- 				}
 
- 			},
 
- 			resize = function(e) {
 
- 				var elm;
 
- 				if (e.target === window) {
 
- 					resizeTm && cancelAnimationFrame(resizeTm);
 
- 					resizeTm = requestAnimationFrame(function() {
 
- 						if (elm = funcObj.fullElm()) {
 
- 							$(elm).trigger('resize', {fullscreen: 'on'});
 
- 						}
 
- 					});
 
- 				}
 
- 			};
 
- 		
 
- 		$(document).on('fullscreenchange.' + namespace + ' webkitfullscreenchange.' + namespace + ' mozfullscreenchange.' + namespace + ' MSFullscreenChange.' + namespace, function(e){
 
- 			if (self.UA.Fullscreen) {
 
- 				var elm = funcObj.fullElm(),
 
- 					win = $(window);
 
- 				
 
- 				resizeTm && cancelAnimationFrame(resizeTm);
 
- 				if (elm === null) {
 
- 					win.off('resize.' + namespace, resize);
 
- 					if (orgStyle) {
 
- 						elm = orgStyle.elm;
 
- 						restoreStyle(elm);
 
- 						$(elm).trigger('resize', {fullscreen: 'off'});
 
- 					}
 
- 				} else {
 
- 					$(elm).addClass(cls + ' ' + clsN)
 
- 						.attr('style', 'width:100%; height:100%; margin:0; padding:0;')
 
- 						.trigger('resize', {fullscreen: 'on'});
 
- 					win.on('resize.' + namespace, resize);
 
- 					checkDialog();
 
- 				}
 
- 				win.trigger('resize');
 
- 			}
 
- 		});
 
- 		
 
- 		/**
 
- 		 * Toggle Full Scrren Mode
 
- 		 * 
 
- 		 * @param  Object target
 
- 		 * @param  Bool   full
 
- 		 * @return Object | Null  DOM node object of current full scrren
 
- 		 */
 
- 		self.toggleFullscreen = function(target, full) {
 
- 			var elm = $(target).get(0),
 
- 				curElm = null;
 
- 			
 
- 			curElm = funcObj.fullElm();
 
- 			if (curElm) {
 
- 				if (curElm == elm) {
 
- 					if (full === true) {
 
- 						return curElm;
 
- 					}
 
- 				} else {
 
- 					if (full === false) {
 
- 						return curElm;
 
- 					}
 
- 				}
 
- 				funcObj.exitFull();
 
- 				return null;
 
- 			} else {
 
- 				if (full === false) {
 
- 					return null;
 
- 				}
 
- 			}
 
- 			
 
- 			orgStyle = {elm: elm, style: $(elm).attr('style')};
 
- 			if (funcObj.toFull(elm) !== false) {
 
- 				return elm;
 
- 			} else {
 
- 				orgStyle = null;
 
- 				return null;
 
- 			}
 
- 		};
 
- 	})();
 
- 	
 
- 	// Closure for toggleMaximize
 
- 	(function(){
 
- 		var cls = 'elfinder-maximized',
 
- 		resizeTm,
 
- 		resize = function(e) {
 
- 			if (e.target === window && e.data && e.data.elm) {
 
- 				var elm = e.data.elm;
 
- 				resizeTm && cancelAnimationFrame(resizeTm);
 
- 				resizeTm = requestAnimationFrame(function() {
 
- 					elm.trigger('resize', {maximize: 'on'});
 
- 				});
 
- 			}
 
- 		},
 
- 		exitMax = function(elm) {
 
- 			$(window).off('resize.' + namespace, resize);
 
- 			$('body').css('overflow', elm.data('bodyOvf'));
 
- 			elm.removeClass(cls)
 
- 				.attr('style', elm.data('orgStyle'))
 
- 				.removeData('bodyOvf')
 
- 				.removeData('orgStyle');
 
- 			elm.trigger('resize', {maximize: 'off'});
 
- 		},
 
- 		toMax = function(elm) {
 
- 			elm.data('bodyOvf', $('body').css('overflow') || '')
 
- 				.data('orgStyle', elm.attr('style'))
 
- 				.addClass(cls)
 
- 				.css(self.getMaximizeCss());
 
- 			$('body').css('overflow', 'hidden');
 
- 			$(window).on('resize.' + namespace, {elm: elm}, resize);
 
- 			elm.trigger('resize', {maximize: 'on'});
 
- 		};
 
- 		
 
- 		/**
 
- 		 * Toggle Maximize target node
 
- 		 * 
 
- 		 * @param  Object target
 
- 		 * @param  Bool   max
 
- 		 * @return void
 
- 		 */
 
- 		self.toggleMaximize = function(target, max) {
 
- 			var elm = $(target),
 
- 				maximized = elm.hasClass(cls);
 
- 			
 
- 			if (maximized) {
 
- 				if (max === true) {
 
- 					return;
 
- 				}
 
- 				exitMax(elm);
 
- 			} else {
 
- 				if (max === false) {
 
- 					return;
 
- 				}
 
- 				toMax(elm);
 
- 			}
 
- 		};
 
- 	})();
 
- 	
 
- 	/*************  init stuffs  ****************/
 
- 	Object.assign($.ui.keyCode, {
 
- 		'F1' : 112,
 
- 		'F2' : 113,
 
- 		'F3' : 114,
 
- 		'F4' : 115,
 
- 		'F5' : 116,
 
- 		'F6' : 117,
 
- 		'F7' : 118,
 
- 		'F8' : 119,
 
- 		'F9' : 120,
 
- 		'F10' : 121,
 
- 		'F11' : 122,
 
- 		'F12' : 123,
 
- 		'DIG0' : 48,
 
- 		'DIG1' : 49,
 
- 		'DIG2' : 50,
 
- 		'DIG3' : 51,
 
- 		'DIG4' : 52,
 
- 		'DIG5' : 53,
 
- 		'DIG6' : 54,
 
- 		'DIG7' : 55,
 
- 		'DIG8' : 56,
 
- 		'DIG9' : 57,
 
- 		'NUM0' : 96,
 
- 		'NUM1' : 97,
 
- 		'NUM2' : 98,
 
- 		'NUM3' : 99,
 
- 		'NUM4' : 100,
 
- 		'NUM5' : 101,
 
- 		'NUM6' : 102,
 
- 		'NUM7' : 103,
 
- 		'NUM8' : 104,
 
- 		'NUM9' : 105,
 
- 		'CONTEXTMENU' : 93,
 
- 		'DOT'  : 190
 
- 	});
 
- 	
 
- 	this.dragUpload = false;
 
- 	this.xhrUpload  = (typeof XMLHttpRequestUpload != 'undefined' || typeof XMLHttpRequestEventTarget != 'undefined') && typeof File != 'undefined' && typeof FormData != 'undefined';
 
- 	
 
- 	// configure transport object
 
- 	this.transport = {};
 
- 	if (typeof(this.options.transport) == 'object') {
 
- 		this.transport = this.options.transport;
 
- 		if (typeof(this.transport.init) == 'function') {
 
- 			this.transport.init(this);
 
- 		}
 
- 	}
 
- 	
 
- 	if (typeof(this.transport.send) != 'function') {
 
- 		this.transport.send = function(opts) {
 
- 			if (!self.UA.IE) {
 
- 				// keep native xhr object for handling property responseURL
 
- 				opts._xhr = new XMLHttpRequest();
 
- 				opts.xhr = function() { return opts._xhr; };
 
- 			}
 
- 			return $.ajax(opts);
 
- 		};
 
- 	}
 
- 	
 
- 	if (this.transport.upload == 'iframe') {
 
- 		this.transport.upload = $.proxy(this.uploads.iframe, this);
 
- 	} else if (typeof(this.transport.upload) == 'function') {
 
- 		this.dragUpload = !!this.options.dragUploadAllow;
 
- 	} else if (this.xhrUpload && !!this.options.dragUploadAllow) {
 
- 		this.transport.upload = $.proxy(this.uploads.xhr, this);
 
- 		this.dragUpload = true;
 
- 	} else {
 
- 		this.transport.upload = $.proxy(this.uploads.iframe, this);
 
- 	}
 
- 	/**
 
- 	 * Decoding 'raw' string converted to unicode
 
- 	 * 
 
- 	 * @param  String str
 
- 	 * @return String
 
- 	 */
 
- 	this.decodeRawString = function(str) {
 
- 		var charCodes = function(str) {
 
- 			var i, len, arr;
 
- 			for (i=0,len=str.length,arr=[]; i<len; i++) {
 
- 				arr.push(str.charCodeAt(i));
 
- 			}
 
- 			return arr;
 
- 		},
 
- 		scalarValues = function(arr) {
 
- 			var scalars = [], i, len, c;
 
- 			if (typeof arr === 'string') {arr = charCodes(arr);}
 
- 			for (i=0,len=arr.length; c=arr[i],i<len; i++) {
 
- 				if (c >= 0xd800 && c <= 0xdbff) {
 
- 					scalars.push((c & 1023) + 64 << 10 | arr[++i] & 1023);
 
- 				} else {
 
- 					scalars.push(c);
 
- 				}
 
- 			}
 
- 			return scalars;
 
- 		},
 
- 		decodeUTF8 = function(arr) {
 
- 			var i, len, c, str, char = String.fromCharCode;
 
- 			for (i=0,len=arr.length,str=""; c=arr[i],i<len; i++) {
 
- 				if (c <= 0x7f) {
 
- 					str += char(c);
 
- 				} else if (c <= 0xdf && c >= 0xc2) {
 
- 					str += char((c&31)<<6 | arr[++i]&63);
 
- 				} else if (c <= 0xef && c >= 0xe0) {
 
- 					str += char((c&15)<<12 | (arr[++i]&63)<<6 | arr[++i]&63);
 
- 				} else if (c <= 0xf7 && c >= 0xf0) {
 
- 					str += char(
 
- 						0xd800 | ((c&7)<<8 | (arr[++i]&63)<<2 | arr[++i]>>>4&3) - 64,
 
- 						0xdc00 | (arr[i++]&15)<<6 | arr[i]&63
 
- 					);
 
- 				} else {
 
- 					str += char(0xfffd);
 
- 				}
 
- 			}
 
- 			return str;
 
- 		};
 
- 		
 
- 		return decodeUTF8(scalarValues(str));
 
- 	};
 
- 	/**
 
- 	 * Gets target file contents by file.hash
 
- 	 *
 
- 	 * @param      String  hash          The hash
 
- 	 * @param      String  responseType  'blob' or 'arraybuffer' (default)
 
- 	 * @return     arraybuffer|blob  The contents.
 
- 	 */
 
- 	this.getContents = function(hash, responseType) {
 
- 		var self = this,
 
- 			dfd = $.Deferred(),
 
- 			type = responseType || 'arraybuffer',
 
- 			url, req;
 
- 		dfd.fail(function() {
 
- 			req && req.state() === 'pending' && req.reject();
 
- 		});
 
- 		url = self.openUrl(hash);
 
- 		if (!self.isSameOrigin(url)) {
 
- 			url = self.openUrl(hash, true);
 
- 		}
 
- 		req = self.request({
 
- 			data    : {cmd : 'get'},
 
- 			options : {
 
- 				url: url,
 
- 				type: 'get',
 
- 				cache : true,
 
- 				dataType : 'binary',
 
- 				responseType : type,
 
- 				processData: false
 
- 			}
 
- 		})
 
- 		.fail(function() {
 
- 			dfd.reject();
 
- 		})
 
- 		.done(function(data) {
 
- 			dfd.resolve(data);
 
- 		});
 
- 		return dfd;
 
- 	};
 
- 	this.getMimetype = function(name, orgMime) {
 
- 		var mime = orgMime,
 
- 			ext, m;
 
- 		m = (name + '').match(/\.([^.]+)$/);
 
- 		if (m && (ext = m[1])) {
 
- 			if (!extToMimeTable) {
 
- 				extToMimeTable = self.arrayFlip(self.mimeTypes);
 
- 			}
 
- 			if (!(mime = extToMimeTable[ext.toLowerCase()])) {
 
- 				mime = orgMime;
 
- 			}
 
- 		}
 
- 		return mime;
 
- 	};
 
- 	/**
 
- 	 * Supported check hash algorisms
 
- 	 * 
 
- 	 * @type Array
 
- 	 */
 
- 	self.hashCheckers = [];
 
- 	/**
 
- 	 * Closure of getContentsHashes()
 
- 	 */
 
- 	(function(self) {
 
- 		var hashLibs = {
 
- 				check : true
 
- 			},
 
- 			md5Calc = function(arr) {
 
- 				var spark = new hashLibs.SparkMD5.ArrayBuffer(),
 
- 					job;
 
- 				job = self.asyncJob(function(buf) {
 
- 					spark.append(buf);
 
- 				}, arr).done(function() {
 
- 					job._md5 = spark.end();
 
- 				});
 
- 				return job;
 
- 			},
 
- 			shaCalc = function(arr, length) {
 
- 				var sha, job;
 
- 				try {
 
- 					sha = new hashLibs.jsSHA('SHA' + (length.substr(0, 1) === '3'? length : ('-' + length)), 'ARRAYBUFFER');
 
- 					job = self.asyncJob(function(buf) {
 
- 						sha.update(buf);
 
- 					}, arr).done(function() {
 
- 						job._sha = sha.getHash('HEX');
 
- 					});
 
- 				} catch(e) {
 
- 					job = $.Deferred.reject();
 
- 				}
 
- 				return job;
 
- 			};
 
- 		// make fm.hashCheckers
 
- 		if (self.options.cdns.sparkmd5) {
 
- 			self.hashCheckers.push('md5');
 
- 		}
 
- 		if (self.options.cdns.jssha) {
 
- 			self.hashCheckers = self.hashCheckers.concat(['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512', 'shake128', 'shake256']);
 
- 		}
 
- 		/**
 
- 		 * Gets the contents hashes.
 
- 		 *
 
- 		 * @param      String  target      target file.hash
 
- 		 * @param      Object  needHashes  need hash lib names
 
- 		 * @return     Object  hashes with lib name as key
 
- 		 */
 
- 		self.getContentsHashes = function(target, needHashes) {
 
- 			var dfd = $.Deferred(),
 
- 				needs = self.arrayFlip(needHashes || ['md5'], true),
 
- 				libs = [],
 
- 				jobs = [],
 
- 				res = {},
 
- 				req;
 
- 			dfd.fail(function() {
 
- 				req && req.reject();
 
- 			});
 
- 			if (hashLibs.check) {
 
- 				delete hashLibs.check;
 
- 				// load SparkMD5
 
- 				var libsmd5 = $.Deferred();
 
- 				if (window.ArrayBuffer && self.options.cdns.sparkmd5) {
 
- 					libs.push(libsmd5);
 
- 					self.loadScript([self.options.cdns.sparkmd5],
 
- 						function(res) { 
 
- 							var SparkMD5 = res || window.SparkMD5;
 
- 							window.SparkMD5 && delete window.SparkMD5;
 
- 							libsmd5.resolve();
 
- 							if (SparkMD5) {
 
- 								hashLibs.SparkMD5 = SparkMD5;
 
- 							}
 
- 						},
 
- 						{
 
- 							tryRequire: true,
 
- 							error: function() {
 
- 								libsmd5.reject();
 
- 							}
 
- 						}
 
- 					);
 
- 				}
 
- 				// load jsSha
 
- 				var libssha = $.Deferred();
 
- 				if (window.ArrayBuffer && self.options.cdns.jssha) {
 
- 					libs.push(libssha);
 
- 					self.loadScript([self.options.cdns.jssha],
 
- 						function(res) { 
 
- 							var jsSHA = res || window.jsSHA;
 
- 							window.jsSHA && delete window.jsSHA;
 
- 							libssha.resolve();
 
- 							if (jsSHA) {
 
- 								hashLibs.jsSHA = jsSHA;
 
- 							}
 
- 						},
 
- 						{
 
- 							tryRequire: true,
 
- 							error: function() {
 
- 								libssha.reject();
 
- 							}
 
- 						}
 
- 					);
 
- 				}
 
- 			}
 
- 			
 
- 			$.when.apply(null, libs).always(function() {
 
- 				if (Object.keys(hashLibs).length) {
 
- 					req = self.getContents(target).done(function(arrayBuffer) {
 
- 						var arr = (arrayBuffer instanceof ArrayBuffer && arrayBuffer.byteLength > 0)? self.sliceArrayBuffer(arrayBuffer, 1048576) : false,
 
- 							i;
 
- 						if (needs.md5 && hashLibs.SparkMD5) {
 
- 							jobs.push(function() {
 
- 								var job = md5Calc(arr).done(function() {
 
- 									var f;
 
- 									res.md5 = job._md5;
 
- 									if (f = self.file(target)) {
 
- 										f.md5 = job._md5;
 
- 									}
 
- 									dfd.notify(res);
 
- 								});
 
- 								dfd.fail(function() {
 
- 									job.reject();
 
- 								});
 
- 								return job;
 
- 							});
 
- 						}
 
- 						if (hashLibs.jsSHA) {
 
- 							$.each(['1', '224', '256', '384', '512', '3-224', '3-256', '3-384', '3-512', 'ke128', 'ke256'], function(i, v) {
 
- 								if (needs['sha' + v]) {
 
- 									jobs.push(function() {
 
- 										var job = shaCalc(arr, v).done(function() {
 
- 											var f;
 
- 											res['sha' + v] = job._sha;
 
- 											if (f = self.file(target)) {
 
- 												f['sha' + v] = job._sha;
 
- 											}
 
- 											dfd.notify(res);
 
- 										});
 
- 										return job;
 
- 									});
 
- 								}
 
- 							});
 
- 						}
 
- 						if (jobs.length) {
 
- 							self.sequence(jobs).always(function() {
 
- 								dfd.resolve(res);
 
- 							});
 
- 						} else {
 
- 							dfd.reject();
 
- 						}
 
- 					}).fail(function() {
 
- 						dfd.reject();
 
- 					});
 
- 				} else {
 
- 					dfd.reject();
 
- 				}
 
- 			});
 
- 			return dfd;
 
- 		};
 
- 	})(this);
 
- 	/**
 
- 	 * Parse error value to display
 
- 	 *
 
- 	 * @param  Mixed  error
 
- 	 * @return Mixed  parsed error
 
- 	 */
 
- 	this.parseError = function(error) {
 
- 		var arg = error;
 
- 		if ($.isPlainObject(arg)) {
 
- 			arg = arg.error;
 
- 		}
 
- 		return arg;
 
- 	};
 
- 	/**
 
- 	 * Alias for this.trigger('error', {error : 'message'})
 
- 	 *
 
- 	 * @param  String  error message
 
- 	 * @return elFinder
 
- 	 **/
 
- 	this.error = function() {
 
- 		var arg = arguments[0],
 
- 			opts = arguments[1] || null,
 
- 			err;
 
- 		if (arguments.length == 1 && typeof(arg) === 'function') {
 
- 			return self.bind('error', arg);
 
- 		} else {
 
- 			err = this.parseError(arg);
 
- 			return (err === true || !err)? this : self.trigger('error', {error: err, opts : opts});
 
- 		}
 
- 	};
 
- 	
 
- 	// create bind/trigger aliases for build-in events
 
- 	$.each(events, function(i, name) {
 
- 		self[name] = function() {
 
- 			var arg = arguments[0];
 
- 			return arguments.length == 1 && typeof(arg) == 'function'
 
- 				? self.bind(name, arg)
 
- 				: self.trigger(name, $.isPlainObject(arg) ? arg : {});
 
- 		};
 
- 	});
 
- 	// bind core event handlers
 
- 	this
 
- 		.enable(function() {
 
- 			if (!enabled && self.api && self.visible() && self.ui.overlay.is(':hidden') && ! node.children('.elfinder-dialog.' + self.res('class', 'editing') + ':visible').length) {
 
- 				enabled = true;
 
- 				document.activeElement && document.activeElement.blur();
 
- 				node.removeClass('elfinder-disabled');
 
- 			}
 
- 		})
 
- 		.disable(function() {
 
- 			prevEnabled = enabled;
 
- 			enabled = false;
 
- 			node.addClass('elfinder-disabled');
 
- 		})
 
- 		.open(function() {
 
- 			selected = [];
 
- 		})
 
- 		.select(function(e) {
 
- 			var cnt = 0,
 
- 				unselects = [];
 
- 			selected = $.grep(e.data.selected || e.data.value|| [], function(hash) {
 
- 				if (unselects.length || (self.maxTargets && ++cnt > self.maxTargets)) {
 
- 					unselects.push(hash);
 
- 					return false;
 
- 				} else {
 
- 					return files[hash] ? true : false;
 
- 				}
 
- 			});
 
- 			if (unselects.length) {
 
- 				self.trigger('unselectfiles', {files: unselects, inselect: true});
 
- 				self.toast({mode: 'warning', msg: self.i18n(['errMaxTargets', self.maxTargets])});
 
- 			}
 
- 		})
 
- 		.error(function(e) { 
 
- 			var opts  = {
 
- 					cssClass  : 'elfinder-dialog-error',
 
- 					title     : self.i18n(self.i18n('error')),
 
- 					resizable : false,
 
- 					destroyOnClose : true,
 
- 					buttons   : {}
 
- 			};
 
- 			
 
- 			opts.buttons[self.i18n(self.i18n('btnClose'))] = function() { $(this).elfinderdialog('close'); };
 
- 			if (e.data.opts && $.isPlainObject(e.data.opts)) {
 
- 				Object.assign(opts, e.data.opts);
 
- 			}
 
- 			self.dialog('<span class="elfinder-dialog-icon elfinder-dialog-icon-error"/>'+self.i18n(e.data.error), opts);
 
- 		})
 
- 		.bind('tmb', function(e) {
 
- 			$.each(e.data.images||[], function(hash, tmb) {
 
- 				if (files[hash]) {
 
- 					files[hash].tmb = tmb;
 
- 				}
 
- 			});
 
- 		})
 
- 		.bind('searchstart', function(e) {
 
- 			Object.assign(self.searchStatus, e.data);
 
- 			self.searchStatus.state = 1;
 
- 		})
 
- 		.bind('search', function(e) {
 
- 			self.searchStatus.state = 2;
 
- 		})
 
- 		.bind('searchend', function() {
 
- 			self.searchStatus.state = 0;
 
- 			self.searchStatus.ininc = false;
 
- 			self.searchStatus.mixed = false;
 
- 		})
 
- 		.bind('canMakeEmptyFile', function(e) {
 
- 			var data = e.data,
 
- 				obj = {};
 
- 			if (data && Array.isArray(data.mimes)) {
 
- 				if (!data.unshift) {
 
- 					obj = self.mimesCanMakeEmpty;
 
- 				}
 
- 				$.each(data.mimes, function() {
 
- 					if (!obj[this]) {
 
- 						obj[this] = self.mimeTypes[this];
 
- 					}
 
- 				});
 
- 				if (data.unshift) {
 
- 					self.mimesCanMakeEmpty = Object.assign(obj, self.mimesCanMakeEmpty);
 
- 				}
 
- 			}
 
- 		})
 
- 		.bind('themechange', function() {
 
- 			requestAnimationFrame(function() {
 
- 				self.trigger('uiresize');
 
- 			});
 
- 		})
 
- 		;
 
- 	// We listen and emit a sound on delete according to option
 
- 	if (true === this.options.sound) {
 
- 		this.bind('playsound', function(e) {
 
- 			var play  = beeper.canPlayType && beeper.canPlayType('audio/wav; codecs="1"'),
 
- 				file = e.data && e.data.soundFile;
 
- 			play && file && play != '' && play != 'no' && $(beeper).html('<source src="' + soundPath + file + '" type="audio/wav">')[0].play();
 
- 		});
 
- 	}
 
- 	// bind external event handlers
 
- 	$.each(this.options.handlers, function(event, callback) {
 
- 		self.bind(event, callback);
 
- 	});
 
- 	/**
 
- 	 * History object. Store visited folders
 
- 	 *
 
- 	 * @type Object
 
- 	 **/
 
- 	this.history = new this.history(this);
 
- 	
 
- 	/**
 
- 	 * Root hashed
 
- 	 * 
 
- 	 * @type Object
 
- 	 */
 
- 	this.roots = {};
 
- 	
 
- 	/**
 
- 	 * leaf roots
 
- 	 * 
 
- 	 * @type Object
 
- 	 */
 
- 	this.leafRoots = {};
 
- 	
 
- 	this.volumeExpires = {};
 
- 	/**
 
- 	 * Loaded commands
 
- 	 *
 
- 	 * @type Object
 
- 	 **/
 
- 	this._commands = {};
 
- 	
 
- 	if (!Array.isArray(this.options.commands)) {
 
- 		this.options.commands = [];
 
- 	}
 
- 	
 
- 	if ($.inArray('*', this.options.commands) !== -1) {
 
- 		this.options.commands = Object.keys(this.commands);
 
- 	}
 
- 	
 
- 	/**
 
- 	 * UI command map of cwd volume ( That volume driver option `uiCmdMap` )
 
- 	 *
 
- 	 * @type Object
 
- 	 **/
 
- 	this.commandMap = {};
 
- 	
 
- 	/**
 
- 	 * cwd options of each volume
 
- 	 * key: volumeid
 
- 	 * val: options object
 
- 	 * 
 
- 	 * @type Object
 
- 	 */
 
- 	this.volOptions = {};
 
- 	/**
 
- 	 * Has volOptions data
 
- 	 * 
 
- 	 * @type Boolean
 
- 	 */
 
- 	this.hasVolOptions = false;
 
- 	/**
 
- 	 * Hash of trash holders
 
- 	 * key: trash folder hash
 
- 	 * val: source volume hash
 
- 	 * 
 
- 	 * @type Object
 
- 	 */
 
- 	this.trashes = {};
 
- 	/**
 
- 	 * cwd options of each folder/file
 
- 	 * key: hash
 
- 	 * val: options object
 
- 	 *
 
- 	 * @type Object
 
- 	 */
 
- 	this.optionsByHashes = {};
 
- 	
 
- 	/**
 
- 	 * UI Auto Hide Functions
 
- 	 * Each auto hide function mast be call to `fm.trigger('uiautohide')` at end of process
 
- 	 *
 
- 	 * @type Array
 
- 	 **/
 
- 	this.uiAutoHide = [];
 
- 	
 
- 	// trigger `uiautohide`
 
- 	this.one('open', function() {
 
- 		if (self.uiAutoHide.length) {
 
- 			setTimeout(function() {
 
- 				self.trigger('uiautohide');
 
- 			}, 500);
 
- 		}
 
- 	});
 
- 	
 
- 	// Auto Hide Functions sequential processing start
 
- 	this.bind('uiautohide', function() {
 
- 		if (self.uiAutoHide.length) {
 
- 			self.uiAutoHide.shift()();
 
- 		}
 
- 	});
 
- 	if (this.options.width) {
 
- 		width = this.options.width;
 
- 	}
 
- 	
 
- 	if (this.options.height) {
 
- 		height = this.options.height;
 
- 	}
 
- 	
 
- 	if (this.options.heightBase) {
 
- 		heightBase = $(this.options.heightBase);
 
- 	}
 
- 	
 
- 	if (this.options.soundPath) {
 
- 		soundPath = this.options.soundPath.replace(/\/+$/, '') + '/';
 
- 	} else {
 
- 		soundPath = this.baseUrl + soundPath;
 
- 	}
 
- 	
 
- 	self.one('opendone', function() {
 
- 		var tm;
 
- 		// attach events to document
 
- 		$(document)
 
- 			// disable elfinder on click outside elfinder
 
- 			.on('click.'+namespace, function(e) { enabled && ! self.options.enableAlways && !$(e.target).closest(node).length && self.disable(); })
 
- 			// exec shortcuts
 
- 			.on(keydown+' '+keypress+' '+keyup+' '+mousedown, execShortcut);
 
- 		
 
- 		// attach events to window
 
- 		self.options.useBrowserHistory && $(window)
 
- 			.on('popstate.' + namespace, function(ev) {
 
- 				var state = ev.originalEvent.state || {},
 
- 					hasThash = state.thash? true : false,
 
- 					dialog = node.find('.elfinder-frontmost:visible'),
 
- 					input = node.find('.elfinder-navbar-dir,.elfinder-cwd-filename').find('input,textarea'),
 
- 					onOpen, toast;
 
- 				if (!hasThash) {
 
- 					state = { thash: self.cwd().hash };
 
- 					// scroll to elFinder node
 
- 					$('html,body').animate({ scrollTop: node.offset().top });
 
- 				}
 
- 				if (dialog.length || input.length) {
 
- 					history.pushState(state, null, location.pathname + location.search + '#elf_' + state.thash);
 
- 					if (dialog.length) {
 
- 						if (!dialog.hasClass(self.res('class', 'preventback'))) {
 
- 							if (dialog.hasClass('elfinder-contextmenu')) {
 
- 								$(document).trigger($.Event('keydown', { keyCode: $.ui.keyCode.ESCAPE, ctrlKey : false, shiftKey : false, altKey : false, metaKey : false }));
 
- 							} else if (dialog.hasClass('elfinder-dialog')) {
 
- 								dialog.elfinderdialog('close');
 
- 							} else {
 
- 								dialog.trigger('close');
 
- 							}
 
- 						}
 
- 					} else {
 
- 						input.trigger($.Event('keydown', { keyCode: $.ui.keyCode.ESCAPE, ctrlKey : false, shiftKey : false, altKey : false, metaKey : false }));
 
- 					}
 
- 				} else {
 
- 					if (hasThash) {
 
- 						!$.isEmptyObject(self.files()) && self.request({
 
- 							data   : {cmd  : 'open', target : state.thash, onhistory : 1},
 
- 							notify : {type : 'open', cnt : 1, hideCnt : true},
 
- 							syncOnFail : true
 
- 						});
 
- 					} else {
 
- 						onOpen = function() {
 
- 							toast.trigger('click');
 
- 						};
 
- 						self.one('open', onOpen, true);
 
- 						toast = self.toast({
 
- 							msg: self.i18n('pressAgainToExit'),
 
- 							onHidden: function() {
 
- 								self.unbind('open', onOpen);
 
- 								history.pushState(state, null, location.pathname + location.search + '#elf_' + state.thash);
 
- 							}
 
- 						});
 
- 					}
 
- 				}
 
- 			});
 
- 		
 
- 		$(window).on('resize.' + namespace, function(e){
 
- 			if (e.target === this) {
 
- 				tm && cancelAnimationFrame(tm);
 
- 				tm = requestAnimationFrame(function() {
 
- 					var prv = node.data('resizeSize') || {w: 0, h: 0},
 
- 						size = {w: Math.round(node.width()), h: Math.round(node.height())};
 
- 					node.data('resizeSize', size);
 
- 					if (size.w !== prv.w || size.h !== prv.h) {
 
- 						node.trigger('resize');
 
- 						self.trigger('resize', {width : size.w, height : size.h});
 
- 					}
 
- 				});
 
- 			}
 
- 		})
 
- 		.on('beforeunload.' + namespace,function(e){
 
- 			var msg, cnt;
 
- 			if (node.is(':visible')) {
 
- 				if (self.ui.notify.children().length && $.inArray('hasNotifyDialog', self.options.windowCloseConfirm) !== -1) {
 
- 					msg = self.i18n('ntfsmth');
 
- 				} else if (node.find('.'+self.res('class', 'editing')).length && $.inArray('editingFile', self.options.windowCloseConfirm) !== -1) {
 
- 					msg = self.i18n('editingFile');
 
- 				} else if ((cnt = Object.keys(self.selected()).length) && $.inArray('hasSelectedItem', self.options.windowCloseConfirm) !== -1) {
 
- 					msg = self.i18n('hasSelected', ''+cnt);
 
- 				} else if ((cnt = Object.keys(self.clipboard()).length) && $.inArray('hasClipboardData', self.options.windowCloseConfirm) !== -1) {
 
- 					msg = self.i18n('hasClipboard', ''+cnt);
 
- 				}
 
- 				if (msg) {
 
- 					e.returnValue = msg;
 
- 					return msg;
 
- 				}
 
- 			}
 
- 			self.trigger('unload');
 
- 		});
 
- 		// bind window onmessage for CORS
 
- 		$(window).on('message.' + namespace, function(e){
 
- 			var res = e.originalEvent || null,
 
- 				obj, data;
 
- 			if (res && self.uploadURL.indexOf(res.origin) === 0) {
 
- 				try {
 
- 					obj = JSON.parse(res.data);
 
- 					data = obj.data || null;
 
- 					if (data) {
 
- 						if (data.error) {
 
- 							if (obj.bind) {
 
- 								self.trigger(obj.bind+'fail', data);
 
- 							}
 
- 							self.error(data.error);
 
- 						} else {
 
- 							data.warning && self.error(data.warning);
 
- 							self.updateCache(data);
 
- 							data.removed && data.removed.length && self.remove(data);
 
- 							data.added   && data.added.length   && self.add(data);
 
- 							data.changed && data.changed.length && self.change(data);
 
- 							if (obj.bind) {
 
- 								self.trigger(obj.bind, data);
 
- 								self.trigger(obj.bind+'done');
 
- 							}
 
- 							data.sync && self.sync();
 
- 						}
 
- 					}
 
- 				} catch (e) {
 
- 					self.sync();
 
- 				}
 
- 			}
 
- 		});
 
- 		// elFinder enable always
 
- 		if (self.options.enableAlways) {
 
- 			$(window).on('focus.' + namespace, function(e){
 
- 				(e.target === this) && self.enable();
 
- 			});
 
- 			if (inFrame) {
 
- 				$(window.top).on('focus.' + namespace, function() {
 
- 					if (self.enable() && (! parentIframe || parentIframe.is(':visible'))) {
 
- 						requestAnimationFrame(function() {
 
- 							$(window).trigger('focus');
 
- 						});
 
- 					}
 
- 				});
 
- 			}
 
- 		} else if (inFrame) {
 
- 			$(window).on('blur.' + namespace, function(e){
 
- 				enabled && e.target === this && self.disable();
 
- 			});
 
- 		}
 
- 		// return focus to the window on click (elFInder in the frame)
 
- 		if (inFrame) {
 
- 			node.on('click', function(e) {
 
- 				$(window).trigger('focus');
 
- 			});
 
- 		}
 
- 		
 
- 		// elFinder to enable by mouse over
 
- 		if (self.options.enableByMouseOver) {
 
- 			node.on('mouseenter touchstart', function(e) {
 
- 				(inFrame) && $(window).trigger('focus');
 
- 				! self.enabled() && self.enable();
 
- 			});
 
- 		}
 
- 	});
 
- 	// store instance in node
 
- 	node[0].elfinder = this;
 
- 	// auto load language file
 
- 	dfrdsBeforeBootup.push((function() {
 
- 		var lang   = self.lang,
 
- 			langJs = self.i18nBaseUrl + 'elfinder.' + lang + '.js',
 
- 			dfd    = $.Deferred().done(function() {
 
- 				if (self.i18[lang]) {
 
- 					self.lang = lang;
 
- 				}
 
- 				self.trigger('i18load');
 
- 				i18n = self.lang === 'en' 
 
- 					? self.i18['en'] 
 
- 					: $.extend(true, {}, self.i18['en'], self.i18[self.lang]);
 
- 			});
 
- 		
 
- 		if (!self.i18[lang]) {
 
- 			self.lang = 'en';
 
- 			if (self.hasRequire) {
 
- 				require([langJs], function() {
 
- 					dfd.resolve();
 
- 				}, function() {
 
- 					dfd.resolve();
 
- 				});
 
- 			} else {
 
- 				self.loadScript([langJs], function() {
 
- 					dfd.resolve();
 
- 				}, {
 
- 					loadType: 'tag',
 
- 					error : function() {
 
- 						dfd.resolve();
 
- 					}
 
- 				});
 
- 			}
 
- 		} else {
 
- 			dfd.resolve();
 
- 		}
 
- 		return dfd;
 
- 	})());
 
- 	
 
- 	// elFinder boot up function
 
- 	bootUp = function() {
 
- 		var columnNames;
 
- 		/**
 
- 		 * i18 messages
 
- 		 *
 
- 		 * @type Object
 
- 		 **/
 
- 		self.messages = i18n.messages;
 
- 		
 
- 		// check jquery ui
 
- 		if (!($.fn.selectable && $.fn.draggable && $.fn.droppable && $.fn.resizable && $.fn.slider)) {
 
- 			return alert(self.i18n('errJqui'));
 
- 		}
 
- 		
 
- 		// check node
 
- 		if (!node.length) {
 
- 			return alert(self.i18n('errNode'));
 
- 		}
 
- 		// check connector url
 
- 		if (!self.options.url) {
 
- 			return alert(self.i18n('errURL'));
 
- 		}
 
- 		
 
- 		// column key/name map for fm.getColumnName()
 
- 		columnNames = Object.assign({
 
- 			name : self.i18n('name'),
 
- 			perm : self.i18n('perms'),
 
- 			date : self.i18n('modify'),
 
- 			size : self.i18n('size'),
 
- 			kind : self.i18n('kind'),
 
- 			modestr : self.i18n('mode'),
 
- 			modeoct : self.i18n('mode'),
 
- 			modeboth : self.i18n('mode')
 
- 		}, self.options.uiOptions.cwd.listView.columnsCustomName);
 
- 		/**
 
- 		 * Gets the column name of cwd list view
 
- 		 *
 
- 		 * @param      String  key     The key
 
- 		 * @return     String  The column name.
 
- 		 */
 
- 		self.getColumnName = function(key) {
 
- 			return columnNames[key] || self.i18n(key);
 
- 		};
 
- 		/**
 
- 		 * Interface direction
 
- 		 *
 
- 		 * @type String
 
- 		 * @default "ltr"
 
- 		 **/
 
- 		self.direction = i18n.direction;
 
- 		
 
- 		/**
 
- 		 * Date/time format
 
- 		 *
 
- 		 * @type String
 
- 		 * @default "m.d.Y"
 
- 		 **/
 
- 		self.dateFormat = self.options.dateFormat || i18n.dateFormat;
 
- 		
 
- 		/**
 
- 		 * Date format like "Yesterday 10:20:12"
 
- 		 *
 
- 		 * @type String
 
- 		 * @default "{day} {time}"
 
- 		 **/
 
- 		self.fancyFormat = self.options.fancyDateFormat || i18n.fancyDateFormat;
 
- 		
 
- 		/**
 
- 		 * Date format for if upload file has not original unique name
 
- 		 * e.g. Clipboard image data, Image data taken with iOS
 
- 		 *
 
- 		 * @type String
 
- 		 * @default "ymd-His"
 
- 		 **/
 
- 		self.nonameDateFormat = (self.options.nonameDateFormat || i18n.nonameDateFormat).replace(/[\/\\]/g, '_');
 
- 		/**
 
- 		 * Css classes 
 
- 		 *
 
- 		 * @type String
 
- 		 **/
 
- 		self.cssClass = 'ui-helper-reset ui-helper-clearfix ui-widget ui-widget-content ui-corner-all elfinder elfinder-'
 
- 				+(self.direction == 'rtl' ? 'rtl' : 'ltr')
 
- 				+(self.UA.Touch? (' elfinder-touch' + (self.options.resizable ? ' touch-punch' : '')) : '')
 
- 				+(self.UA.Mobile? ' elfinder-mobile' : '')
 
- 				+(self.UA.iOS? ' elfinder-ios' : '')
 
- 				+' '+self.options.cssClass;
 
- 		// prepare node
 
- 		node.addClass(self.cssClass)
 
- 			.on(mousedown, function() {
 
- 				!enabled && self.enable();
 
- 			});
 
- 		// draggable closure
 
- 		(function() {
 
- 			var ltr, wzRect, wzBottom, wzBottom2, nodeStyle,
 
- 				keyEvt = keydown + 'draggable' + ' keyup.' + namespace + 'draggable';
 
- 			
 
- 			/**
 
- 			 * Base draggable options
 
- 			 *
 
- 			 * @type Object
 
- 			 **/
 
- 			self.draggable = {
 
- 				appendTo   : node,
 
- 				addClasses : false,
 
- 				distance   : 4,
 
- 				revert     : true,
 
- 				refreshPositions : false,
 
- 				cursor     : 'crosshair',
 
- 				cursorAt   : {left : 50, top : 47},
 
- 				scroll     : false,
 
- 				start      : function(e, ui) {
 
- 					var helper   = ui.helper,
 
- 						targets  = $.grep(helper.data('files')||[], function(h) {
 
- 							if (h) {
 
- 								remember[h] = true;
 
- 								return true;
 
- 							}
 
- 							return false;
 
- 						}),
 
- 						locked   = false,
 
- 						cnt, h;
 
- 					
 
- 					// fix node size
 
- 					nodeStyle = node.attr('style');
 
- 					node.width(node.width()).height(node.height());
 
- 					
 
- 					// set var for drag()
 
- 					ltr = (self.direction === 'ltr');
 
- 					wzRect = self.getUI('workzone').data('rectangle');
 
- 					wzBottom = wzRect.top + wzRect.height;
 
- 					wzBottom2 = wzBottom - self.getUI('navdock').outerHeight(true);
 
- 					
 
- 					self.draggingUiHelper = helper;
 
- 					cnt = targets.length;
 
- 					while (cnt--) {
 
- 						h = targets[cnt];
 
- 						if (files[h].locked) {
 
- 							locked = true;
 
- 							helper.data('locked', true);
 
- 							break;
 
- 						}
 
- 					}
 
- 					!locked && self.trigger('lockfiles', {files : targets});
 
- 		
 
- 					helper.data('autoScrTm', setInterval(function() {
 
- 						if (helper.data('autoScr')) {
 
- 							self.autoScroll[helper.data('autoScr')](helper.data('autoScrVal'));
 
- 						}
 
- 					}, 50));
 
- 				},
 
- 				drag       : function(e, ui) {
 
- 					var helper = ui.helper,
 
- 						autoScr, autoUp, bottom;
 
- 					
 
- 					if ((autoUp = wzRect.top > e.pageY) || wzBottom2 < e.pageY) {
 
- 						if (wzRect.cwdEdge > e.pageX) {
 
- 							autoScr = (ltr? 'navbar' : 'cwd') + (autoUp? 'Up' : 'Down');
 
- 						} else {
 
- 							autoScr = (ltr? 'cwd' : 'navbar') + (autoUp? 'Up' : 'Down');
 
- 						}
 
- 						if (!autoUp) {
 
- 							if (autoScr.substr(0, 3) === 'cwd') {
 
- 								if (wzBottom < e.pageY) {
 
- 									bottom = wzBottom;
 
- 								} else {
 
- 									autoScr = null;
 
- 								}
 
- 							} else {
 
- 								bottom = wzBottom2;
 
- 							}
 
- 						}
 
- 						if (autoScr) {
 
- 							helper.data('autoScr', autoScr);
 
- 							helper.data('autoScrVal', Math.pow((autoUp? wzRect.top - e.pageY : e.pageY - bottom), 1.3));
 
- 						}
 
- 					}
 
- 					if (! autoScr) {
 
- 						if (helper.data('autoScr')) {
 
- 							helper.data('refreshPositions', 1).data('autoScr', null);
 
- 						}
 
- 					}
 
- 					if (helper.data('refreshPositions') && $(this).elfUiWidgetInstance('draggable')) {
 
- 						if (helper.data('refreshPositions') > 0) {
 
- 							$(this).draggable('option', { refreshPositions : true, elfRefresh : true });
 
- 							helper.data('refreshPositions', -1);
 
- 						} else {
 
- 							$(this).draggable('option', { refreshPositions : false, elfRefresh : false });
 
- 							helper.data('refreshPositions', null);
 
- 						}
 
- 					}
 
- 				},
 
- 				stop       : function(e, ui) {
 
- 					var helper = ui.helper,
 
- 						files;
 
- 					
 
- 					$(document).off(keyEvt);
 
- 					$(this).elfUiWidgetInstance('draggable') && $(this).draggable('option', { refreshPositions : false });
 
- 					self.draggingUiHelper = null;
 
- 					self.trigger('focus').trigger('dragstop');
 
- 					if (! helper.data('droped')) {
 
- 						files = $.grep(helper.data('files')||[], function(h) { return h? true : false ;});
 
- 						self.trigger('unlockfiles', {files : files});
 
- 						self.trigger('selectfiles', {files : self.selected()});
 
- 					}
 
- 					self.enable();
 
- 					
 
- 					// restore node style
 
- 					node.attr('style', nodeStyle);
 
- 					
 
- 					helper.data('autoScrTm') && clearInterval(helper.data('autoScrTm'));
 
- 				},
 
- 				helper     : function(e, ui) {
 
- 					var element = this.id ? $(this) : $(this).parents('[id]:first'),
 
- 						helper  = $('<div class="elfinder-drag-helper"><span class="elfinder-drag-helper-icon-status"/></div>'),
 
- 						icon    = function(f) {
 
- 							var mime = f.mime, i, tmb = self.tmb(f);
 
- 							i = '<div class="elfinder-cwd-icon elfinder-cwd-icon-drag '+self.mime2class(mime)+' ui-corner-all"/>';
 
- 							if (tmb) {
 
- 								i = $(i).addClass(tmb.className).css('background-image', "url('"+tmb.url+"')").get(0).outerHTML;
 
- 							} else if (f.icon) {
 
- 								i = $(i).css(self.getIconStyle(f, true)).get(0).outerHTML;
 
- 							}
 
- 							if (f.csscls) {
 
- 								i = '<div class="'+f.csscls+'">' + i + '</div>';
 
- 							}
 
- 							return i;
 
- 						},
 
- 						hashes, l, ctr;
 
- 					
 
- 					self.draggingUiHelper && self.draggingUiHelper.stop(true, true);
 
- 					
 
- 					self.trigger('dragstart', {target : element[0], originalEvent : e}, true);
 
- 					
 
- 					hashes = element.hasClass(self.res('class', 'cwdfile')) 
 
- 						? self.selected() 
 
- 						: [self.navId2Hash(element.attr('id'))];
 
- 					
 
- 					helper.append(icon(files[hashes[0]])).data('files', hashes).data('locked', false).data('droped', false).data('namespace', namespace).data('dropover', 0);
 
- 		
 
- 					if ((l = hashes.length) > 1) {
 
- 						helper.append(icon(files[hashes[l-1]]) + '<span class="elfinder-drag-num">'+l+'</span>');
 
- 					}
 
- 					
 
- 					$(document).on(keyEvt, function(e){
 
- 						var chk = (e.shiftKey||e.ctrlKey||e.metaKey);
 
- 						if (ctr !== chk) {
 
- 							ctr = chk;
 
- 							if (helper.is(':visible') && helper.data('dropover') && ! helper.data('droped')) {
 
- 								helper.toggleClass('elfinder-drag-helper-plus', helper.data('locked')? true : ctr);
 
- 								self.trigger(ctr? 'unlockfiles' : 'lockfiles', {files : hashes, helper: helper});
 
- 							}
 
- 						}
 
- 					});
 
- 					
 
- 					return helper;
 
- 				}
 
- 			};
 
- 		})();
 
- 		// in getFileCallback set - change default actions on double click/enter/ctrl+enter
 
- 		if (self.commands.getfile) {
 
- 			if (typeof(self.options.getFileCallback) == 'function') {
 
- 				self.bind('dblclick', function(e) {
 
- 					e.preventDefault();
 
- 					self.exec('getfile').fail(function() {
 
- 						self.exec('open', e.data && e.data.file? [ e.data.file ]: void(0));
 
- 					});
 
- 				});
 
- 				self.shortcut({
 
- 					pattern     : 'enter',
 
- 					description : self.i18n('cmdgetfile'),
 
- 					callback    : function() { self.exec('getfile').fail(function() { self.exec(self.OS == 'mac' ? 'rename' : 'open'); }); }
 
- 				})
 
- 				.shortcut({
 
- 					pattern     : 'ctrl+enter',
 
- 					description : self.i18n(self.OS == 'mac' ? 'cmdrename' : 'cmdopen'),
 
- 					callback    : function() { self.exec(self.OS == 'mac' ? 'rename' : 'open'); }
 
- 				});
 
- 			} else {
 
- 				self.options.getFileCallback = null;
 
- 			}
 
- 		}
 
- 		// load commands
 
- 		$.each(self.commands, function(name, cmd) {
 
- 			var proto = Object.assign({}, cmd.prototype),
 
- 				extendsCmd, opts;
 
- 			if ($.isFunction(cmd) && !self._commands[name] && (cmd.prototype.forceLoad || $.inArray(name, self.options.commands) !== -1)) {
 
- 				extendsCmd = cmd.prototype.extendsCmd || '';
 
- 				if (extendsCmd) {
 
- 					if ($.isFunction(self.commands[extendsCmd])) {
 
- 						cmd.prototype = Object.assign({}, base, new self.commands[extendsCmd](), cmd.prototype);
 
- 					} else {
 
- 						return true;
 
- 					}
 
- 				} else {
 
- 					cmd.prototype = Object.assign({}, base, cmd.prototype);
 
- 				}
 
- 				self._commands[name] = new cmd();
 
- 				cmd.prototype = proto;
 
- 				opts = self.options.commandsOptions[name] || {};
 
- 				if (extendsCmd && self.options.commandsOptions[extendsCmd]) {
 
- 					opts = $.extend(true, {}, self.options.commandsOptions[extendsCmd], opts);
 
- 				}
 
- 				self._commands[name].setup(name, opts);
 
- 				// setup linked commands
 
- 				if (self._commands[name].linkedCmds.length) {
 
- 					$.each(self._commands[name].linkedCmds, function(i, n) {
 
- 						var lcmd = self.commands[n];
 
- 						if ($.isFunction(lcmd) && !self._commands[n]) {
 
- 							lcmd.prototype = base;
 
- 							self._commands[n] = new lcmd();
 
- 							self._commands[n].setup(n, self.options.commandsOptions[n]||{});
 
- 						}
 
- 					});
 
- 				}
 
- 			}
 
- 		});
 
- 		/**
 
- 		 * UI nodes
 
- 		 *
 
- 		 * @type Object
 
- 		 **/
 
- 		self.ui = {
 
- 			// container for nav panel and current folder container
 
- 			workzone : $('<div/>').appendTo(node).elfinderworkzone(self),
 
- 			// container for folders tree / places
 
- 			navbar : $('<div/>').appendTo(node).elfindernavbar(self, self.options.uiOptions.navbar || {}),
 
- 			// container for for preview etc at below the navbar
 
- 			navdock : $('<div/>').appendTo(node).elfindernavdock(self, self.options.uiOptions.navdock || {}),
 
- 			// contextmenu
 
- 			contextmenu : $('<div/>').appendTo(node).elfindercontextmenu(self),
 
- 			// overlay
 
- 			overlay : $('<div/>').appendTo(node).elfinderoverlay({
 
- 				show : function() { self.disable(); },
 
- 				hide : function() { prevEnabled && self.enable(); }
 
- 			}),
 
- 			// current folder container
 
- 			cwd : $('<div/>').appendTo(node).elfindercwd(self, self.options.uiOptions.cwd || {}),
 
- 			// notification dialog window
 
- 			notify : self.dialog('', {
 
- 				cssClass      : 'elfinder-dialog-notify',
 
- 				position      : self.options.notifyDialog.position,
 
- 				absolute      : true,
 
- 				resizable     : false,
 
- 				autoOpen      : false,
 
- 				closeOnEscape : false,
 
- 				title         : ' ',
 
- 				width         : self.options.notifyDialog.width? parseInt(self.options.notifyDialog.width) : null,
 
- 				minHeight     : null
 
- 			}),
 
- 			statusbar : $('<div class="ui-widget-header ui-helper-clearfix ui-corner-bottom elfinder-statusbar"/>').hide().appendTo(node),
 
- 			toast : $('<div class="elfinder-toast"/>').appendTo(node),
 
- 			bottomtray : $('<div class="elfinder-bottomtray">').appendTo(node)
 
- 		};
 
- 		self.trigger('uiready');
 
- 		// load required ui
 
- 		$.each(self.options.ui || [], function(i, ui) {
 
- 			var name = 'elfinder'+ui,
 
- 				opts = self.options.uiOptions[ui] || {};
 
- 	
 
- 			if (!self.ui[ui] && $.fn[name]) {
 
- 				// regist to self.ui before make instance
 
- 				self.ui[ui] = $('<'+(opts.tag || 'div')+'/>').appendTo(node);
 
- 				self.ui[ui][name](self, opts);
 
- 			}
 
- 		});
 
- 		
 
- 		// update size	
 
- 		self.resize(width, height);
 
- 		
 
- 		// make node resizable
 
- 		if (self.options.resizable) {
 
- 			node.resizable({
 
- 				resize    : function(e, ui) {
 
- 					self.resize(ui.size.width, ui.size.height);
 
- 				},
 
- 				handles   : 'se',
 
- 				minWidth  : 300,
 
- 				minHeight : 200
 
- 			});
 
- 			if (self.UA.Touch) {
 
- 				node.addClass('touch-punch');
 
- 			}
 
- 		}
 
- 		(function() {
 
- 			var navbar = self.getUI('navbar'),
 
- 				cwd    = self.getUI('cwd').parent();
 
- 			
 
- 			self.autoScroll = {
 
- 				navbarUp   : function(v) {
 
- 					navbar.scrollTop(Math.max(0, navbar.scrollTop() - v));
 
- 				},
 
- 				navbarDown : function(v) {
 
- 					navbar.scrollTop(navbar.scrollTop() + v);
 
- 				},
 
- 				cwdUp     : function(v) {
 
- 					cwd.scrollTop(Math.max(0, cwd.scrollTop() - v));
 
- 				},
 
- 				cwdDown   : function(v) {
 
- 					cwd.scrollTop(cwd.scrollTop() + v);
 
- 				}
 
- 			};
 
- 		})();
 
- 		// Swipe on the touch devices to show/hide of toolbar or navbar
 
- 		if (self.UA.Touch) {
 
- 			(function() {
 
- 				var lastX, lastY, nodeOffset, nodeWidth, nodeTop, navbarW, toolbarH,
 
- 					navbar = self.getUI('navbar'),
 
- 					toolbar = self.getUI('toolbar'),
 
- 					moveEv = 'touchmove.stopscroll',
 
- 					moveTm,
 
- 					moveUpOn = function(e) {
 
- 						var touches = e.originalEvent.touches || [{}],
 
- 							y = touches[0].pageY || null;
 
- 						if (!lastY || y < lastY) {
 
- 							e.preventDefault();
 
- 							moveTm && clearTimeout(moveTm);
 
- 						}
 
- 					},
 
- 					moveDownOn = function(e) {
 
- 						e.preventDefault();
 
- 						moveTm && clearTimeout(moveTm);
 
- 					},
 
- 					moveOff = function() {
 
- 						moveTm = setTimeout(function() {
 
- 							node.off(moveEv);
 
- 						}, 100);
 
- 					},
 
- 					handleW, handleH = 50;
 
- 				navbar = navbar.children().length? navbar : null;
 
- 				toolbar = toolbar.length? toolbar : null;
 
- 				node.on('touchstart touchmove touchend', function(e) {
 
- 					if (e.type === 'touchend') {
 
- 						lastX = false;
 
- 						lastY = false;
 
- 						moveOff();
 
- 						return;
 
- 					}
 
- 					
 
- 					var touches = e.originalEvent.touches || [{}],
 
- 						x = touches[0].pageX || null,
 
- 						y = touches[0].pageY || null,
 
- 						ltr = (self.direction === 'ltr'),
 
- 						navbarMode, treeWidth, swipeX, moveX, toolbarT, mode;
 
- 					
 
- 					if (x === null || y === null || (e.type === 'touchstart' && touches.length > 1)) {
 
- 						return;
 
- 					}
 
- 					
 
- 					if (e.type === 'touchstart') {
 
- 						nodeOffset = node.offset();
 
- 						nodeWidth = node.width();
 
- 						if (navbar) {
 
- 							lastX = false;
 
- 							if (navbar.is(':hidden')) {
 
- 								if (! handleW) {
 
- 									handleW = Math.max(50, nodeWidth / 10);
 
- 								}
 
- 								if ((ltr? (x - nodeOffset.left) : (nodeWidth + nodeOffset.left - x)) < handleW) {
 
- 									lastX = x;
 
- 								}
 
- 							} else if (! e.originalEvent._preventSwipeX) {
 
- 								navbarW = navbar.width();
 
- 								if (ltr) {
 
- 									swipeX = (x < nodeOffset.left + navbarW);
 
- 								} else {
 
- 									swipeX = (x > nodeOffset.left + nodeWidth - navbarW);
 
- 								}
 
- 								if (swipeX) {
 
- 									handleW = Math.max(50, nodeWidth / 10);
 
- 									lastX = x;
 
- 								} else {
 
- 									lastX = false;
 
- 								}
 
- 							}
 
- 						}
 
- 						if (toolbar) {
 
- 							lastY = false;
 
- 							if (! e.originalEvent._preventSwipeY) {
 
- 								toolbarH = toolbar.height();
 
- 								nodeTop = nodeOffset.top;
 
- 								if (y - nodeTop < (toolbar.is(':hidden')? handleH : (toolbarH + 30))) {
 
- 									lastY = y;
 
- 									node.on(moveEv, toolbar.is(':hidden')? moveDownOn: moveUpOn);
 
- 								}
 
- 							}
 
- 						}
 
- 					} else {
 
- 						if (navbar && lastX !== false) {
 
- 							navbarMode = (ltr? (lastX > x) : (lastX < x))? 'navhide' : 'navshow';
 
- 							moveX = Math.abs(lastX - x);
 
- 							if (navbarMode === 'navhide' && moveX > navbarW * 0.6
 
- 								|| (moveX > (navbarMode === 'navhide'? navbarW / 3 : 45)
 
- 									&& (navbarMode === 'navshow'
 
- 										|| (ltr? x < nodeOffset.left + 20 : x > nodeOffset.left + nodeWidth - 20)
 
- 									))
 
- 							) {
 
- 								self.getUI('navbar').trigger(navbarMode, {handleW: handleW});
 
- 								lastX = false;
 
- 							}
 
- 						}
 
- 						if (toolbar && lastY !== false ) {
 
- 							toolbarT = toolbar.offset().top;
 
- 							if (Math.abs(lastY - y) > Math.min(45, toolbarH / 3)) {
 
- 								mode = (lastY > y)? 'slideUp' : 'slideDown';
 
- 								if (mode === 'slideDown' || toolbarT + 20 > y) {
 
- 									if (toolbar.is(mode === 'slideDown' ? ':hidden' : ':visible')) {
 
- 										toolbar.stop(true, true).trigger('toggle', {duration: 100, handleH: handleH});
 
- 									}
 
- 									lastY = false;
 
- 								}
 
- 							}
 
- 						}
 
- 					}
 
- 				});
 
- 			})();
 
- 		}
 
- 		if (self.dragUpload) {
 
- 			// add event listener for HTML5 DnD upload
 
- 			(function() {
 
- 				var isin = function(e) {
 
- 					return (e.target.nodeName !== 'TEXTAREA' && e.target.nodeName !== 'INPUT' && $(e.target).closest('div.ui-dialog-content').length === 0);
 
- 				},
 
- 				ent       = 'native-drag-enter',
 
- 				disable   = 'native-drag-disable',
 
- 				c         = 'class',
 
- 				navdir    = self.res(c, 'navdir'),
 
- 				droppable = self.res(c, 'droppable'),
 
- 				dropover  = self.res(c, 'adroppable'),
 
- 				arrow     = self.res(c, 'navarrow'),
 
- 				clDropActive = self.res(c, 'adroppable'),
 
- 				wz        = self.getUI('workzone'),
 
- 				ltr       = (self.direction === 'ltr'),
 
- 				clearTm   = function() {
 
- 					autoScrTm && cancelAnimationFrame(autoScrTm);
 
- 					autoScrTm = null;
 
- 				},
 
- 				wzRect, autoScrFn, autoScrTm;
 
- 				
 
- 				node.on('dragenter', function(e) {
 
- 					clearTm();
 
- 					if (isin(e)) {
 
- 						e.preventDefault();
 
- 						e.stopPropagation();
 
- 						wzRect = wz.data('rectangle');
 
- 					}
 
- 				})
 
- 				.on('dragleave', function(e) {
 
- 					clearTm();
 
- 					if (isin(e)) {
 
- 						e.preventDefault();
 
- 						e.stopPropagation();
 
- 					}
 
- 				})
 
- 				.on('dragover', function(e) {
 
- 					var autoUp;
 
- 					if (isin(e)) {
 
- 						e.preventDefault();
 
- 						e.stopPropagation();
 
- 						e.originalEvent.dataTransfer.dropEffect = 'none';
 
- 						if (! autoScrTm) {
 
- 							autoScrTm = requestAnimationFrame(function() {
 
- 								var wzBottom = wzRect.top + wzRect.height,
 
- 									wzBottom2 = wzBottom - self.getUI('navdock').outerHeight(true),
 
- 									fn;
 
- 								if ((autoUp = e.pageY < wzRect.top) || e.pageY > wzBottom2 ) {
 
- 									if (wzRect.cwdEdge > e.pageX) {
 
- 										fn = (ltr? 'navbar' : 'cwd') + (autoUp? 'Up' : 'Down');
 
- 									} else {
 
- 										fn = (ltr? 'cwd' : 'navbar') + (autoUp? 'Up' : 'Down');
 
- 									}
 
- 									if (!autoUp) {
 
- 										if (fn.substr(0, 3) === 'cwd') {
 
- 											if (wzBottom < e.pageY) {
 
- 												wzBottom2 = wzBottom;
 
- 											} else {
 
- 												fn = '';
 
- 											}
 
- 										}
 
- 									}
 
- 									fn && self.autoScroll[fn](Math.pow((autoUp? wzRect.top - e.pageY : e.pageY - wzBottom2), 1.3));
 
- 								}
 
- 								autoScrTm = null;
 
- 							});
 
- 						}
 
- 					} else {
 
- 						clearTm();
 
- 					}
 
- 				})
 
- 				.on('drop', function(e) {
 
- 					clearTm();
 
- 					if (isin(e)) {
 
- 						e.stopPropagation();
 
- 						e.preventDefault();
 
- 					}
 
- 				});
 
- 				
 
- 				node.on('dragenter', '.native-droppable', function(e){
 
- 					if (e.originalEvent.dataTransfer) {
 
- 						var $elm = $(e.currentTarget),
 
- 							id   = e.currentTarget.id || null,
 
- 							cwd  = null,
 
- 							elfFrom;
 
- 						if (!id) { // target is cwd
 
- 							cwd = self.cwd();
 
- 							$elm.data(disable, false);
 
- 							try {
 
- 								$.each(e.originalEvent.dataTransfer.types, function(i, v){
 
- 									if (v.substr(0, 13) === 'elfinderfrom:') {
 
- 										elfFrom = v.substr(13).toLowerCase();
 
- 									}
 
- 								});
 
- 							} catch(e) {}
 
- 						}
 
- 						if (!cwd || (cwd.write && (!elfFrom || elfFrom !== (window.location.href + cwd.hash).toLowerCase()))) {
 
- 							e.preventDefault();
 
- 							e.stopPropagation();
 
- 							$elm.data(ent, true);
 
- 							$elm.addClass(clDropActive);
 
- 						} else {
 
- 							$elm.data(disable, true);
 
- 						}
 
- 					}
 
- 				})
 
- 				.on('dragleave', '.native-droppable', function(e){
 
- 					if (e.originalEvent.dataTransfer) {
 
- 						var $elm = $(e.currentTarget);
 
- 						e.preventDefault();
 
- 						e.stopPropagation();
 
- 						if ($elm.data(ent)) {
 
- 							$elm.data(ent, false);
 
- 						} else {
 
- 							$elm.removeClass(clDropActive);
 
- 						}
 
- 					}
 
- 				})
 
- 				.on('dragover', '.native-droppable', function(e){
 
- 					if (e.originalEvent.dataTransfer) {
 
- 						var $elm = $(e.currentTarget);
 
- 						e.preventDefault();
 
- 						e.stopPropagation();
 
- 						e.originalEvent.dataTransfer.dropEffect = $elm.data(disable)? 'none' : 'copy';
 
- 						$elm.data(ent, false);
 
- 					}
 
- 				})
 
- 				.on('drop', '.native-droppable', function(e){
 
- 					if (e.originalEvent && e.originalEvent.dataTransfer) {
 
- 						var $elm = $(e.currentTarget),
 
- 							id;
 
- 						e.preventDefault();
 
- 						e.stopPropagation();
 
- 						$elm.removeClass(clDropActive);
 
- 						if (e.currentTarget.id) {
 
- 							id = $elm.hasClass(navdir)? self.navId2Hash(e.currentTarget.id) : self.cwdId2Hash(e.currentTarget.id);
 
- 						} else {
 
- 							id = self.cwd().hash;
 
- 						}
 
- 						e.originalEvent._target = id;
 
- 						self.exec('upload', {dropEvt: e.originalEvent, target: id}, void 0, id);
 
- 					}
 
- 				});
 
- 			})();
 
- 		}
 
- 		// trigger event cssloaded if cddAutoLoad disabled
 
- 		if (self.cssloaded === null) {
 
- 			// check css loaded and remove hide
 
- 			(function() {
 
- 				var loaded = function() {
 
- 						if (node.data('cssautoloadHide')) {
 
- 							node.data('cssautoloadHide').remove();
 
- 							node.removeData('cssautoloadHide');
 
- 						}
 
- 						self.cssloaded = true;
 
- 						requestAnimationFrame(function() {
 
- 							self.trigger('cssloaded');
 
- 						});
 
- 					},
 
- 					cnt, fi;
 
- 				if (node.css('visibility') === 'hidden') {
 
- 					cnt = 1000; // timeout 10 secs
 
- 					fi  = setInterval(function() {
 
- 						if (--cnt < 0 || node.css('visibility') !== 'hidden') {
 
- 							clearInterval(fi);
 
- 							loaded();
 
- 						}
 
- 					}, 10);
 
- 				} else {
 
- 					loaded();
 
- 				}
 
- 			})();
 
- 		} else {
 
- 			self.cssloaded = true;
 
- 			self.trigger('cssloaded');
 
- 		}
 
- 		// calculate elFinder node z-index
 
- 		self.zIndexCalc();
 
- 		// send initial request and start to pray >_<
 
- 		self.trigger('init')
 
- 			.request({
 
- 				data        : {cmd : 'open', target : self.startDir(), init : 1, tree : 1}, 
 
- 				preventDone : true,
 
- 				notify      : {type : 'open', cnt : 1, hideCnt : true},
 
- 				freeze      : true
 
- 			})
 
- 			.fail(function() {
 
- 				self.trigger('fail').disable().lastDir('');
 
- 				listeners = {};
 
- 				shortcuts = {};
 
- 				$(document).add(node).off('.'+namespace);
 
- 				self.trigger = function() { };
 
- 			})
 
- 			.done(function(data) {
 
- 				var trashDisable = function(th) {
 
- 						var src = self.file(self.trashes[th]),
 
- 							d = self.options.debug,
 
- 							error;
 
- 						
 
- 						if (src && src.volumeid) {
 
- 							delete self.volOptions[src.volumeid].trashHash;
 
- 						}
 
- 						self.trashes[th] = false;
 
- 						self.debug('backend-error', 'Trash hash "'+th+'" was not found or not writable.');
 
- 					},
 
- 					toChkTh = {};
 
- 				
 
- 				// regist rawStringDecoder
 
- 				if (self.options.rawStringDecoder) {
 
- 					self.registRawStringDecoder(self.options.rawStringDecoder);
 
- 				}
 
- 				// re-calculate elFinder node z-index
 
- 				self.zIndexCalc();
 
- 				
 
- 				self.load().debug('api', self.api);
 
- 				// update ui's size after init
 
- 				node.trigger('resize');
 
- 				// initial open
 
- 				open(data);
 
- 				self.trigger('open', data, false);
 
- 				self.trigger('opendone');
 
- 				
 
- 				if (inFrame && self.options.enableAlways) {
 
- 					$(window).trigger('focus');
 
- 				}
 
- 				
 
- 				// check self.trashes
 
- 				$.each(self.trashes, function(th) {
 
- 					var dir = self.file(th),
 
- 						src;
 
- 					if (! dir) {
 
- 						toChkTh[th] = true;
 
- 					} else if (dir.mime !== 'directory' || ! dir.write) {
 
- 						trashDisable(th);
 
- 					}
 
- 				});
 
- 				if (Object.keys(toChkTh).length) {
 
- 					self.request({
 
- 						data : {cmd : 'info', targets : Object.keys(toChkTh)},
 
- 						preventDefault : true
 
- 					}).done(function(data) {
 
- 						if (data && data.files) {
 
- 							$.each(data.files, function(i, dir) {
 
- 								if (dir.mime === 'directory' && dir.write) {
 
- 									delete toChkTh[dir.hash];
 
- 								}
 
- 							});
 
- 						}
 
- 					}).always(function() {
 
- 						$.each(toChkTh, trashDisable);
 
- 					});
 
- 				}
 
- 				// to enable / disable
 
- 				self[self.options.enableAlways? 'enable' : 'disable']();
 
- 			});
 
- 		
 
- 		// self.timeEnd('load');
 
- 		// End of bootUp()
 
- 	};
 
- 	
 
- 	// call bootCallback function with elFinder instance, extraObject - { dfrdsBeforeBootup: dfrdsBeforeBootup }
 
- 	if (bootCallback && typeof bootCallback === 'function') {
 
- 		self.bootCallback = bootCallback;
 
- 		bootCallback.call(node.get(0), self, { dfrdsBeforeBootup: dfrdsBeforeBootup });
 
- 	}
 
- 	
 
- 	// call dfrdsBeforeBootup functions then boot up elFinder
 
- 	$.when.apply(null, dfrdsBeforeBootup).done(function() {
 
- 		bootUp();
 
- 	}).fail(function(error) {
 
- 		self.error(error);
 
- 	});
 
- };
 
- //register elFinder to global scope
 
- if (typeof toGlobal === 'undefined' || toGlobal) {
 
- 	window.elFinder = elFinder;
 
- }
 
- /**
 
-  * Prototype
 
-  * 
 
-  * @type  Object
 
-  */
 
- elFinder.prototype = {
 
- 	
 
- 	uniqueid : 0,
 
- 	
 
- 	res : function(type, id) {
 
- 		return this.resources[type] && this.resources[type][id];
 
- 	}, 
 
- 	/**
 
- 	 * User os. Required to bind native shortcuts for open/rename
 
- 	 *
 
- 	 * @type String
 
- 	 **/
 
- 	OS : navigator.userAgent.indexOf('Mac') !== -1 ? 'mac' : navigator.userAgent.indexOf('Win') !== -1  ? 'win' : 'other',
 
- 	
 
- 	/**
 
- 	 * User browser UA.
 
- 	 * jQuery.browser: version deprecated: 1.3, removed: 1.9
 
- 	 *
 
- 	 * @type Object
 
- 	 **/
 
- 	UA : (function(){
 
- 		var self = this,
 
- 			webkit = !document.unqueID && !window.opera && !window.sidebar && window.localStorage && 'WebkitAppearance' in document.documentElement.style,
 
- 			chrome = webkit && window.chrome,
 
- 			/*setRotated = function() {
 
- 				var a = ((screen && screen.orientation && screen.orientation.angle) || window.orientation || 0) + 0;
 
- 				if (a === -90) {
 
- 					a = 270;
 
- 				}
 
- 				UA.Angle = a;
 
- 				UA.Rotated = a % 180 === 0? false : true;
 
- 			},*/
 
- 			UA = {
 
- 				// Browser IE <= IE 6
 
- 				ltIE6   : typeof window.addEventListener == "undefined" && typeof document.documentElement.style.maxHeight == "undefined",
 
- 				// Browser IE <= IE 7
 
- 				ltIE7   : typeof window.addEventListener == "undefined" && typeof document.querySelectorAll == "undefined",
 
- 				// Browser IE <= IE 8
 
- 				ltIE8   : typeof window.addEventListener == "undefined" && typeof document.getElementsByClassName == "undefined",
 
- 				// Browser IE <= IE 9
 
- 				ltIE9  : document.uniqueID && document.documentMode <= 9,
 
- 				// Browser IE <= IE 10
 
- 				ltIE10  : document.uniqueID && document.documentMode <= 10,
 
- 				// Browser IE >= IE 11
 
- 				gtIE11  : document.uniqueID && document.documentMode >= 11,
 
- 				IE      : document.uniqueID,
 
- 				Firefox : window.sidebar,
 
- 				Opera   : window.opera,
 
- 				Webkit  : webkit,
 
- 				Chrome  : chrome,
 
- 				Edge    : (chrome && window.msCredentials)? true : false,
 
- 				Safari  : webkit && !window.chrome,
 
- 				Mobile  : typeof window.orientation != "undefined",
 
- 				Touch   : typeof window.ontouchstart != "undefined",
 
- 				iOS     : navigator.platform.match(/^iP(?:[ao]d|hone)/),
 
- 				Fullscreen : (typeof (document.exitFullscreen || document.webkitExitFullscreen || document.mozCancelFullScreen || document.msExitFullscreen) !== 'undefined'),
 
- 				Angle   : 0,
 
- 				Rotated : false,
 
- 				CSS : (function() {
 
- 					var aStyle = document.createElement('a').style,
 
- 						pStyle = document.createElement('p').style,
 
- 						css;
 
- 					css = 'position:sticky;position:-webkit-sticky;';
 
- 					css += 'width:-webkit-max-content;width:-moz-max-content;width:-ms-max-content;width:max-content;';
 
- 					aStyle.cssText = css;
 
- 					return {
 
- 						positionSticky : aStyle.position.indexOf('sticky')!==-1,
 
- 						widthMaxContent : aStyle.width.indexOf('max-content')!==-1,
 
- 						flex : typeof pStyle.flex !== 'undefined'
 
- 					};
 
- 				})()
 
- 			};
 
- 			return UA;
 
- 	})(),
 
- 	
 
- 	/**
 
- 	 * Has RequireJS?
 
- 	 * 
 
- 	 * @type Boolean
 
- 	 */
 
- 	hasRequire : (typeof define === 'function' && define.amd),
 
- 	
 
- 	/**
 
- 	 * Current request command
 
- 	 * 
 
- 	 * @type  String
 
- 	 */
 
- 	currentReqCmd : '',
 
- 	
 
- 	/**
 
- 	 * Current keyboard state
 
- 	 * 
 
- 	 * @type  Object
 
- 	 */
 
- 	keyState : {},
 
- 	
 
- 	/**
 
- 	 * Internationalization object
 
- 	 * 
 
- 	 * @type  Object
 
- 	 */
 
- 	i18 : {
 
- 		en : {
 
- 			translator      : '',
 
- 			language        : 'English',
 
- 			direction       : 'ltr',
 
- 			dateFormat      : 'd.m.Y H:i',
 
- 			fancyDateFormat : '$1 H:i',
 
- 			nonameDateFormat : 'ymd-His',
 
- 			messages        : {}
 
- 		},
 
- 		months : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
 
- 		monthsShort : ['msJan', 'msFeb', 'msMar', 'msApr', 'msMay', 'msJun', 'msJul', 'msAug', 'msSep', 'msOct', 'msNov', 'msDec'],
 
- 		days : ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
 
- 		daysShort : ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
 
- 	},
 
- 	
 
- 	/**
 
- 	 * File mimetype to kind mapping
 
- 	 * 
 
- 	 * @type  Object
 
- 	 */
 
- 	kinds : 	{
 
- 			'unknown'                       : 'Unknown',
 
- 			'directory'                     : 'Folder',
 
- 			'group'                         : 'Selects',
 
- 			'symlink'                       : 'Alias',
 
- 			'symlink-broken'                : 'AliasBroken',
 
- 			'application/x-empty'           : 'TextPlain',
 
- 			'application/postscript'        : 'Postscript',
 
- 			'application/vnd.ms-office'     : 'MsOffice',
 
- 			'application/msword'            : 'MsWord',
 
- 			'application/vnd.ms-word'       : 'MsWord',
 
- 			'application/vnd.openxmlformats-officedocument.wordprocessingml.document' : 'MsWord',
 
- 			'application/vnd.ms-word.document.macroEnabled.12'                        : 'MsWord',
 
- 			'application/vnd.openxmlformats-officedocument.wordprocessingml.template' : 'MsWord',
 
- 			'application/vnd.ms-word.template.macroEnabled.12'                        : 'MsWord',
 
- 			'application/vnd.ms-excel'      : 'MsExcel',
 
- 			'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'       : 'MsExcel',
 
- 			'application/vnd.ms-excel.sheet.macroEnabled.12'                          : 'MsExcel',
 
- 			'application/vnd.openxmlformats-officedocument.spreadsheetml.template'    : 'MsExcel',
 
- 			'application/vnd.ms-excel.template.macroEnabled.12'                       : 'MsExcel',
 
- 			'application/vnd.ms-excel.sheet.binary.macroEnabled.12'                   : 'MsExcel',
 
- 			'application/vnd.ms-excel.addin.macroEnabled.12'                          : 'MsExcel',
 
- 			'application/vnd.ms-powerpoint' : 'MsPP',
 
- 			'application/vnd.openxmlformats-officedocument.presentationml.presentation' : 'MsPP',
 
- 			'application/vnd.ms-powerpoint.presentation.macroEnabled.12'              : 'MsPP',
 
- 			'application/vnd.openxmlformats-officedocument.presentationml.slideshow'  : 'MsPP',
 
- 			'application/vnd.ms-powerpoint.slideshow.macroEnabled.12'                 : 'MsPP',
 
- 			'application/vnd.openxmlformats-officedocument.presentationml.template'   : 'MsPP',
 
- 			'application/vnd.ms-powerpoint.template.macroEnabled.12'                  : 'MsPP',
 
- 			'application/vnd.ms-powerpoint.addin.macroEnabled.12'                     : 'MsPP',
 
- 			'application/vnd.openxmlformats-officedocument.presentationml.slide'      : 'MsPP',
 
- 			'application/vnd.ms-powerpoint.slide.macroEnabled.12'                     : 'MsPP',
 
- 			'application/pdf'               : 'PDF',
 
- 			'application/xml'               : 'XML',
 
- 			'application/vnd.oasis.opendocument.text' : 'OO',
 
- 			'application/vnd.oasis.opendocument.text-template'         : 'OO',
 
- 			'application/vnd.oasis.opendocument.text-web'              : 'OO',
 
- 			'application/vnd.oasis.opendocument.text-master'           : 'OO',
 
- 			'application/vnd.oasis.opendocument.graphics'              : 'OO',
 
- 			'application/vnd.oasis.opendocument.graphics-template'     : 'OO',
 
- 			'application/vnd.oasis.opendocument.presentation'          : 'OO',
 
- 			'application/vnd.oasis.opendocument.presentation-template' : 'OO',
 
- 			'application/vnd.oasis.opendocument.spreadsheet'           : 'OO',
 
- 			'application/vnd.oasis.opendocument.spreadsheet-template'  : 'OO',
 
- 			'application/vnd.oasis.opendocument.chart'                 : 'OO',
 
- 			'application/vnd.oasis.opendocument.formula'               : 'OO',
 
- 			'application/vnd.oasis.opendocument.database'              : 'OO',
 
- 			'application/vnd.oasis.opendocument.image'                 : 'OO',
 
- 			'application/vnd.openofficeorg.extension'                  : 'OO',
 
- 			'application/x-shockwave-flash' : 'AppFlash',
 
- 			'application/flash-video'       : 'Flash video',
 
- 			'application/x-bittorrent'      : 'Torrent',
 
- 			'application/javascript'        : 'JS',
 
- 			'application/rtf'               : 'RTF',
 
- 			'application/rtfd'              : 'RTF',
 
- 			'application/x-font-ttf'        : 'TTF',
 
- 			'application/x-font-otf'        : 'OTF',
 
- 			'application/x-rpm'             : 'RPM',
 
- 			'application/x-web-config'      : 'TextPlain',
 
- 			'application/xhtml+xml'         : 'HTML',
 
- 			'application/docbook+xml'       : 'DOCBOOK',
 
- 			'application/x-awk'             : 'AWK',
 
- 			'application/x-gzip'            : 'GZIP',
 
- 			'application/x-bzip2'           : 'BZIP',
 
- 			'application/x-xz'              : 'XZ',
 
- 			'application/zip'               : 'ZIP',
 
- 			'application/x-zip'               : 'ZIP',
 
- 			'application/x-rar'             : 'RAR',
 
- 			'application/x-tar'             : 'TAR',
 
- 			'application/x-7z-compressed'   : '7z',
 
- 			'application/x-jar'             : 'JAR',
 
- 			'text/plain'                    : 'TextPlain',
 
- 			'text/x-php'                    : 'PHP',
 
- 			'text/html'                     : 'HTML',
 
- 			'text/javascript'               : 'JS',
 
- 			'text/css'                      : 'CSS',
 
- 			'text/rtf'                      : 'RTF',
 
- 			'text/rtfd'                     : 'RTF',
 
- 			'text/x-c'                      : 'C',
 
- 			'text/x-csrc'                   : 'C',
 
- 			'text/x-chdr'                   : 'CHeader',
 
- 			'text/x-c++'                    : 'CPP',
 
- 			'text/x-c++src'                 : 'CPP',
 
- 			'text/x-c++hdr'                 : 'CPPHeader',
 
- 			'text/x-shellscript'            : 'Shell',
 
- 			'application/x-csh'             : 'Shell',
 
- 			'text/x-python'                 : 'Python',
 
- 			'text/x-java'                   : 'Java',
 
- 			'text/x-java-source'            : 'Java',
 
- 			'text/x-ruby'                   : 'Ruby',
 
- 			'text/x-perl'                   : 'Perl',
 
- 			'text/x-sql'                    : 'SQL',
 
- 			'text/xml'                      : 'XML',
 
- 			'text/x-comma-separated-values' : 'CSV',
 
- 			'text/x-markdown'               : 'Markdown',
 
- 			'image/x-ms-bmp'                : 'BMP',
 
- 			'image/jpeg'                    : 'JPEG',
 
- 			'image/gif'                     : 'GIF',
 
- 			'image/png'                     : 'PNG',
 
- 			'image/tiff'                    : 'TIFF',
 
- 			'image/x-targa'                 : 'TGA',
 
- 			'image/vnd.adobe.photoshop'     : 'PSD',
 
- 			'image/xbm'                     : 'XBITMAP',
 
- 			'image/pxm'                     : 'PXM',
 
- 			'audio/mpeg'                    : 'AudioMPEG',
 
- 			'audio/midi'                    : 'AudioMIDI',
 
- 			'audio/ogg'                     : 'AudioOGG',
 
- 			'audio/mp4'                     : 'AudioMPEG4',
 
- 			'audio/x-m4a'                   : 'AudioMPEG4',
 
- 			'audio/wav'                     : 'AudioWAV',
 
- 			'audio/x-mp3-playlist'          : 'AudioPlaylist',
 
- 			'video/x-dv'                    : 'VideoDV',
 
- 			'video/mp4'                     : 'VideoMPEG4',
 
- 			'video/mpeg'                    : 'VideoMPEG',
 
- 			'video/x-msvideo'               : 'VideoAVI',
 
- 			'video/quicktime'               : 'VideoMOV',
 
- 			'video/x-ms-wmv'                : 'VideoWM',
 
- 			'video/x-flv'                   : 'VideoFlash',
 
- 			'video/x-matroska'              : 'VideoMKV',
 
- 			'video/ogg'                     : 'VideoOGG'
 
- 		},
 
- 	
 
- 	/**
 
- 	 * File mimetype to file extention mapping
 
- 	 * 
 
- 	 * @type  Object
 
- 	 * @see   elFinder.mimetypes.js
 
- 	 */
 
- 	mimeTypes : {},
 
- 	
 
- 	/**
 
- 	 * Ajax request data validation rules
 
- 	 * 
 
- 	 * @type  Object
 
- 	 */
 
- 	rules : {
 
- 		defaults : function(data) {
 
- 			if (!data
 
- 			|| (data.added && !Array.isArray(data.added))
 
- 			||  (data.removed && !Array.isArray(data.removed))
 
- 			||  (data.changed && !Array.isArray(data.changed))) {
 
- 				return false;
 
- 			}
 
- 			return true;
 
- 		},
 
- 		open    : function(data) { return data && data.cwd && data.files && $.isPlainObject(data.cwd) && Array.isArray(data.files); },
 
- 		tree    : function(data) { return data && data.tree && Array.isArray(data.tree); },
 
- 		parents : function(data) { return data && data.tree && Array.isArray(data.tree); },
 
- 		tmb     : function(data) { return data && data.images && ($.isPlainObject(data.images) || Array.isArray(data.images)); },
 
- 		upload  : function(data) { return data && ($.isPlainObject(data.added) || Array.isArray(data.added));},
 
- 		search  : function(data) { return data && data.files && Array.isArray(data.files); }
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Commands costructors
 
- 	 *
 
- 	 * @type Object
 
- 	 */
 
- 	commands : {},
 
- 	
 
- 	/**
 
- 	 * Commands to add the item (space delimited)
 
- 	 * 
 
- 	 * @type String
 
- 	 */
 
- 	cmdsToAdd : 'archive duplicate extract mkdir mkfile paste rm upload',
 
- 	
 
- 	parseUploadData : function(text) {
 
- 		var self = this,
 
- 			data;
 
- 		
 
- 		if (!$.trim(text)) {
 
- 			return {error : ['errResponse', 'errDataEmpty']};
 
- 		}
 
- 		
 
- 		try {
 
- 			data = JSON.parse(text);
 
- 		} catch (e) {
 
- 			return {error : ['errResponse', 'errDataNotJSON']};
 
- 		}
 
- 		
 
- 		data = self.normalize(data);
 
- 		if (!self.validResponse('upload', data)) {
 
- 			return {error : (response.norError || ['errResponse'])};
 
- 		}
 
- 		data.removed = $.merge((data.removed || []), $.map(data.added || [], function(f) { return self.file(f.hash)? f.hash : null; }));
 
- 		return data;
 
- 		
 
- 	},
 
- 	
 
- 	iframeCnt : 0,
 
- 	
 
- 	uploads : {
 
- 		// xhr muiti uploading flag
 
- 		xhrUploading: false,
 
- 		
 
- 		// Timer of request fail to sync
 
- 		failSyncTm: null,
 
- 		
 
- 		// current chunkfail requesting chunk
 
- 		chunkfailReq: {},
 
- 		
 
- 		// check file/dir exists
 
- 		checkExists: function(files, target, fm, isDir) {
 
- 			var dfrd = $.Deferred(),
 
- 				names, renames = [], hashes = {}, chkFiles = [],
 
- 				cancel = function() {
 
- 					var i = files.length;
 
- 					while (--i > -1) {
 
- 						files[i]._remove = true;
 
- 					}
 
- 				},
 
- 				resolve = function() {
 
- 					dfrd.resolve(renames, hashes);
 
- 				},
 
- 				check = function() {
 
- 					var existed = [], exists = [], i, c,
 
- 						pathStr = target !== fm.cwd().hash? fm.path(target, true) + fm.option('separator', target) : '',
 
- 						confirm = function(ndx) {
 
- 							var last = ndx == exists.length-1,
 
- 								opts = {
 
- 									cssClass : 'elfinder-confirm-upload',
 
- 									title  : fm.i18n('cmdupload'),
 
- 									text   : ['errExists', pathStr + exists[ndx].name, 'confirmRepl'], 
 
- 									all    : !last,
 
- 									accept : {
 
- 										label    : 'btnYes',
 
- 										callback : function(all) {
 
- 											!last && !all
 
- 												? confirm(++ndx)
 
- 												: resolve();
 
- 										}
 
- 									},
 
- 									reject : {
 
- 										label    : 'btnNo',
 
- 										callback : function(all) {
 
- 											var i;
 
- 			
 
- 											if (all) {
 
- 												i = exists.length;
 
- 												while (ndx < i--) {
 
- 													files[exists[i].i]._remove = true;
 
- 												}
 
- 											} else {
 
- 												files[exists[ndx].i]._remove = true;
 
- 											}
 
- 			
 
- 											!last && !all
 
- 												? confirm(++ndx)
 
- 												: resolve();
 
- 										}
 
- 									},
 
- 									cancel : {
 
- 										label    : 'btnCancel',
 
- 										callback : function() {
 
- 											cancel();
 
- 											resolve();
 
- 										}
 
- 									},
 
- 									buttons : [
 
- 										{
 
- 											label : 'btnBackup',
 
- 											cssClass : 'elfinder-confirm-btn-backup',
 
- 											callback : function(all) {
 
- 												var i;
 
- 												if (all) {
 
- 													i = exists.length;
 
- 													while (ndx < i--) {
 
- 														renames.push(exists[i].name);
 
- 													}
 
- 												} else {
 
- 													renames.push(exists[ndx].name);
 
- 												}
 
- 												!last && !all
 
- 													? confirm(++ndx)
 
- 													: resolve();
 
- 											}
 
- 										}
 
- 									]
 
- 								};
 
- 							
 
- 							if (!isDir) {
 
- 								opts.buttons.push({
 
- 									label : 'btnRename' + (last? '' : 'All'),
 
- 									cssClass : 'elfinder-confirm-btn-rename',
 
- 									callback : function() {
 
- 										renames = null;
 
- 										resolve();
 
- 									}
 
- 								});
 
- 							}
 
- 							if (fm.iframeCnt > 0) {
 
- 								delete opts.reject;
 
- 							}
 
- 							fm.confirm(opts);
 
- 						};
 
- 					
 
- 					if (! fm.file(target).read) {
 
- 						// for dropbox type
 
- 						resolve();
 
- 						return;
 
- 					}
 
- 					
 
- 					names = $.map(files, function(file, i) { return file.name && (!fm.UA.iOS || file.name !== 'image.jpg')? {i: i, name: file.name} : null ;});
 
- 					
 
- 					fm.request({
 
- 						data : {cmd : 'ls', target : target, intersect : $.map(names, function(item) { return item.name;})},
 
- 						notify : {type : 'preupload', cnt : 1, hideCnt : true},
 
- 						preventDefault : true
 
- 					})
 
- 					.done(function(data) {
 
- 						var existedArr, cwdItems;
 
- 						if (data) {
 
- 							if (data.error) {
 
- 								cancel();
 
- 							} else {
 
- 								if (fm.options.overwriteUploadConfirm && fm.option('uploadOverwrite', target)) {
 
- 									if (data.list) {
 
- 										if (Array.isArray(data.list)) {
 
- 											existed = data.list || [];
 
- 										} else {
 
- 											existedArr = [];
 
- 											existed = $.map(data.list, function(n) {
 
- 												if (typeof n === 'string') {
 
- 													return n;
 
- 												} else {
 
- 													// support to >=2.1.11 plugin Normalizer, Sanitizer
 
- 													existedArr = existedArr.concat(n);
 
- 													return false;
 
- 												}
 
- 											});
 
- 											if (existedArr.length) {
 
- 												existed = existed.concat(existedArr);
 
- 											}
 
- 											hashes = data.list;
 
- 										}
 
- 										exists = $.grep(names, function(name){
 
- 											return $.inArray(name.name, existed) !== -1 ? true : false ;
 
- 										});
 
- 										if (exists.length && existed.length && target == fm.cwd().hash) {
 
- 											cwdItems = $.map(fm.files(target), function(file) { return file.name; } );
 
- 											if ($.grep(existed, function(n) { 
 
- 												return $.inArray(n, cwdItems) === -1? true : false;
 
- 											}).length){
 
- 												fm.sync();
 
- 											}
 
- 										}
 
- 									}
 
- 								}
 
- 							}
 
- 						}
 
- 						if (exists.length > 0) {
 
- 							confirm(0);
 
- 						} else {
 
- 							resolve();
 
- 						}
 
- 					})
 
- 					.fail(function(error) {
 
- 						cancel();
 
- 						resolve();
 
- 						error && fm.error(error);
 
- 					});
 
- 				};
 
- 			if (fm.api >= 2.1 && typeof files[0] == 'object') {
 
- 				check();
 
- 			} else {
 
- 				resolve();
 
- 			}
 
- 			return dfrd;
 
- 		},
 
- 		
 
- 		// check droped contents
 
- 		checkFile : function(data, fm, target) {
 
- 			if (!!data.checked || data.type == 'files') {
 
- 				return data.files;
 
- 			} else if (data.type == 'data') {
 
- 				var dfrd = $.Deferred(),
 
- 				scanDfd = $.Deferred(),
 
- 				files = [],
 
- 				paths = [],
 
- 				dirctorys = [],
 
- 				processing = 0,
 
- 				items,
 
- 				mkdirs = [],
 
- 				cancel = false,
 
- 				toArray = function(list) {
 
- 					return Array.prototype.slice.call(list || [], 0);
 
- 				},
 
- 				doScan = function(items) {
 
- 					var entry, readEntries,
 
- 						excludes = fm.options.folderUploadExclude[fm.OS] || null,
 
- 						length = items.length,
 
- 						check = function() {
 
- 							if (--processing < 1 && scanDfd.state() === 'pending') {
 
- 								scanDfd.resolve();
 
- 							}
 
- 						},
 
- 						pushItem = function(file) {
 
- 							if (! excludes || ! file.name.match(excludes)) {
 
- 								paths.push(entry.fullPath || '');
 
- 								files.push(file);
 
- 							}
 
- 							check();
 
- 						},
 
- 						readEntries = function(dirReader) {
 
- 							var entries = [],
 
- 								read = function() {
 
- 									dirReader.readEntries(function(results) {
 
- 										if (cancel || !results.length) {
 
- 											for (var i = 0; i < entries.length; i++) {
 
- 												if (cancel) {
 
- 													scanDfd.reject();
 
- 													break;
 
- 												}
 
- 												doScan([entries[i]]);
 
- 											}
 
- 											check();
 
- 										} else {
 
- 											entries = entries.concat(toArray(results));
 
- 											read();
 
- 										}
 
- 									}, check);
 
- 								};
 
- 							read();
 
- 						};
 
- 					
 
- 					processing++;
 
- 					for (var i = 0; i < length; i++) {
 
- 						if (cancel) {
 
- 							scanDfd.reject();
 
- 							break;
 
- 						}
 
- 						entry = items[i];
 
- 						if (entry) {
 
- 							if (entry.isFile) {
 
- 								processing++;
 
- 								entry.file(pushItem, check);
 
- 							} else if (entry.isDirectory) {
 
- 								if (fm.api >= 2.1) {
 
- 									processing++;
 
- 									mkdirs.push(entry.fullPath);
 
- 									readEntries(entry.createReader()); // Start reading dirs.
 
- 								}
 
- 							}
 
- 						}
 
- 					}
 
- 					check();
 
- 					return scanDfd;
 
- 				}, hasDirs;
 
- 				
 
- 				items = $.map(data.files.items, function(item){
 
- 					return item.getAsEntry? item.getAsEntry() : item.webkitGetAsEntry();
 
- 				});
 
- 				$.each(items, function(i, item) {
 
- 					if (item.isDirectory) {
 
- 						hasDirs = true;
 
- 						return false;
 
- 					}
 
- 				});
 
- 				if (items.length > 0) {
 
- 					fm.uploads.checkExists(items, target, fm, hasDirs).done(function(renames, hashes){
 
- 						var dfds = [];
 
- 						if (fm.options.overwriteUploadConfirm && fm.option('uploadOverwrite', target)) {
 
- 							if (renames === null) {
 
- 								data.overwrite = 0;
 
- 								renames = [];
 
- 							}
 
- 							items = $.grep(items, function(item){
 
- 								var i, bak, hash, dfd, hi;
 
- 								if (item.isDirectory && renames.length) {
 
- 									i = $.inArray(item.name, renames);
 
- 									if (i !== -1) {
 
- 										renames.splice(i, 1);
 
- 										bak = fm.uniqueName(item.name + fm.options.backupSuffix , null, '');
 
- 										$.each(hashes, function(h, name) {
 
- 											if (item.name == name) {
 
- 												hash = h;
 
- 												return false;
 
- 											}
 
- 										});
 
- 										if (! hash) {
 
- 											hash = fm.fileByName(item.name, target).hash;
 
- 										}
 
- 										fm.lockfiles({files : [hash]});
 
- 										dfd = fm.request({
 
- 											data   : {cmd : 'rename', target : hash, name : bak},
 
- 											notify : {type : 'rename', cnt : 1}
 
- 										})
 
- 										.fail(function() {
 
- 											item._remove = true;
 
- 											fm.sync();
 
- 										})
 
- 										.always(function() {
 
- 											fm.unlockfiles({files : [hash]});
 
- 										});
 
- 										dfds.push(dfd);
 
- 									}
 
- 								}
 
- 								return !item._remove? true : false;
 
- 							});
 
- 						}
 
- 						$.when.apply($, dfds).done(function(){
 
- 							var notifyto, msg,
 
- 								id = +new Date();
 
- 							
 
- 							if (items.length > 0) {
 
- 								msg = fm.escape(items[0].name);
 
- 								if (items.length > 1) {
 
- 									msg += ' ... ' + items.length + fm.i18n('items');
 
- 								}
 
- 								notifyto = setTimeout(function() {
 
- 									fm.notify({
 
- 										type : 'readdir',
 
- 										id : id,
 
- 										cnt : 1,
 
- 										hideCnt: true,
 
- 										msg : fm.i18n('ntfreaddir') + ' (' + msg + ')',
 
- 										cancel: function() {
 
- 											cancel = true;
 
- 										}
 
- 									});
 
- 								}, fm.options.notifyDelay);
 
- 								doScan(items).done(function() {
 
- 									notifyto && clearTimeout(notifyto);
 
- 									fm.notify({type : 'readdir', id: id, cnt : -1});
 
- 									if (cancel) {
 
- 										dfrd.reject();
 
- 									} else {
 
- 										dfrd.resolve([files, paths, renames, hashes, mkdirs]);
 
- 									}
 
- 								}).fail(function() {
 
- 									dfrd.reject();
 
- 								});
 
- 							} else {
 
- 								dfrd.reject();
 
- 							}
 
- 						});
 
- 					});
 
- 					return dfrd.promise();
 
- 				} else {
 
- 					return dfrd.reject();
 
- 				}
 
- 			} else {
 
- 				var ret = [];
 
- 				var check = [];
 
- 				var str = data.files[0];
 
- 				if (data.type == 'html') {
 
- 					var tmp = $("<html/>").append($.parseHTML(str.replace(/ src=/ig, ' _elfsrc='))),
 
- 						atag;
 
- 					$('img[_elfsrc]', tmp).each(function(){
 
- 						var url, purl,
 
- 						self = $(this),
 
- 						pa = self.closest('a');
 
- 						if (pa && pa.attr('href') && pa.attr('href').match(/\.(?:jpe?g|gif|bmp|png)/i)) {
 
- 							purl = pa.attr('href');
 
- 						}
 
- 						url = self.attr('_elfsrc');
 
- 						if (url) {
 
- 							if (purl) {
 
- 								$.inArray(purl, ret) == -1 && ret.push(purl);
 
- 								$.inArray(url, check) == -1 &&  check.push(url);
 
- 							} else {
 
- 								$.inArray(url, ret) == -1 && ret.push(url);
 
- 							}
 
- 						}
 
- 						// Probably it's clipboard data
 
- 						if (ret.length === 1 && ret[0].match(/^data:image\/png/)) {
 
- 							data.clipdata = true;
 
- 						}
 
- 					});
 
- 					atag = $('a[href]', tmp);
 
- 					atag.each(function(){
 
- 						var text, loc,
 
- 							parseUrl = function(url) {
 
- 								var a = document.createElement('a');
 
- 								a.href = url;
 
- 								return a;
 
- 							};
 
- 						if (text = $(this).text()) {
 
- 							loc = parseUrl($(this).attr('href'));
 
- 							if (loc.href && loc.href.match(/^(?:ht|f)tp/i) && (atag.length === 1 || ! loc.pathname.match(/(?:\.html?|\/[^\/.]*)$/i) || $.trim(text).match(/\.[a-z0-9-]{1,10}$/i))) {
 
- 								if ($.inArray(loc.href, ret) == -1 && $.inArray(loc.href, check) == -1) ret.push(loc.href);
 
- 							}
 
- 						}
 
- 					});
 
- 				} else {
 
- 					var regex, m, url;
 
- 					regex = /(http[^<>"{}|\\^\[\]`\s]+)/ig;
 
- 					while (m = regex.exec(str)) {
 
- 						url = m[1].replace(/&/g, '&');
 
- 						if ($.inArray(url, ret) == -1) ret.push(url);
 
- 					}
 
- 				}
 
- 				return ret;
 
- 			}
 
- 		},
 
- 		// upload transport using XMLHttpRequest
 
- 		xhr : function(data, fm) { 
 
- 			var self   = fm ? fm : this,
 
- 				node        = self.getUI(),
 
- 				xhr         = new XMLHttpRequest(),
 
- 				notifyto    = null, notifyto2 = null,
 
- 				dataChecked = data.checked,
 
- 				isDataType  = (data.isDataType || data.type == 'data'),
 
- 				target      = (data.target || self.cwd().hash),
 
- 				dropEvt     = (data.dropEvt || null),
 
- 				extraData  = data.extraData || null,
 
- 				chunkEnable = (self.option('uploadMaxConn', target) != -1),
 
- 				multiMax    = Math.min(5, Math.max(1, self.option('uploadMaxConn', target))),
 
- 				retryWait   = 10000, // 10 sec
 
- 				retryMax    = 30, // 10 sec * 30 = 300 secs (Max 5 mins)
 
- 				retry       = 0,
 
- 				getFile     = function(files) {
 
- 					var dfd = $.Deferred(),
 
- 						file;
 
- 					if (files.promise) {
 
- 						files.always(function(f) {
 
- 							dfd.resolve(Array.isArray(f) && f.length? (isDataType? f[0][0] : f[0]) : {});
 
- 						});
 
- 					} else {
 
- 						dfd.resolve(files.length? (isDataType? files[0][0] : files[0]) : {});
 
- 					}
 
- 					return dfd;
 
- 				},
 
- 				dfrd   = $.Deferred()
 
- 					.fail(function(err) {
 
- 						var error = self.parseError(err),
 
- 							userAbort;
 
- 						if (error === 'userabort') {
 
- 							userAbort = true;
 
- 							error = void 0;
 
- 						}
 
- 						if (files && (self.uploads.xhrUploading || userAbort)) {
 
- 							// send request om fail
 
- 							getFile(files).done(function(file) {
 
- 								if (! file._cid) {
 
- 									// send sync request
 
- 									self.uploads.failSyncTm && clearTimeout(self.uploads.failSyncTm);
 
- 									self.uploads.failSyncTm = setTimeout(function() {
 
- 										self.sync(target);
 
- 									}, 1000);
 
- 								} else if (! self.uploads.chunkfailReq[file._cid]) {
 
- 									// send chunkfail request
 
- 									self.uploads.chunkfailReq[file._cid] = true;
 
- 									setTimeout(function() {
 
- 										fm.request({
 
- 											data : {
 
- 												cmd: 'upload',
 
- 												target: target,
 
- 												chunk: file._chunk,
 
- 												cid: file._cid,
 
- 												upload: ['chunkfail'],
 
- 												mimes: 'chunkfail'
 
- 											},
 
- 											options : {
 
- 												type: 'post',
 
- 												url: self.uploadURL
 
- 											},
 
- 											preventDefault: true
 
- 										}).always(function() {
 
- 											delete self.uploads.chunkfailReq[file._chunk];
 
- 										});
 
- 									}, 1000);
 
- 								}
 
- 							});
 
- 						}
 
- 						!userAbort && self.sync();
 
- 						self.uploads.xhrUploading = false;
 
- 						files = null;
 
- 						error && self.error(error);
 
- 					})
 
- 					.done(function(data) {
 
- 						self.uploads.xhrUploading = false;
 
- 						files = null;
 
- 						if (data) {
 
- 							self.currentReqCmd = 'upload';
 
- 							data.warning && self.error(data.warning);
 
- 							self.updateCache(data);
 
- 							data.removed && data.removed.length && self.remove(data);
 
- 							data.added   && data.added.length   && self.add(data);
 
- 							data.changed && data.changed.length && self.change(data);
 
- 							self.trigger('upload', data, false);
 
- 							self.trigger('uploaddone');
 
- 							if (data.toasts && Array.isArray(data.toasts)) {
 
- 								$.each(data.toasts, function() {
 
- 									this.msg && self.toast(this);
 
- 								});
 
- 							}
 
- 							data.sync && self.sync();
 
- 							data.debug && fm.debug('backend-debug', data);
 
- 						}
 
- 					})
 
- 					.always(function() {
 
- 						self.abortXHR(xhr);
 
- 						// unregist fnAbort function
 
- 						node.off('uploadabort', fnAbort);
 
- 						$(window).off('unload', fnAbort);
 
- 						notifyto && clearTimeout(notifyto);
 
- 						notifyto2 && clearTimeout(notifyto2);
 
- 						dataChecked && !data.multiupload && checkNotify() && self.notify({type : 'upload', cnt : -cnt, progress : 0, size : 0});
 
- 						chunkMerge && notifyElm.children('.elfinder-notify-chunkmerge').length && self.notify({type : 'chunkmerge', cnt : -1});
 
- 					}),
 
- 				formData    = new FormData(),
 
- 				files       = data.input ? data.input.files : self.uploads.checkFile(data, self, target), 
 
- 				cnt         = data.checked? (isDataType? files[0].length : files.length) : files.length,
 
- 				loaded      = 0,
 
- 				prev        = 0,
 
- 				filesize    = 0,
 
- 				notify      = false,
 
- 				notifyElm   = self.ui.notify,
 
- 				cancelBtn   = true,
 
- 				abort       = false,
 
- 				checkNotify = function() {
 
- 					if (!notify && (ntfUpload = notifyElm.children('.elfinder-notify-upload')).length) {
 
- 						notify = true;
 
- 					}
 
- 					return notify;
 
- 				},
 
- 				fnAbort     = function(e, error) {
 
- 					abort = true;
 
- 					self.abortXHR(xhr, { quiet: true, abort: true });
 
- 					dfrd.reject(error);
 
- 					if (checkNotify()) {
 
- 						self.notify({type : 'upload', cnt : ntfUpload.data('cnt') * -1, progress : 0, size : 0});
 
- 					}
 
- 				},
 
- 				cancelToggle = function(show) {
 
- 					ntfUpload.children('.elfinder-notify-cancel')[show? 'show':'hide']();
 
- 				},
 
- 				startNotify = function(size) {
 
- 					if (!size) size = filesize;
 
- 					return setTimeout(function() {
 
- 						notify = true;
 
- 						self.notify({type : 'upload', cnt : cnt, progress : loaded - prev, size : size,
 
- 							cancel: function() {
 
- 								node.trigger('uploadabort', 'userabort');
 
- 							}
 
- 						});
 
- 						ntfUpload = notifyElm.children('.elfinder-notify-upload');
 
- 						prev = loaded;
 
- 						if (data.multiupload) {
 
- 							cancelBtn && cancelToggle(true);
 
- 						} else {
 
- 							cancelToggle(cancelBtn && loaded < size);
 
- 						}
 
- 					}, self.options.notifyDelay);
 
- 				},
 
- 				doRetry = function() {
 
- 					if (retry++ <= retryMax) {
 
- 						if (checkNotify() && prev) {
 
- 							self.notify({type : 'upload', cnt : 0, progress : 0, size : prev});
 
- 						}
 
- 						self.abortXHR(xhr, { quiet: true });
 
- 						prev = loaded = 0;
 
- 						setTimeout(function() {
 
- 							var reqId;
 
- 							if (! abort) {
 
- 								xhr.open('POST', self.uploadURL, true);
 
- 								if (self.api >= 2.1029) {
 
- 									reqId = (+ new Date()).toString(16) + Math.floor(1000 * Math.random()).toString(16);
 
- 									(typeof formData['delete'] === 'function') && formData['delete']('reqid');
 
- 									formData.append('reqid', reqId);
 
- 									xhr._requestId = reqId;
 
- 								}
 
- 								xhr.send(formData);
 
- 							}
 
- 						}, retryWait);
 
- 					} else {
 
- 						node.trigger('uploadabort', ['errAbort', 'errTimeout']);
 
- 					}
 
- 				},
 
- 				progress = function() {
 
- 					var node;
 
- 					if (notify) {
 
- 						dfrd.notifyWith(ntfUpload, [{
 
- 							cnt: ntfUpload.data('cnt'),
 
- 							progress: ntfUpload.data('progress'),
 
- 							total: ntfUpload.data('total')
 
- 						}]);
 
- 					}
 
- 				},
 
- 				renames = (data.renames || null),
 
- 				hashes = (data.hashes || null),
 
- 				chunkMerge = false,
 
- 				ntfUpload = $();
 
- 			
 
- 			// regist fnAbort function
 
- 			node.one('uploadabort', fnAbort);
 
- 			$(window).one('unload.' + fm.namespace, fnAbort);
 
- 			
 
- 			!chunkMerge && (prev = loaded);
 
- 			
 
- 			if (!isDataType && !cnt) {
 
- 				return dfrd.reject(['errUploadNoFiles']);
 
- 			}
 
- 			
 
- 			xhr.addEventListener('error', function() {
 
- 				if (xhr.status == 0) {
 
- 					if (abort) {
 
- 						dfrd.reject();
 
- 					} else {
 
- 						// ff bug while send zero sized file
 
- 						// for safari - send directory
 
- 						if (!isDataType && data.files && $.grep(data.files, function(f){return ! f.type && f.size === (self.UA.Safari? 1802 : 0)? true : false;}).length) {
 
- 							errors.push('errFolderUpload');
 
- 							dfrd.reject(['errAbort', 'errFolderUpload']);
 
- 						} else if (data.input && $.grep(data.input.files, function(f){return ! f.type && f.size === (self.UA.Safari? 1802 : 0)? true : false;}).length) {
 
- 							dfrd.reject(['errUploadNoFiles']);
 
- 						} else {
 
- 							doRetry();
 
- 						}
 
- 					}
 
- 				} else {
 
- 					node.trigger('uploadabort', 'errConnect');
 
- 				}
 
- 			}, false);
 
- 			
 
- 			xhr.addEventListener('load', function(e) {
 
- 				var status = xhr.status, res, curr = 0, error = '', errData, errObj;
 
- 				
 
- 				if (status >= 400) {
 
- 					if (status > 500) {
 
- 						error = 'errResponse';
 
- 					} else {
 
- 						error = ['errResponse', 'errServerError'];
 
- 					}
 
- 				} else {
 
- 					if (!xhr.responseText) {
 
- 						error = ['errResponse', 'errDataEmpty'];
 
- 					}
 
- 				}
 
- 				
 
- 				if (error) {
 
- 					node.trigger('uploadabort');
 
- 					getFile(files).done(function(file) {
 
- 						return dfrd.reject(file._cid? null : error);
 
- 					});
 
- 				}
 
- 				
 
- 				loaded = filesize;
 
- 				
 
- 				if (checkNotify() && (curr = loaded - prev)) {
 
- 					self.notify({type : 'upload', cnt : 0, progress : curr, size : 0});
 
- 					progress();
 
- 				}
 
- 				res = self.parseUploadData(xhr.responseText);
 
- 				
 
- 				// chunked upload commit
 
- 				if (res._chunkmerged) {
 
- 					formData = new FormData();
 
- 					var _file = [{_chunkmerged: res._chunkmerged, _name: res._name, _mtime: res._mtime}];
 
- 					chunkMerge = true;
 
- 					node.off('uploadabort', fnAbort);
 
- 					notifyto2 = setTimeout(function() {
 
- 						self.notify({type : 'chunkmerge', cnt : 1});
 
- 					}, self.options.notifyDelay);
 
- 					isDataType? send(_file, files[1]) : send(_file);
 
- 					return;
 
- 				}
 
- 				
 
- 				res._multiupload = data.multiupload? true : false;
 
- 				if (res.error) {
 
- 					errData = {
 
- 						cmd: 'upload',
 
- 						err: res,
 
- 						xhr: xhr,
 
- 						rc: xhr.status
 
- 					};
 
- 					self.trigger('uploadfail', res);
 
- 					// trigger "requestError" event
 
- 					self.trigger('requestError', errData);
 
- 					if (errData._event && errData._event.isDefaultPrevented()) {
 
- 						res.error = '';
 
- 					}
 
- 					if (res._chunkfailure || res._multiupload) {
 
- 						abort = true;
 
- 						self.uploads.xhrUploading = false;
 
- 						notifyto && clearTimeout(notifyto);
 
- 						if (ntfUpload.length) {
 
- 							self.notify({type : 'upload', cnt : -cnt, progress : 0, size : 0});
 
- 							dfrd.reject(res);
 
- 						} else {
 
- 							// for multi connection
 
- 							dfrd.reject();
 
- 						}
 
- 					} else {
 
- 						dfrd.reject(res);
 
- 					}
 
- 				} else {
 
- 					dfrd.resolve(res);
 
- 				}
 
- 			}, false);
 
- 			
 
- 			xhr.upload.addEventListener('loadstart', function(e) {
 
- 				if (!chunkMerge && e.lengthComputable) {
 
- 					loaded = e.loaded;
 
- 					retry && (loaded = 0);
 
- 					filesize = e.total;
 
- 					if (!loaded) {
 
- 						loaded = parseInt(filesize * 0.05);
 
- 					}
 
- 					if (checkNotify()) {
 
- 						self.notify({type : 'upload', cnt : 0, progress : loaded - prev, size : data.multiupload? 0 : filesize});
 
- 						prev = loaded;
 
- 						progress();
 
- 					}
 
- 				}
 
- 			}, false);
 
- 			
 
- 			xhr.upload.addEventListener('progress', function(e) {
 
- 				var curr;
 
- 				if (e.lengthComputable && !chunkMerge && xhr.readyState < 2) {
 
- 					
 
- 					loaded = e.loaded;
 
- 					// to avoid strange bug in safari (not in chrome) with drag&drop.
 
- 					// bug: macos finder opened in any folder,
 
- 					// reset safari cache (option+command+e), reload elfinder page,
 
- 					// drop file from finder
 
- 					// on first attempt request starts (progress callback called ones) but never ends.
 
- 					// any next drop - successfull.
 
- 					if (!data.checked && loaded > 0 && !notifyto) {
 
- 						notifyto = startNotify(xhr._totalSize - loaded);
 
- 					}
 
- 					
 
- 					if (!filesize) {
 
- 						filesize = e.total;
 
- 						if (!loaded) {
 
- 							loaded = parseInt(filesize * 0.05);
 
- 						}
 
- 					}
 
- 					
 
- 					curr = loaded - prev;
 
- 					if (checkNotify() && (curr/e.total) >= 0.05) {
 
- 						self.notify({type : 'upload', cnt : 0, progress : curr, size : 0});
 
- 						prev = loaded;
 
- 						progress();
 
- 					}
 
- 					
 
- 					if (! data.multiupload && loaded >= filesize) {
 
- 						cancelBtn = false;
 
- 						cancelToggle(false);
 
- 					}
 
- 				}
 
- 			}, false);
 
- 			
 
- 			var send = function(files, paths){
 
- 				var size = 0,
 
- 				fcnt = 1,
 
- 				sfiles = [],
 
- 				c = 0,
 
- 				total = cnt,
 
- 				maxFileSize,
 
- 				totalSize = 0,
 
- 				chunked = [],
 
- 				chunkID = new Date().getTime().toString().substr(-9), // for take care of the 32bit backend system
 
- 				BYTES_PER_CHUNK = Math.min((fm.uplMaxSize? fm.uplMaxSize : 2097152) - 8190, fm.options.uploadMaxChunkSize), // uplMaxSize margin 8kb or options.uploadMaxChunkSize
 
- 				blobSlice = chunkEnable? false : '',
 
- 				blobSize, blobMtime, i, start, end, chunks, blob, chunk, added, done, last, failChunk,
 
- 				multi = function(files, num){
 
- 					var sfiles = [], cid, sfilesLen = 0, cancelChk;
 
- 					if (!abort) {
 
- 						while(files.length && sfiles.length < num) {
 
- 							sfiles.push(files.shift());
 
- 						}
 
- 						sfilesLen = sfiles.length;
 
- 						if (sfilesLen) {
 
- 							cancelChk = sfilesLen;
 
- 							for (var i=0; i < sfilesLen; i++) {
 
- 								if (abort) {
 
- 									break;
 
- 								}
 
- 								cid = isDataType? (sfiles[i][0][0]._cid || null) : (sfiles[i][0]._cid || null);
 
- 								if (!!failChunk[cid]) {
 
- 									last--;
 
- 									continue;
 
- 								}
 
- 								fm.exec('upload', {
 
- 									type: data.type,
 
- 									isDataType: isDataType,
 
- 									files: sfiles[i],
 
- 									checked: true,
 
- 									target: target,
 
- 									dropEvt: dropEvt,
 
- 									renames: renames,
 
- 									hashes: hashes,
 
- 									multiupload: true,
 
- 									overwrite: data.overwrite === 0? 0 : void 0
 
- 								}, void 0, target)
 
- 								.fail(function(error) {
 
- 									if (error && error === 'No such command') {
 
- 										abort = true;
 
- 										fm.error(['errUpload', 'errPerm']);
 
- 									}
 
- 									if (cid) {	
 
- 										failChunk[cid] = true;
 
- 									}
 
- 								})
 
- 								.always(function(e) {
 
- 									if (e && e.added) added = $.merge(added, e.added);
 
- 									if (last <= ++done) {
 
- 										fm.trigger('multiupload', {added: added});
 
- 										notifyto && clearTimeout(notifyto);
 
- 										if (checkNotify()) {
 
- 											self.notify({type : 'upload', cnt : -cnt, progress : 0, size : 0});
 
- 										}
 
- 									}
 
- 									if (files.length) {
 
- 										multi(files, 1); // Next one
 
- 									} else {
 
- 										if (--cancelChk <= 1) {
 
- 											cancelBtn = false;
 
- 											cancelToggle(false);
 
- 										}
 
- 									}
 
- 								});
 
- 							}
 
- 						}
 
- 					}
 
- 					if (sfiles.length < 1 || abort) {
 
- 						if (abort) {
 
- 							notifyto && clearTimeout(notifyto);
 
- 							if (cid) {
 
- 								failChunk[cid] = true;
 
- 							}
 
- 							dfrd.reject();
 
- 						} else {
 
- 							dfrd.resolve();
 
- 							self.uploads.xhrUploading = false;
 
- 						}
 
- 					}
 
- 				},
 
- 				check = function(){
 
- 					if (!self.uploads.xhrUploading) {
 
- 						self.uploads.xhrUploading = true;
 
- 						multi(sfiles, multiMax); // Max connection: 3
 
- 					} else {
 
- 						setTimeout(check, 100);
 
- 					}
 
- 				},
 
- 				reqId;
 
- 				if (! dataChecked && (isDataType || data.type == 'files')) {
 
- 					if (! (maxFileSize = fm.option('uploadMaxSize', target))) {
 
- 						maxFileSize = 0;
 
- 					}
 
- 					for (i=0; i < files.length; i++) {
 
- 						try {
 
- 							blob = files[i];
 
- 							blobSize = blob.size;
 
- 							if (blobSlice === false) {
 
- 								blobSlice = '';
 
- 								if (self.api >= 2.1) {
 
- 									if ('slice' in blob) {
 
- 										blobSlice = 'slice';
 
- 									} else if ('mozSlice' in blob) {
 
- 										blobSlice = 'mozSlice';
 
- 									} else if ('webkitSlice' in blob) {
 
- 										blobSlice = 'webkitSlice';
 
- 									}
 
- 								}
 
- 							}
 
- 						} catch(e) {
 
- 							cnt--;
 
- 							total--;
 
- 							continue;
 
- 						}
 
- 						
 
- 						// file size check
 
- 						if ((maxFileSize && blobSize > maxFileSize) || (!blobSlice && fm.uplMaxSize && blobSize > fm.uplMaxSize)) {
 
- 							self.error(['errUploadFile', blob.name, 'errUploadFileSize']);
 
- 							cnt--;
 
- 							total--;
 
- 							continue;
 
- 						}
 
- 						
 
- 						// file mime check
 
- 						if (blob.type && ! self.uploadMimeCheck(blob.type, target)) {
 
- 							self.error(['errUploadFile', blob.name, 'errUploadMime', '(' + blob.type + ')']);
 
- 							cnt--;
 
- 							total--;
 
- 							continue;
 
- 						}
 
- 						
 
- 						if (blobSlice && blobSize > BYTES_PER_CHUNK) {
 
- 							start = 0;
 
- 							end = BYTES_PER_CHUNK;
 
- 							chunks = -1;
 
- 							total = Math.floor((blobSize - 1) / BYTES_PER_CHUNK);
 
- 							blobMtime = blob.lastModified? Math.round(blob.lastModified/1000) : 0;
 
- 							totalSize += blobSize;
 
- 							chunked[chunkID] = 0;
 
- 							while(start < blobSize) {
 
- 								chunk = blob[blobSlice](start, end);
 
- 								chunk._chunk = blob.name + '.' + (++chunks) + '_' + total + '.part';
 
- 								chunk._cid   = chunkID;
 
- 								chunk._range = start + ',' + chunk.size + ',' + blobSize;
 
- 								chunk._mtime = blobMtime;
 
- 								chunked[chunkID]++;
 
- 								
 
- 								if (size) {
 
- 									c++;
 
- 								}
 
- 								if (typeof sfiles[c] == 'undefined') {
 
- 									sfiles[c] = [];
 
- 									if (isDataType) {
 
- 										sfiles[c][0] = [];
 
- 										sfiles[c][1] = [];
 
- 									}
 
- 								}
 
- 								size = BYTES_PER_CHUNK;
 
- 								fcnt = 1;
 
- 								if (isDataType) {
 
- 									sfiles[c][0].push(chunk);
 
- 									sfiles[c][1].push(paths[i]);
 
- 								} else {
 
- 									sfiles[c].push(chunk);
 
- 								}
 
- 								start = end;
 
- 								end = start + BYTES_PER_CHUNK;
 
- 							}
 
- 							if (chunk == null) {
 
- 								self.error(['errUploadFile', blob.name, 'errUploadFileSize']);
 
- 								cnt--;
 
- 								total--;
 
- 							} else {
 
- 								total += chunks;
 
- 								size = 0;
 
- 								fcnt = 1;
 
- 								c++;
 
- 							}
 
- 							continue;
 
- 						}
 
- 						if ((fm.uplMaxSize && size + blobSize > fm.uplMaxSize) || fcnt > fm.uplMaxFile) {
 
- 							size = 0;
 
- 							fcnt = 1;
 
- 							c++;
 
- 						}
 
- 						if (typeof sfiles[c] == 'undefined') {
 
- 							sfiles[c] = [];
 
- 							if (isDataType) {
 
- 								sfiles[c][0] = [];
 
- 								sfiles[c][1] = [];
 
- 							}
 
- 						}
 
- 						if (isDataType) {
 
- 							sfiles[c][0].push(blob);
 
- 							sfiles[c][1].push(paths[i]);
 
- 						} else {
 
- 							sfiles[c].push(blob);
 
- 						}
 
- 						size += blobSize;
 
- 						totalSize += blobSize;
 
- 						fcnt++;
 
- 					}
 
- 					
 
- 					if (sfiles.length == 0) {
 
- 						// no data
 
- 						data.checked = true;
 
- 						return false;
 
- 					}
 
- 					
 
- 					if (sfiles.length > 1) {
 
- 						// multi upload
 
- 						notifyto = startNotify(totalSize);
 
- 						added = [];
 
- 						done = 0;
 
- 						last = sfiles.length;
 
- 						failChunk = [];
 
- 						check();
 
- 						return true;
 
- 					}
 
- 					
 
- 					// single upload
 
- 					if (isDataType) {
 
- 						files = sfiles[0][0];
 
- 						paths = sfiles[0][1];
 
- 					} else {
 
- 						files = sfiles[0];
 
- 					}
 
- 				}
 
- 				
 
- 				if (!dataChecked) {
 
- 					if (!fm.UA.Safari || !data.files) {
 
- 						notifyto = startNotify(totalSize);
 
- 					} else {
 
- 						xhr._totalSize = totalSize;
 
- 					}
 
- 				}
 
- 				
 
- 				dataChecked = true;
 
- 				
 
- 				if (! files.length) {
 
- 					dfrd.reject(['errUploadNoFiles']);
 
- 				}
 
- 				
 
- 				xhr.open('POST', self.uploadURL, true);
 
- 				
 
- 				// set request headers
 
- 				if (fm.customHeaders) {
 
- 					$.each(fm.customHeaders, function(key) {
 
- 						xhr.setRequestHeader(key, this);
 
- 					});
 
- 				}
 
- 				
 
- 				// set xhrFields
 
- 				if (fm.xhrFields) {
 
- 					$.each(fm.xhrFields, function(key) {
 
- 						if (key in xhr) {
 
- 							xhr[key] = this;
 
- 						}
 
- 					});
 
- 				}
 
- 				if (self.api >= 2.1029) {
 
- 					// request ID
 
- 					reqId = (+ new Date()).toString(16) + Math.floor(1000 * Math.random()).toString(16);
 
- 					formData.append('reqid', reqId);
 
- 					xhr._requestId = reqId;
 
- 				}
 
- 				formData.append('cmd', 'upload');
 
- 				formData.append(self.newAPI ? 'target' : 'current', target);
 
- 				if (renames && renames.length) {
 
- 					$.each(renames, function(i, v) {
 
- 						formData.append('renames[]', v);
 
- 					});
 
- 					formData.append('suffix', fm.options.backupSuffix);
 
- 				}
 
- 				if (hashes) {
 
- 					$.each(hashes, function(i, v) {
 
- 						formData.append('hashes['+ i +']', v);
 
- 					});
 
- 				}
 
- 				$.each(self.customData, function(key, val) {
 
- 					formData.append(key, val);
 
- 				});
 
- 				$.each(self.options.onlyMimes, function(i, mime) {
 
- 					formData.append('mimes[]', mime);
 
- 				});
 
- 				
 
- 				$.each(files, function(i, file) {
 
- 					if (file._chunkmerged) {
 
- 						formData.append('chunk', file._chunkmerged);
 
- 						formData.append('upload[]', file._name);
 
- 						formData.append('mtime[]', file._mtime);
 
- 					} else {
 
- 						if (file._chunkfail) {
 
- 							formData.append('upload[]', 'chunkfail');
 
- 							formData.append('mimes', 'chunkfail');
 
- 						} else {
 
- 							formData.append('upload[]', file);
 
- 							if (data.clipdata) {
 
- 								data.overwrite = 0;
 
- 								formData.append('name[]', fm.date(fm.nonameDateFormat) + '.png');
 
- 							}
 
- 							if (file.name && fm.UA.iOS) {
 
- 								if (file.name.match(/^image\.jpe?g$/i)) {
 
- 									data.overwrite = 0;
 
- 									formData.append('name[]', fm.date(fm.nonameDateFormat) + '.jpg');
 
- 								} else if (file.name.match(/^capturedvideo\.mov$/i)) {
 
- 									data.overwrite = 0;
 
- 									formData.append('name[]', fm.date(fm.nonameDateFormat) + '.mov');
 
- 								}
 
- 							}
 
- 						}
 
- 						if (file._chunk) {
 
- 							formData.append('chunk', file._chunk);
 
- 							formData.append('cid'  , file._cid);
 
- 							formData.append('range', file._range);
 
- 							formData.append('mtime[]', file._mtime);
 
- 						} else {
 
- 							formData.append('mtime[]', file.lastModified? Math.round(file.lastModified/1000) : 0);
 
- 						}
 
- 					}
 
- 				});
 
- 				
 
- 				if (isDataType) {
 
- 					$.each(paths, function(i, path) {
 
- 						formData.append('upload_path[]', path);
 
- 					});
 
- 				}
 
- 				
 
- 				if (data.overwrite === 0) {
 
- 					formData.append('overwrite', 0);
 
- 				}
 
- 				
 
- 				// send int value that which meta key was pressed when dropped  as `dropWith`
 
- 				if (dropEvt) {
 
- 					formData.append('dropWith', parseInt(
 
- 						(dropEvt.altKey  ? '1' : '0')+
 
- 						(dropEvt.ctrlKey ? '1' : '0')+
 
- 						(dropEvt.metaKey ? '1' : '0')+
 
- 						(dropEvt.shiftKey? '1' : '0'), 2));
 
- 				}
 
- 				
 
- 				// set extraData on current request
 
- 				if (extraData) {
 
- 					$.each(extraData, function(key, val) {
 
- 						formData.append(key, val);
 
- 					});
 
- 				}
 
- 				xhr.send(formData);
 
- 				
 
- 				return true;
 
- 			};
 
- 			
 
- 			if (! isDataType) {
 
- 				if (files.length > 0) {
 
- 					if (! data.clipdata && renames == null) {
 
- 						var mkdirs = [],
 
- 							paths = [],
 
- 							excludes = fm.options.folderUploadExclude[fm.OS] || null;
 
- 						$.each(files, function(i, file) {
 
- 							var relPath = file.webkitRelativePath || file.relativePath || '',
 
- 								idx, rootDir;
 
- 							if (! relPath) {
 
- 								return false;
 
- 							}
 
- 							if (excludes && file.name.match(excludes)) {
 
- 								file._remove = true;
 
- 								relPath = void(0);
 
- 							} else {
 
- 								// add '/' as prefix to make same to folder uploading with DnD, see #2607
 
- 								relPath = '/' + relPath.replace(/\/[^\/]*$/, '').replace(/^\//, '');
 
- 								if (relPath && $.inArray(relPath, mkdirs) === -1) {
 
- 									mkdirs.push(relPath);
 
- 									// checking the root directory to supports <input type="file" webkitdirectory> see #2378
 
- 									idx = relPath.substr(1).indexOf('/');
 
- 									if (idx !== -1 && (rootDir = relPath.substr(0, idx + 1)) && $.inArray(rootDir, mkdirs) === -1) {
 
- 										mkdirs.unshift(rootDir);
 
- 									}
 
- 								}
 
- 							}
 
- 							paths.push(relPath);
 
- 						});
 
- 						renames = [];
 
- 						hashes = {};
 
- 						if (mkdirs.length) {
 
- 							(function() {
 
- 								var checkDirs = $.map(mkdirs, function(name) { return name.substr(1).indexOf('/') === -1 ? {name: name.substr(1)} : null;}),
 
- 									cancelDirs = [];
 
- 								fm.uploads.checkExists(checkDirs, target, fm, true).done(
 
- 									function(res, res2) {
 
- 										var dfds = [], dfd, bak, hash;
 
- 										if (fm.options.overwriteUploadConfirm && fm.option('uploadOverwrite', target)) {
 
- 											cancelDirs = $.map(checkDirs, function(dir) { return dir._remove? dir.name : null ;} );
 
- 											checkDirs = $.grep(checkDirs, function(dir) { return !dir._remove? true : false ;} );
 
- 										}
 
- 										if (cancelDirs.length) {
 
- 											$.each(paths.concat(), function(i, path) {
 
- 												if ($.inArray(path, cancelDirs) === 0) {
 
- 													files[i]._remove = true;
 
- 													paths[i] = void(0);
 
- 												}
 
- 											});
 
- 										}
 
- 										files = $.grep(files, function(file) { return file._remove? false : true; });
 
- 										paths = $.grep(paths, function(path) { return path === void 0 ? false : true; });
 
- 										if (checkDirs.length) {
 
- 											dfd = $.Deferred();
 
- 											if (res.length) {
 
- 												$.each(res, function(i, existName) {
 
- 													// backup
 
- 													bak = fm.uniqueName(existName + fm.options.backupSuffix , null, '');
 
- 													$.each(res2, function(h, name) {
 
- 														if (res[0] == name) {
 
- 															hash = h;
 
- 															return false;
 
- 														}
 
- 													});
 
- 													if (! hash) {
 
- 														hash = fm.fileByName(res[0], target).hash;
 
- 													}
 
- 													fm.lockfiles({files : [hash]});
 
- 													dfds.push(
 
- 														fm.request({
 
- 															data   : {cmd : 'rename', target : hash, name : bak},
 
- 															notify : {type : 'rename', cnt : 1}
 
- 														})
 
- 														.fail(function(error) {
 
- 															dfrd.reject(error);
 
- 															fm.sync();
 
- 														})
 
- 														.always(function() {
 
- 															fm.unlockfiles({files : [hash]});
 
- 														})
 
- 													);
 
- 												});
 
- 											} else {
 
- 												dfds.push(null);
 
- 											}
 
- 											
 
- 											$.when.apply($, dfds).done(function() {
 
- 												// ensure directories
 
- 												fm.request({
 
- 													data   : {cmd : 'mkdir', target : target, dirs : mkdirs},
 
- 													notify : {type : 'mkdir', cnt : mkdirs.length},
 
- 													preventFail: true
 
- 												})
 
- 												.fail(function(error) {
 
- 													error = error || ['errUnknown'];
 
- 													if (error[0] === 'errCmdParams') {
 
- 														multiMax = 1;
 
- 													} else {
 
- 														multiMax = 0;
 
- 														dfrd.reject(error);
 
- 													}
 
- 												})
 
- 												.done(function(data) {
 
- 													var rm = false;
 
- 													if (!data.hashes) {
 
- 														data.hashes = {};
 
- 													}
 
- 													paths = $.map(paths.concat(), function(p, i) {
 
- 														if (p === '/') {
 
- 															return target;
 
- 														} else {
 
- 															if (data.hashes[p]) {
 
- 																return data.hashes[p];
 
- 															} else {
 
- 																rm = true;
 
- 																files[i]._remove = true;
 
- 																return null;
 
- 															}
 
- 														}
 
- 													});
 
- 													if (rm) {
 
- 														files = $.grep(files, function(file) { return file._remove? false : true; });
 
- 													}
 
- 												})
 
- 												.always(function(data) {
 
- 													if (multiMax) {
 
- 														isDataType = true;
 
- 														if (! send(files, paths)) {
 
- 															dfrd.reject();
 
- 														}
 
- 													}
 
- 												});
 
- 											});
 
- 										} else {
 
- 											dfrd.reject();
 
- 										}
 
- 									}
 
- 								);
 
- 							})();
 
- 						} else {
 
- 							fm.uploads.checkExists(files, target, fm).done(
 
- 								function(res, res2){
 
- 									if (fm.options.overwriteUploadConfirm && fm.option('uploadOverwrite', target)) {
 
- 										hashes = res2;
 
- 										if (res === null) {
 
- 											data.overwrite = 0;
 
- 										} else {
 
- 											renames = res;
 
- 										}
 
- 										files = $.grep(files, function(file){return !file._remove? true : false ;});
 
- 									}
 
- 									cnt = files.length;
 
- 									if (cnt > 0) {
 
- 										if (! send(files)) {
 
- 											dfrd.reject();
 
- 										}
 
- 									} else {
 
- 										dfrd.reject();
 
- 									}
 
- 								}
 
- 							);
 
- 						}
 
- 					} else {
 
- 						if (! send(files)) {
 
- 							dfrd.reject();
 
- 						}
 
- 					}
 
- 				} else {
 
- 					dfrd.reject();
 
- 				}
 
- 			} else {
 
- 				if (dataChecked) {
 
- 					send(files[0], files[1]);
 
- 				} else {
 
- 					files.done(function(result) { // result: [files, paths, renames, hashes, mkdirs]
 
- 						renames = [];
 
- 						cnt = result[0].length;
 
- 						if (cnt) {
 
- 							if (result[4] && result[4].length) {
 
- 								// ensure directories
 
- 								fm.request({
 
- 									data   : {cmd : 'mkdir', target : target, dirs : result[4]},
 
- 									notify : {type : 'mkdir', cnt : result[4].length},
 
- 									preventFail: true
 
- 								})
 
- 								.fail(function(error) {
 
- 									error = error || ['errUnknown'];
 
- 									if (error[0] === 'errCmdParams') {
 
- 										multiMax = 1;
 
- 									} else {
 
- 										multiMax = 0;
 
- 										dfrd.reject(error);
 
- 									}
 
- 								})
 
- 								.done(function(data) {
 
- 									var rm = false;
 
- 									if (!data.hashes) {
 
- 										data.hashes = {};
 
- 									}
 
- 									result[1] = $.map(result[1], function(p, i) {
 
- 										p = p.replace(/\/[^\/]*$/, '');
 
- 										if (p === '') {
 
- 											return target;
 
- 										} else {
 
- 											if (data.hashes[p]) {
 
- 												return data.hashes[p];
 
- 											} else {
 
- 												rm = true;
 
- 												result[0][i]._remove = true;
 
- 												return null;
 
- 											}
 
- 										}
 
- 									});
 
- 									if (rm) {
 
- 										result[0] = $.grep(result[0], function(file) { return file._remove? false : true; });
 
- 									}
 
- 								})
 
- 								.always(function(data) {
 
- 									if (multiMax) {
 
- 										renames = result[2];
 
- 										hashes = result[3];
 
- 										send(result[0], result[1]);
 
- 									}
 
- 								});
 
- 								return;
 
- 							} else {
 
- 								result[1] = $.map(result[1], function() { return target; });
 
- 							}
 
- 							renames = result[2];
 
- 							hashes = result[3];
 
- 							send(result[0], result[1]);
 
- 						} else {
 
- 							dfrd.reject(['errUploadNoFiles']);
 
- 						}
 
- 					}).fail(function(){
 
- 						dfrd.reject();
 
- 					});
 
- 				}
 
- 			}
 
- 			return dfrd;
 
- 		},
 
- 		
 
- 		// upload transport using iframe
 
- 		iframe : function(data, fm) { 
 
- 			var self   = fm ? fm : this,
 
- 				input  = data.input? data.input : false,
 
- 				files  = !input ? self.uploads.checkFile(data, self) : false,
 
- 				dfrd   = $.Deferred()
 
- 					.fail(function(error) {
 
- 						error && self.error(error);
 
- 					}),
 
- 				name = 'iframe-'+fm.namespace+(++self.iframeCnt),
 
- 				form = $('<form action="'+self.uploadURL+'" method="post" enctype="multipart/form-data" encoding="multipart/form-data" target="'+name+'" style="display:none"><input type="hidden" name="cmd" value="upload" /></form>'),
 
- 				msie = this.UA.IE,
 
- 				// clear timeouts, close notification dialog, remove form/iframe
 
- 				onload = function() {
 
- 					abortto  && clearTimeout(abortto);
 
- 					notifyto && clearTimeout(notifyto);
 
- 					notify   && self.notify({type : 'upload', cnt : -cnt});
 
- 					
 
- 					setTimeout(function() {
 
- 						msie && $('<iframe src="javascript:false;"/>').appendTo(form);
 
- 						form.remove();
 
- 						iframe.remove();
 
- 					}, 100);
 
- 				},
 
- 				iframe = $('<iframe src="'+(msie ? 'javascript:false;' : 'about:blank')+'" name="'+name+'" style="position:absolute;left:-1000px;top:-1000px" />')
 
- 					.on('load', function() {
 
- 						iframe.off('load')
 
- 							.on('load', function() {
 
- 								onload();
 
- 								// data will be processed in callback response or window onmessage
 
- 								dfrd.resolve();
 
- 							});
 
- 							
 
- 							// notify dialog
 
- 							notifyto = setTimeout(function() {
 
- 								notify = true;
 
- 								self.notify({type : 'upload', cnt : cnt});
 
- 							}, self.options.notifyDelay);
 
- 							
 
- 							// emulate abort on timeout
 
- 							if (self.options.iframeTimeout > 0) {
 
- 								abortto = setTimeout(function() {
 
- 									onload();
 
- 									dfrd.reject([errors.connect, errors.timeout]);
 
- 								}, self.options.iframeTimeout);
 
- 							}
 
- 							
 
- 							form.submit();
 
- 					}),
 
- 				target  = (data.target || self.cwd().hash),
 
- 				names   = [],
 
- 				dfds    = [],
 
- 				renames = [],
 
- 				hashes  = {},
 
- 				cnt, notify, notifyto, abortto;
 
- 			if (files && files.length) {
 
- 				$.each(files, function(i, val) {
 
- 					form.append('<input type="hidden" name="upload[]" value="'+val+'"/>');
 
- 				});
 
- 				cnt = 1;
 
- 			} else if (input && $(input).is(':file') && $(input).val()) {
 
- 				if (fm.options.overwriteUploadConfirm && fm.option('uploadOverwrite', target)) {
 
- 					names = input.files? input.files : [{ name: $(input).val().replace(/^(?:.+[\\\/])?([^\\\/]+)$/, '$1') }];
 
- 					//names = $.map(names, function(file){return file.name? { name: file.name } : null ;});
 
- 					dfds.push(self.uploads.checkExists(names, target, self).done(
 
- 						function(res, res2){
 
- 							hashes = res2;
 
- 							if (res === null) {
 
- 								data.overwrite = 0;
 
- 							} else{
 
- 								renames = res;
 
- 								cnt = $.grep(names, function(file){return !file._remove? true : false ;}).length;
 
- 								if (cnt != names.length) {
 
- 									cnt = 0;
 
- 								}
 
- 							}
 
- 						}
 
- 					));
 
- 				}
 
- 				cnt = input.files ? input.files.length : 1;
 
- 				form.append(input);
 
- 			} else {
 
- 				return dfrd.reject();
 
- 			}
 
- 			
 
- 			$.when.apply($, dfds).done(function() {
 
- 				if (cnt < 1) {
 
- 					return dfrd.reject();
 
- 				}
 
- 				form.append('<input type="hidden" name="'+(self.newAPI ? 'target' : 'current')+'" value="'+target+'"/>')
 
- 					.append('<input type="hidden" name="html" value="1"/>')
 
- 					.append('<input type="hidden" name="node" value="'+self.id+'"/>')
 
- 					.append($(input).attr('name', 'upload[]'));
 
- 				
 
- 				if (renames.length > 0) {
 
- 					$.each(renames, function(i, rename) {
 
- 						form.append('<input type="hidden" name="renames[]" value="'+self.escape(rename)+'"/>');
 
- 					});
 
- 					form.append('<input type="hidden" name="suffix" value="'+fm.options.backupSuffix+'"/>');
 
- 				}
 
- 				if (hashes) {
 
- 					$.each(renames, function(i, v) {
 
- 						form.append('<input type="hidden" name="['+i+']" value="'+self.escape(v)+'"/>');
 
- 					});
 
- 				}
 
- 				
 
- 				if (data.overwrite === 0) {
 
- 					form.append('<input type="hidden" name="overwrite" value="0"/>');
 
- 				}
 
- 				
 
- 				$.each(self.options.onlyMimes||[], function(i, mime) {
 
- 					form.append('<input type="hidden" name="mimes[]" value="'+self.escape(mime)+'"/>');
 
- 				});
 
- 				
 
- 				$.each(self.customData, function(key, val) {
 
- 					form.append('<input type="hidden" name="'+key+'" value="'+self.escape(val)+'"/>');
 
- 				});
 
- 				
 
- 				form.appendTo('body');
 
- 				iframe.appendTo('body');
 
- 			});
 
- 			
 
- 			return dfrd;
 
- 		}
 
- 	},
 
- 	
 
- 	
 
- 	/**
 
- 	 * Bind callback to event(s) The callback is executed at most once per event.
 
- 	 * To bind to multiply events at once, separate events names by space
 
- 	 *
 
- 	 * @param  String    event name
 
- 	 * @param  Function  callback
 
- 	 * @param  Boolan    priority first
 
- 	 * @return elFinder
 
- 	 */
 
- 	one : function(ev, callback, priorityFirst) {
 
- 		var self  = this,
 
- 			event = ev.toLowerCase(),
 
- 			h     = function(e, f) {
 
- 				if (!self.toUnbindEvents[event]) {
 
- 					self.toUnbindEvents[event] = [];
 
- 				}
 
- 				self.toUnbindEvents[event].push({
 
- 					type: event,
 
- 					callback: h
 
- 				});
 
- 				return (callback.done? callback.done : callback).apply(this, arguments);
 
- 			};
 
- 		if (callback.done) {
 
- 			h = {done: h};
 
- 		}
 
- 		return this.bind(event, h, priorityFirst);
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Set/get data into/from localStorage
 
- 	 *
 
- 	 * @param  String       key
 
- 	 * @param  String|void  value
 
- 	 * @return String|null
 
- 	 */
 
- 	localStorage : function(key, val) {
 
- 		var self   = this,
 
- 			s      = window.localStorage,
 
- 			oldkey = 'elfinder-'+(key || '')+this.id, // old key of elFinder < 2.1.6
 
- 			prefix = window.location.pathname+'-elfinder-',
 
- 			suffix = this.id,
 
- 			clrs   = [],
 
- 			retval, oldval, t, precnt, sufcnt;
 
- 		// reset this node data
 
- 		if (typeof(key) === 'undefined') {
 
- 			precnt = prefix.length;
 
- 			sufcnt = suffix.length * -1;
 
- 			$.each(s, function(key) {
 
- 				if (key.substr(0, precnt) === prefix && key.substr(sufcnt) === suffix) {
 
- 					clrs.push(key);
 
- 				}
 
- 			});
 
- 			$.each(clrs, function(i, key) {
 
- 				s.removeItem(key);
 
- 			});
 
- 			return true;
 
- 		}
 
- 		
 
- 		// new key of elFinder >= 2.1.6
 
- 		key = prefix+key+suffix;
 
- 		
 
- 		if (val === null) {
 
- 			return s.removeItem(key);
 
- 		}
 
- 		
 
- 		if (val === void(0) && !(retval = s.getItem(key)) && (oldval = s.getItem(oldkey))) {
 
- 			val = oldval;
 
- 			s.removeItem(oldkey);
 
- 		}
 
- 		
 
- 		if (val !== void(0)) {
 
- 			t = typeof val;
 
- 			if (t !== 'string' && t !== 'number') {
 
- 				val = JSON.stringify(val);
 
- 			}
 
- 			try {
 
- 				s.setItem(key, val);
 
- 			} catch (e) {
 
- 				try {
 
- 					s.clear();
 
- 					s.setItem(key, val);
 
- 				} catch (e) {
 
- 					self.debug('error', e.toString());
 
- 				}
 
- 			}
 
- 			retval = s.getItem(key);
 
- 		}
 
- 		if (retval && (retval.substr(0,1) === '{' || retval.substr(0,1) === '[')) {
 
- 			try {
 
- 				return JSON.parse(retval);
 
- 			} catch(e) {}
 
- 		}
 
- 		return retval;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Get/set cookie
 
- 	 *
 
- 	 * @param  String       cookie name
 
- 	 * @param  String|void  cookie value
 
- 	 * @return String|null
 
- 	 */
 
- 	cookie : function(name, value) {
 
- 		var d, o, c, i, retval, t;
 
- 		name = 'elfinder-'+name+this.id;
 
- 		if (value === void(0)) {
 
- 			if (document.cookie && document.cookie != '') {
 
- 				c = document.cookie.split(';');
 
- 				name += '=';
 
- 				for (i=0; i<c.length; i++) {
 
- 					c[i] = $.trim(c[i]);
 
- 					if (c[i].substring(0, name.length) == name) {
 
- 						retval = decodeURIComponent(c[i].substring(name.length));
 
- 						if (retval.substr(0,1) === '{' || retval.substr(0,1) === '[') {
 
- 							try {
 
- 								return JSON.parse(retval);
 
- 							} catch(e) {}
 
- 						}
 
- 						return retval;
 
- 					}
 
- 				}
 
- 			}
 
- 			return null;
 
- 		}
 
- 		o = Object.assign({}, this.options.cookie);
 
- 		if (value === null) {
 
- 			value = '';
 
- 			o.expires = -1;
 
- 		} else {
 
- 			t = typeof value;
 
- 			if (t !== 'string' && t !== 'number') {
 
- 				value = JSON.stringify(value);
 
- 			}
 
- 		}
 
- 		if (typeof(o.expires) == 'number') {
 
- 			d = new Date();
 
- 			d.setTime(d.getTime()+(o.expires * 86400000));
 
- 			o.expires = d;
 
- 		}
 
- 		document.cookie = name+'='+encodeURIComponent(value)+'; expires='+o.expires.toUTCString()+(o.path ? '; path='+o.path : '')+(o.domain ? '; domain='+o.domain : '')+(o.secure ? '; secure' : '');
 
- 		if (value && (value.substr(0,1) === '{' || value.substr(0,1) === '[')) {
 
- 			try {
 
- 				return JSON.parse(value);
 
- 			} catch(e) {}
 
- 		}
 
- 		return value;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Get start directory (by location.hash or last opened directory)
 
- 	 * 
 
- 	 * @return String
 
- 	 */
 
- 	startDir : function() {
 
- 		var locHash = window.location.hash;
 
- 		if (locHash && locHash.match(/^#elf_/)) {
 
- 			return locHash.replace(/^#elf_/, '');
 
- 		} else if (this.options.startPathHash) {
 
- 			return this.options.startPathHash;
 
- 		} else {
 
- 			return this.lastDir();
 
- 		}
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Get/set last opened directory
 
- 	 * 
 
- 	 * @param  String|undefined  dir hash
 
- 	 * @return String
 
- 	 */
 
- 	lastDir : function(hash) { 
 
- 		return this.options.rememberLastDir ? this.storage('lastdir', hash) : '';
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Node for escape html entities in texts
 
- 	 * 
 
- 	 * @type jQuery
 
- 	 */
 
- 	_node : $('<span/>'),
 
- 	
 
- 	/**
 
- 	 * Replace not html-safe symbols to html entities
 
- 	 * 
 
- 	 * @param  String  text to escape
 
- 	 * @return String
 
- 	 */
 
- 	escape : function(name) {
 
- 		return this._node.text(name).html().replace(/"/g, '"').replace(/'/g, ''');
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Cleanup ajax data.
 
- 	 * For old api convert data into new api format
 
- 	 * 
 
- 	 * @param  String  command name
 
- 	 * @param  Object  data from backend
 
- 	 * @return Object
 
- 	 */
 
- 	normalize : function(data) {
 
- 		var self   = this,
 
- 			fileFilter = (function() {
 
- 				var func, filter;
 
- 				if (filter = self.options.fileFilter) {
 
- 					if (typeof filter === 'function') {
 
- 						func = function(file) {
 
- 							return filter.call(self, file);
 
- 						};
 
- 					} else if (filter instanceof RegExp) {
 
- 						func = function(file) {
 
- 							return filter.test(file.name);
 
- 						};
 
- 					}
 
- 				}
 
- 				return func? func : null;
 
- 			})(),
 
- 			chkCmdMap = function(opts) {
 
- 				// Disable command to replace with other command
 
- 				var disabled;
 
- 				if (opts.uiCmdMap) {
 
- 					if ($.isPlainObject(opts.uiCmdMap) && Object.keys(opts.uiCmdMap).length) {
 
- 						if (!opts.disabledFlip) {
 
- 							opts.disabledFlip = {};
 
- 						}
 
- 						disabled = opts.disabledFlip;
 
- 						$.each(opts.uiCmdMap, function(f, t) {
 
- 							if (t === 'hidden' && !disabled[f]) {
 
- 								opts.disabled.push(f);
 
- 								opts.disabledFlip[f] = true;
 
- 							}
 
- 						});
 
- 					} else {
 
- 						delete opts.uiCmdMap;
 
- 					}
 
- 				}
 
- 			},
 
- 			normalizeOptions = function(opts) {
 
- 				var getType = function(v) {
 
- 					var type = typeof v;
 
- 					if (type === 'object' && Array.isArray(v)) {
 
- 						type = 'array';
 
- 					}
 
- 					return type;
 
- 				};
 
- 				$.each(self.optionProperties, function(k, empty) {
 
- 					if (empty !== void(0)) {
 
- 						if (opts[k] && getType(opts[k]) !== getType(empty)) {
 
- 							opts[k] = empty;
 
- 						}
 
- 					}
 
- 				});
 
- 				if (opts['disabled']) {
 
- 					opts['disabledFlip'] = self.arrayFlip(opts['disabled'], true);
 
- 				} else {
 
- 					opts['disabledFlip'] = {};
 
- 				}
 
- 				return opts;
 
- 			},
 
- 			filter = function(file, asMap, type) { 
 
- 				var res = asMap? file : true,
 
- 					ign = asMap? null : false,
 
- 					vid, targetOptions, isRoot, rootNames;
 
- 				
 
- 				if (file && file.hash && file.name && file.mime) {
 
- 					if (file.mime === 'application/x-empty') {
 
- 						file.mime = 'text/plain';
 
- 					}
 
- 					
 
- 					isRoot = self.isRoot(file);
 
- 					if (isRoot && ! file.volumeid) {
 
- 						self.debug('warning', 'The volume root statuses requires `volumeid` property.');
 
- 					}
 
- 					if (isRoot || file.mime === 'directory') {
 
- 						// Prevention of circular reference
 
- 						if (file.phash) {
 
- 							if (file.phash === file.hash) {
 
- 								error = error.concat(['Parent folder of "$1" is itself.', file.name]);
 
- 								return ign;
 
- 							}
 
- 							if (isRoot && file.volumeid && file.phash.indexOf(file.volumeid) === 0) {
 
- 								error = error.concat(['Parent folder of "$1" is inner itself.', file.name]);
 
- 								return ign;
 
- 							}
 
- 						}
 
- 						
 
- 						// set options, tmbUrls for each volume
 
- 						if (file.volumeid) {
 
- 							vid = file.volumeid;
 
- 							
 
- 							if (isRoot) {
 
- 								// make or update of leaf roots cache
 
- 								if (file.phash) {
 
- 									if (! self.leafRoots[file.phash]) {
 
- 										self.leafRoots[file.phash] = [ file.hash ];
 
- 									} else {
 
- 										if ($.inArray(file.hash, self.leafRoots[file.phash]) === -1) {
 
- 											self.leafRoots[file.phash].push(file.hash);
 
- 										}
 
- 									}
 
- 								}
 
- 								self.hasVolOptions = true;
 
- 								if (! self.volOptions[vid]) {
 
- 									self.volOptions[vid] = {
 
- 										// set dispInlineRegex
 
- 										dispInlineRegex: self.options.dispInlineRegex
 
- 									};
 
- 								}
 
- 								
 
- 								targetOptions = self.volOptions[vid];
 
- 								
 
- 								if (file.options) {
 
- 									// >= v.2.1.14 has file.options
 
- 									Object.assign(targetOptions, file.options);
 
- 								}
 
- 								
 
- 								// for compat <= v2.1.13
 
- 								if (file.disabled) {
 
- 									targetOptions.disabled = file.disabled;
 
- 									targetOptions.disabledFlip = self.arrayFlip(file.disabled, true);
 
- 								}
 
- 								if (file.tmbUrl) {
 
- 									targetOptions.tmbUrl = file.tmbUrl;
 
- 								}
 
- 								
 
- 								// '/' required at the end of url
 
- 								if (targetOptions.url && targetOptions.url.substr(-1) !== '/') {
 
- 									targetOptions.url += '/';
 
- 								}
 
- 								// check uiCmdMap
 
- 								chkCmdMap(targetOptions);
 
- 								
 
- 								// check trash bin hash
 
- 								if (targetOptions.trashHash) {
 
- 									if (self.trashes[targetOptions.trashHash] === false) {
 
- 										delete targetOptions.trashHash;
 
- 									} else {
 
- 										self.trashes[targetOptions.trashHash] = file.hash;
 
- 									}
 
- 								}
 
- 								
 
- 								// set immediate properties
 
- 								$.each(self.optionProperties, function(k) {
 
- 									if (targetOptions[k]) {
 
- 										file[k] = targetOptions[k];
 
- 									}
 
- 								});
 
- 								// regist fm.roots
 
- 								if (type !== 'cwd') {
 
- 									self.roots[vid] = file.hash;
 
- 								}
 
- 								// regist fm.volumeExpires
 
- 								if (file.expires) {
 
- 									self.volumeExpires[vid] = file.expires;
 
- 								}
 
- 							}
 
- 							
 
- 							if (prevId !== vid) {
 
- 								prevId = vid;
 
- 								i18nFolderName = self.option('i18nFolderName', vid);
 
- 							}
 
- 						}
 
- 						
 
- 						// volume root i18n name
 
- 						if (isRoot && ! file.i18) {
 
- 							name = 'volume_' + file.name,
 
- 							i18 = self.i18n(false, name);
 
- 	
 
- 							if (name !== i18) {
 
- 								file.i18 = i18;
 
- 							}
 
- 						}
 
- 						
 
- 						// i18nFolderName
 
- 						if (i18nFolderName && ! file.i18) {
 
- 							name = 'folder_' + file.name,
 
- 							i18 = self.i18n(false, name);
 
- 	
 
- 							if (name !== i18) {
 
- 								file.i18 = i18;
 
- 							}
 
- 						}
 
- 						
 
- 						if (isRoot) {
 
- 							if (rootNames = self.storage('rootNames')) {
 
- 								if (rootNames[file.hash]) {
 
- 									file._name = file.name;
 
- 									file._i18 = file.i18;
 
- 									file.name = rootNames[file.hash] = rootNames[file.hash];
 
- 									delete file.i18;
 
- 								}
 
- 								self.storage('rootNames', rootNames);
 
- 							}
 
- 						}
 
- 						// lock trash bins holder
 
- 						if (self.trashes[file.hash]) {
 
- 							file.locked = true;
 
- 						}
 
- 					} else {
 
- 						if (fileFilter) {
 
- 							try {
 
- 								if (! fileFilter(file)) {
 
- 									return ign;
 
- 								}
 
- 							} catch(e) {
 
- 								self.debug(e);
 
- 							}
 
- 						}
 
- 						if (file.size == 0) {
 
- 							file.mime = self.getMimetype(file.name, file.mime);
 
- 						}
 
- 					}
 
- 					
 
- 					if (file.options) {
 
- 						self.optionsByHashes[file.hash] = normalizeOptions(file.options);
 
- 					}
 
- 					
 
- 					delete file.options;
 
- 					
 
- 					return res;
 
- 				}
 
- 				return ign;
 
- 			},
 
- 			getDescendants = function(hashes) {
 
- 				var res = [];
 
- 				$.each(self.files(), function(h, f) {
 
- 					$.each(self.parents(h), function(i, ph) {
 
- 						if ($.inArray(ph, hashes) !== -1 && $.inArray(h, hashes) === -1) {
 
- 							res.push(h);
 
- 							return false;
 
- 						}
 
- 					});
 
- 				});
 
- 				return res;
 
- 			},
 
- 			applyLeafRootStats = function(dataArr, type) {
 
- 				$.each(dataArr, function(i, f) {
 
- 					var pfile, done;
 
- 					if (self.leafRoots[f.hash]) {
 
- 						self.applyLeafRootStats(f);
 
- 					}
 
- 					// update leaf root parent stat
 
- 					if (type !== 'change' && f.phash && self.isRoot(f) && (pfile = self.file(f.phash))) {
 
- 						self.applyLeafRootStats(pfile);
 
- 						// add to data.changed
 
- 						if (!data.changed) {
 
- 							data.changed = [pfile];
 
- 						} else {
 
- 							$.each(data.changed, function(i, f) {
 
- 								if (f.hash === pfile.hash) {
 
- 									data.changed[i] = pfile;
 
- 									done = true;
 
- 									return false;
 
- 								}
 
- 							});
 
- 							if (!done) {
 
- 								data.changed.push(pfile);
 
- 							}
 
- 						}
 
- 					}
 
- 				});
 
- 			},
 
- 			error = [],
 
- 			name, i18, i18nFolderName, prevId, cData;
 
- 		
 
- 		// set cunstom data
 
- 		if (data.customData && data.customData !== self.prevCustomData) {
 
- 			self.prevCustomData = data.customData;
 
- 			try {
 
- 				cData = JSON.parse(data.customData);
 
- 				if ($.isPlainObject(cData)) {
 
- 					self.prevCustomData = cData;
 
- 					$.each(Object.keys(cData), function(i, key) {
 
- 						if (cData[key] === null) {
 
- 							delete cData[key];
 
- 							delete self.optsCustomData[key];
 
- 						}
 
- 					});
 
- 					self.customData = Object.assign({}, self.optsCustomData, cData);
 
- 				}
 
- 			} catch(e) {}
 
- 		}
 
- 		if (data.options) {
 
- 			normalizeOptions(data.options);
 
- 		}
 
- 		
 
- 		if (data.cwd) {
 
- 			if (data.cwd.volumeid && data.options && Object.keys(data.options).length && self.isRoot(data.cwd)) {
 
- 				self.hasVolOptions = true;
 
- 				self.volOptions[data.cwd.volumeid] = data.options;
 
- 			}
 
- 			data.cwd = filter(data.cwd, true, 'cwd');
 
- 		}
 
- 		if (data.files) {
 
- 			data.files = $.grep(data.files, filter);
 
- 		} 
 
- 		if (data.tree) {
 
- 			data.tree = $.grep(data.tree, filter);
 
- 		}
 
- 		if (data.added) {
 
- 			data.added = $.grep(data.added, filter);
 
- 		}
 
- 		if (data.changed) {
 
- 			data.changed = $.grep(data.changed, filter);
 
- 		}
 
- 		if (data.removed && data.removed.length && self.searchStatus.state === 2) {
 
- 			data.removed = data.removed.concat(getDescendants(data.removed));
 
- 		}
 
- 		if (data.api) {
 
- 			data.init = true;
 
- 		}
 
- 		if (Object.keys(self.leafRoots).length) {
 
- 			data.files && applyLeafRootStats(data.files);
 
- 			data.tree && applyLeafRootStats(data.tree);
 
- 			data.added && applyLeafRootStats(data.added);
 
- 			data.changed && applyLeafRootStats(data.changed, 'change');
 
- 		}
 
- 		// merge options that apply only to cwd
 
- 		if (data.cwd && data.cwd.options && data.options) {
 
- 			Object.assign(data.options, normalizeOptions(data.cwd.options));
 
- 		}
 
- 		// '/' required at the end of url
 
- 		if (data.options && data.options.url && data.options.url.substr(-1) !== '/') {
 
- 			data.options.url += '/';
 
- 		}
 
- 		
 
- 		// check error
 
- 		if (error.length) {
 
- 			data.norError = ['errResponse'].concat(error);
 
- 		}
 
- 		
 
- 		return data;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Update sort options
 
- 	 *
 
- 	 * @param {String} sort type
 
- 	 * @param {String} sort order
 
- 	 * @param {Boolean} show folder first
 
- 	 */
 
- 	setSort : function(type, order, stickFolders, alsoTreeview) {
 
- 		this.storage('sortType', (this.sortType = this.sortRules[type] ? type : 'name'));
 
- 		this.storage('sortOrder', (this.sortOrder = /asc|desc/.test(order) ? order : 'asc'));
 
- 		this.storage('sortStickFolders', (this.sortStickFolders = !!stickFolders) ? 1 : '');
 
- 		this.storage('sortAlsoTreeview', (this.sortAlsoTreeview = !!alsoTreeview) ? 1 : '');
 
- 		this.trigger('sortchange');
 
- 	},
 
- 	
 
- 	_sortRules : {
 
- 		name : function(file1, file2) {
 
- 			return elFinder.prototype.naturalCompare(file1.i18 || file1.name, file2.i18 || file2.name);
 
- 		},
 
- 		size : function(file1, file2) { 
 
- 			var size1 = parseInt(file1.size) || 0,
 
- 				size2 = parseInt(file2.size) || 0;
 
- 				
 
- 			return size1 === size2 ? 0 : size1 > size2 ? 1 : -1;
 
- 		},
 
- 		kind : function(file1, file2) {
 
- 			return elFinder.prototype.naturalCompare(file1.mime, file2.mime);
 
- 		},
 
- 		date : function(file1, file2) { 
 
- 			var date1 = file1.ts || file1.date || 0,
 
- 				date2 = file2.ts || file2.date || 0;
 
- 			return date1 === date2 ? 0 : date1 > date2 ? 1 : -1;
 
- 		},
 
- 		perm : function(file1, file2) { 
 
- 			var val = function(file) { return (file.write? 2 : 0) + (file.read? 1 : 0); },
 
- 				v1  = val(file1),
 
- 				v2  = val(file2);
 
- 			return v1 === v2 ? 0 : v1 > v2 ? 1 : -1;
 
- 		},
 
- 		mode : function(file1, file2) { 
 
- 			var v1 = file1.mode || (file1.perm || ''),
 
- 				v2 = file2.mode || (file2.perm || '');
 
- 			return elFinder.prototype.naturalCompare(v1, v2);
 
- 		},
 
- 		owner : function(file1, file2) { 
 
- 			var v1 = file1.owner || '',
 
- 				v2 = file2.owner || '';
 
- 			return elFinder.prototype.naturalCompare(v1, v2);
 
- 		},
 
- 		group : function(file1, file2) { 
 
- 			var v1 = file1.group || '',
 
- 				v2 = file2.group || '';
 
- 			return elFinder.prototype.naturalCompare(v1, v2);
 
- 		}
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Valid sort rule names
 
- 	 * 
 
- 	 * @type Object
 
- 	 */
 
- 	sorters : {},
 
- 	
 
- 	/**
 
- 	 * Compare strings for natural sort
 
- 	 *
 
- 	 * @param  String
 
- 	 * @param  String
 
- 	 * @return Number
 
- 	 */
 
- 	naturalCompare : function(a, b) {
 
- 		var self = elFinder.prototype.naturalCompare;
 
- 		if (typeof self.loc == 'undefined') {
 
- 			self.loc = (navigator.userLanguage || navigator.browserLanguage || navigator.language || 'en-US');
 
- 		}
 
- 		if (typeof self.sort == 'undefined') {
 
- 			if ('11'.localeCompare('2', self.loc, {numeric: true}) > 0) {
 
- 				// Native support
 
- 				if (window.Intl && window.Intl.Collator) {
 
- 					self.sort = new Intl.Collator(self.loc, {numeric: true}).compare;
 
- 				} else {
 
- 					self.sort = function(a, b) {
 
- 						return a.localeCompare(b, self.loc, {numeric: true});
 
- 					};
 
- 				}
 
- 			} else {
 
- 				/*
 
- 				 * Edited for elFinder (emulates localeCompare() by numeric) by Naoki Sawada aka nao-pon
 
- 				 */
 
- 				/*
 
- 				 * Huddle/javascript-natural-sort (https://github.com/Huddle/javascript-natural-sort)
 
- 				 */
 
- 				/*
 
- 				 * Natural Sort algorithm for Javascript - Version 0.7 - Released under MIT license
 
- 				 * Author: Jim Palmer (based on chunking idea from Dave Koelle)
 
- 				 * http://opensource.org/licenses/mit-license.php
 
- 				 */
 
- 				self.sort = function(a, b) {
 
- 					var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi,
 
- 					sre = /(^[ ]*|[ ]*$)/g,
 
- 					dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
 
- 					hre = /^0x[0-9a-f]+$/i,
 
- 					ore = /^0/,
 
- 					syre = /^[\x01\x21-\x2f\x3a-\x40\x5b-\x60\x7b-\x7e]/, // symbol first - (Naoki Sawada)
 
- 					i = function(s) { return self.sort.insensitive && (''+s).toLowerCase() || ''+s; },
 
- 					// convert all to strings strip whitespace
 
- 					// first character is "_", it's smallest - (Naoki Sawada)
 
- 					x = i(a).replace(sre, '').replace(/^_/, "\x01") || '',
 
- 					y = i(b).replace(sre, '').replace(/^_/, "\x01") || '',
 
- 					// chunk/tokenize
 
- 					xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
 
- 					yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
 
- 					// numeric, hex or date detection
 
- 					xD = parseInt(x.match(hre)) || (xN.length != 1 && x.match(dre) && Date.parse(x)),
 
- 					yD = parseInt(y.match(hre)) || xD && y.match(dre) && Date.parse(y) || null,
 
- 					oFxNcL, oFyNcL,
 
- 					locRes = 0;
 
- 					// first try and sort Hex codes or Dates
 
- 					if (yD) {
 
- 						if ( xD < yD ) return -1;
 
- 						else if ( xD > yD ) return 1;
 
- 					}
 
- 					// natural sorting through split numeric strings and default strings
 
- 					for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {
 
- 						// find floats not starting with '0', string or 0 if not defined (Clint Priest)
 
- 						oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0;
 
- 						oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0;
 
- 						// handle numeric vs string comparison - number < string - (Kyle Adams)
 
- 						// but symbol first < number - (Naoki Sawada)
 
- 						if (isNaN(oFxNcL) !== isNaN(oFyNcL)) {
 
- 							if (isNaN(oFxNcL) && (typeof oFxNcL !== 'string' || ! oFxNcL.match(syre))) {
 
- 								return 1;
 
- 							} else if (typeof oFyNcL !== 'string' || ! oFyNcL.match(syre)) {
 
- 								return -1;
 
- 							}
 
- 						}
 
- 						// use decimal number comparison if either value is string zero
 
- 						if (parseInt(oFxNcL, 10) === 0) oFxNcL = 0;
 
- 						if (parseInt(oFyNcL, 10) === 0) oFyNcL = 0;
 
- 						// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
 
- 						if (typeof oFxNcL !== typeof oFyNcL) {
 
- 							oFxNcL += '';
 
- 							oFyNcL += '';
 
- 						}
 
- 						// use locale sensitive sort for strings when case insensitive
 
- 						// note: localeCompare interleaves uppercase with lowercase (e.g. A,a,B,b)
 
- 						if (self.sort.insensitive && typeof oFxNcL === 'string' && typeof oFyNcL === 'string') {
 
- 							locRes = oFxNcL.localeCompare(oFyNcL, self.loc);
 
- 							if (locRes !== 0) return locRes;
 
- 						}
 
- 						if (oFxNcL < oFyNcL) return -1;
 
- 						if (oFxNcL > oFyNcL) return 1;
 
- 					}
 
- 					return 0;
 
- 				};
 
- 				self.sort.insensitive = true;
 
- 			}
 
- 		}
 
- 		return self.sort(a, b);
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Compare files based on elFinder.sort
 
- 	 *
 
- 	 * @param  Object  file
 
- 	 * @param  Object  file
 
- 	 * @return Number
 
- 	 */
 
- 	compare : function(file1, file2) {
 
- 		var self  = this,
 
- 			type  = self.sortType,
 
- 			asc   = self.sortOrder == 'asc',
 
- 			stick = self.sortStickFolders,
 
- 			rules = self.sortRules,
 
- 			sort  = rules[type],
 
- 			d1    = file1.mime == 'directory',
 
- 			d2    = file2.mime == 'directory',
 
- 			res;
 
- 			
 
- 		if (stick) {
 
- 			if (d1 && !d2) {
 
- 				return -1;
 
- 			} else if (!d1 && d2) {
 
- 				return 1;
 
- 			}
 
- 		}
 
- 		
 
- 		res = asc ? sort(file1, file2) : sort(file2, file1);
 
- 		
 
- 		return type !== 'name' && res === 0
 
- 			? res = asc ? rules.name(file1, file2) : rules.name(file2, file1)
 
- 			: res;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Sort files based on config
 
- 	 *
 
- 	 * @param  Array  files
 
- 	 * @return Array
 
- 	 */
 
- 	sortFiles : function(files) {
 
- 		return files.sort(this.compare);
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Open notification dialog 
 
- 	 * and append/update message for required notification type.
 
- 	 *
 
- 	 * @param  Object  options
 
- 	 * @example  
 
- 	 * this.notify({
 
- 	 *    type : 'copy',
 
- 	 *    msg : 'Copy files', // not required for known types @see this.notifyType
 
- 	 *    cnt : 3,
 
- 	 *    hideCnt  : false,   // true for not show count
 
- 	 *    progress : 10,      // progress bar percents (use cnt : 0 to update progress bar)
 
- 	 *    cancel   : callback // callback function for cancel button
 
- 	 * })
 
- 	 * @return elFinder
 
- 	 */
 
- 	notify : function(opts) {
 
- 		var type     = opts.type,
 
- 			id       = opts.id? 'elfinder-notify-'+opts.id : '',
 
- 			msg      = this.i18n((typeof opts.msg !== 'undefined')? opts.msg : (this.messages['ntf'+type] ? 'ntf'+type : 'ntfsmth')),
 
- 			ndialog  = this.ui.notify,
 
- 			notify   = ndialog.children('.elfinder-notify-'+type+(id? ('.'+id) : '')),
 
- 			button   = notify.children('div.elfinder-notify-cancel').children('button'),
 
- 			ntpl     = '<div class="elfinder-notify elfinder-notify-{type}'+(id? (' '+id) : '')+'"><span class="elfinder-dialog-icon elfinder-dialog-icon-{type}"/><span class="elfinder-notify-msg">{msg}</span> <span class="elfinder-notify-cnt"/><div class="elfinder-notify-progressbar"><div class="elfinder-notify-progress"/></div><div class="elfinder-notify-cancel"/></div>',
 
- 			delta    = opts.cnt,
 
- 			size     = (typeof opts.size != 'undefined')? parseInt(opts.size) : null,
 
- 			progress = (typeof opts.progress != 'undefined' && opts.progress >= 0) ? opts.progress : null,
 
- 			cancel   = opts.cancel,
 
- 			clhover  = 'ui-state-hover',
 
- 			close    = function() {
 
- 				notify._esc && $(document).off('keydown', notify._esc);
 
- 				notify.remove();
 
- 				!ndialog.children().length && ndialog.elfinderdialog('close');
 
- 			},
 
- 			cnt, total, prc;
 
- 		if (!type) {
 
- 			return this;
 
- 		}
 
- 		
 
- 		if (!notify.length) {
 
- 			notify = $(ntpl.replace(/\{type\}/g, type).replace(/\{msg\}/g, msg))
 
- 				.appendTo(ndialog)
 
- 				.data('cnt', 0);
 
- 			if (progress != null) {
 
- 				notify.data({progress : 0, total : 0});
 
- 			}
 
- 			if (cancel) {
 
- 				button = $('<button type="button" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"><span class="ui-button-text">'+this.i18n('btnCancel')+'</span></button>')
 
- 					.on('mouseenter mouseleave', function(e) { 
 
- 						$(this).toggleClass(clhover, e.type === 'mouseenter');
 
- 					});
 
- 				notify.children('div.elfinder-notify-cancel').append(button);
 
- 			}
 
- 		} else if (typeof opts.msg !== 'undefined') {
 
- 			notify.children('span.elfinder-notify-msg').html(msg);
 
- 		}
 
- 		cnt = delta + parseInt(notify.data('cnt'));
 
- 		
 
- 		if (cnt > 0) {
 
- 			if (cancel && button.length) {
 
- 				if ($.isFunction(cancel) || (typeof cancel === 'object' && cancel.promise)) {
 
- 					notify._esc = function(e) {
 
- 						if (e.type == 'keydown' && e.keyCode != $.ui.keyCode.ESCAPE) {
 
- 							return;
 
- 						}
 
- 						e.preventDefault();
 
- 						e.stopPropagation();
 
- 						close();
 
- 						if (cancel.promise) {
 
- 							cancel.reject(0); // 0 is canceling flag
 
- 						} else {
 
- 							cancel(e);
 
- 						}
 
- 					};
 
- 					button.on('click', function(e) {
 
- 						notify._esc(e);
 
- 					});
 
- 					$(document).on('keydown.' + this.namespace, notify._esc);
 
- 				}
 
- 			}
 
- 			
 
- 			!opts.hideCnt && notify.children('.elfinder-notify-cnt').text('('+cnt+')');
 
- 			ndialog.is(':hidden') && ndialog.elfinderdialog('open', this).height('auto');
 
- 			notify.data('cnt', cnt);
 
- 			
 
- 			if ((progress != null)
 
- 			&& (total = notify.data('total')) >= 0
 
- 			&& (prc = notify.data('progress')) >= 0) {
 
- 				total += size != null? size : delta;
 
- 				prc   += progress;
 
- 				(size == null && delta < 0) && (prc += delta * 100);
 
- 				notify.data({progress : prc, total : total});
 
- 				if (size != null) {
 
- 					prc *= 100;
 
- 					total = Math.max(1, total);
 
- 				}
 
- 				progress = parseInt(prc/total);
 
- 				
 
- 				notify.find('.elfinder-notify-progress')
 
- 					.animate({
 
- 						width : (progress < 100 ? progress : 100)+'%'
 
- 					}, 20);
 
- 			}
 
- 			
 
- 		} else {
 
- 			close();
 
- 		}
 
- 		
 
- 		return this;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Open confirmation dialog 
 
- 	 *
 
- 	 * @param  Object  options
 
- 	 * @example  
 
- 	 * this.confirm({
 
- 	 *    cssClass : 'elfinder-confirm-mydialog',
 
- 	 *    title : 'Remove files',
 
- 	 *    text  : 'Here is question text',
 
- 	 *    accept : {  // accept callback - required
 
- 	 *      label : 'Continue',
 
- 	 *      callback : function(applyToAll) { fm.log('Ok') }
 
- 	 *    },
 
- 	 *    cancel : { // cancel callback - required
 
- 	 *      label : 'Cancel',
 
- 	 *      callback : function() { fm.log('Cancel')}
 
- 	 *    },
 
- 	 *    reject : { // reject callback - optionally
 
- 	 *      label : 'No',
 
- 	 *      callback : function(applyToAll) { fm.log('No')}
 
- 	 *    },
 
- 	 *    buttons : [ // additional buttons callback - optionally
 
- 	 *      {
 
- 	 *        label : 'Btn1',
 
- 	 *        callback : function(applyToAll) { fm.log('Btn1')}
 
- 	 *      }
 
- 	 *    ],
 
- 	 *    all : true  // display checkbox "Apply to all"
 
- 	 * })
 
- 	 * @return elFinder
 
- 	 */
 
- 	confirm : function(opts) {
 
- 		var self     = this,
 
- 			complete = false,
 
- 			options = {
 
- 				cssClass  : 'elfinder-dialog-confirm',
 
- 				modal     : true,
 
- 				resizable : false,
 
- 				title     : this.i18n(opts.title || 'confirmReq'),
 
- 				buttons   : {},
 
- 				close     : function() { 
 
- 					!complete && opts.cancel.callback();
 
- 					$(this).elfinderdialog('destroy');
 
- 				}
 
- 			},
 
- 			apply = this.i18n('apllyAll'),
 
- 			label, checkbox, btnNum;
 
- 		if (opts.cssClass) {
 
- 			options.cssClass += ' ' + opts.cssClass;
 
- 		}
 
- 		options.buttons[this.i18n(opts.accept.label)] = function() {
 
- 			opts.accept.callback(!!(checkbox && checkbox.prop('checked')));
 
- 			complete = true;
 
- 			$(this).elfinderdialog('close');
 
- 		};
 
- 		options.buttons[this.i18n(opts.accept.label)]._cssClass = 'elfinder-confirm-accept';
 
- 		
 
- 		if (opts.reject) {
 
- 			options.buttons[this.i18n(opts.reject.label)] = function() {
 
- 				opts.reject.callback(!!(checkbox && checkbox.prop('checked')));
 
- 				complete = true;
 
- 				$(this).elfinderdialog('close');
 
- 			};
 
- 			options.buttons[this.i18n(opts.reject.label)]._cssClass = 'elfinder-confirm-reject';
 
- 		}
 
- 		
 
- 		if (opts.buttons && opts.buttons.length > 0) {
 
- 			btnNum = 1;
 
- 			$.each(opts.buttons, function(i, v){
 
- 				options.buttons[self.i18n(v.label)] = function() {
 
- 					v.callback(!!(checkbox && checkbox.prop('checked')));
 
- 					complete = true;
 
- 					$(this).elfinderdialog('close');
 
- 				};
 
- 				options.buttons[self.i18n(v.label)]._cssClass = 'elfinder-confirm-extbtn' + (btnNum++);
 
- 				if (v.cssClass) {
 
- 					options.buttons[self.i18n(v.label)]._cssClass += ' ' + v.cssClass;
 
- 				}
 
- 			});
 
- 		}
 
- 		
 
- 		options.buttons[this.i18n(opts.cancel.label)] = function() {
 
- 			$(this).elfinderdialog('close');
 
- 		};
 
- 		options.buttons[this.i18n(opts.cancel.label)]._cssClass = 'elfinder-confirm-cancel';
 
- 		
 
- 		if (opts.all) {
 
- 			options.create = function() {
 
- 				var base = $('<div class="elfinder-dialog-confirm-applyall"/>');
 
- 				checkbox = $('<input type="checkbox" />');
 
- 				$(this).next().find('.ui-dialog-buttonset')
 
- 					.prepend(base.append($('<label>'+apply+'</label>').prepend(checkbox)));
 
- 			};
 
- 		}
 
- 		
 
- 		if (opts.optionsCallback && $.isFunction(opts.optionsCallback)) {
 
- 			opts.optionsCallback(options);
 
- 		}
 
- 		
 
- 		return this.dialog('<span class="elfinder-dialog-icon elfinder-dialog-icon-confirm"/>' + this.i18n(opts.text), options);
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Create unique file name in required dir
 
- 	 * 
 
- 	 * @param  String  file name
 
- 	 * @param  String  parent dir hash
 
- 	 * @param  String  glue
 
- 	 * @return String
 
- 	 */
 
- 	uniqueName : function(prefix, phash, glue) {
 
- 		var i = 0, ext = '', p, name;
 
- 		
 
- 		prefix = this.i18n(false, prefix);
 
- 		phash = phash || this.cwd().hash;
 
- 		glue = (typeof glue === 'undefined')? ' ' : glue;
 
- 		if (p = prefix.match(/^(.+)(\.[^.]+)$/)) {
 
- 			ext    = p[2];
 
- 			prefix = p[1];
 
- 		}
 
- 		
 
- 		name   = prefix+ext;
 
- 		
 
- 		if (!this.fileByName(name, phash)) {
 
- 			return name;
 
- 		}
 
- 		while (i < 10000) {
 
- 			name = prefix + glue + (++i) + ext;
 
- 			if (!this.fileByName(name, phash)) {
 
- 				return name;
 
- 			}
 
- 		}
 
- 		return prefix + Math.random() + ext;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Return message translated onto current language
 
- 	 * Allowed accept HTML element that was wrapped in jQuery object
 
- 	 * To be careful to XSS vulnerability of HTML element Ex. You should use `fm.escape(file.name)`
 
- 	 *
 
- 	 * @param  String|Array  message[s]|Object jQuery
 
- 	 * @return String
 
- 	 **/
 
- 	i18n : function() {
 
- 		var self = this,
 
- 			messages = this.messages, 
 
- 			input    = [],
 
- 			ignore   = [], 
 
- 			message = function(m) {
 
- 				var file;
 
- 				if (m.indexOf('#') === 0) {
 
- 					if ((file = self.file(m.substr(1)))) {
 
- 						return file.name;
 
- 					}
 
- 				}
 
- 				return m;
 
- 			},
 
- 			i, j, m, escFunc, start = 0, isErr;
 
- 		
 
- 		if (arguments.length && arguments[0] === false) {
 
- 			escFunc = function(m){ return m; };
 
- 			start = 1;
 
- 		}
 
- 		for (i = start; i< arguments.length; i++) {
 
- 			m = arguments[i];
 
- 			
 
- 			if (Array.isArray(m)) {
 
- 				for (j = 0; j < m.length; j++) {
 
- 					if (m[j] instanceof jQuery) {
 
- 						// jQuery object is HTML element
 
- 						input.push(m[j]);
 
- 					} else if (typeof m[j] !== 'undefined'){
 
- 						input.push(message('' + m[j]));
 
- 					}
 
- 				}
 
- 			} else if (m instanceof jQuery) {
 
- 				// jQuery object is HTML element
 
- 				input.push(m[j]);
 
- 			} else if (typeof m !== 'undefined'){
 
- 				input.push(message('' + m));
 
- 			}
 
- 		}
 
- 		
 
- 		for (i = 0; i < input.length; i++) {
 
- 			// dont translate placeholders
 
- 			if ($.inArray(i, ignore) !== -1) {
 
- 				continue;
 
- 			}
 
- 			m = input[i];
 
- 			if (typeof m == 'string') {
 
- 				isErr = !!(messages[m] && m.match(/^err/));
 
- 				// translate message
 
- 				m = messages[m] || (escFunc? escFunc(m) : self.escape(m));
 
- 				// replace placeholders in message
 
- 				m = m.replace(/\$(\d+)/g, function(match, placeholder) {
 
- 					var res;
 
- 					placeholder = i + parseInt(placeholder);
 
- 					if (placeholder > 0 && input[placeholder]) {
 
- 						ignore.push(placeholder);
 
- 					}
 
- 					res = escFunc? escFunc(input[placeholder]) : self.escape(input[placeholder]);
 
- 					if (isErr) {
 
- 						res = '<span class="elfinder-err-var elfinder-err-var' + placeholder + '">' + res + '</span>';
 
- 					}
 
- 					return res;
 
- 				});
 
- 			} else {
 
- 				// get HTML from jQuery object
 
- 				m = m.get(0).outerHTML;
 
- 			}
 
- 			input[i] = m;
 
- 		}
 
- 		return $.grep(input, function(m, i) { return $.inArray(i, ignore) === -1 ? true : false; }).join('<br>');
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Get icon style from file.icon
 
- 	 * 
 
- 	 * @param  Object  elFinder file object
 
- 	 * @return String|Object
 
- 	 */
 
- 	getIconStyle : function(file, asObject) {
 
- 		var self = this,
 
- 			template = {
 
- 				'background' : 'url(\'{url}\') 0 0 no-repeat',
 
- 				'background-size' : 'contain'
 
- 			},
 
- 			style = '',
 
- 			cssObj = {},
 
- 			i = 0;
 
- 		if (file.icon) {
 
- 			style = 'style="';
 
- 			$.each(template, function(k, v) {
 
- 				if (i++ === 0) {
 
- 					v = v.replace('{url}', self.escape(file.icon));
 
- 				}
 
- 				if (asObject) {
 
- 					cssObj[k] = v;
 
- 				} else {
 
- 					style += k+':'+v+';';
 
- 				}
 
- 			});
 
- 			style += '"';
 
- 		}
 
- 		return asObject? cssObj : style;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Convert mimetype into css classes
 
- 	 * 
 
- 	 * @param  String  file mimetype
 
- 	 * @return String
 
- 	 */
 
- 	mime2class : function(mimeType) {
 
- 		var prefix = 'elfinder-cwd-icon-',
 
- 			mime   = mimeType.toLowerCase(),
 
- 			isText = this.textMimes[mime];
 
- 		
 
- 		mime = mime.split('/');
 
- 		if (isText) {
 
- 			mime[0] += ' ' + prefix + 'text';
 
- 		} else if (mime[1] && mime[1].match(/\+xml$/)) {
 
- 			mime[0] += ' ' + prefix + 'xml';
 
- 		}
 
- 		
 
- 		return prefix + mime[0] + (mime[1] ? ' ' + prefix + mime[1].replace(/(\.|\+)/g, '-') : '');
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Return localized kind of file
 
- 	 * 
 
- 	 * @param  Object|String  file or file mimetype
 
- 	 * @return String
 
- 	 */
 
- 	mime2kind : function(f) {
 
- 		var isObj = typeof(f) == 'object' ? true : false,
 
- 			mime  = isObj ? f.mime : f,
 
- 			kind;
 
- 		
 
- 		if (isObj && f.alias && mime != 'symlink-broken') {
 
- 			kind = 'Alias';
 
- 		} else if (this.kinds[mime]) {
 
- 			if (isObj && mime === 'directory' && (! f.phash || f.isroot)) {
 
- 				kind = 'Root';
 
- 			} else {
 
- 				kind = this.kinds[mime];
 
- 			}
 
- 		}
 
- 		if (! kind) {
 
- 			if (mime.indexOf('text') === 0) {
 
- 				kind = 'Text';
 
- 			} else if (mime.indexOf('image') === 0) {
 
- 				kind = 'Image';
 
- 			} else if (mime.indexOf('audio') === 0) {
 
- 				kind = 'Audio';
 
- 			} else if (mime.indexOf('video') === 0) {
 
- 				kind = 'Video';
 
- 			} else if (mime.indexOf('application') === 0) {
 
- 				kind = 'App';
 
- 			} else {
 
- 				kind = mime;
 
- 			}
 
- 		}
 
- 		
 
- 		return this.messages['kind'+kind] ? this.i18n('kind'+kind) : mime;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Return boolean Is mime-type text file
 
- 	 * 
 
- 	 * @param  String  mime-type
 
- 	 * @return Boolean
 
- 	 */
 
- 	mimeIsText : function(mime) {
 
- 		return (this.textMimes[mime.toLowerCase()] || (mime.indexOf('text/') === 0 && mime.substr(5, 3) !== 'rtf') || mime.match(/^application\/.+\+xml$/))? true : false;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Returns a date string formatted according to the given format string
 
- 	 * 
 
- 	 * @param  String  format string
 
- 	 * @param  Object  Date object
 
- 	 * @return String
 
- 	 */
 
- 	date : function(format, date) {
 
- 		var self = this,
 
- 			output, d, dw, m, y, h, g, i, s;
 
- 		
 
- 		if (! date) {
 
- 			date = new Date();
 
- 		}
 
- 		
 
- 		h  = date[self.getHours]();
 
- 		g  = h > 12 ? h - 12 : h;
 
- 		i  = date[self.getMinutes]();
 
- 		s  = date[self.getSeconds]();
 
- 		d  = date[self.getDate]();
 
- 		dw = date[self.getDay]();
 
- 		m  = date[self.getMonth]() + 1;
 
- 		y  = date[self.getFullYear]();
 
- 		
 
- 		output = format.replace(/[a-z]/gi, function(val) {
 
- 			switch (val) {
 
- 				case 'd': return d > 9 ? d : '0'+d;
 
- 				case 'j': return d;
 
- 				case 'D': return self.i18n(self.i18.daysShort[dw]);
 
- 				case 'l': return self.i18n(self.i18.days[dw]);
 
- 				case 'm': return m > 9 ? m : '0'+m;
 
- 				case 'n': return m;
 
- 				case 'M': return self.i18n(self.i18.monthsShort[m-1]);
 
- 				case 'F': return self.i18n(self.i18.months[m-1]);
 
- 				case 'Y': return y;
 
- 				case 'y': return (''+y).substr(2);
 
- 				case 'H': return h > 9 ? h : '0'+h;
 
- 				case 'G': return h;
 
- 				case 'g': return g;
 
- 				case 'h': return g > 9 ? g : '0'+g;
 
- 				case 'a': return h >= 12 ? 'pm' : 'am';
 
- 				case 'A': return h >= 12 ? 'PM' : 'AM';
 
- 				case 'i': return i > 9 ? i : '0'+i;
 
- 				case 's': return s > 9 ? s : '0'+s;
 
- 			}
 
- 			return val;
 
- 		});
 
- 		
 
- 		return output;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Return localized date
 
- 	 * 
 
- 	 * @param  Object  file object
 
- 	 * @return String
 
- 	 */
 
- 	formatDate : function(file, t) {
 
- 		var self = this, 
 
- 			ts   = t || file.ts, 
 
- 			i18  = self.i18,
 
- 			date, format, output, d, dw, m, y, h, g, i, s;
 
- 		if (self.options.clientFormatDate && ts > 0) {
 
- 			date = new Date(ts*1000);
 
- 			format = ts >= this.yesterday 
 
- 				? this.fancyFormat 
 
- 				: this.dateFormat;
 
- 			output = self.date(format, date);
 
- 			
 
- 			return ts >= this.yesterday
 
- 				? output.replace('$1', this.i18n(ts >= this.today ? 'Today' : 'Yesterday'))
 
- 				: output;
 
- 		} else if (file.date) {
 
- 			return file.date.replace(/([a-z]+)\s/i, function(a1, a2) { return self.i18n(a2)+' '; });
 
- 		}
 
- 		
 
- 		return self.i18n('dateUnknown');
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Return localized number string
 
- 	 * 
 
- 	 * @param  Number
 
- 	 * @return String
 
- 	 */
 
- 	toLocaleString : function(num) {
 
- 		var v = new Number(num);
 
- 		if (v) {
 
- 			if (v.toLocaleString) {
 
- 				return v.toLocaleString();
 
- 			} else {
 
- 				return String(num).replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
 
- 			}
 
- 		}
 
- 		return num;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Return css class marks file permissions
 
- 	 * 
 
- 	 * @param  Object  file 
 
- 	 * @return String
 
- 	 */
 
- 	perms2class : function(o) {
 
- 		var c = '';
 
- 		
 
- 		if (!o.read && !o.write) {
 
- 			c = 'elfinder-na';
 
- 		} else if (!o.read) {
 
- 			c = 'elfinder-wo';
 
- 		} else if (!o.write) {
 
- 			c = 'elfinder-ro';
 
- 		}
 
- 		
 
- 		if (o.type) {
 
- 			c += ' elfinder-' + this.escape(o.type);
 
- 		}
 
- 		
 
- 		return c;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Return localized string with file permissions
 
- 	 * 
 
- 	 * @param  Object  file
 
- 	 * @return String
 
- 	 */
 
- 	formatPermissions : function(f) {
 
- 		var p  = [];
 
- 			
 
- 		f.read && p.push(this.i18n('read'));
 
- 		f.write && p.push(this.i18n('write'));	
 
- 		return p.length ? p.join(' '+this.i18n('and')+' ') : this.i18n('noaccess');
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Return formated file size
 
- 	 * 
 
- 	 * @param  Number  file size
 
- 	 * @return String
 
- 	 */
 
- 	formatSize : function(s) {
 
- 		var n = 1, u = 'b';
 
- 		
 
- 		if (s == 'unknown') {
 
- 			return this.i18n('unknown');
 
- 		}
 
- 		
 
- 		if (s > 1073741824) {
 
- 			n = 1073741824;
 
- 			u = 'GB';
 
- 		} else if (s > 1048576) {
 
- 			n = 1048576;
 
- 			u = 'MB';
 
- 		} else if (s > 1024) {
 
- 			n = 1024;
 
- 			u = 'KB';
 
- 		}
 
- 		s = s/n;
 
- 		return (s > 0 ? n >= 1048576 ? s.toFixed(2) : Math.round(s) : 0) +' '+u;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Return formated file mode by options.fileModeStyle
 
- 	 * 
 
- 	 * @param  String  file mode
 
- 	 * @param  String  format style
 
- 	 * @return String
 
- 	 */
 
- 	formatFileMode : function(p, style) {
 
- 		var i, o, s, b, sticy, suid, sgid, str, oct;
 
- 		
 
- 		if (!style) {
 
- 			style = this.options.fileModeStyle.toLowerCase();
 
- 		}
 
- 		p = $.trim(p);
 
- 		if (p.match(/[rwxs-]{9}$/i)) {
 
- 			str = p = p.substr(-9);
 
- 			if (style == 'string') {
 
- 				return str;
 
- 			}
 
- 			oct = '';
 
- 			s = 0;
 
- 			for (i=0; i<7; i=i+3) {
 
- 				o = p.substr(i, 3);
 
- 				b = 0;
 
- 				if (o.match(/[r]/i)) {
 
- 					b += 4;
 
- 				}
 
- 				if (o.match(/[w]/i)) {
 
- 					b += 2;
 
- 				}
 
- 				if (o.match(/[xs]/i)) {
 
- 					if (o.match(/[xs]/)) {
 
- 						b += 1;
 
- 					}
 
- 					if (o.match(/[s]/i)) {
 
- 						if (i == 0) {
 
- 							s += 4;
 
- 						} else if (i == 3) {
 
- 							s += 2;
 
- 						}
 
- 					}
 
- 				}
 
- 				oct += b.toString(8);
 
- 			}
 
- 			if (s) {
 
- 				oct = s.toString(8) + oct;
 
- 			}
 
- 		} else {
 
- 			p = parseInt(p, 8);
 
- 			oct = p? p.toString(8) : '';
 
- 			if (!p || style == 'octal') {
 
- 				return oct;
 
- 			}
 
- 			o = p.toString(8);
 
- 			s = 0;
 
- 			if (o.length > 3) {
 
- 				o = o.substr(-4);
 
- 				s = parseInt(o.substr(0, 1), 8);
 
- 				o = o.substr(1);
 
- 			}
 
- 			sticy = ((s & 1) == 1); // not support
 
- 			sgid = ((s & 2) == 2);
 
- 			suid = ((s & 4) == 4);
 
- 			str = '';
 
- 			for(i=0; i<3; i++) {
 
- 				if ((parseInt(o.substr(i, 1), 8) & 4) == 4) {
 
- 					str += 'r';
 
- 				} else {
 
- 					str += '-';
 
- 				}
 
- 				if ((parseInt(o.substr(i, 1), 8) & 2) == 2) {
 
- 					str += 'w';
 
- 				} else {
 
- 					str += '-';
 
- 				}
 
- 				if ((parseInt(o.substr(i, 1), 8) & 1) == 1) {
 
- 					str += ((i==0 && suid)||(i==1 && sgid))? 's' : 'x';
 
- 				} else {
 
- 					str += '-';
 
- 				}
 
- 			}
 
- 		}
 
- 		if (style == 'both') {
 
- 			return str + ' (' + oct + ')';
 
- 		} else if (style == 'string') {
 
- 			return str;
 
- 		} else {
 
- 			return oct;
 
- 		}
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Regist this.decodeRawString function
 
- 	 * 
 
- 	 * @return void
 
- 	 */
 
- 	registRawStringDecoder : function(rawStringDecoder) {
 
- 		if ($.isFunction(rawStringDecoder)) {
 
- 			this.decodeRawString = this.options.rawStringDecoder = rawStringDecoder;
 
- 		}
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Return boolean that uploadable MIME type into target folder
 
- 	 * 
 
- 	 * @param  String  mime    MIME type
 
- 	 * @param  String  target  target folder hash
 
- 	 * @return Bool
 
- 	 */
 
- 	uploadMimeCheck : function(mime, target) {
 
- 		target = target || this.cwd().hash;
 
- 		var res   = true, // default is allow
 
- 			mimeChecker = this.option('uploadMime', target),
 
- 			allow,
 
- 			deny,
 
- 			check = function(checker) {
 
- 				var ret = false;
 
- 				if (typeof checker === 'string' && checker.toLowerCase() === 'all') {
 
- 					ret = true;
 
- 				} else if (Array.isArray(checker) && checker.length) {
 
- 					$.each(checker, function(i, v) {
 
- 						v = v.toLowerCase();
 
- 						if (v === 'all' || mime.indexOf(v) === 0) {
 
- 							ret = true;
 
- 							return false;
 
- 						}
 
- 					});
 
- 				}
 
- 				return ret;
 
- 			};
 
- 		if (mime && $.isPlainObject(mimeChecker)) {
 
- 			mime = mime.toLowerCase();
 
- 			allow = check(mimeChecker.allow);
 
- 			deny = check(mimeChecker.deny);
 
- 			if (mimeChecker.firstOrder === 'allow') {
 
- 				res = false; // default is deny
 
- 				if (! deny && allow === true) { // match only allow
 
- 					res = true;
 
- 				}
 
- 			} else {
 
- 				res = true; // default is allow
 
- 				if (deny === true && ! allow) { // match only deny
 
- 					res = false;
 
- 				}
 
- 			}
 
- 		}
 
- 		return res;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * call chained sequence of async deferred functions
 
- 	 * 
 
- 	 * @param  Array   tasks async functions
 
- 	 * @return Object  jQuery.Deferred
 
- 	 */
 
- 	sequence : function(tasks) {
 
- 		var l = tasks.length,
 
- 			chain = function(task, idx) {
 
- 				++idx;
 
- 				if (tasks[idx]) {
 
- 					return chain(task.then(tasks[idx]), idx);
 
- 				} else {
 
- 					return task;
 
- 				}
 
- 			};
 
- 		if (l > 1) {
 
- 			return chain(tasks[0](), 0);
 
- 		} else {
 
- 			return tasks[0]();
 
- 		}
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Reload contents of target URL for clear browser cache
 
- 	 * 
 
- 	 * @param  String  url target URL
 
- 	 * @return Object  jQuery.Deferred
 
- 	 */
 
- 	reloadContents : function(url) {
 
- 		var dfd = $.Deferred(),
 
- 			ifm;
 
- 		try {
 
- 			ifm = $('<iframe width="1" height="1" scrolling="no" frameborder="no" style="position:absolute; top:-1px; left:-1px" crossorigin="use-credentials">')
 
- 				.attr('src', url)
 
- 				.one('load', function() {
 
- 					var ifm = $(this);
 
- 					try {
 
- 						this.contentDocument.location.reload(true);
 
- 						ifm.one('load', function() {
 
- 							ifm.remove();
 
- 							dfd.resolve();
 
- 						});
 
- 					} catch(e) {
 
- 						ifm.attr('src', '').attr('src', url).one('load', function() {
 
- 							ifm.remove();
 
- 							dfd.resolve();
 
- 						});
 
- 					}
 
- 				})
 
- 				.appendTo('body');
 
- 		} catch(e) {
 
- 			ifm && ifm.remove();
 
- 			dfd.reject();
 
- 		}
 
- 		return dfd;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Make netmount option for OAuth2
 
- 	 * 
 
- 	 * @param  String   protocol
 
- 	 * @param  String   name
 
- 	 * @param  String   host
 
- 	 * @param  Object   opts  Default {noOffline: false, root: 'root', pathI18n: 'folderId', folders: true}
 
- 			}
 
- 	 * 
 
- 	 * @return Object
 
- 	 */
 
- 	makeNetmountOptionOauth : function(protocol, name, host, opt) {
 
- 		var noOffline = typeof opt === 'boolean'? opt : null, // for backward compat
 
- 			opts = Object.assign({
 
- 				noOffline : false,
 
- 				root      : 'root',
 
- 				pathI18n  : 'folderId',
 
- 				folders   : true
 
- 			}, (noOffline === null? (opt || {}) : {noOffline : noOffline})),
 
- 			addFolders = function(fm, bro, folders) {
 
- 				var self = this,
 
- 					cnt  = Object.keys($.isPlainObject(folders)? folders : {}).length,
 
- 					select;
 
- 				
 
- 				bro.next().remove();
 
- 				if (cnt) {
 
- 					select = $('<select class="ui-corner-all elfinder-tabstop" style="max-width:200px;">').append(
 
- 						$($.map(folders, function(n,i){return '<option value="'+fm.escape((i+'').trim())+'">'+fm.escape(n)+'</option>';}).join(''))
 
- 					).on('change click', function(e){
 
- 						var node = $(this),
 
- 							path = node.val(),
 
- 							spn;
 
- 						self.inputs.path.val(path);
 
- 						if (opts.folders && (e.type === 'change' || node.data('current') !== path)) {
 
- 							node.next().remove();
 
- 							node.data('current', path);
 
- 							if (path != opts.root) {
 
- 								spn = spinner();
 
- 								if (xhr && xhr.state() === 'pending') {
 
- 									fm.abortXHR(xhr, { quiet: true , abort: true });
 
- 								}
 
- 								node.after(spn);
 
- 								xhr = fm.request({
 
- 									data : {cmd : 'netmount', protocol: protocol, host: host, user: 'init', path: path, pass: 'folders'},
 
- 									preventDefault : true
 
- 								}).done(function(data){
 
- 									addFolders.call(self, fm, node, data.folders);
 
- 								}).always(function() {
 
- 									fm.abortXHR(xhr, { quiet: true });
 
- 									spn.remove();
 
- 								}).xhr;
 
- 							}
 
- 						}
 
- 					});
 
- 					bro.after($('<div/>').append(select))
 
- 						.closest('.ui-dialog').trigger('tabstopsInit');
 
- 					select.trigger('focus');
 
- 				}
 
- 			},
 
- 			spinner = function() {
 
- 				return $('<div class="elfinder-netmount-spinner"/>').append('<span class="elfinder-spinner"/>');
 
- 			},
 
- 			xhr;
 
- 		return {
 
- 			vars : {},
 
- 			name : name,
 
- 			inputs: {
 
- 				offline  : $('<input type="checkbox"/>').on('change', function() {
 
- 					$(this).parents('table.elfinder-netmount-tb').find('select:first').trigger('change', 'reset');
 
- 				}),
 
- 				host     : $('<span><span class="elfinder-spinner"/></span><input type="hidden"/>'),
 
- 				path     : $('<input type="text" value="'+opts.root+'"/>'),
 
- 				user     : $('<input type="hidden"/>'),
 
- 				pass     : $('<input type="hidden"/>')
 
- 			},
 
- 			select: function(fm, ev, d){
 
- 				var f = this.inputs,
 
- 					oline = f.offline,
 
- 					f0 = $(f.host[0]),
 
- 					data = d || null;
 
- 				this.vars.mbtn = f.host.closest('.ui-dialog').children('.ui-dialog-buttonpane:first').find('button.elfinder-btncnt-0');
 
- 				if (! f0.data('inrequest')
 
- 						&& (f0.find('span.elfinder-spinner').length
 
- 							|| data === 'reset'
 
- 							|| (data === 'winfocus' && ! f0.siblings('span.elfinder-button-icon-reload').length))
 
- 							)
 
- 				{
 
- 					if (oline.parent().children().length === 1) {
 
- 						f.path.parent().prev().html(fm.i18n(opts.pathI18n));
 
- 						oline.attr('title', fm.i18n('offlineAccess'));
 
- 						oline.uniqueId().after($('<label/>').attr('for', oline.attr('id')).html(' '+fm.i18n('offlineAccess')));
 
- 					}
 
- 					f0.data('inrequest', true).empty().addClass('elfinder-spinner')
 
- 						.parent().find('span.elfinder-button-icon').remove();
 
- 					fm.request({
 
- 						data : {cmd : 'netmount', protocol: protocol, host: host, user: 'init', options: {id: fm.id, offline: oline.prop('checked')? 1:0, pass: f.host[1].value}},
 
- 						preventDefault : true
 
- 					}).done(function(data){
 
- 						f0.removeClass("elfinder-spinner").html(data.body.replace(/\{msg:([^}]+)\}/g, function(whole,s1){return fm.i18n(s1, host);}));
 
- 					});
 
- 					opts.noOffline && oline.closest('tr').hide();
 
- 				} else {
 
- 					oline.closest('tr')[(opts.noOffline || f.user.val())? 'hide':'show']();
 
- 					f0.data('funcexpup') && f0.data('funcexpup')();
 
- 				}
 
- 				this.vars.mbtn[$(f.host[1]).val()? 'show':'hide']();
 
- 			},
 
- 			done: function(fm, data){
 
- 				var f = this.inputs,
 
- 					p = this.protocol,
 
- 					f0 = $(f.host[0]),
 
- 					f1 = $(f.host[1]),
 
- 					expires = ' ';
 
- 				
 
- 				opts.noOffline && f.offline.closest('tr').hide();
 
- 				if (data.mode == 'makebtn') {
 
- 					f0.removeClass('elfinder-spinner').removeData('expires').removeData('funcexpup');
 
- 					f.host.find('input').on('mouseenter mouseleave', function(){$(this).toggleClass('ui-state-hover');});
 
- 					f1.val('');
 
- 					f.path.val(opts.root).next().remove();
 
- 					f.user.val('');
 
- 					f.pass.val('');
 
- 					! opts.noOffline && f.offline.closest('tr').show();
 
- 					this.vars.mbtn.hide();
 
- 				} else if (data.mode == 'folders') {
 
- 					if (data.folders) {
 
- 						addFolders.call(this, fm, f.path.nextAll(':last'), data.folders);
 
- 					}
 
- 				} else {
 
- 					if (data.expires) {
 
- 						expires = '()';
 
- 						f0.data('expires', data.expires);
 
- 					}
 
- 					f0.html(host + expires).removeClass('elfinder-spinner');
 
- 					if (data.expires) {
 
- 						f0.data('funcexpup', function() {
 
- 							var rem = Math.floor((f0.data('expires') - (+new Date()) / 1000) / 60);
 
- 							if (rem < 3) {
 
- 								f0.parent().children('.elfinder-button-icon-reload').click();
 
- 							} else {
 
- 								f0.text(f0.text().replace(/\(.*\)/, '('+fm.i18n(['minsLeft', rem])+')'));
 
- 								setTimeout(function() {
 
- 									if (f0.is(':visible')) {
 
- 										f0.data('funcexpup')();
 
- 									}
 
- 								}, 60000);
 
- 							}
 
- 						});
 
- 						f0.data('funcexpup')();
 
- 					}
 
- 					if (data.reset) {
 
- 						p.trigger('change', 'reset');
 
- 						return;
 
- 					}
 
- 					f0.parent().append($('<span class="elfinder-button-icon elfinder-button-icon-reload" title="'+fm.i18n('reAuth')+'">')
 
- 						.on('click', function() {
 
- 							f1.val('reauth');
 
- 							p.trigger('change', 'reset');
 
- 						}));
 
- 					f1.val(protocol);
 
- 					this.vars.mbtn.show();
 
- 					if (data.folders) {
 
- 						addFolders.call(this, fm, f.path, data.folders);
 
- 					}
 
- 					f.user.val('done');
 
- 					f.pass.val('done');
 
- 					f.offline.closest('tr').hide();
 
- 				}
 
- 				f0.removeData('inrequest');
 
- 			},
 
- 			fail: function(fm, err){
 
- 				$(this.inputs.host[0]).removeData('inrequest');
 
- 				this.protocol.trigger('change', 'reset');
 
- 			},
 
- 			integrateInfo: opts.integrate
 
- 		};
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Find cwd's nodes from files
 
- 	 * 
 
- 	 * @param  Array    files
 
- 	 * @param  Object   opts   {firstOnly: true|false}
 
- 	 */
 
- 	findCwdNodes : function(files, opts) {
 
- 		var self    = this,
 
- 			cwd     = this.getUI('cwd'),
 
- 			cwdHash = this.cwd().hash,
 
- 			newItem = $();
 
- 		
 
- 		opts = opts || {};
 
- 		
 
- 		$.each(files, function(i, f) {
 
- 			if (f.phash === cwdHash || self.searchStatus.state > 1) {
 
- 				newItem = newItem.add(cwd.find('#'+self.cwdHash2Id(f.hash)));
 
- 				if (opts.firstOnly) {
 
- 					return false;
 
- 				}
 
- 			}
 
- 		});
 
- 		
 
- 		return newItem;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Convert from relative URL to abstract URL based on current URL
 
- 	 * 
 
- 	 * @param  String  URL
 
- 	 * @return String
 
- 	 */
 
- 	convAbsUrl : function(url) {
 
- 		if (url.match(/^http/i)) {
 
- 			return url;
 
- 		}
 
- 		if (url.substr(0,2) === '//') {
 
- 			return window.location.protocol + url;
 
- 		}
 
- 		var root = window.location.protocol + '//' + window.location.host,
 
- 			reg  = /[^\/]+\/\.\.\//,
 
- 			ret;
 
- 		if (url.substr(0, 1) === '/') {
 
- 			ret = root + url;
 
- 		} else {
 
- 			ret = root + window.location.pathname.replace(/\/[^\/]+$/, '/') + url;
 
- 		}
 
- 		ret = ret.replace('/./', '/');
 
- 		while(reg.test(ret)) {
 
- 			ret = ret.replace(reg, '');
 
- 		}
 
- 		return ret;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Is same origin to current site
 
- 	 * 
 
- 	 * @param  String  check url
 
- 	 * @return Boolean
 
- 	 */
 
- 	isSameOrigin : function (checkUrl) {
 
- 		var url;
 
- 		checkUrl = this.convAbsUrl(checkUrl);
 
- 		if (location.origin && window.URL) {
 
- 			try {
 
- 				url = new URL(checkUrl);
 
- 				return location.origin === url.origin;
 
- 			} catch(e) {}
 
- 		}
 
- 		url = document.createElement('a');
 
- 		url.href = checkUrl;
 
- 		return location.protocol === url.protocol && location.host === url.host && location.port && url.port;
 
- 	},
 
- 	
 
- 	navHash2Id : function(hash) {
 
- 		return this.navPrefix + hash;
 
- 	},
 
- 	
 
- 	navId2Hash : function(id) {
 
- 		return typeof(id) == 'string' ? id.substr(this.navPrefix.length) : false;
 
- 	},
 
- 	
 
- 	cwdHash2Id : function(hash) {
 
- 		return this.cwdPrefix + hash;
 
- 	},
 
- 	
 
- 	cwdId2Hash : function(id) {
 
- 		return typeof(id) == 'string' ? id.substr(this.cwdPrefix.length) : false;
 
- 	},
 
- 	
 
- 	isInWindow : function(elem, nochkHide) {
 
- 		var elm, rect;
 
- 		if (! (elm = elem.get(0))) {
 
- 			return false;
 
- 		}
 
- 		if (! nochkHide && elm.offsetParent === null) {
 
- 			return false;
 
- 		}
 
- 		rect = elm.getBoundingClientRect();
 
- 		return document.elementFromPoint(rect.left, rect.top)? true : false;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * calculate elFinder node z-index
 
- 	 * 
 
- 	 * @return void
 
- 	 */
 
- 	zIndexCalc : function() {
 
- 		var self = this,
 
- 			node = this.getUI(),
 
- 			ni = node.css('z-index');
 
- 		if (ni && ni !== 'auto' && ni !== 'inherit') {
 
- 			self.zIndex = ni;
 
- 		} else {
 
- 			node.parents().each(function(i, n) {
 
- 				var z = $(n).css('z-index');
 
- 				if (z !== 'auto' && z !== 'inherit' && (z = parseInt(z))) {
 
- 					self.zIndex = z;
 
- 					return false;
 
- 				}
 
- 			});
 
- 		}
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Load JavaScript files
 
- 	 * 
 
- 	 * @param  Array    urls      to load JavaScript file URLs
 
- 	 * @param  Function callback  call back function on script loaded
 
- 	 * @param  Object   opts      Additional options to $.ajax OR {loadType: 'tag'} to load by script tag
 
- 	 * @param  Object   check     { obj: (Object)ParentObject, name: (String)"Attribute name", timeout: (Integer)milliseconds }
 
- 	 * @return elFinder
 
- 	 */
 
- 	loadScript : function(urls, callback, opts, check) {
 
- 		var defOpts = {
 
- 				dataType : 'script',
 
- 				cache    : true
 
- 			},
 
- 			success, cnt, scripts = {}, results = {};
 
- 		
 
- 		opts = opts || {};
 
- 		if (opts.tryRequire && this.hasRequire) {
 
- 			require(urls, callback, opts.error);
 
- 		} else {
 
- 			success = function() {
 
- 				var cnt, fi, hasError;
 
- 				$.each(results, function(i, status) {
 
- 					if (status !== 'success' && status !== 'notmodified') {
 
- 						hasError = true;
 
- 						return false;
 
- 					}
 
- 				});
 
- 				if (!hasError) {
 
- 					if ($.isFunction(callback)) {
 
- 						if (check) {
 
- 							if (typeof check.obj[check.name] === 'undefined') {
 
- 								cnt = check.timeout? (check.timeout / 10) : 1;
 
- 								fi = setInterval(function() {
 
- 									if (--cnt < 0 || typeof check.obj[check.name] !== 'undefined') {
 
- 										clearInterval(fi);
 
- 										callback();
 
- 									}
 
- 								}, 10);
 
- 							} else {
 
- 								callback();
 
- 							}
 
- 						} else {
 
- 							callback();
 
- 						}
 
- 					}
 
- 				} else {
 
- 					if (opts.error && $.isFunction(opts.error)) {
 
- 						opts.error({ loadResults: results });
 
- 					}
 
- 				}
 
- 			};
 
- 			if (opts.loadType === 'tag') {
 
- 				$('head > script').each(function() {
 
- 					scripts[this.src] = this;
 
- 				});
 
- 				cnt = urls.length;
 
- 				$.each(urls, function(i, url) {
 
- 					var done = false,
 
- 						script;
 
- 					
 
- 					if (scripts[url]) {
 
- 						results[i] = scripts[url]._error || 'success';
 
- 						(--cnt < 1) && success();
 
- 					} else {
 
- 						script = document.createElement('script');
 
- 						script.charset = opts.charset || 'UTF-8';
 
- 						$('head').append(script);
 
- 						script.onload = script.onreadystatechange = function() {
 
- 							if ( !done && (!this.readyState ||
 
- 									this.readyState === 'loaded' || this.readyState === 'complete') ) {
 
- 								done = true;
 
- 								results[i] = 'success';
 
- 								(--cnt < 1) && success();
 
- 							}
 
- 						};
 
- 						script.onerror = function(err) {
 
- 							results[i] = script._error = (err && err.type)? err.type : 'error';
 
- 							(--cnt < 1) && success();
 
- 						};
 
- 						script.src = url;
 
- 					}
 
- 				});
 
- 			} else {
 
- 				opts = $.isPlainObject(opts)? Object.assign(defOpts, opts) : defOpts;
 
- 				cnt = 0;
 
- 				(function appendScript(d, status) {
 
- 					if (d !== void(0)) {
 
- 						results[cnt++] = status;
 
- 					}
 
- 					if (urls.length) {
 
- 						$.ajax(Object.assign({}, opts, {
 
- 							url: urls.shift(),
 
- 							success: appendScript,
 
- 							error: appendScript
 
- 						}));
 
- 					} else {
 
- 						success();
 
- 					}
 
- 				})();
 
- 			}
 
- 		}
 
- 		return this;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Load CSS files
 
- 	 * 
 
- 	 * @param  Array    to load CSS file URLs
 
- 	 * @param  Object   options
 
- 	 * @return elFinder
 
- 	 */
 
- 	loadCss : function(urls, opts) {
 
- 		var self = this,
 
- 			clName, dfds;
 
- 		if (typeof urls === 'string') {
 
- 			urls = [ urls ];
 
- 		}
 
- 		if (opts) {
 
- 			if (opts.className) {
 
- 				clName = opts.className;
 
- 			}
 
- 			if (opts.dfd && opts.dfd.promise) {
 
- 				dfds = [];
 
- 			}
 
- 		}
 
- 		$.each(urls, function(i, url) {
 
- 			var link, df;
 
- 			url = self.convAbsUrl(url).replace(/^https?:/i, '');
 
- 			if (dfds) {
 
- 				dfds[i] = $.Deferred();
 
- 			}
 
- 			if (! $("head > link[href='+url+']").length) {
 
- 				link = document.createElement('link');
 
- 				link.type = 'text/css';
 
- 				link.rel = 'stylesheet';
 
- 				link.href = url;
 
- 				if (clName) {
 
- 					link.className = clName;
 
- 				}
 
- 				if (dfds) {
 
- 					link.onload = function() {
 
- 						dfds[i].resolve();
 
- 					};
 
- 					link.onerror = function() {
 
- 						dfds[i].reject();
 
- 					};
 
- 				}
 
- 				$('head').append(link);
 
- 			} else {
 
- 				dfds && dfds[i].resolve();
 
- 			}
 
- 		});
 
- 		if (dfds) {
 
- 			$.when.apply(null, dfds).done(function() {
 
- 				opts.dfd.resolve();
 
- 			}).fail(function() {
 
- 				opts.dfd.reject();
 
- 			});
 
- 		}
 
- 		return this;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Abortable async job performer
 
- 	 * 
 
- 	 * @param func Function
 
- 	 * @param arr  Array
 
- 	 * @param opts Object
 
- 	 * 
 
- 	 * @return Object $.Deferred that has an extended method _abort()
 
- 	 */
 
- 	asyncJob : function(func, arr, opts) {
 
- 		var dfrd = $.Deferred(),
 
- 			abortFlg = false,
 
- 			parms = Object.assign({
 
- 				interval : 0,
 
- 				numPerOnce : 1
 
- 			}, opts || {}),
 
- 			resArr = [],
 
- 			vars =[],
 
- 			curVars = [],
 
- 			exec,
 
- 			tm;
 
- 		
 
- 		dfrd._abort = function(resolve) {
 
- 			tm && clearTimeout(tm);
 
- 			vars = [];
 
- 			abortFlg = true;
 
- 			if (dfrd.state() === 'pending') {
 
- 				dfrd[resolve? 'resolve' : 'reject'](resArr);
 
- 			}
 
- 		};
 
- 		
 
- 		dfrd.fail(function() {
 
- 			dfrd._abort();
 
- 		}).always(function() {
 
- 			dfrd._abort = function() {};
 
- 		});
 
- 		if (typeof func === 'function' && Array.isArray(arr)) {
 
- 			vars = arr.concat();
 
- 			exec = function() {
 
- 				var i, len, res;
 
- 				if (abortFlg) {
 
- 					return;
 
- 				}
 
- 				curVars = vars.splice(0, parms.numPerOnce);
 
- 				len = curVars.length;
 
- 				for (i = 0; i < len; i++) {
 
- 					if (abortFlg) {
 
- 						break;
 
- 					}
 
- 					res = func(curVars[i]);
 
- 					(res !== null) && resArr.push(res);
 
- 				}
 
- 				if (abortFlg) {
 
- 					return;
 
- 				}
 
- 				if (vars.length) {
 
- 					tm = setTimeout(exec, parms.interval);
 
- 				} else {
 
- 					dfrd.resolve(resArr);
 
- 				}
 
- 			};
 
- 			if (vars.length) {
 
- 				tm = setTimeout(exec, 0);
 
- 			} else {
 
- 				dfrd.resolve(resArr);
 
- 			}
 
- 		} else {
 
- 			dfrd.reject();
 
- 		}
 
- 		return dfrd;
 
- 	},
 
- 	
 
- 	getSize : function(targets) {
 
- 		var self = this,
 
- 			reqs = [],
 
- 			tgtlen = targets.length,
 
- 			dfrd = $.Deferred().fail(function() {
 
- 				$.each(reqs, function(i, req) {
 
- 					if (req) {
 
- 						req.syncOnFail && req.syncOnFail(false);
 
- 						req.reject();
 
- 					}
 
- 				});
 
- 			}),
 
- 			getLeafRoots = function(file) {
 
- 				var targets = [];
 
- 				if (file.mime === 'directory') {
 
- 					$.each(self.leafRoots, function(hash, roots) {
 
- 						var phash;
 
- 						if (hash === file.hash) {
 
- 							targets.push.apply(targets, roots);
 
- 						} else {
 
- 							phash = (self.file(hash) || {}).phash;
 
- 							while(phash) {
 
- 								if (phash === file.hash) {
 
- 									targets.push.apply(targets, roots);
 
- 								}
 
- 								phash = (self.file(phash) || {}).phash;
 
- 							}
 
- 						}
 
- 					});
 
- 				}
 
- 				return targets;
 
- 			},
 
- 			checkPhash = function(hash) {
 
- 				var dfd = $.Deferred(),
 
- 					dir = self.file(hash),
 
- 					target = dir? dir.phash : hash;
 
- 				if (target && ! self.file(target)) {
 
- 					self.request({
 
- 						data : {
 
- 							cmd    : 'parents',
 
- 							target : target
 
- 						},
 
- 						preventFail : true
 
- 					}).done(function() {
 
- 						self.one('parentsdone', function() {
 
- 							dfd.resolve();
 
- 						});
 
- 					}).fail(function() {
 
- 						dfd.resolve();
 
- 					});
 
- 				} else {
 
- 					dfd.resolve();
 
- 				}
 
- 				return dfd;
 
- 			},
 
- 			cache = function() {
 
- 				var dfd = $.Deferred(),
 
- 					cnt = Object.keys(self.leafRoots).length;
 
- 				
 
- 				if (cnt > 0) {
 
- 					$.each(self.leafRoots, function(hash) {
 
- 						checkPhash(hash).done(function() {
 
- 							--cnt;
 
- 							if (cnt < 1) {
 
- 								dfd.resolve();
 
- 							}
 
- 						});
 
- 					});
 
- 				} else {
 
- 					dfd.resolve();
 
- 				}
 
- 				return dfd;
 
- 			};
 
- 		self.autoSync('stop');
 
- 		cache().done(function() {
 
- 			var files = [], grps = {}, dfds = [], cache = [], singles = {};
 
- 			
 
- 			$.each(targets, function() {
 
- 				files.push.apply(files, getLeafRoots(self.file(this)));
 
- 			});
 
- 			targets.push.apply(targets, files);
 
- 			
 
- 			$.each(targets, function() {
 
- 				var root = self.root(this),
 
- 					file = self.file(this);
 
- 				if (file && (file.sizeInfo || file.mime !== 'directory')) {
 
- 					cache.push($.Deferred().resolve(file.sizeInfo? file.sizeInfo : {size: file.size, dirCnt: 0, fileCnt : 1}));
 
- 				} else {
 
- 					if (! grps[root]) {
 
- 						grps[root] = [ this ];
 
- 					} else {
 
- 						grps[root].push(this);
 
- 					}
 
- 				}
 
- 			});
 
- 			
 
- 			$.each(grps, function() {
 
- 				var idx = dfds.length;
 
- 				if (this.length === 1) {
 
- 					singles[idx] = this[0];
 
- 				}
 
- 				dfds.push(self.request({
 
- 					data : {cmd : 'size', targets : this},
 
- 					preventDefault : true
 
- 				}));
 
- 			});
 
- 			reqs.push.apply(reqs, dfds);
 
- 			dfds.push.apply(dfds, cache);
 
- 			
 
- 			$.when.apply($, dfds).fail(function() {
 
- 				dfrd.reject();
 
- 			}).done(function() {
 
- 				var cache = function(h, data) {
 
- 						var file;
 
- 						if (file = self.file(h)) {
 
- 							file.sizeInfo = { isCache: true };
 
- 							$.each(['size', 'dirCnt', 'fileCnt'], function() {
 
- 								file.sizeInfo[this] = data[this] || 0;
 
- 							});
 
- 							file.size = parseInt(file.sizeInfo.size);
 
- 							changed.push(file);
 
- 						}
 
- 					},
 
- 					size = 0,
 
- 					fileCnt = 0,
 
- 					dirCnt = 0,
 
- 					argLen = arguments.length,
 
- 					cnts = [],
 
- 					cntsTxt = '',
 
- 					changed = [],
 
- 					i, file, data;
 
- 				
 
- 				for (i = 0; i < argLen; i++) {
 
- 					data = arguments[i];
 
- 					file = null;
 
- 					if (!data.isCache) {
 
- 						if (singles[i] && (file = self.file(singles[i]))) {
 
- 							cache(singles[i], data);
 
- 						} else if (data.sizes && $.isPlainObject(data.sizes)) {
 
- 							$.each(data.sizes, function(h, sizeInfo) {
 
- 								cache(h, sizeInfo);
 
- 							});
 
- 						}
 
- 					}
 
- 					size += parseInt(data.size);
 
- 					if (fileCnt !== false) {
 
- 						if (typeof data.fileCnt === 'undefined') {
 
- 							fileCnt = false;
 
- 						}
 
- 						fileCnt += parseInt(data.fileCnt || 0);
 
- 					}
 
- 					if (dirCnt !== false) {
 
- 						if (typeof data.dirCnt === 'undefined') {
 
- 							dirCnt = false;
 
- 						}
 
- 						dirCnt += parseInt(data.dirCnt || 0);
 
- 					}
 
- 				}
 
- 				changed.length && self.change({changed: changed});
 
- 				
 
- 				if (dirCnt !== false){
 
- 					cnts.push(self.i18n('folders') + ': ' + (dirCnt - (tgtlen > 1? 0 : 1)));
 
- 				}
 
- 				if (fileCnt !== false){
 
- 					cnts.push(self.i18n('files') + ': ' + fileCnt);
 
- 				}
 
- 				if (cnts.length) {
 
- 					cntsTxt = '<br>' + cnts.join(', ');
 
- 				}
 
- 				dfrd.resolve({
 
- 					size: size,
 
- 					fileCnt: fileCnt,
 
- 					dirCnt: dirCnt,
 
- 					formated: (size >= 0 ? self.formatSize(size) : self.i18n('unknown')) + cntsTxt
 
- 				});
 
- 			});
 
- 			
 
- 			self.autoSync();
 
- 		});
 
- 		
 
- 		return dfrd;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Gets the theme object by settings of options.themes
 
- 	 *
 
- 	 * @param  String  themeid  The themeid
 
- 	 * @return Object  jQuery.Deferred
 
- 	 */
 
- 	getTheme : function(themeid) {
 
- 		var self = this,
 
- 			dfd = $.Deferred(),
 
- 			absUrl = function(url, base) {
 
- 				if (Array.isArray(url)) {
 
- 					return $.map(url, function(v) {
 
- 						return absUrl(v, base);
 
- 					});
 
- 				} else {
 
- 					return url.match(/^(?:http|\/\/)/i)? url : (base || self.baseUrl) + url.replace(/^(?:\.\/|\/)/, '');
 
- 				}
 
- 			},
 
- 			themeObj, m;
 
- 		if (themeid && (themeObj = self.options.themes[themeid])) {
 
- 			if (typeof themeObj === 'string') {
 
- 				url = absUrl(themeObj);
 
- 				if (m = url.match(/^(.+\/)[^/]+\.json$/i)) {
 
- 					$.getJSON(url).done(function(data) {
 
- 						themeObj = data;
 
- 						themeObj.id = themeid;
 
- 						if (themeObj.cssurls) {
 
- 							themeObj.cssurls = absUrl(themeObj.cssurls, m[1]);
 
- 						}
 
- 						dfd.resolve(themeObj);
 
- 					}).fail(function() {
 
- 						dfd.reject();
 
- 					});
 
- 				} else {
 
- 					dfd.resolve({
 
- 						id: themeid,
 
- 						name: themeid,
 
- 						cssurls: [url]
 
- 					});
 
- 				}
 
- 			} else if ($.isPlainObject(themeObj) && themeObj.cssurls) {
 
- 				themeObj.id = themeid;
 
- 				themeObj.cssurls = absUrl(themeObj.cssurls);
 
- 				if (!Array.isArray(themeObj.cssurls)) {
 
- 					themeObj.cssurls = [themeObj.cssurls];
 
- 				}
 
- 				if (!themeObj.name) {
 
- 					themeObj.name = themeid;
 
- 				}
 
- 				dfd.resolve(themeObj);
 
- 			} else {
 
- 				dfd.reject();
 
- 			}
 
- 		} else {
 
- 			dfd.reject();
 
- 		}
 
- 		return dfd;
 
- 	},
 
- 	/**
 
- 	 * Change current theme
 
- 	 *
 
- 	 * @param  String  themeid  The themeid
 
- 	 * @return Object  this elFinder instance
 
- 	 */
 
- 	changeTheme : function(themeid) {
 
- 		var self = this;
 
- 		if (themeid) {
 
- 			if (self.options.themes[themeid] && (!self.theme || self.theme.id !== themeid)) {
 
- 				self.getTheme(themeid).done(function(themeObj) {
 
- 					if (themeObj.cssurls) {
 
- 						$('head>link.elfinder-theme-ext').remove();
 
- 						self.loadCss(themeObj.cssurls, {
 
- 							className: 'elfinder-theme-ext',
 
- 							dfd: $.Deferred().done(function() {
 
- 								self.theme = themeObj;
 
- 								self.trigger && self.trigger('themechange');
 
- 							})
 
- 						});
 
- 					}
 
- 				});
 
- 			} else if (themeid === 'default' && self.theme) {
 
- 				$('head>link.elfinder-theme-ext').remove();
 
- 				self.theme = null;
 
- 				self.trigger && self.trigger('themechange');
 
- 			}
 
- 		}
 
- 		return this;
 
- 	},
 
- 	/**
 
- 	 * Apply leaf root stats to target directory
 
- 	 *
 
- 	 * @param      object     dir     object of target directory
 
- 	 * @param      boolean    update  is force update
 
- 	 * 
 
- 	 * @return     boolean    dir object was chenged 
 
- 	 */
 
- 	applyLeafRootStats : function(dir, update) {
 
- 		var self = this,
 
- 			prev = update? dir : (self.file(dir.hash) || dir),
 
- 			prevTs = prev.ts,
 
- 			change = false;
 
- 		// backup original stats
 
- 		if (update || !dir._realStats) {
 
- 			dir._realStats = {
 
- 				locked: dir.locked || 0,
 
- 				dirs: dir.dirs || 0,
 
- 				ts: dir.ts
 
- 			};
 
- 		}
 
- 		// set lock
 
- 		dir.locked = 1;
 
- 		if (!prev.locked) {
 
- 			change = true;
 
- 		}
 
- 		// has leaf root to `dirs: 1`
 
- 		dir.dirs = 1;
 
- 		if (!prev.dirs) {
 
- 			change = true;
 
- 		}
 
- 		// set ts
 
- 		$.each(self.leafRoots[dir.hash], function() {
 
- 			var f = self.file(this);
 
- 			if (f && f.ts && (dir.ts || 0) < f.ts) {
 
- 				dir.ts = f.ts;
 
- 			}
 
- 		});
 
- 		if (prevTs !== dir.ts) {
 
- 			change = true;
 
- 		}
 
- 		return change;
 
- 	},
 
- 	/**
 
- 	 * To aborted XHR object
 
- 	 * 
 
- 	 * @param Object xhr
 
- 	 * @param Object opts
 
- 	 * 
 
- 	 * @return void
 
- 	 */
 
- 	abortXHR : function(xhr, o) {
 
- 		var opts = o || {};
 
- 		
 
- 		if (xhr) {
 
- 			opts.quiet && (xhr.quiet = true);
 
- 			if (opts.abort && xhr._requestId) {
 
- 				this.request({
 
- 					data: {
 
- 						cmd: 'abort',
 
- 						id: xhr._requestId
 
- 					},
 
- 					preventDefault: true
 
- 				});
 
- 			}
 
- 			xhr.abort();
 
- 			xhr = void 0;
 
- 		}
 
- 	},
 
- 	/**
 
- 	 * Gets the request identifier
 
- 	 *
 
- 	 * @return  String  The request identifier.
 
- 	 */
 
- 	getRequestId : function() {
 
- 		return (+ new Date()).toString(16) + Math.floor(1000 * Math.random()).toString(16);
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Flip key and value of array or object
 
- 	 * 
 
- 	 * @param  Array | Object  { a: 1, b: 1, c: 2 }
 
- 	 * @param  Mixed           Static value
 
- 	 * @return Object          { 1: "b", 2: "c" }
 
- 	 */
 
- 	arrayFlip : function (trans, val) {
 
- 		var key,
 
- 			tmpArr = {},
 
- 			isArr = $.isArray(trans);
 
- 		for (key in trans) {
 
- 			if (isArr || trans.hasOwnProperty(key)) {
 
- 				tmpArr[trans[key]] = val || key;
 
- 			}
 
- 		}
 
- 		return tmpArr;
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Return array ["name without extention", "extention"]
 
- 	 * 
 
- 	 * @param String name
 
- 	 * 
 
- 	 * @return Array
 
- 	 * 
 
- 	 */
 
- 	splitFileExtention : function(name) {
 
- 		var m;
 
- 		if (m = name.match(/^(.+?)?\.((?:tar\.(?:gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(?:gz|bz2)|[a-z0-9]{1,10})$/i)) {
 
- 			if (typeof m[1] === 'undefined') {
 
- 				m[1] = '';
 
- 			}
 
- 			return [m[1], m[2]];
 
- 		} else {
 
- 			return [name, ''];
 
- 		}
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Slice the ArrayBuffer by sliceSize
 
- 	 *
 
- 	 * @param      arraybuffer  arrayBuffer  The array buffer
 
- 	 * @param      Number       sliceSize    The slice size
 
- 	 * @return     Array   Array of sleced arraybuffer
 
- 	 */
 
- 	sliceArrayBuffer : function(arrayBuffer, sliceSize) {
 
- 		var segments= [],
 
- 			fi = 0;
 
- 		while(fi * sliceSize < arrayBuffer.byteLength){
 
- 			segments.push(arrayBuffer.slice(fi * sliceSize, (fi + 1) * sliceSize));
 
- 			fi++;
 
- 		}
 
- 		return segments;
 
- 	},
 
- 	arrayBufferToBase64 : function(ab) {
 
- 		if (!window.btoa) {
 
- 			return '';
 
- 		}
 
- 		var dView = new Uint8Array(ab), // Get a byte view
 
- 			arr = Array.prototype.slice.call(dView), // Create a normal array
 
- 			arr1 = arr.map(function(item) {
 
- 				return String.fromCharCode(item); // Convert
 
- 			});
 
- 	    return window.btoa(arr1.join('')); // Form a string
 
- 	},
 
- 	log : function(m) { window.console && window.console.log && window.console.log(m); return this; },
 
- 	
 
- 	debug : function(type, m) {
 
- 		var d = this.options.debug;
 
- 		if (d && (d === 'all' || d[type])) {
 
- 			window.console && window.console.log && window.console.log('elfinder debug: ['+type+'] ['+this.id+']', m);
 
- 		} 
 
- 		
 
- 		if (type === 'backend-error') {
 
- 			if (! this.cwd().hash || (d && (d === 'all' || d['backend-error']))) {
 
- 				m = Array.isArray(m)? m : [ m ];
 
- 				this.error(m);
 
- 			}
 
- 		} else if (type === 'backend-debug') {
 
- 			this.trigger('backenddebug', m);
 
- 		}
 
- 		
 
- 		return this;
 
- 	},
 
- 	time : function(l) { window.console && window.console.time && window.console.time(l); },
 
- 	timeEnd : function(l) { window.console && window.console.timeEnd && window.console.timeEnd(l); }
 
- 	
 
- };
 
- /**
 
-  * for conpat ex. ie8...
 
-  *
 
-  * Object.keys() - JavaScript | MDN
 
-  * https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
 
-  */
 
- if (!Object.keys) {
 
- 	Object.keys = (function () {
 
- 		var hasOwnProperty = Object.prototype.hasOwnProperty,
 
- 				hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
 
- 				dontEnums = [
 
- 					'toString',
 
- 					'toLocaleString',
 
- 					'valueOf',
 
- 					'hasOwnProperty',
 
- 					'isPrototypeOf',
 
- 					'propertyIsEnumerable',
 
- 					'constructor'
 
- 				],
 
- 				dontEnumsLength = dontEnums.length;
 
- 		return function (obj) {
 
- 			if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');
 
- 			var result = [];
 
- 			for (var prop in obj) {
 
- 				if (hasOwnProperty.call(obj, prop)) result.push(prop);
 
- 			}
 
- 			if (hasDontEnumBug) {
 
- 				for (var i=0; i < dontEnumsLength; i++) {
 
- 					if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
 
- 				}
 
- 			}
 
- 			return result;
 
- 		};
 
- 	})();
 
- }
 
- // Array.isArray
 
- if (!Array.isArray) {
 
- 	Array.isArray = function(arr) {
 
- 		return jQuery.isArray(arr);
 
- 	};
 
- }
 
- // Object.assign
 
- if (!Object.assign) {
 
- 	Object.assign = function() {
 
- 		return jQuery.extend.apply(null, arguments);
 
- 	};
 
- }
 
- // String.repeat
 
- if (!String.prototype.repeat) {
 
- 	String.prototype.repeat = function(count) {
 
- 		'use strict';
 
- 		if (this == null) {
 
- 			throw new TypeError('can\'t convert ' + this + ' to object');
 
- 		}
 
- 		var str = '' + this;
 
- 		count = +count;
 
- 		if (count != count) {
 
- 			count = 0;
 
- 		}
 
- 		if (count < 0) {
 
- 			throw new RangeError('repeat count must be non-negative');
 
- 		}
 
- 		if (count == Infinity) {
 
- 			throw new RangeError('repeat count must be less than infinity');
 
- 		}
 
- 		count = Math.floor(count);
 
- 		if (str.length == 0 || count == 0) {
 
- 			return '';
 
- 		}
 
- 		// Ensuring count is a 31-bit integer allows us to heavily optimize the
 
- 		// main part. But anyway, most current (August 2014) browsers can't handle
 
- 		// strings 1 << 28 chars or longer, so:
 
- 		if (str.length * count >= 1 << 28) {
 
- 			throw new RangeError('repeat count must not overflow maximum string size');
 
- 		}
 
- 		var rpt = '';
 
- 		for (var i = 0; i < count; i++) {
 
- 			rpt += str;
 
- 		}
 
- 		return rpt;
 
- 	};
 
- }
 
- // String.trim
 
- if (!String.prototype.trim) {
 
- 	String.prototype.trim = function() {
 
- 		return this.replace(/^\s+|\s+$/g, '');
 
- 	};
 
- }
 
- // Array.apply
 
- (function () {
 
- 	try {
 
- 		Array.apply(null, {});
 
- 		return;
 
- 	} catch (e) { }
 
- 	var toString = Object.prototype.toString,
 
- 		arrayType = '[object Array]',
 
- 		_apply = Function.prototype.apply,
 
- 		slice = /*@cc_on @if (@_jscript_version <= 5.8)
 
- 			function () {
 
- 				var a = [], i = this.length;
 
- 				while (i-- > 0) a[i] = this[i];
 
- 				return a;
 
- 			}@else@*/Array.prototype.slice/*@end@*/;
 
- 	Function.prototype.apply = function apply(thisArg, argArray) {
 
- 		return _apply.call(this, thisArg,
 
- 			toString.call(argArray) === arrayType ? argArray : slice.call(argArray));
 
- 	};
 
- })();
 
- // Array.from
 
- if (!Array.from) {
 
- 	Array.from = function(obj) {
 
- 		return obj.length === 1 ? [obj[0]] : Array.apply(null, obj);
 
- 	};
 
- }
 
- // window.requestAnimationFrame and window.cancelAnimationFrame
 
- if (!window.cancelAnimationFrame) {
 
- // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 
- // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
 
- // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
 
- // MIT license
 
- (function() {
 
-     var lastTime = 0;
 
-     var vendors = ['ms', 'moz', 'webkit', 'o'];
 
-     for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
 
-         window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
 
-         window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 
 
-                                    || window[vendors[x]+'CancelRequestAnimationFrame'];
 
-     }
 
-  
 
-     if (!window.requestAnimationFrame)
 
-         window.requestAnimationFrame = function(callback, element) {
 
-             var currTime = new Date().getTime();
 
-             var timeToCall = Math.max(0, 16 - (currTime - lastTime));
 
-             var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 
 
-               timeToCall);
 
-             lastTime = currTime + timeToCall;
 
-             return id;
 
-         };
 
-  
 
-     if (!window.cancelAnimationFrame)
 
-         window.cancelAnimationFrame = function(id) {
 
-             clearTimeout(id);
 
-         };
 
- }());
 
- }
 
- /*
 
-  * File: /js/elFinder.version.js
 
-  */
 
- /**
 
-  * Application version
 
-  *
 
-  * @type String
 
-  **/
 
- elFinder.prototype.version = '2.1.43';
 
- /*
 
-  * File: /js/jquery.elfinder.js
 
-  */
 
- /*** jQuery UI droppable performance tune for elFinder ***/
 
- (function(){
 
- if ($.ui) {
 
- 	if ($.ui.ddmanager) {
 
- 		var origin = $.ui.ddmanager.prepareOffsets;
 
- 		$.ui.ddmanager.prepareOffsets = function( t, event ) {
 
- 			var isOutView = function(elem) {
 
- 				if (elem.is(':hidden')) {
 
- 					return true;
 
- 				}
 
- 				var rect = elem[0].getBoundingClientRect();
 
- 				return document.elementFromPoint(rect.left, rect.top)? false : true;
 
- 			};
 
- 			
 
- 			if (event.type === 'mousedown' || t.options.elfRefresh) {
 
- 				var i, d,
 
- 				m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
 
- 				l = m.length;
 
- 				for ( i = 0; i < l; i++ ) {
 
- 					d = m[ i ];
 
- 					if (d.options.autoDisable && (!d.options.disabled || d.options.autoDisable > 1)) {
 
- 						d.options.disabled = isOutView(d.element);
 
- 						d.options.autoDisable = d.options.disabled? 2 : 1;
 
- 					}
 
- 				}
 
- 			}
 
- 			
 
- 			// call origin function
 
- 			return origin( t, event );
 
- 		};
 
- 	}
 
- }
 
- })();
 
-  /**
 
-  *
 
-  * jquery.binarytransport.js
 
-  *
 
-  * @description. jQuery ajax transport for making binary data type requests.
 
-  * @version 1.0 
 
-  * @author Henry Algus <henryalgus@gmail.com>
 
-  *
 
-  */
 
- // use this transport for "binary" data type
 
- $.ajaxTransport('+binary', function(options, originalOptions, jqXHR) {
 
- 	// check for conditions and support for blob / arraybuffer response type
 
- 	if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob)))))
 
- 	{
 
- 		var xhr;
 
- 		return {
 
- 			// create new XMLHttpRequest
 
- 			send: function(headers, callback){
 
- 				// setup all variables
 
- 				xhr = new XMLHttpRequest();
 
- 				var url = options.url,
 
- 					type = options.type,
 
- 					async = options.async || true,
 
- 					// blob or arraybuffer. Default is blob
 
- 					dataType = options.responseType || 'blob',
 
- 					data = options.data || null,
 
- 					username = options.username,
 
- 					password = options.password;
 
- 					
 
- 				xhr.addEventListener('load', function(){
 
- 					var data = {};
 
- 					data[options.dataType] = xhr.response;
 
- 					// make callback and send data
 
- 					callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders());
 
- 				});
 
- 				xhr.open(type, url, async, username, password);
 
- 				
 
- 				// setup custom headers
 
- 				for (var i in headers ) {
 
- 					xhr.setRequestHeader(i, headers[i] );
 
- 				}
 
- 				// setuo xhrFields
 
- 				if (options.xhrFields) {
 
- 					for (var key in options.xhrFields) {
 
- 						if (key in xhr) {
 
- 							xhr[key] = options.xhrFields[key];
 
- 						}
 
- 					}
 
- 				}
 
- 				xhr.responseType = dataType;
 
- 				xhr.send(data);
 
- 			},
 
- 			abort: function(){
 
- 				xhr.abort();
 
- 			}
 
- 		};
 
- 	}
 
- });
 
- /*!
 
-  * jQuery UI Touch Punch 0.2.3
 
-  *
 
-  * Copyright 2011–2014, Dave Furfero
 
-  * Dual licensed under the MIT or GPL Version 2 licenses.
 
-  *
 
-  * Depends:
 
-  *	jquery.ui.widget.js
 
-  *	jquery.ui.mouse.js
 
-  */
 
- (function ($) {
 
-   // Detect touch support
 
-   $.support.touch = 'ontouchend' in document;
 
-   // Ignore browsers without touch support
 
-   if (!$.support.touch) {
 
- 	return;
 
-   }
 
-   var mouseProto = $.ui.mouse.prototype,
 
- 	  _mouseInit = mouseProto._mouseInit,
 
- 	  _mouseDestroy = mouseProto._mouseDestroy,
 
- 	  touchHandled,
 
- 	  posX, posY;
 
-   /**
 
-    * Simulate a mouse event based on a corresponding touch event
 
-    * @param {Object} event A touch event
 
-    * @param {String} simulatedType The corresponding mouse event
 
-    */
 
-   function simulateMouseEvent (event, simulatedType) {
 
- 	// Ignore multi-touch events
 
- 	if (event.originalEvent.touches.length > 1) {
 
- 	  return;
 
- 	}
 
- 	if (! $(event.currentTarget).hasClass('touch-punch-keep-default')) {
 
- 		event.preventDefault();
 
- 	}
 
- 	var touch = event.originalEvent.changedTouches[0],
 
- 		simulatedEvent = document.createEvent('MouseEvents');
 
- 	
 
- 	// Initialize the simulated mouse event using the touch event's coordinates
 
- 	simulatedEvent.initMouseEvent(
 
- 	  simulatedType,	// type
 
- 	  true,				// bubbles					  
 
- 	  true,				// cancelable				  
 
- 	  window,			// view						  
 
- 	  1,				// detail					  
 
- 	  touch.screenX,	// screenX					  
 
- 	  touch.screenY,	// screenY					  
 
- 	  touch.clientX,	// clientX					  
 
- 	  touch.clientY,	// clientY					  
 
- 	  false,			// ctrlKey					  
 
- 	  false,			// altKey					  
 
- 	  false,			// shiftKey					  
 
- 	  false,			// metaKey					  
 
- 	  0,				// button					  
 
- 	  null				// relatedTarget			  
 
- 	);
 
- 	// Dispatch the simulated event to the target element
 
- 	event.target.dispatchEvent(simulatedEvent);
 
-   }
 
-   /**
 
-    * Handle the jQuery UI widget's touchstart events
 
-    * @param {Object} event The widget element's touchstart event
 
-    */
 
-   mouseProto._touchStart = function (event) {
 
- 	var self = this;
 
- 	// Ignore the event if another widget is already being handled
 
- 	if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) {
 
- 	  return;
 
- 	}
 
- 	// Track element position to avoid "false" move
 
- 	posX = event.originalEvent.changedTouches[0].screenX.toFixed(0);
 
- 	posY = event.originalEvent.changedTouches[0].screenY.toFixed(0);
 
- 	// Set the flag to prevent other widgets from inheriting the touch event
 
- 	touchHandled = true;
 
- 	// Track movement to determine if interaction was a click
 
- 	self._touchMoved = false;
 
- 	// Simulate the mouseover event
 
- 	simulateMouseEvent(event, 'mouseover');
 
- 	// Simulate the mousemove event
 
- 	simulateMouseEvent(event, 'mousemove');
 
- 	// Simulate the mousedown event
 
- 	simulateMouseEvent(event, 'mousedown');
 
-   };
 
-   /**
 
-    * Handle the jQuery UI widget's touchmove events
 
-    * @param {Object} event The document's touchmove event
 
-    */
 
-   mouseProto._touchMove = function (event) {
 
- 	// Ignore event if not handled
 
- 	if (!touchHandled) {
 
- 	  return;
 
- 	}
 
- 	// Ignore if it's a "false" move (position not changed)
 
- 	var x = event.originalEvent.changedTouches[0].screenX.toFixed(0);
 
- 	var y = event.originalEvent.changedTouches[0].screenY.toFixed(0);
 
- 	// Ignore if it's a "false" move (position not changed)
 
- 	if (Math.abs(posX - x) <= 4 && Math.abs(posY - y) <= 4) {
 
- 		return;
 
- 	}
 
- 	// Interaction was not a click
 
- 	this._touchMoved = true;
 
- 	// Simulate the mousemove event
 
- 	simulateMouseEvent(event, 'mousemove');
 
-   };
 
-   /**
 
-    * Handle the jQuery UI widget's touchend events
 
-    * @param {Object} event The document's touchend event
 
-    */
 
-   mouseProto._touchEnd = function (event) {
 
- 	// Ignore event if not handled
 
- 	if (!touchHandled) {
 
- 	  return;
 
- 	}
 
- 	// Simulate the mouseup event
 
- 	simulateMouseEvent(event, 'mouseup');
 
- 	// Simulate the mouseout event
 
- 	simulateMouseEvent(event, 'mouseout');
 
- 	// If the touch interaction did not move, it should trigger a click
 
- 	if (!this._touchMoved) {
 
- 	  // Simulate the click event
 
- 	  simulateMouseEvent(event, 'click');
 
- 	}
 
- 	// Unset the flag to allow other widgets to inherit the touch event
 
- 	touchHandled = false;
 
- 	this._touchMoved = false;
 
-   };
 
-   /**
 
-    * A duck punch of the $.ui.mouse _mouseInit method to support touch events.
 
-    * This method extends the widget with bound touch event handlers that
 
-    * translate touch events to mouse events and pass them to the widget's
 
-    * original mouse event handling methods.
 
-    */
 
-   mouseProto._mouseInit = function () {
 
- 	
 
- 	var self = this;
 
- 	if (self.element.hasClass('touch-punch')) {
 
- 		// Delegate the touch handlers to the widget's element
 
- 		self.element.on({
 
- 		  touchstart: $.proxy(self, '_touchStart'),
 
- 		  touchmove: $.proxy(self, '_touchMove'),
 
- 		  touchend: $.proxy(self, '_touchEnd')
 
- 		});
 
- 	}
 
- 	// Call the original $.ui.mouse init method
 
- 	_mouseInit.call(self);
 
-   };
 
-   /**
 
-    * Remove the touch event handlers
 
-    */
 
-   mouseProto._mouseDestroy = function () {
 
- 	
 
- 	var self = this;
 
- 	if (self.element.hasClass('touch-punch')) {
 
- 		// Delegate the touch handlers to the widget's element
 
- 		self.element.off({
 
- 		  touchstart: $.proxy(self, '_touchStart'),
 
- 		  touchmove: $.proxy(self, '_touchMove'),
 
- 		  touchend: $.proxy(self, '_touchEnd')
 
- 		});
 
- 	}
 
- 	// Call the original $.ui.mouse destroy method
 
- 	_mouseDestroy.call(self);
 
-   };
 
- })(jQuery);
 
- $.fn.elfinder = function(o, o2) {
 
- 	
 
- 	if (o === 'instance') {
 
- 		return this.getElFinder();
 
- 	}
 
- 	
 
- 	return this.each(function() {
 
- 		
 
- 		var cmd          = typeof o  === 'string'  ? o  : '',
 
- 			bootCallback = typeof o2 === 'function'? o2 : void(0),
 
- 			opts;
 
- 		
 
- 		if (!this.elfinder) {
 
- 			if ($.isPlainObject(o)) {
 
- 				new elFinder(this, o, bootCallback);
 
- 			}
 
- 		} else {
 
- 			switch(cmd) {
 
- 				case 'close':
 
- 				case 'hide':
 
- 					this.elfinder.hide();
 
- 					break;
 
- 					
 
- 				case 'open':
 
- 				case 'show':
 
- 					this.elfinder.show();
 
- 					break;
 
- 					
 
- 				case 'destroy':
 
- 					this.elfinder.destroy();
 
- 					break;
 
- 				
 
- 				case 'reload':
 
- 				case 'restart':
 
- 					if (this.elfinder) {
 
- 						opts = this.elfinder.options;
 
- 						bootCallback = this.elfinder.bootCallback;
 
- 						this.elfinder.destroy();
 
- 						new elFinder(this, $.extend(true, opts, $.isPlainObject(o2)? o2 : {}), bootCallback);
 
- 					}
 
- 					break;
 
- 			}
 
- 		}
 
- 	});
 
- };
 
- $.fn.getElFinder = function() {
 
- 	var instance;
 
- 	
 
- 	this.each(function() {
 
- 		if (this.elfinder) {
 
- 			instance = this.elfinder;
 
- 			return false;
 
- 		}
 
- 	});
 
- 	
 
- 	return instance;
 
- };
 
- $.fn.elfUiWidgetInstance = function(name) {
 
- 	try {
 
- 		return this[name]('instance');
 
- 	} catch(e) {
 
- 		// fallback for jQuery UI < 1.11
 
- 		var data = this.data('ui-' + name);
 
- 		if (data && typeof data === 'object' && data.widgetFullName === 'ui-' + name) {
 
- 			return data;
 
- 		}
 
- 		return null;
 
- 	}
 
- };
 
- // function scrollRight
 
- if (! $.fn.scrollRight) {
 
- 	$.fn.extend({
 
- 		scrollRight: function (val) {
 
- 			var node = this.get(0);
 
- 			if (val === undefined) {
 
- 				return Math.max(0, node.scrollWidth - (node.scrollLeft + node.clientWidth));
 
- 			}
 
- 			return this.scrollLeft(node.scrollWidth - node.clientWidth - val);
 
- 		}
 
- 	});
 
- }
 
- // function scrollBottom
 
- if (! $.fn.scrollBottom) {
 
- 	$.fn.extend({
 
- 		scrollBottom: function(val) { 
 
- 			var node = this.get(0);
 
- 			if (val === undefined) {
 
- 				return Math.max(0, node.scrollHeight - (node.scrollTop + node.clientHeight));
 
- 			}
 
- 			return this.scrollTop(node.scrollHeight - node.clientHeight - val);
 
- 		}
 
- 	});
 
- }
 
- /*
 
-  * File: /js/elFinder.mimetypes.js
 
-  */
 
- elFinder.prototype.mimeTypes = {"application\/x-executable":"exe","application\/x-jar":"jar","application\/x-gzip":"gz","application\/x-bzip2":"tbz","application\/x-rar":"rar","text\/x-php":"php","text\/javascript":"js","application\/rtfd":"rtfd","text\/x-python":"py","text\/x-ruby":"rb","text\/x-shellscript":"sh","text\/x-perl":"pl","text\/xml":"xml","text\/x-csrc":"c","text\/x-chdr":"h","text\/x-c++src":"cpp","text\/x-c++hdr":"hh","text\/x-markdown":"md","text\/x-yaml":"yml","image\/x-ms-bmp":"bmp","image\/x-targa":"tga","image\/xbm":"xbm","image\/pxm":"pxm","audio\/wav":"wav","video\/x-dv":"dv","video\/x-ms-wmv":"wm","video\/ogg":"ogm","video\/MP2T":"m2ts","application\/x-mpegURL":"m3u8","application\/dash+xml":"mpd","application\/andrew-inset":"ez","application\/applixware":"aw","application\/atom+xml":"atom","application\/atomcat+xml":"atomcat","application\/atomsvc+xml":"atomsvc","application\/ccxml+xml":"ccxml","application\/cdmi-capability":"cdmia","application\/cdmi-container":"cdmic","application\/cdmi-domain":"cdmid","application\/cdmi-object":"cdmio","application\/cdmi-queue":"cdmiq","application\/cu-seeme":"cu","application\/davmount+xml":"davmount","application\/docbook+xml":"dbk","application\/dssc+der":"dssc","application\/dssc+xml":"xdssc","application\/ecmascript":"ecma","application\/emma+xml":"emma","application\/epub+zip":"epub","application\/exi":"exi","application\/font-tdpfr":"pfr","application\/gml+xml":"gml","application\/gpx+xml":"gpx","application\/gxf":"gxf","application\/hyperstudio":"stk","application\/inkml+xml":"ink","application\/ipfix":"ipfix","application\/java-serialized-object":"ser","application\/java-vm":"class","application\/json":"json","application\/jsonml+json":"jsonml","application\/lost+xml":"lostxml","application\/mac-binhex40":"hqx","application\/mac-compactpro":"cpt","application\/mads+xml":"mads","application\/marc":"mrc","application\/marcxml+xml":"mrcx","application\/mathematica":"ma","application\/mathml+xml":"mathml","application\/mbox":"mbox","application\/mediaservercontrol+xml":"mscml","application\/metalink+xml":"metalink","application\/metalink4+xml":"meta4","application\/mets+xml":"mets","application\/mods+xml":"mods","application\/mp21":"m21","application\/mp4":"mp4s","application\/msword":"doc","application\/mxf":"mxf","application\/octet-stream":"bin","application\/oda":"oda","application\/oebps-package+xml":"opf","application\/ogg":"ogx","application\/omdoc+xml":"omdoc","application\/onenote":"onetoc","application\/oxps":"oxps","application\/patch-ops-error+xml":"xer","application\/pdf":"pdf","application\/pgp-encrypted":"pgp","application\/pgp-signature":"asc","application\/pics-rules":"prf","application\/pkcs10":"p10","application\/pkcs7-mime":"p7m","application\/pkcs7-signature":"p7s","application\/pkcs8":"p8","application\/pkix-attr-cert":"ac","application\/pkix-cert":"cer","application\/pkix-crl":"crl","application\/pkix-pkipath":"pkipath","application\/pkixcmp":"pki","application\/pls+xml":"pls","application\/postscript":"ai","application\/prs.cww":"cww","application\/pskc+xml":"pskcxml","application\/rdf+xml":"rdf","application\/reginfo+xml":"rif","application\/relax-ng-compact-syntax":"rnc","application\/resource-lists+xml":"rl","application\/resource-lists-diff+xml":"rld","application\/rls-services+xml":"rs","application\/rpki-ghostbusters":"gbr","application\/rpki-manifest":"mft","application\/rpki-roa":"roa","application\/rsd+xml":"rsd","application\/rss+xml":"rss","application\/rtf":"rtf","application\/sbml+xml":"sbml","application\/scvp-cv-request":"scq","application\/scvp-cv-response":"scs","application\/scvp-vp-request":"spq","application\/scvp-vp-response":"spp","application\/sdp":"sdp","application\/set-payment-initiation":"setpay","application\/set-registration-initiation":"setreg","application\/shf+xml":"shf","application\/smil+xml":"smi","application\/sparql-query":"rq","application\/sparql-results+xml":"srx","application\/srgs":"gram","application\/srgs+xml":"grxml","application\/sru+xml":"sru","application\/ssdl+xml":"ssdl","application\/ssml+xml":"ssml","application\/tei+xml":"tei","application\/thraud+xml":"tfi","application\/timestamped-data":"tsd","application\/vnd.3gpp.pic-bw-large":"plb","application\/vnd.3gpp.pic-bw-small":"psb","application\/vnd.3gpp.pic-bw-var":"pvb","application\/vnd.3gpp2.tcap":"tcap","application\/vnd.3m.post-it-notes":"pwn","application\/vnd.accpac.simply.aso":"aso","application\/vnd.accpac.simply.imp":"imp","application\/vnd.acucobol":"acu","application\/vnd.acucorp":"atc","application\/vnd.adobe.air-application-installer-package+zip":"air","application\/vnd.adobe.formscentral.fcdt":"fcdt","application\/vnd.adobe.fxp":"fxp","application\/vnd.adobe.xdp+xml":"xdp","application\/vnd.adobe.xfdf":"xfdf","application\/vnd.ahead.space":"ahead","application\/vnd.airzip.filesecure.azf":"azf","application\/vnd.airzip.filesecure.azs":"azs","application\/vnd.amazon.ebook":"azw","application\/vnd.americandynamics.acc":"acc","application\/vnd.amiga.ami":"ami","application\/vnd.android.package-archive":"apk","application\/vnd.anser-web-certificate-issue-initiation":"cii","application\/vnd.anser-web-funds-transfer-initiation":"fti","application\/vnd.antix.game-component":"atx","application\/vnd.apple.installer+xml":"mpkg","application\/vnd.aristanetworks.swi":"swi","application\/vnd.astraea-software.iota":"iota","application\/vnd.audiograph":"aep","application\/vnd.blueice.multipass":"mpm","application\/vnd.bmi":"bmi","application\/vnd.businessobjects":"rep","application\/vnd.chemdraw+xml":"cdxml","application\/vnd.chipnuts.karaoke-mmd":"mmd","application\/vnd.cinderella":"cdy","application\/vnd.claymore":"cla","application\/vnd.cloanto.rp9":"rp9","application\/vnd.clonk.c4group":"c4g","application\/vnd.cluetrust.cartomobile-config":"c11amc","application\/vnd.cluetrust.cartomobile-config-pkg":"c11amz","application\/vnd.commonspace":"csp","application\/vnd.contact.cmsg":"cdbcmsg","application\/vnd.cosmocaller":"cmc","application\/vnd.crick.clicker":"clkx","application\/vnd.crick.clicker.keyboard":"clkk","application\/vnd.crick.clicker.palette":"clkp","application\/vnd.crick.clicker.template":"clkt","application\/vnd.crick.clicker.wordbank":"clkw","application\/vnd.criticaltools.wbs+xml":"wbs","application\/vnd.ctc-posml":"pml","application\/vnd.cups-ppd":"ppd","application\/vnd.curl.car":"car","application\/vnd.curl.pcurl":"pcurl","application\/vnd.dart":"dart","application\/vnd.data-vision.rdz":"rdz","application\/vnd.dece.data":"uvf","application\/vnd.dece.ttml+xml":"uvt","application\/vnd.dece.unspecified":"uvx","application\/vnd.dece.zip":"uvz","application\/vnd.denovo.fcselayout-link":"fe_launch","application\/vnd.dna":"dna","application\/vnd.dolby.mlp":"mlp","application\/vnd.dpgraph":"dpg","application\/vnd.dreamfactory":"dfac","application\/vnd.ds-keypoint":"kpxx","application\/vnd.dvb.ait":"ait","application\/vnd.dvb.service":"svc","application\/vnd.dynageo":"geo","application\/vnd.ecowin.chart":"mag","application\/vnd.enliven":"nml","application\/vnd.epson.esf":"esf","application\/vnd.epson.msf":"msf","application\/vnd.epson.quickanime":"qam","application\/vnd.epson.salt":"slt","application\/vnd.epson.ssf":"ssf","application\/vnd.eszigno3+xml":"es3","application\/vnd.ezpix-album":"ez2","application\/vnd.ezpix-package":"ez3","application\/vnd.fdf":"fdf","application\/vnd.fdsn.mseed":"mseed","application\/vnd.fdsn.seed":"seed","application\/vnd.flographit":"gph","application\/vnd.fluxtime.clip":"ftc","application\/vnd.framemaker":"fm","application\/vnd.frogans.fnc":"fnc","application\/vnd.frogans.ltf":"ltf","application\/vnd.fsc.weblaunch":"fsc","application\/vnd.fujitsu.oasys":"oas","application\/vnd.fujitsu.oasys2":"oa2","application\/vnd.fujitsu.oasys3":"oa3","application\/vnd.fujitsu.oasysgp":"fg5","application\/vnd.fujitsu.oasysprs":"bh2","application\/vnd.fujixerox.ddd":"ddd","application\/vnd.fujixerox.docuworks":"xdw","application\/vnd.fujixerox.docuworks.binder":"xbd","application\/vnd.fuzzysheet":"fzs","application\/vnd.genomatix.tuxedo":"txd","application\/vnd.geogebra.file":"ggb","application\/vnd.geogebra.tool":"ggt","application\/vnd.geometry-explorer":"gex","application\/vnd.geonext":"gxt","application\/vnd.geoplan":"g2w","application\/vnd.geospace":"g3w","application\/vnd.gmx":"gmx","application\/vnd.google-earth.kml+xml":"kml","application\/vnd.google-earth.kmz":"kmz","application\/vnd.grafeq":"gqf","application\/vnd.groove-account":"gac","application\/vnd.groove-help":"ghf","application\/vnd.groove-identity-message":"gim","application\/vnd.groove-injector":"grv","application\/vnd.groove-tool-message":"gtm","application\/vnd.groove-tool-template":"tpl","application\/vnd.groove-vcard":"vcg","application\/vnd.hal+xml":"hal","application\/vnd.handheld-entertainment+xml":"zmm","application\/vnd.hbci":"hbci","application\/vnd.hhe.lesson-player":"les","application\/vnd.hp-hpgl":"hpgl","application\/vnd.hp-hpid":"hpid","application\/vnd.hp-hps":"hps","application\/vnd.hp-jlyt":"jlt","application\/vnd.hp-pcl":"pcl","application\/vnd.hp-pclxl":"pclxl","application\/vnd.hydrostatix.sof-data":"sfd-hdstx","application\/vnd.ibm.minipay":"mpy","application\/vnd.ibm.modcap":"afp","application\/vnd.ibm.rights-management":"irm","application\/vnd.ibm.secure-container":"sc","application\/vnd.iccprofile":"icc","application\/vnd.igloader":"igl","application\/vnd.immervision-ivp":"ivp","application\/vnd.immervision-ivu":"ivu","application\/vnd.insors.igm":"igm","application\/vnd.intercon.formnet":"xpw","application\/vnd.intergeo":"i2g","application\/vnd.intu.qbo":"qbo","application\/vnd.intu.qfx":"qfx","application\/vnd.ipunplugged.rcprofile":"rcprofile","application\/vnd.irepository.package+xml":"irp","application\/vnd.is-xpr":"xpr","application\/vnd.isac.fcs":"fcs","application\/vnd.jam":"jam","application\/vnd.jcp.javame.midlet-rms":"rms","application\/vnd.jisp":"jisp","application\/vnd.joost.joda-archive":"joda","application\/vnd.kahootz":"ktz","application\/vnd.kde.karbon":"karbon","application\/vnd.kde.kchart":"chrt","application\/vnd.kde.kformula":"kfo","application\/vnd.kde.kivio":"flw","application\/vnd.kde.kontour":"kon","application\/vnd.kde.kpresenter":"kpr","application\/vnd.kde.kspread":"ksp","application\/vnd.kde.kword":"kwd","application\/vnd.kenameaapp":"htke","application\/vnd.kidspiration":"kia","application\/vnd.kinar":"kne","application\/vnd.koan":"skp","application\/vnd.kodak-descriptor":"sse","application\/vnd.las.las+xml":"lasxml","application\/vnd.llamagraphics.life-balance.desktop":"lbd","application\/vnd.llamagraphics.life-balance.exchange+xml":"lbe","application\/vnd.lotus-1-2-3":123,"application\/vnd.lotus-approach":"apr","application\/vnd.lotus-freelance":"pre","application\/vnd.lotus-notes":"nsf","application\/vnd.lotus-organizer":"org","application\/vnd.lotus-screencam":"scm","application\/vnd.lotus-wordpro":"lwp","application\/vnd.macports.portpkg":"portpkg","application\/vnd.mcd":"mcd","application\/vnd.medcalcdata":"mc1","application\/vnd.mediastation.cdkey":"cdkey","application\/vnd.mfer":"mwf","application\/vnd.mfmp":"mfm","application\/vnd.micrografx.flo":"flo","application\/vnd.micrografx.igx":"igx","application\/vnd.mif":"mif","application\/vnd.mobius.daf":"daf","application\/vnd.mobius.dis":"dis","application\/vnd.mobius.mbk":"mbk","application\/vnd.mobius.mqy":"mqy","application\/vnd.mobius.msl":"msl","application\/vnd.mobius.plc":"plc","application\/vnd.mobius.txf":"txf","application\/vnd.mophun.application":"mpn","application\/vnd.mophun.certificate":"mpc","application\/vnd.mozilla.xul+xml":"xul","application\/vnd.ms-artgalry":"cil","application\/vnd.ms-cab-compressed":"cab","application\/vnd.ms-excel":"xls","application\/vnd.ms-excel.addin.macroenabled.12":"xlam","application\/vnd.ms-excel.sheet.binary.macroenabled.12":"xlsb","application\/vnd.ms-excel.sheet.macroenabled.12":"xlsm","application\/vnd.ms-excel.template.macroenabled.12":"xltm","application\/vnd.ms-fontobject":"eot","application\/vnd.ms-htmlhelp":"chm","application\/vnd.ms-ims":"ims","application\/vnd.ms-lrm":"lrm","application\/vnd.ms-officetheme":"thmx","application\/vnd.ms-pki.seccat":"cat","application\/vnd.ms-pki.stl":"stl","application\/vnd.ms-powerpoint":"ppt","application\/vnd.ms-powerpoint.addin.macroenabled.12":"ppam","application\/vnd.ms-powerpoint.presentation.macroenabled.12":"pptm","application\/vnd.ms-powerpoint.slide.macroenabled.12":"sldm","application\/vnd.ms-powerpoint.slideshow.macroenabled.12":"ppsm","application\/vnd.ms-powerpoint.template.macroenabled.12":"potm","application\/vnd.ms-project":"mpp","application\/vnd.ms-word.document.macroenabled.12":"docm","application\/vnd.ms-word.template.macroenabled.12":"dotm","application\/vnd.ms-works":"wps","application\/vnd.ms-wpl":"wpl","application\/vnd.ms-xpsdocument":"xps","application\/vnd.mseq":"mseq","application\/vnd.musician":"mus","application\/vnd.muvee.style":"msty","application\/vnd.mynfc":"taglet","application\/vnd.neurolanguage.nlu":"nlu","application\/vnd.nitf":"ntf","application\/vnd.noblenet-directory":"nnd","application\/vnd.noblenet-sealer":"nns","application\/vnd.noblenet-web":"nnw","application\/vnd.nokia.n-gage.data":"ngdat","application\/vnd.nokia.n-gage.symbian.install":"n-gage","application\/vnd.nokia.radio-preset":"rpst","application\/vnd.nokia.radio-presets":"rpss","application\/vnd.novadigm.edm":"edm","application\/vnd.novadigm.edx":"edx","application\/vnd.novadigm.ext":"ext","application\/vnd.oasis.opendocument.chart":"odc","application\/vnd.oasis.opendocument.chart-template":"otc","application\/vnd.oasis.opendocument.database":"odb","application\/vnd.oasis.opendocument.formula":"odf","application\/vnd.oasis.opendocument.formula-template":"odft","application\/vnd.oasis.opendocument.graphics":"odg","application\/vnd.oasis.opendocument.graphics-template":"otg","application\/vnd.oasis.opendocument.image":"odi","application\/vnd.oasis.opendocument.image-template":"oti","application\/vnd.oasis.opendocument.presentation":"odp","application\/vnd.oasis.opendocument.presentation-template":"otp","application\/vnd.oasis.opendocument.spreadsheet":"ods","application\/vnd.oasis.opendocument.spreadsheet-template":"ots","application\/vnd.oasis.opendocument.text":"odt","application\/vnd.oasis.opendocument.text-master":"odm","application\/vnd.oasis.opendocument.text-template":"ott","application\/vnd.oasis.opendocument.text-web":"oth","application\/vnd.olpc-sugar":"xo","application\/vnd.oma.dd2+xml":"dd2","application\/vnd.openofficeorg.extension":"oxt","application\/vnd.openxmlformats-officedocument.presentationml.presentation":"pptx","application\/vnd.openxmlformats-officedocument.presentationml.slide":"sldx","application\/vnd.openxmlformats-officedocument.presentationml.slideshow":"ppsx","application\/vnd.openxmlformats-officedocument.presentationml.template":"potx","application\/vnd.openxmlformats-officedocument.spreadsheetml.sheet":"xlsx","application\/vnd.openxmlformats-officedocument.spreadsheetml.template":"xltx","application\/vnd.openxmlformats-officedocument.wordprocessingml.document":"docx","application\/vnd.openxmlformats-officedocument.wordprocessingml.template":"dotx","application\/vnd.osgeo.mapguide.package":"mgp","application\/vnd.osgi.dp":"dp","application\/vnd.osgi.subsystem":"esa","application\/vnd.palm":"pdb","application\/vnd.pawaafile":"paw","application\/vnd.pg.format":"str","application\/vnd.pg.osasli":"ei6","application\/vnd.picsel":"efif","application\/vnd.pmi.widget":"wg","application\/vnd.pocketlearn":"plf","application\/vnd.powerbuilder6":"pbd","application\/vnd.previewsystems.box":"box","application\/vnd.proteus.magazine":"mgz","application\/vnd.publishare-delta-tree":"qps","application\/vnd.pvi.ptid1":"ptid","application\/vnd.quark.quarkxpress":"qxd","application\/vnd.realvnc.bed":"bed","application\/vnd.recordare.musicxml":"mxl","application\/vnd.recordare.musicxml+xml":"musicxml","application\/vnd.rig.cryptonote":"cryptonote","application\/vnd.rim.cod":"cod","application\/vnd.rn-realmedia":"rm","application\/vnd.rn-realmedia-vbr":"rmvb","application\/vnd.route66.link66+xml":"link66","application\/vnd.sailingtracker.track":"st","application\/vnd.seemail":"see","application\/vnd.sema":"sema","application\/vnd.semd":"semd","application\/vnd.semf":"semf","application\/vnd.shana.informed.formdata":"ifm","application\/vnd.shana.informed.formtemplate":"itp","application\/vnd.shana.informed.interchange":"iif","application\/vnd.shana.informed.package":"ipk","application\/vnd.simtech-mindmapper":"twd","application\/vnd.smaf":"mmf","application\/vnd.smart.teacher":"teacher","application\/vnd.solent.sdkm+xml":"sdkm","application\/vnd.spotfire.dxp":"dxp","application\/vnd.spotfire.sfs":"sfs","application\/vnd.stardivision.calc":"sdc","application\/vnd.stardivision.draw":"sda","application\/vnd.stardivision.impress":"sdd","application\/vnd.stardivision.math":"smf","application\/vnd.stardivision.writer":"sdw","application\/vnd.stardivision.writer-global":"sgl","application\/vnd.stepmania.package":"smzip","application\/vnd.stepmania.stepchart":"sm","application\/vnd.sun.xml.calc":"sxc","application\/vnd.sun.xml.calc.template":"stc","application\/vnd.sun.xml.draw":"sxd","application\/vnd.sun.xml.draw.template":"std","application\/vnd.sun.xml.impress":"sxi","application\/vnd.sun.xml.impress.template":"sti","application\/vnd.sun.xml.math":"sxm","application\/vnd.sun.xml.writer":"sxw","application\/vnd.sun.xml.writer.global":"sxg","application\/vnd.sun.xml.writer.template":"stw","application\/vnd.sus-calendar":"sus","application\/vnd.svd":"svd","application\/vnd.symbian.install":"sis","application\/vnd.syncml+xml":"xsm","application\/vnd.syncml.dm+wbxml":"bdm","application\/vnd.syncml.dm+xml":"xdm","application\/vnd.tao.intent-module-archive":"tao","application\/vnd.tcpdump.pcap":"pcap","application\/vnd.tmobile-livetv":"tmo","application\/vnd.trid.tpt":"tpt","application\/vnd.triscape.mxs":"mxs","application\/vnd.trueapp":"tra","application\/vnd.ufdl":"ufd","application\/vnd.uiq.theme":"utz","application\/vnd.umajin":"umj","application\/vnd.unity":"unityweb","application\/vnd.uoml+xml":"uoml","application\/vnd.vcx":"vcx","application\/vnd.visio":"vsd","application\/vnd.visionary":"vis","application\/vnd.vsf":"vsf","application\/vnd.wap.wbxml":"wbxml","application\/vnd.wap.wmlc":"wmlc","application\/vnd.wap.wmlscriptc":"wmlsc","application\/vnd.webturbo":"wtb","application\/vnd.wolfram.player":"nbp","application\/vnd.wordperfect":"wpd","application\/vnd.wqd":"wqd","application\/vnd.wt.stf":"stf","application\/vnd.xara":"xar","application\/vnd.xfdl":"xfdl","application\/vnd.yamaha.hv-dic":"hvd","application\/vnd.yamaha.hv-script":"hvs","application\/vnd.yamaha.hv-voice":"hvp","application\/vnd.yamaha.openscoreformat":"osf","application\/vnd.yamaha.openscoreformat.osfpvg+xml":"osfpvg","application\/vnd.yamaha.smaf-audio":"saf","application\/vnd.yamaha.smaf-phrase":"spf","application\/vnd.yellowriver-custom-menu":"cmp","application\/vnd.zul":"zir","application\/vnd.zzazz.deck+xml":"zaz","application\/voicexml+xml":"vxml","application\/widget":"wgt","application\/winhlp":"hlp","application\/wsdl+xml":"wsdl","application\/wspolicy+xml":"wspolicy","application\/x-7z-compressed":"7z","application\/x-abiword":"abw","application\/x-ace-compressed":"ace","application\/x-apple-diskimage":"dmg","application\/x-authorware-bin":"aab","application\/x-authorware-map":"aam","application\/x-authorware-seg":"aas","application\/x-bcpio":"bcpio","application\/x-bittorrent":"torrent","application\/x-blorb":"blb","application\/x-bzip":"bz","application\/x-cbr":"cbr","application\/x-cdlink":"vcd","application\/x-cfs-compressed":"cfs","application\/x-chat":"chat","application\/x-chess-pgn":"pgn","application\/x-conference":"nsc","application\/x-cpio":"cpio","application\/x-csh":"csh","application\/x-debian-package":"deb","application\/x-dgc-compressed":"dgc","application\/x-director":"dir","application\/x-doom":"wad","application\/x-dtbncx+xml":"ncx","application\/x-dtbook+xml":"dtb","application\/x-dtbresource+xml":"res","application\/x-dvi":"dvi","application\/x-envoy":"evy","application\/x-eva":"eva","application\/x-font-bdf":"bdf","application\/x-font-ghostscript":"gsf","application\/x-font-linux-psf":"psf","application\/x-font-pcf":"pcf","application\/x-font-snf":"snf","application\/x-font-type1":"pfa","application\/x-freearc":"arc","application\/x-futuresplash":"spl","application\/x-gca-compressed":"gca","application\/x-glulx":"ulx","application\/x-gnumeric":"gnumeric","application\/x-gramps-xml":"gramps","application\/x-gtar":"gtar","application\/x-hdf":"hdf","application\/x-install-instructions":"install","application\/x-iso9660-image":"iso","application\/x-java-jnlp-file":"jnlp","application\/x-latex":"latex","application\/x-lzh-compressed":"lzh","application\/x-mie":"mie","application\/x-mobipocket-ebook":"prc","application\/x-ms-application":"application","application\/x-ms-shortcut":"lnk","application\/x-ms-wmd":"wmd","application\/x-ms-wmz":"wmz","application\/x-ms-xbap":"xbap","application\/x-msaccess":"mdb","application\/x-msbinder":"obd","application\/x-mscardfile":"crd","application\/x-msclip":"clp","application\/x-msdownload":"dll","application\/x-msmediaview":"mvb","application\/x-msmetafile":"wmf","application\/x-msmoney":"mny","application\/x-mspublisher":"pub","application\/x-msschedule":"scd","application\/x-msterminal":"trm","application\/x-mswrite":"wri","application\/x-netcdf":"nc","application\/x-nzb":"nzb","application\/x-pkcs12":"p12","application\/x-pkcs7-certificates":"p7b","application\/x-pkcs7-certreqresp":"p7r","application\/x-research-info-systems":"ris","application\/x-shar":"shar","application\/x-shockwave-flash":"swf","application\/x-silverlight-app":"xap","application\/x-sql":"sql","application\/x-stuffit":"sit","application\/x-stuffitx":"sitx","application\/x-subrip":"srt","application\/x-sv4cpio":"sv4cpio","application\/x-sv4crc":"sv4crc","application\/x-t3vm-image":"t3","application\/x-tads":"gam","application\/x-tar":"tar","application\/x-tcl":"tcl","application\/x-tex":"tex","application\/x-tex-tfm":"tfm","application\/x-texinfo":"texinfo","application\/x-tgif":"obj","application\/x-ustar":"ustar","application\/x-wais-source":"src","application\/x-x509-ca-cert":"der","application\/x-xfig":"fig","application\/x-xliff+xml":"xlf","application\/x-xpinstall":"xpi","application\/x-xz":"xz","application\/x-zmachine":"z1","application\/xaml+xml":"xaml","application\/xcap-diff+xml":"xdf","application\/xenc+xml":"xenc","application\/xhtml+xml":"xhtml","application\/xml":"xsl","application\/xml-dtd":"dtd","application\/xop+xml":"xop","application\/xproc+xml":"xpl","application\/xslt+xml":"xslt","application\/xspf+xml":"xspf","application\/xv+xml":"mxml","application\/yang":"yang","application\/yin+xml":"yin","application\/zip":"zip","audio\/adpcm":"adp","audio\/basic":"au","audio\/midi":"mid","audio\/mp4":"m4a","audio\/mpeg":"mpga","audio\/ogg":"oga","audio\/s3m":"s3m","audio\/silk":"sil","audio\/vnd.dece.audio":"uva","audio\/vnd.digital-winds":"eol","audio\/vnd.dra":"dra","audio\/vnd.dts":"dts","audio\/vnd.dts.hd":"dtshd","audio\/vnd.lucent.voice":"lvp","audio\/vnd.ms-playready.media.pya":"pya","audio\/vnd.nuera.ecelp4800":"ecelp4800","audio\/vnd.nuera.ecelp7470":"ecelp7470","audio\/vnd.nuera.ecelp9600":"ecelp9600","audio\/vnd.rip":"rip","audio\/webm":"weba","audio\/x-aac":"aac","audio\/x-aiff":"aif","audio\/x-caf":"caf","audio\/x-flac":"flac","audio\/x-matroska":"mka","audio\/x-mpegurl":"m3u","audio\/x-ms-wax":"wax","audio\/x-ms-wma":"wma","audio\/x-pn-realaudio":"ram","audio\/x-pn-realaudio-plugin":"rmp","audio\/xm":"xm","chemical\/x-cdx":"cdx","chemical\/x-cif":"cif","chemical\/x-cmdf":"cmdf","chemical\/x-cml":"cml","chemical\/x-csml":"csml","chemical\/x-xyz":"xyz","font\/collection":"ttc","font\/otf":"otf","font\/ttf":"ttf","font\/woff":"woff","font\/woff2":"woff2","image\/cgm":"cgm","image\/g3fax":"g3","image\/gif":"gif","image\/ief":"ief","image\/jpeg":"jpeg","image\/ktx":"ktx","image\/png":"png","image\/prs.btif":"btif","image\/sgi":"sgi","image\/svg+xml":"svg","image\/tiff":"tiff","image\/vnd.adobe.photoshop":"psd","image\/vnd.dece.graphic":"uvi","image\/vnd.djvu":"djvu","image\/vnd.dvb.subtitle":"sub","image\/vnd.dwg":"dwg","image\/vnd.dxf":"dxf","image\/vnd.fastbidsheet":"fbs","image\/vnd.fpx":"fpx","image\/vnd.fst":"fst","image\/vnd.fujixerox.edmics-mmr":"mmr","image\/vnd.fujixerox.edmics-rlc":"rlc","image\/vnd.ms-modi":"mdi","image\/vnd.ms-photo":"wdp","image\/vnd.net-fpx":"npx","image\/vnd.wap.wbmp":"wbmp","image\/vnd.xiff":"xif","image\/webp":"webp","image\/x-3ds":"3ds","image\/x-cmu-raster":"ras","image\/x-cmx":"cmx","image\/x-freehand":"fh","image\/x-icon":"ico","image\/x-mrsid-image":"sid","image\/x-pcx":"pcx","image\/x-pict":"pic","image\/x-portable-anymap":"pnm","image\/x-portable-bitmap":"pbm","image\/x-portable-graymap":"pgm","image\/x-portable-pixmap":"ppm","image\/x-rgb":"rgb","image\/x-xpixmap":"xpm","image\/x-xwindowdump":"xwd","message\/rfc822":"eml","model\/iges":"igs","model\/mesh":"msh","model\/vnd.collada+xml":"dae","model\/vnd.dwf":"dwf","model\/vnd.gdl":"gdl","model\/vnd.gtw":"gtw","model\/vnd.vtu":"vtu","model\/vrml":"wrl","model\/x3d+binary":"x3db","model\/x3d+vrml":"x3dv","model\/x3d+xml":"x3d","text\/cache-manifest":"appcache","text\/calendar":"ics","text\/css":"css","text\/csv":"csv","text\/html":"html","text\/n3":"n3","text\/plain":"txt","text\/prs.lines.tag":"dsc","text\/richtext":"rtx","text\/sgml":"sgml","text\/tab-separated-values":"tsv","text\/troff":"t","text\/turtle":"ttl","text\/uri-list":"uri","text\/vcard":"vcard","text\/vnd.curl":"curl","text\/vnd.curl.dcurl":"dcurl","text\/vnd.curl.mcurl":"mcurl","text\/vnd.curl.scurl":"scurl","text\/vnd.fly":"fly","text\/vnd.fmi.flexstor":"flx","text\/vnd.graphviz":"gv","text\/vnd.in3d.3dml":"3dml","text\/vnd.in3d.spot":"spot","text\/vnd.sun.j2me.app-descriptor":"jad","text\/vnd.wap.wml":"wml","text\/vnd.wap.wmlscript":"wmls","text\/x-asm":"s","text\/x-c":"cc","text\/x-fortran":"f","text\/x-java-source":"java","text\/x-nfo":"nfo","text\/x-opml":"opml","text\/x-pascal":"p","text\/x-setext":"etx","text\/x-sfv":"sfv","text\/x-uuencode":"uu","text\/x-vcalendar":"vcs","text\/x-vcard":"vcf","video\/3gpp":"3gp","video\/3gpp2":"3g2","video\/h261":"h261","video\/h263":"h263","video\/h264":"h264","video\/jpeg":"jpgv","video\/jpm":"jpm","video\/mj2":"mj2","video\/mp4":"mp4","video\/mpeg":"mpeg","video\/quicktime":"qt","video\/vnd.dece.hd":"uvh","video\/vnd.dece.mobile":"uvm","video\/vnd.dece.pd":"uvp","video\/vnd.dece.sd":"uvs","video\/vnd.dece.video":"uvv","video\/vnd.dvb.file":"dvb","video\/vnd.fvt":"fvt","video\/vnd.mpegurl":"mxu","video\/vnd.ms-playready.media.pyv":"pyv","video\/vnd.uvvu.mp4":"uvu","video\/vnd.vivo":"viv","video\/webm":"webm","video\/x-f4v":"f4v","video\/x-fli":"fli","video\/x-flv":"flv","video\/x-m4v":"m4v","video\/x-matroska":"mkv","video\/x-mng":"mng","video\/x-ms-asf":"asf","video\/x-ms-vob":"vob","video\/x-ms-wmx":"wmx","video\/x-ms-wvx":"wvx","video\/x-msvideo":"avi","video\/x-sgi-movie":"movie","video\/x-smv":"smv","x-conference\/x-cooltalk":"ice","text\/x-sql":"sql","image\/x-pixlr-data":"pxd","image\/x-adobe-dng":"dng","image\/x-sketch":"sketch","image\/x-xcf":"xcf","audio\/amr":"amr","application\/plt":"plt","application\/sat":"sat","application\/step":"step","text\/x-httpd-cgi":"cgi","text\/x-asap":"asp","text\/x-jsp":"jsp"};
 
- /*
 
-  * File: /js/elFinder.options.js
 
-  */
 
- /**
 
-  * Default elFinder config
 
-  *
 
-  * @type  Object
 
-  * @autor Dmitry (dio) Levashov
 
-  */
 
- elFinder.prototype._options = {
 
- 	/**
 
- 	 * URLs of 3rd party libraries CDN
 
- 	 * 
 
- 	 * @type Object
 
- 	 */
 
- 	cdns : {
 
- 		// for editor etc.
 
- 		ace        : 'https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.1',
 
- 		codemirror : 'https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.40.2',
 
- 		ckeditor   : 'https://cdnjs.cloudflare.com/ajax/libs/ckeditor/4.10.0',
 
- 		ckeditor5  : 'https://cdn.ckeditor.com/ckeditor5/11.1.1',
 
- 		tinymce    : 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.8.3',
 
- 		simplemde  : 'https://cdnjs.cloudflare.com/ajax/libs/simplemde/1.11.2',
 
- 		fabric16   : 'https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.7',
 
- 		tui        : 'https://uicdn.toast.com',
 
- 		// for quicklook etc.
 
- 		hls        : 'https://cdnjs.cloudflare.com/ajax/libs/hls.js/0.10.1/hls.min.js',
 
- 		dash       : 'https://cdnjs.cloudflare.com/ajax/libs/dashjs/2.9.1/dash.all.min.js',
 
- 		flv        : 'https://cdnjs.cloudflare.com/ajax/libs/flv.js/1.4.2/flv.min.js',
 
- 		prettify   : 'https://cdn.jsdelivr.net/gh/google/code-prettify@453bd5f51e61245339b738b1bbdd42d7848722ba/loader/run_prettify.js',
 
- 		psd        : 'https://cdnjs.cloudflare.com/ajax/libs/psd.js/3.2.0/psd.min.js',
 
- 		rar        : 'https://cdn.jsdelivr.net/gh/nao-pon/rar.js@6cef13ec66dd67992fc7f3ea22f132d770ebaf8b/rar.min.js',
 
- 		zlibUnzip  : 'https://cdn.jsdelivr.net/gh/imaya/zlib.js@0.3.1/bin/unzip.min.js', // need check unzipFiles() in quicklook.plugins.js when update
 
- 		zlibGunzip : 'https://cdn.jsdelivr.net/gh/imaya/zlib.js@0.3.1/bin/gunzip.min.js',
 
- 		marked     : 'https://cdnjs.cloudflare.com/ajax/libs/marked/0.5.1/marked.min.js',
 
- 		sparkmd5   : 'https://cdnjs.cloudflare.com/ajax/libs/spark-md5/3.0.0/spark-md5.min.js',
 
- 		jssha      : 'https://cdnjs.cloudflare.com/ajax/libs/jsSHA/2.3.1/sha.js',
 
- 		amr        : 'https://cdn.jsdelivr.net/gh/yxl/opencore-amr-js@dcf3d2b5f384a1d9ded2a54e4c137a81747b222b/js/amrnb.js'
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Connector url. Required!
 
- 	 *
 
- 	 * @type String
 
- 	 */
 
- 	url : '',
 
- 	/**
 
- 	 * Ajax request type.
 
- 	 *
 
- 	 * @type String
 
- 	 * @default "get"
 
- 	 */
 
- 	requestType : 'get',
 
- 	
 
- 	/**
 
- 	 * Use CORS to connector url
 
- 	 * 
 
- 	 * @type Boolean|null  true|false|null(Auto detect)
 
- 	 */
 
- 	cors : null,
 
- 	/**
 
- 	 * Maximum number of concurrent connections on request
 
- 	 * 
 
- 	 * @type Number
 
- 	 * @default 3
 
- 	 */
 
- 	requestMaxConn : 3,
 
- 	/**
 
- 	 * Transport to send request to backend.
 
- 	 * Required for future extensions using websockets/webdav etc.
 
- 	 * Must be an object with "send" method.
 
- 	 * transport.send must return $.Deferred() object
 
- 	 *
 
- 	 * @type Object
 
- 	 * @default null
 
- 	 * @example
 
- 	 *  transport : {
 
- 	 *    init : function(elfinderInstance) { },
 
- 	 *    send : function(options) {
 
- 	 *      var dfrd = $.Deferred();
 
- 	 *      // connect to backend ...
 
- 	 *      return dfrd;
 
- 	 *    },
 
- 	 *    upload : function(data) {
 
- 	 *      var dfrd = $.Deferred();
 
- 	 *      // upload ...
 
- 	 *      return dfrd;
 
- 	 *    }
 
- 	 *    
 
- 	 *  }
 
- 	 **/
 
- 	transport : {},
 
- 	/**
 
- 	 * URL to upload file to.
 
- 	 * If not set - connector URL will be used
 
- 	 *
 
- 	 * @type String
 
- 	 * @default  ''
 
- 	 */
 
- 	urlUpload : '',
 
- 	/**
 
- 	 * Allow to drag and drop to upload files
 
- 	 *
 
- 	 * @type Boolean|String
 
- 	 * @default  'auto'
 
- 	 */
 
- 	dragUploadAllow : 'auto',
 
- 	
 
- 	/**
 
- 	 * Confirmation dialog displayed at the time of overwriting upload
 
- 	 * 
 
- 	 * @type Boolean
 
- 	 * @default true
 
- 	 */
 
- 	overwriteUploadConfirm : true,
 
- 	
 
- 	/**
 
- 	 * Max size of chunked data of file upload
 
- 	 * 
 
- 	 * @type Number
 
- 	 * @default  10485760(10MB)
 
- 	 */
 
- 	uploadMaxChunkSize : 10485760,
 
- 	
 
- 	/**
 
- 	 * Regular expression of file name to exclude when uploading folder
 
- 	 * 
 
- 	 * @type Object
 
- 	 * @default { win: /^(?:desktop\.ini|thumbs\.db)$/i, mac: /^\.ds_store$/i }
 
- 	 */
 
- 	folderUploadExclude : {
 
- 		win: /^(?:desktop\.ini|thumbs\.db)$/i,
 
- 		mac: /^\.ds_store$/i
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Timeout for upload using iframe
 
- 	 *
 
- 	 * @type Number
 
- 	 * @default  0 - no timeout
 
- 	 */
 
- 	iframeTimeout : 0,
 
- 	
 
- 	/**
 
- 	 * Data to append to all requests and to upload files
 
- 	 *
 
- 	 * @type Object
 
- 	 * @default  {}
 
- 	 */
 
- 	customData : {},
 
- 	
 
- 	/**
 
- 	 * Event listeners to bind on elFinder init
 
- 	 *
 
- 	 * @type Object
 
- 	 * @default  {}
 
- 	 */
 
- 	handlers : {},
 
- 	/**
 
- 	 * Any custom headers to send across every ajax request
 
- 	 *
 
- 	 * @type Object
 
- 	 * @default {}
 
- 	 */
 
- 	customHeaders : {},
 
- 	/**
 
- 	 * Any custom xhrFields to send across every ajax request
 
- 	 *
 
- 	 * @type Object
 
- 	 * @default {}
 
- 	 */
 
- 	xhrFields : {},
 
- 	/**
 
- 	 * Interface language
 
- 	 *
 
- 	 * @type String
 
- 	 * @default "en"
 
- 	 */
 
- 	lang : 'en',
 
- 	/**
 
- 	 * Base URL of elfFinder library starting from Manager HTML
 
- 	 * Auto detect when empty value
 
- 	 * 
 
- 	 * @type String
 
- 	 * @default ""
 
- 	 */
 
- 	baseUrl : '',
 
- 	/**
 
- 	 * Base URL of i18n js files
 
- 	 * baseUrl + "js/i18n/" when empty value
 
- 	 * 
 
- 	 * @type String
 
- 	 * @default ""
 
- 	 */
 
- 	i18nBaseUrl : '',
 
- 	
 
- 	/**
 
- 	 * Auto load required CSS
 
- 	 * `false` to disable this function or
 
- 	 * CSS URL Array to load additional CSS files
 
- 	 * 
 
- 	 * @type Boolean|Array
 
- 	 * @default true
 
- 	 */
 
- 	cssAutoLoad : true,
 
- 	/**
 
- 	 * Theme to load
 
- 	 * {"themeid" : "Theme CSS URL"} or
 
- 	 * {"themeid" : "Theme manifesto.json URL"} or
 
- 	 * Theme manifesto.json Object
 
- 	 * {
 
- 	 *   "themeid" : {
 
- 	 *     "name":"Theme Name",
 
- 	 *     "cssurls":"Theme CSS URL",
 
- 	 *     "author":"Author Name",
 
- 	 *     "email":"Author Email",
 
- 	 *     "license":"License",
 
- 	 *     "link":"Web Site URL",
 
- 	 *     "image":"Screen Shot URL",
 
- 	 *     "description":"Description"
 
- 	 *   }
 
- 	 * }
 
- 	 * 
 
- 	 * @type Object
 
- 	 */
 
- 	themes : {},
 
- 	/**
 
- 	 * Theme id to initial theme
 
- 	 * 
 
- 	 * @type String|Null
 
- 	 */
 
- 	theme : null,
 
- 	
 
- 	/**
 
- 	 * Additional css class for filemanager node.
 
- 	 *
 
- 	 * @type String
 
- 	 */
 
- 	cssClass : '',
 
- 	/**
 
- 	 * Active commands list. '*' means all of the commands that have been load.
 
- 	 * If some required commands will be missed here, elFinder will add its
 
- 	 *
 
- 	 * @type Array
 
- 	 */
 
- 	commands : ['*'],
 
- 	// Available commands list
 
- 	//commands : [
 
- 	//	'archive', 'back', 'chmod', 'colwidth', 'copy', 'cut', 'download', 'duplicate', 'edit', 'extract',
 
- 	//	'forward', 'fullscreen', 'getfile', 'help', 'home', 'info', 'mkdir', 'mkfile', 'netmount', 'netunmount',
 
- 	//	'open', 'opendir', 'paste', 'places', 'quicklook', 'reload', 'rename', 'resize', 'restore', 'rm',
 
- 	//	'search', 'sort', 'up', 'upload', 'view', 'zipdl'
 
- 	//],
 
- 	
 
- 	/**
 
- 	 * Commands options.
 
- 	 *
 
- 	 * @type Object
 
- 	 **/
 
- 	commandsOptions : {
 
- 		// // configure shortcuts of any command
 
- 		// // add `shortcuts` property into each command
 
- 		// any_command_name : {
 
- 		// 	shortcuts : [] // for disable this command's shortcuts
 
- 		// },
 
- 		// any_command_name : {
 
- 		// 	shortcuts : function(fm, shortcuts) {
 
- 		// 		// for add `CTRL + E` for this command action
 
- 		// 		shortcuts[0]['pattern'] += ' ctrl+e';
 
- 		// 		return shortcuts;
 
- 		// 	}
 
- 		// },
 
- 		// any_command_name : {
 
- 		// 	shortcuts : function(fm, shortcuts) {
 
- 		// 		// for full customize of this command's shortcuts
 
- 		// 		return [ { pattern: 'ctrl+e ctrl+down numpad_enter' + (fm.OS != 'mac' && ' enter') } ];
 
- 		// 	}
 
- 		// },
 
- 		// "getfile" command options.
 
- 		getfile : {
 
- 			onlyURL  : false,
 
- 			// allow to return multiple files info
 
- 			multiple : false,
 
- 			// allow to return filers info
 
- 			folders  : false,
 
- 			// action after callback (""/"close"/"destroy")
 
- 			oncomplete : '',
 
- 			// action when callback is fail (""/"close"/"destroy")
 
- 			onerror : '',
 
- 			// get path before callback call
 
- 			getPath    : true, 
 
- 			// get image sizes before callback call
 
- 			getImgSize : false
 
- 		},
 
- 		open : {
 
- 			// HTTP method that request to the connector when item URL is not valid URL.
 
- 			// If you set to "get" will be displayed request parameter in the browser's location field
 
- 			// so if you want to conceal its parameters should be given "post".
 
- 			// Nevertheless, please specify "get" if you want to enable the partial request by HTTP Range header.
 
- 			method : 'post',
 
- 			// Where to open into : 'window'(default), 'tab' or 'tabs'
 
- 			// 'tabs' opens in each tabs
 
- 			into   : 'window',
 
- 			// Default command list of action when select file
 
- 			// String value that is 'Command Name' or 'Command Name1/CommandName2...'
 
- 			selectAction : 'open'
 
- 		},
 
- 		opennew : {
 
- 			// URL of to open elFinder manager
 
- 			// Default '' : Origin URL
 
- 			url : '',
 
- 			// Use search query of origin URL
 
- 			useOriginQuery : true
 
- 		},
 
- 		// "upload" command options.
 
- 		upload : {
 
- 			// Open elFinder upload dialog: 'button' OR Open system OS upload dialog: 'uploadbutton'
 
- 			ui : 'button'
 
- 		},
 
- 		// "download" command options.
 
- 		download : {
 
- 			// max request to download files when zipdl disabled
 
- 			maxRequests : 10,
 
- 			// minimum count of files to use zipdl
 
- 			minFilesZipdl : 2
 
- 		},
 
- 		// "quicklook" command options.
 
- 		quicklook : {
 
- 			autoplay : true,
 
- 			width    : 450,
 
- 			height   : 300,
 
- 			// ControlsList of HTML5 audio/video preview
 
- 			// see https://googlechrome.github.io/samples/media/controlslist.html
 
- 			mediaControlsList : '', // e.g. 'nodownload nofullscreen noremoteplayback'
 
- 			// Show toolbar of PDF preview (with <embed> tag)
 
- 			pdfToolbar : true,
 
- 			// Maximum characters length to preview
 
- 			textMaxlen : 2000,
 
- 			// quicklook window must be contained in elFinder node on window open (true|false)
 
- 			contain : false,
 
- 			// preview window into NavDock (0 : undocked | 1 : docked(show) | 2 : docked(hide))
 
- 			docked   : 0,
 
- 			// Docked preview height ('auto' or Number of pixel) 'auto' is setted to the Navbar width
 
- 			dockHeight : 'auto',
 
- 			// media auto play when docked
 
- 			dockAutoplay : false,
 
- 			// Google Maps API key (Require Maps JavaScript API)
 
- 			googleMapsApiKey : '',
 
- 			// Google Maps API Options
 
- 			googleMapsOpts : {
 
- 				maps : {},
 
- 				kml : {
 
- 					suppressInfoWindows : false,
 
- 					preserveViewport : false
 
- 				}
 
- 			},
 
- 			// ViewerJS (https://viewerjs.org/) Options
 
- 			// To enable this you need to place ViewerJS on the same server as elFinder and specify that URL in `url`.
 
- 			viewerjs : {
 
- 				url: '', // Example '/ViewerJS/index.html'
 
- 				mimes: ['application/pdf', 'application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.spreadsheet', 'application/vnd.oasis.opendocument.presentation']
 
- 			},
 
- 			// MIME types to CAD-Files and 3D-Models online viewer on sharecad.org
 
- 			// Example ['image/vnd.dwg', 'image/vnd.dxf', 'model/vnd.dwf', 'application/vnd.hp-hpgl', 'application/plt', 'application/step', 'model/iges', 'application/vnd.ms-pki.stl', 'application/sat', 'image/cgm', 'application/x-msmetafile']
 
- 			sharecadMimes : [],
 
- 			// MIME types to use Google Docs online viewer
 
- 			// Example ['application/pdf', 'image/tiff', 'application/vnd.ms-office', 'application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/postscript', 'application/rtf']
 
- 			googleDocsMimes : [],
 
- 			// MIME types to use Microsoft Office Online viewer
 
- 			// Example ['application/msword', 'application/vnd.ms-word', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.spreadsheet', 'application/vnd.oasis.opendocument.presentation']
 
- 			// These MIME types override "googleDocsMimes"
 
- 			officeOnlineMimes : [],
 
- 			// File size (byte) threshold when using the dim command for obtain the image size necessary to image preview
 
- 			getDimThreshold : 200000,
 
- 			// MIME-Type regular expression that does not check empty files
 
- 			mimeRegexNotEmptyCheck : /^application\/vnd\.google-apps\./
 
- 		},
 
- 		// "quicklook" command options.
 
- 		edit : {
 
- 			// dialog width, integer(px) or integer+'%' (example: 650, '80%' ...)
 
- 			dialogWidth : void(0),
 
- 			// list of allowed mimetypes to edit of text files
 
- 			// if empty - any text files can be edited
 
- 			mimes : [],
 
- 			// MIME-types of text file to make as empty files
 
- 			makeTextMimes : ['text/plain', 'text/css', 'text/html'],
 
- 			// Use the editor stored in the browser
 
- 			// This value allowd overwrite with user preferences
 
- 			useStoredEditor : false,
 
- 			// Open the maximized editor window
 
- 			// This value allowd overwrite with user preferences
 
- 			editorMaximized : false,
 
- 			// edit files in wysisyg's
 
- 			editors : [
 
- 				// {
 
- 				// 	/**
 
- 				// 	 * editor info
 
- 				// 	 * @type  Object
 
- 				// 	 */
 
- 				// 	info : { name: 'Editor Name' },
 
- 				// 	/**
 
- 				// 	 * files mimetypes allowed to edit in current wysisyg
 
- 				// 	 * @type  Array
 
- 				// 	 */
 
- 				// 	mimes : ['text/html'], 
 
- 				// 	/**
 
- 				// 	 * HTML element for editing area (optional for text editor)
 
- 				// 	 * @type  String
 
- 				// 	 */
 
- 				// 	html : '<textarea></textarea>', 
 
- 				// 	/**
 
- 				// 	 * Initialize editing area node (optional for text editor)
 
- 				// 	 * 
 
- 				// 	 * @param  String  dialog DOM id
 
- 				// 	 * @param  Object  target file object
 
- 				// 	 * @param  String  target file content (text or Data URI Scheme(binary file))
 
- 				// 	 * @param  Object  elFinder instance
 
- 				// 	 * @type  Function
 
- 				// 	 */
 
- 				// 	init : function(id, file, content, fm) {
 
- 				// 		$(this).attr('id', id + '-text').val(content);
 
- 				// 	},
 
- 				// 	/**
 
- 				// 	 * Get edited contents (optional for text editor)
 
- 				// 	 * @type  Function
 
- 				// 	 */
 
- 				// 	getContent : function() {
 
- 				// 		return $(this).val();
 
- 				// 	},
 
- 				// 	/**
 
- 				// 	 * Called when "edit" dialog loaded.
 
- 				// 	 * Place to init wysisyg.
 
- 				// 	 * Can return wysisyg instance
 
- 				// 	 *
 
- 				// 	 * @param  DOMElement  textarea node
 
- 				// 	 * @return Object      editor instance|jQuery.Deferred(return instance on resolve())
 
- 				// 	 */
 
- 				// 	load : function(textarea) { },
 
- 				// 	/**
 
- 				// 	 * Called before "edit" dialog closed.
 
- 				// 	 * Place to destroy wysisyg instance.
 
- 				// 	 *
 
- 				// 	 * @param  DOMElement  textarea node
 
- 				// 	 * @param  Object      wysisyg instance (if was returned by "load" callback)
 
- 				// 	 * @return void
 
- 				// 	 */
 
- 				// 	close : function(textarea, instance) { },
 
- 				// 	/**
 
- 				// 	 * Called before file content send to backend.
 
- 				// 	 * Place to update textarea content if needed.
 
- 				// 	 *
 
- 				// 	 * @param  DOMElement  textarea node
 
- 				// 	 * @param  Object      wysisyg instance (if was returned by "load" callback)
 
- 				// 	 * @return void
 
- 				// 	 */
 
- 				// 	save : function(textarea, instance) {},
 
- 				// 	/**
 
- 				// 	 * Called after load() or save().
 
- 				// 	 * Set focus to wysisyg editor.
 
- 				// 	 *
 
- 				// 	 * @param  DOMElement  textarea node
 
- 				// 	 * @param  Object      wysisyg instance (if was returned by "load" callback)
 
- 				// 	 * @return void
 
- 				// 	 */
 
- 				// 	focus : function(textarea, instance) {}
 
- 				// 	/**
 
- 				// 	 * Called after dialog resized..
 
- 				// 	 *
 
- 				// 	 * @param  DOMElement  textarea node
 
- 				// 	 * @param  Object      wysisyg instance (if was returned by "load" callback)
 
- 				// 	 * @param  Object      resize event object
 
- 				// 	 * @param  Object      data object
 
- 				// 	 * @return void
 
- 				// 	 */
 
- 				// 	resize : function(textarea, instance, event, data) {}
 
- 				// 
 
- 				// }
 
- 			],
 
- 			// Character encodings of select box
 
- 			encodings : ['Big5', 'Big5-HKSCS', 'Cp437', 'Cp737', 'Cp775', 'Cp850', 'Cp852', 'Cp855', 'Cp857', 'Cp858', 
 
- 				'Cp862', 'Cp866', 'Cp874', 'EUC-CN', 'EUC-JP', 'EUC-KR', 'GB18030', 'ISO-2022-CN', 'ISO-2022-JP', 'ISO-2022-KR', 
 
- 				'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 
 
- 				'ISO-8859-8', 'ISO-8859-9', 'ISO-8859-13', 'ISO-8859-15', 'KOI8-R', 'KOI8-U', 'Shift-JIS', 
 
- 				'Windows-1250', 'Windows-1251', 'Windows-1252', 'Windows-1253', 'Windows-1254', 'Windows-1257'],
 
- 			// options for extra editors
 
- 			extraOptions : {
 
- 				// TUI Image Editor's options
 
- 				tuiImgEditOpts : {
 
- 					// Path prefix of icon-a.svg, icon-b.svg, icon-c.svg and icon-d.svg in the Theme. 
 
- 					// `iconsPath` MUST follow the same origin policy.
 
- 					iconsPath : void(0), // default is "./img/tui-"
 
- 					// Theme object
 
- 					theme : {}
 
- 				},
 
- 				// Specify the Creative Cloud API key when using Creative SDK image editor of Creative Cloud.
 
- 				// You can get the API key at https://console.adobe.io/.
 
- 				creativeCloudApiKey : '',
 
- 				// Browsing manager URL for CKEditor, TinyMCE
 
- 				// Uses self location with the empty value or not defined.
 
- 				//managerUrl : 'elfinder.html'
 
- 				managerUrl : null,
 
- 				// CKEditor5' builds mode - 'classic', 'inline' or 'balloon' 
 
- 				ckeditor5Mode : 'balloon',
 
- 				// Setting for Online-Convert.com
 
- 				onlineConvert : {
 
- 					maxSize  : 100, // (MB) Max 100MB on free account
 
- 					showLink : true // It must be enabled with free account
 
- 				}
 
- 			}
 
- 		},
 
- 		search : {
 
- 			// Incremental search from the current view
 
- 			incsearch : {
 
- 				enable : true, // is enable true or false
 
- 				minlen : 1,    // minimum number of characters
 
- 				wait   : 500   // wait milliseconds
 
- 			},
 
- 			// Additional search types
 
- 			searchTypes : {
 
- 				// "SearchMime" is implemented in default
 
- 				SearchMime : {           // The key is search type that send to the connector
 
- 					name : 'btnMime',    // Button text to be processed in i18n()
 
- 					title : 'searchMime' // Button title to be processed in i18n()
 
- 				}
 
- 			}
 
- 		},
 
- 		// "info" command options.
 
- 		info : {
 
- 			// If the URL of the Directory is null,
 
- 			// it is assumed that the link destination is a URL to open the folder in elFinder
 
- 			nullUrlDirLinkSelf : true,
 
- 			// Information items to be hidden by default
 
- 			// These name are 'size', 'aliasfor', 'path', 'link', 'dim', 'modify', 'perms', 'locked', 'owner', 'group', 'perm' and your custom info items label
 
- 			hideItems : [],
 
- 			// Maximum file size (byte) to get file contents hash (md5, sha256 ...)
 
- 			showHashMaxsize : 104857600, // 100 MB
 
- 			// Array of hash algorisms to show on info dialog
 
- 			// These name are 'md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512', 'shake128' and 'shake256'
 
- 			showHashAlgorisms : ['md5', 'sha256'],
 
- 			custom : {
 
- 				// /**
 
- 				//  * Example of custom info `desc`
 
- 				//  */
 
- 				// desc : {
 
- 				// 	/**
 
- 				// 	 * Lable (require)
 
- 				// 	 * It is filtered by the `fm.i18n()`
 
- 				// 	 * 
 
- 				// 	 * @type String
 
- 				// 	 */
 
- 				// 	label : 'Description',
 
- 				// 	
 
- 				// 	/**
 
- 				// 	 * Template (require)
 
- 				// 	 * `{id}` is replaced in dialog.id
 
- 				// 	 * 
 
- 				// 	 * @type String
 
- 				// 	 */
 
- 				// 	tpl : '<div class="elfinder-info-desc"><span class="elfinder-spinner"></span></div>',
 
- 				// 	
 
- 				// 	/**
 
- 				// 	 * Restricts to mimetypes (optional)
 
- 				// 	 * Exact match or category match
 
- 				// 	 * 
 
- 				// 	 * @type Array
 
- 				// 	 */
 
- 				// 	mimes : ['text', 'image/jpeg', 'directory'],
 
- 				// 	
 
- 				// 	/**
 
- 				// 	 * Restricts to file.hash (optional)
 
- 				// 	 * 
 
- 				// 	 * @ type Regex
 
- 				// 	 */
 
- 				// 	hashRegex : /^l\d+_/,
 
- 				// 
 
- 				// 	/**
 
- 				// 	 * Request that asks for the description and sets the field (optional)
 
- 				// 	 * 
 
- 				// 	 * @type Function
 
- 				// 	 */
 
- 				// 	action : function(file, fm, dialog) {
 
- 				// 		fm.request({
 
- 				// 		data : { cmd : 'desc', target: file.hash },
 
- 				// 			preventDefault: true,
 
- 				// 		})
 
- 				// 		.fail(function() {
 
- 				// 			dialog.find('div.elfinder-info-desc').html(fm.i18n('unknown'));
 
- 				// 		})
 
- 				// 		.done(function(data) {
 
- 				// 			dialog.find('div.elfinder-info-desc').html(data.desc);
 
- 				// 		});
 
- 				// 	}
 
- 				// }
 
- 			}
 
- 		},
 
- 		mkdir: {
 
- 			// Enable automatic switching function ["New Folder" / "Into New Folder"] of toolbar buttton
 
- 			intoNewFolderToolbtn: false
 
- 		},
 
- 		resize: {
 
- 			// defalt status of snap to 8px grid of the jpeg image ("enable" or "disable")
 
- 			grid8px : 'disable',
 
- 			// Preset size array [width, height]
 
- 			presetSize : [[320, 240], [400, 400], [640, 480], [800,600]],
 
- 			// File size (bytes) threshold when using the `dim` command for obtain the image size necessary to start editing
 
- 			getDimThreshold : 204800,
 
- 			// File size (bytes) to request to get substitute image (400px) with the `dim` command
 
- 			dimSubImgSize : 307200
 
- 		},
 
- 		rm: {
 
- 			// If trash is valid, items moves immediately to the trash holder without confirm.
 
- 			quickTrash : true,
 
- 			// Maximum wait seconds when checking the number of items to into the trash
 
- 			infoCheckWait : 10,
 
- 			// Maximum number of items that can be placed into the Trash at one time
 
- 			toTrashMaxItems : 1000
 
- 		},
 
- 		help : {
 
- 			// Tabs to show
 
- 			view : ['about', 'shortcuts', 'help', 'integrations', 'debug'],
 
- 			// HTML source URL of the heip tab
 
- 			helpSource : ''
 
- 		},
 
- 		preference : {
 
- 			// dialog width
 
- 			width: 600,
 
- 			// dialog height
 
- 			height: 400,
 
- 			// tabs setting see preference.js : build()
 
- 			categories: null,
 
- 			// preference setting see preference.js : build()
 
- 			prefs: null,
 
- 			// language setting  see preference.js : build()
 
- 			langs: null,
 
- 			// Command list of action when select file
 
- 			// Array value are 'Command Name' or 'Command Name1/CommandName2...'
 
- 			selectActions : ['open', 'edit/download', 'resize/edit/download', 'download', 'quicklook']
 
- 		}
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Callback for prepare boot up
 
- 	 * 
 
- 	 * - The this object in the function is an elFinder node
 
- 	 * - The first parameter is elFinder Instance
 
- 	 * - The second parameter is an object of other parameters
 
- 	 *   For now it can use `dfrdsBeforeBootup` Array
 
- 	 * 
 
- 	 * @type Function
 
- 	 * @default null
 
- 	 * @return void
 
- 	 */
 
- 	bootCallback : null,
 
- 	
 
- 	/**
 
- 	 * Callback for "getfile" commands.
 
- 	 * Required to use elFinder with WYSIWYG editors etc..
 
- 	 *
 
- 	 * @type Function
 
- 	 * @default null (command not active)
 
- 	 */
 
- 	getFileCallback : null,
 
- 	
 
- 	/**
 
- 	 * Default directory view. icons/list
 
- 	 *
 
- 	 * @type String
 
- 	 * @default "icons"
 
- 	 */
 
- 	defaultView : 'icons',
 
- 	
 
- 	/**
 
- 	 * Hash of default directory path to open
 
- 	 * 
 
- 	 * NOTE: This setting will be disabled if the target folder is specified in location.hash.
 
- 	 * 
 
- 	 * If you want to find the hash in Javascript
 
- 	 * can be obtained with the following code. (In the case of a standard hashing method)
 
- 	 * 
 
- 	 * var volumeId = 'l1_'; // volume id
 
- 	 * var path = 'path/to/target'; // without root path
 
- 	 * //var path = 'path\\to\\target'; // use \ on windows server
 
- 	 * var hash = volumeId + btoa(path).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '.').replace(/\.+$/, '');
 
- 	 * 
 
- 	 * @type String
 
- 	 * @default ""
 
- 	 */
 
- 	startPathHash : '',
 
- 	/**
 
- 	 * Emit a sound when a file is deleted
 
- 	 * Sounds are in sounds/ folder
 
- 	 * 
 
- 	 * @type Boolean
 
- 	 * @default true
 
- 	 */
 
- 	sound : true,
 
- 	
 
- 	/**
 
- 	 * UI plugins to load.
 
- 	 * Current dir ui and dialogs loads always.
 
- 	 * Here set not required plugins as folders tree/toolbar/statusbar etc.
 
- 	 *
 
- 	 * @type Array
 
- 	 * @default ['toolbar', 'tree', 'path', 'stat']
 
- 	 * @full ['toolbar', 'places', 'tree', 'path', 'stat']
 
- 	 */
 
- 	ui : ['toolbar', 'tree', 'path', 'stat'],
 
- 	
 
- 	/**
 
- 	 * Some UI plugins options.
 
- 	 * @type Object
 
- 	 */
 
- 	uiOptions : {
 
- 		// toolbar configuration
 
- 		toolbar : [
 
- 			['home', 'back', 'forward', 'up', 'reload'],
 
- 			['netmount'],
 
- 			['mkdir', 'mkfile', 'upload'],
 
- 			['open', 'download', 'getfile'],
 
- 			['undo', 'redo'],
 
- 			['copy', 'cut', 'paste', 'rm', 'empty', 'hide'],
 
- 			['duplicate', 'rename', 'edit', 'resize', 'chmod'],
 
- 			['selectall', 'selectnone', 'selectinvert'],
 
- 			['quicklook', 'info'],
 
- 			['extract', 'archive'],
 
- 			['search'],
 
- 			['view', 'sort'],
 
- 			['preference', 'help'],
 
- 			['fullscreen']
 
- 		],
 
- 		// toolbar extra options
 
- 		toolbarExtra : {
 
- 			// also displays the text label on the button (true / false / 'none')
 
- 			displayTextLabel: false,
 
- 			// Exclude `displayTextLabel` setting UA type
 
- 			labelExcludeUA: ['Mobile'],
 
- 			// auto hide on initial open
 
- 			autoHideUA: ['Mobile'],
 
- 			// Initial setting value of hide button in toolbar setting
 
- 			defaultHides: ['home', 'reload'],
 
- 			// show Preference button ('none', 'auto', 'always')
 
- 			// If you do not include 'preference' in the context menu you should specify 'auto' or 'always'
 
- 			showPreferenceButton: 'none',
 
- 			// show Preference button into contextmenu of the toolbar (true / false)
 
- 			preferenceInContextmenu: true
 
- 		},
 
- 		// directories tree options
 
- 		tree : {
 
- 			// expand current root on init
 
- 			openRootOnLoad : true,
 
- 			// expand current work directory on open
 
- 			openCwdOnOpen  : true,
 
- 			// auto loading current directory parents and do expand their node.
 
- 			syncTree : true,
 
- 			// Maximum number of display of each child trees
 
- 			// The tree of directories with children exceeding this number will be split
 
- 			subTreeMax : 100,
 
- 			// Numbar of max connctions of subdirs request
 
- 			subdirsMaxConn : 2,
 
- 			// Number of max simultaneous processing directory of subdirs
 
- 			subdirsAtOnce : 5,
 
- 			// Durations of each animations
 
- 			durations : {
 
- 				slideUpDown : 'fast',
 
- 				autoScroll : 'fast'
 
- 			}
 
- 			// ,
 
- 			// /**
 
- 			//  * Add CSS class name to navbar directories (optional)
 
- 			//  * see: https://github.com/Studio-42/elFinder/pull/1061,
 
- 			//  *      https://github.com/Studio-42/elFinder/issues/1231
 
- 			//  * 
 
- 			//  * @type Function
 
- 			//  */
 
- 			// getClass: function(dir) {
 
- 			// 	// e.g. This adds the directory's name (lowercase) with prefix as a CSS class
 
- 			// 	return 'elfinder-tree-' + dir.name.replace(/[ "]/g, '').toLowerCase();
 
- 			// }
 
- 		},
 
- 		// navbar options
 
- 		navbar : {
 
- 			minWidth : 150,
 
- 			maxWidth : 500,
 
- 			// auto hide on initial open
 
- 			autoHideUA: [] // e.g. ['Mobile']
 
- 		},
 
- 		navdock : {
 
- 			// disabled navdock ui
 
- 			disabled : false,
 
- 			// percentage of initial maximum height to work zone
 
- 			initMaxHeight : '50%',
 
- 			// percentage of maximum height to work zone by user resize action
 
- 			maxHeight : '90%'
 
- 		},
 
- 		cwd : {
 
- 			// display parent folder with ".." name :)
 
- 			oldSchool : false,
 
- 			
 
- 			// fm.UA types array to show item select checkboxes e.g. ['All'] or ['Mobile'] etc. default: ['Touch']
 
- 			showSelectCheckboxUA : ['Touch'],
 
- 			
 
- 			// file info columns displayed
 
- 			listView : {
 
- 				// name is always displayed, cols are ordered
 
- 				// e.g. ['perm', 'date', 'size', 'kind', 'owner', 'group', 'mode']
 
- 				// mode: 'mode'(by `fileModeStyle` setting), 'modestr'(rwxr-xr-x) , 'modeoct'(755), 'modeboth'(rwxr-xr-x (755))
 
- 				// 'owner', 'group' and 'mode', It's necessary set volume driver option "statOwner" to `true`
 
- 				// for custom, characters that can be used in the name is `a-z0-9_`
 
- 				columns : ['perm', 'date', 'size', 'kind'],
 
- 				// override this if you want custom columns name
 
- 				// example
 
- 				// columnsCustomName : {
 
- 				//		date : 'Last modification',
 
- 				// 		kind : 'Mime type'
 
- 				// }
 
- 				columnsCustomName : {},
 
- 				// fixed list header colmun
 
- 				fixedHeader : true
 
- 			},
 
- 			// icons view setting
 
- 			iconsView : {
 
- 				// default icon size (0-3 in default CSS (cwd.css - elfinder-cwd-size[number]))
 
- 				size: 0,
 
- 				// number of maximum size (3 in default CSS (cwd.css - elfinder-cwd-size[number]))
 
- 				// uses in preference.js
 
- 				sizeMax: 3,
 
- 				// Name of each size
 
- 				sizeNames: {
 
- 					0: 'viewSmall',
 
- 					1: 'viewMedium',
 
- 					2: 'viewLarge',
 
- 					3: 'viewExtraLarge' 
 
- 				}
 
- 			},
 
- 			// /**
 
- 			//  * Add CSS class name to cwd directories (optional)
 
- 			//  * see: https://github.com/Studio-42/elFinder/pull/1061,
 
- 			//  *      https://github.com/Studio-42/elFinder/issues/1231
 
- 			//  * 
 
- 			//  * @type Function
 
- 			//  */
 
- 			// ,
 
- 			// getClass: function(file) {
 
- 			// 	// e.g. This adds the directory's name (lowercase) with prefix as a CSS class
 
- 			// 	return 'elfinder-cwd-' + file.name.replace(/[ "]/g, '').toLowerCase();
 
- 			//}
 
- 			
 
- 			//,
 
- 			//// Template placeholders replacement rules for overwrite. see ui/cwd.js replacement
 
- 			//replacement : {
 
- 			//	tooltip : function(f, fm) {
 
- 			//		var list = fm.viewType == 'list', // current view type
 
- 			//			query = fm.searchStatus.state == 2, // is in search results
 
- 			//			title = fm.formatDate(f) + (f.size > 0 ? ' ('+fm.formatSize(f.size)+')' : ''),
 
- 			//			info  = '';
 
- 			//		if (query && f.path) {
 
- 			//			info = fm.escape(f.path.replace(/\/[^\/]*$/, ''));
 
- 			//		} else {
 
- 			//			info = f.tooltip? fm.escape(f.tooltip).replace(/\r/g, '
') : '';
 
- 			//		}
 
- 			//		if (list) {
 
- 			//			info += (info? '
' : '') + fm.escape(f.name);
 
- 			//		}
 
- 			//		return info? info + '
' + title : title;
 
- 			//	}
 
- 			//}
 
- 		},
 
- 		path : {
 
- 			// Move to head of work zone without UI navbar
 
- 			toWorkzoneWithoutNavbar : true
 
- 		},
 
- 		dialog : {
 
- 			// Enable to auto focusing on mouse over in the target form element
 
- 			focusOnMouseOver : true
 
- 		},
 
- 		toast : {
 
- 			animate : {
 
- 				// to show
 
- 				showMethod: 'fadeIn', // fadeIn, slideDown, and show are built into jQuery
 
- 				showDuration: 300,    // milliseconds
 
- 				showEasing: 'swing',  // swing and linear are built into jQuery
 
- 				// timeout to hide
 
- 				timeOut: 3000,
 
- 				// to hide
 
- 				hideMethod: 'fadeOut',
 
- 				hideDuration: 1500,
 
- 				hideEasing: 'swing'
 
- 			}
 
- 		}
 
- 	},
 
- 	/**
 
- 	 * MIME regex of send HTTP header "Content-Disposition: inline" or allow preview in quicklook
 
- 	 * This option will overwrite by connector configuration
 
- 	 * 
 
- 	 * @type String
 
- 	 * @default '^(?:(?:image|video|audio)|text/plain|application/pdf$)'
 
- 	 * @example
 
- 	 *  dispInlineRegex : '.',  // is allow inline of all of MIME types
 
- 	 *  dispInlineRegex : '$^', // is not allow inline of all of MIME types
 
- 	 */
 
- 	dispInlineRegex : '^(?:(?:image|video|audio)|application/(?:x-mpegURL|dash\+xml)|(?:text/plain|application/pdf)$)',
 
- 	/**
 
- 	 * Display only required files by types
 
- 	 *
 
- 	 * @type Array
 
- 	 * @default []
 
- 	 * @example
 
- 	 *  onlyMimes : ["image"] - display all images
 
- 	 *  onlyMimes : ["image/png", "application/x-shockwave-flash"] - display png and flash
 
- 	 */
 
- 	onlyMimes : [],
 
- 	/**
 
- 	 * Custom files sort rules.
 
- 	 * All default rules (name/size/kind/date/perm/mode/owner/group) set in elFinder._sortRules
 
- 	 *
 
- 	 * @type {Object}
 
- 	 * @example
 
- 	 * sortRules : {
 
- 	 *   name : function(file1, file2) { return file1.name.toLowerCase().localeCompare(file2.name.toLowerCase()); }
 
- 	 * }
 
- 	 */
 
- 	sortRules : {},
 
- 	/**
 
- 	 * Default sort type.
 
- 	 *
 
- 	 * @type {String}
 
- 	 */
 
- 	sortType : 'name',
 
- 	
 
- 	/**
 
- 	 * Default sort order.
 
- 	 *
 
- 	 * @type {String}
 
- 	 * @default "asc"
 
- 	 */
 
- 	sortOrder : 'asc',
 
- 	
 
- 	/**
 
- 	 * Display folders first?
 
- 	 *
 
- 	 * @type {Boolean}
 
- 	 * @default true
 
- 	 */
 
- 	sortStickFolders : true,
 
- 	
 
- 	/**
 
- 	 * Sort also applies to the treeview
 
- 	 *
 
- 	 * @type {Boolean}
 
- 	 * @default false
 
- 	 */
 
- 	sortAlsoTreeview : false,
 
- 	
 
- 	/**
 
- 	 * If true - elFinder will formating dates itself, 
 
- 	 * otherwise - backend date will be used.
 
- 	 *
 
- 	 * @type Boolean
 
- 	 */
 
- 	clientFormatDate : true,
 
- 	
 
- 	/**
 
- 	 * Show UTC dates.
 
- 	 * Required set clientFormatDate to true
 
- 	 *
 
- 	 * @type Boolean
 
- 	 */
 
- 	UTCDate : false,
 
- 	
 
- 	/**
 
- 	 * File modification datetime format.
 
- 	 * Value from selected language data  is used by default.
 
- 	 * Set format here to overwrite it.
 
- 	 *
 
- 	 * @type String
 
- 	 * @default  ""
 
- 	 */
 
- 	dateFormat : '',
 
- 	
 
- 	/**
 
- 	 * File modification datetime format in form "Yesterday 12:23:01".
 
- 	 * Value from selected language data is used by default.
 
- 	 * Set format here to overwrite it.
 
- 	 * Use $1 for "Today"/"Yesterday" placeholder
 
- 	 *
 
- 	 * @type String
 
- 	 * @default  ""
 
- 	 * @example "$1 H:m:i"
 
- 	 */
 
- 	fancyDateFormat : '',
 
- 	
 
- 	/**
 
- 	 * Style of file mode at cwd-list, info dialog
 
- 	 * 'string' (ex. rwxr-xr-x) or 'octal' (ex. 755) or 'both' (ex. rwxr-xr-x (755))
 
- 	 * 
 
- 	 * @type {String}
 
- 	 * @default 'both'
 
- 	 */
 
- 	fileModeStyle : 'both',
 
- 	
 
- 	/**
 
- 	 * elFinder width
 
- 	 *
 
- 	 * @type String|Number
 
- 	 * @default  "auto"
 
- 	 */
 
- 	width : 'auto',
 
- 	
 
- 	/**
 
- 	 * elFinder node height
 
- 	 * Number: pixcel or String: Number + "%"
 
- 	 *
 
- 	 * @type Number | String
 
- 	 * @default  400
 
- 	 */
 
- 	height : 400,
 
- 	
 
- 	/**
 
- 	 * Base node object or selector
 
- 	 * Element which is the reference of the height percentage
 
- 	 *
 
- 	 * @type Object|String
 
- 	 * @default null | $(window) (if height is percentage)
 
- 	 **/
 
- 	heightBase : null,
 
- 	
 
- 	/**
 
- 	 * Make elFinder resizable if jquery ui resizable available
 
- 	 *
 
- 	 * @type Boolean
 
- 	 * @default  true
 
- 	 */
 
- 	resizable : true,
 
- 	
 
- 	/**
 
- 	 * Timeout before open notifications dialogs
 
- 	 *
 
- 	 * @type Number
 
- 	 * @default  500 (.5 sec)
 
- 	 */
 
- 	notifyDelay : 500,
 
- 	
 
- 	/**
 
- 	 * Position CSS, Width of notifications dialogs
 
- 	 *
 
- 	 * @type Object
 
- 	 * @default {position: {}, width : null} - Apply CSS definition
 
- 	 * position: CSS object | null (null: position center & middle)
 
- 	 */
 
- 	notifyDialog : {position: {}, width : null},
 
- 	
 
- 	/**
 
- 	 * Dialog contained in the elFinder node
 
- 	 * 
 
- 	 * @type Boolean
 
- 	 * @default false
 
- 	 */
 
- 	dialogContained : false,
 
- 	
 
- 	/**
 
- 	 * Allow shortcuts
 
- 	 *
 
- 	 * @type Boolean
 
- 	 * @default  true
 
- 	 */
 
- 	allowShortcuts : true,
 
- 	
 
- 	/**
 
- 	 * Remeber last opened dir to open it after reload or in next session
 
- 	 *
 
- 	 * @type Boolean
 
- 	 * @default  true
 
- 	 */
 
- 	rememberLastDir : true,
 
- 	
 
- 	/**
 
- 	 * Clear historys(elFinder) on reload(not browser) function
 
- 	 * Historys was cleared on Reload function on elFinder 2.0 (value is true)
 
- 	 * 
 
- 	 * @type Boolean
 
- 	 * @default  false
 
- 	 */
 
- 	reloadClearHistory : false,
 
- 	
 
- 	/**
 
- 	 * Use browser native history with supported browsers
 
- 	 *
 
- 	 * @type Boolean
 
- 	 * @default  true
 
- 	 */
 
- 	useBrowserHistory : true,
 
- 	
 
- 	/**
 
- 	 * Lazy load config.
 
- 	 * How many files display at once?
 
- 	 *
 
- 	 * @type Number
 
- 	 * @default  50
 
- 	 */
 
- 	showFiles : 50,
 
- 	
 
- 	/**
 
- 	 * Lazy load config.
 
- 	 * Distance in px to cwd bottom edge to start display files
 
- 	 *
 
- 	 * @type Number
 
- 	 * @default  50
 
- 	 */
 
- 	showThreshold : 50,
 
- 	
 
- 	/**
 
- 	 * Additional rule to valid new file name.
 
- 	 * By default not allowed empty names or '..'
 
- 	 * This setting does not have a sense of security.
 
- 	 *
 
- 	 * @type false|RegExp|function
 
- 	 * @default  false
 
- 	 * @example
 
- 	 *  disable names with spaces:
 
- 	 *  validName : /^[^\s]+$/,
 
- 	 */
 
- 	validName : false,
 
- 	
 
- 	/**
 
- 	 * Additional rule to filtering for browsing.
 
- 	 * This setting does not have a sense of security.
 
- 	 * 
 
- 	 * The object `this` is elFinder instance object in this function
 
- 	 *
 
- 	 * @type false|RegExp|function
 
- 	 * @default  false
 
- 	 * @example
 
- 	 *  show only png and jpg files:
 
- 	 *  fileFilter : /.*\.(png|jpg)$/i,
 
- 	 *  
 
- 	 *  show only image type files:
 
- 	 *  fileFilter : function(file) { return file.mime && file.mime.match(/^image\//i); },
 
- 	 */
 
- 	fileFilter : false,
 
- 	
 
- 	/**
 
- 	 * Backup name suffix.
 
- 	 *
 
- 	 * @type String
 
- 	 * @default  "~"
 
- 	 */
 
- 	backupSuffix : '~',
 
- 	
 
- 	/**
 
- 	 * Sync content interval
 
- 	 *
 
- 	 * @type Number
 
- 	 * @default  0 (do not sync)
 
- 	 */
 
- 	sync : 0,
 
- 	
 
- 	/**
 
- 	 * Sync start on load if sync value >= 1000
 
- 	 *
 
- 	 * @type     Bool
 
- 	 * @default  true
 
- 	 */
 
- 	syncStart : true,
 
- 	
 
- 	/**
 
- 	 * How many thumbnails create in one request
 
- 	 *
 
- 	 * @type Number
 
- 	 * @default  5
 
- 	 */
 
- 	loadTmbs : 5,
 
- 	
 
- 	/**
 
- 	 * Cookie option for browsersdoes not suppot localStorage
 
- 	 *
 
- 	 * @type Object
 
- 	 */
 
- 	cookie         : {
 
- 		expires : 30,
 
- 		domain  : '',
 
- 		path    : '/',
 
- 		secure  : false
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Contextmenu config
 
- 	 *
 
- 	 * @type Object
 
- 	 */
 
- 	contextmenu : {
 
- 		// navbarfolder menu
 
- 		navbar : ['open', 'opennew', 'download', '|', 'upload', 'mkdir', '|', 'copy', 'cut', 'paste', 'duplicate', '|', 'rm', 'empty', 'hide', '|', 'rename', '|', 'archive', '|', 'places', 'info', 'chmod', 'netunmount'],
 
- 		// current directory menu
 
- 		cwd    : ['undo', 'redo', '|', 'back', 'up', 'reload', '|', 'upload', 'mkdir', 'mkfile', 'paste', '|', 'empty', 'hide', '|', 'view', 'sort', 'selectall', 'colwidth', '|', 'places', 'info', 'chmod', 'netunmount', '|', 'fullscreen', '|', 'preference'],
 
- 		// current directory file menu
 
- 		files  : ['getfile', '|' ,'open', 'opennew', 'download', 'opendir', 'quicklook', '|', 'upload', 'mkdir', '|', 'copy', 'cut', 'paste', 'duplicate', '|', 'rm', 'empty', 'hide', '|', 'rename', 'edit', 'resize', '|', 'archive', 'extract', '|', 'selectall', 'selectinvert', '|', 'places', 'info', 'chmod', 'netunmount']
 
- 	},
 
- 	/**
 
- 	 * elFinder node enable always
 
- 	 * This value will set to `true` if <body> has elFinder node only
 
- 	 * 
 
- 	 * @type     Bool
 
- 	 * @default  false
 
- 	 */
 
- 	enableAlways : false,
 
- 	
 
- 	/**
 
- 	 * elFinder node enable by mouse over
 
- 	 * 
 
- 	 * @type     Bool
 
- 	 * @default  true
 
- 	 */
 
- 	enableByMouseOver : true,
 
- 	/**
 
- 	 * Show window close confirm dialog
 
- 	 * Value is which state to show
 
- 	 * 'hasNotifyDialog', 'editingFile', 'hasSelectedItem' and 'hasClipboardData'
 
- 	 * 
 
- 	 * @type     Array
 
- 	 * @default  ['hasNotifyDialog', 'editingFile']
 
- 	 */
 
- 	windowCloseConfirm : ['hasNotifyDialog', 'editingFile'],
 
- 	/**
 
- 	 * Function decoding 'raw' string converted to unicode
 
- 	 * It is used instead of fm.decodeRawString(str)
 
- 	 * 
 
- 	 * @type Null|Function
 
- 	 */
 
- 	rawStringDecoder : typeof Encoding === 'object' && $.isFunction(Encoding.convert)? function(str) {
 
- 		return Encoding.convert(str, {
 
- 			to: 'UNICODE',
 
- 			type: 'string'
 
- 		});
 
- 	} : null,
 
- 	/**
 
- 	 * Debug config
 
- 	 *
 
- 	 * @type Array|String('auto')|Boolean(true|false)
 
- 	 */
 
- 	// debug : true
 
- 	debug : ['error', 'warning', 'event-destroy']
 
- };
 
- /*
 
-  * File: /js/elFinder.options.netmount.js
 
-  */
 
- /**
 
-  * Default elFinder config of commandsOptions.netmount
 
-  *
 
-  * @type  Object
 
-  */
 
- elFinder.prototype._options.commandsOptions.netmount = {
 
- 	ftp: {
 
- 		name : 'FTP',
 
- 		inputs: {
 
- 			host     : $('<input type="text"/>'),
 
- 			port     : $('<input type="number" placeholder="21" class="elfinder-input-optional"/>'),
 
- 			path     : $('<input type="text" value="/"/>'),
 
- 			user     : $('<input type="text"/>'),
 
- 			pass     : $('<input type="password" autocomplete="new-password"/>'),
 
- 			FTPS     : $('<input type="checkbox" value="1" title="File Transfer Protocol over SSL/TLS"/>'),
 
- 			encoding : $('<input type="text" placeholder="Optional" class="elfinder-input-optional"/>'),
 
- 			locale   : $('<input type="text" placeholder="Optional" class="elfinder-input-optional"/>')
 
- 		}
 
- 	},
 
- 	dropbox2: elFinder.prototype.makeNetmountOptionOauth('dropbox2', 'Dropbox', 'Dropbox', {noOffline : true,
 
- 		root : '/',
 
- 		pathI18n : 'path',
 
- 		integrate : {
 
- 			title: 'Dropbox.com',
 
- 			link: 'https://www.dropbox.com'
 
- 		}
 
- 	}),
 
- 	googledrive: elFinder.prototype.makeNetmountOptionOauth('googledrive', 'Google Drive', 'Google', {
 
- 		integrate : {
 
- 			title: 'Google Drive',
 
- 			link: 'https://www.google.com/drive/'
 
- 		}
 
- 	}),
 
- 	onedrive: elFinder.prototype.makeNetmountOptionOauth('onedrive', 'One Drive', 'OneDrive', {
 
- 		integrate : {
 
- 			title: 'Microsoft OneDrive',
 
- 			link: 'https://onedrive.live.com'
 
- 		}
 
- 	}),
 
- 	box: elFinder.prototype.makeNetmountOptionOauth('box', 'Box', 'Box', {
 
- 		noOffline : true,
 
- 		integrate : {
 
- 			title: 'Box.com',
 
- 			link: 'https://www.box.com'
 
- 		}
 
- 	})
 
- };
 
- /*
 
-  * File: /js/elFinder.history.js
 
-  */
 
- /**
 
-  * @class elFinder.history
 
-  * Store visited folders
 
-  * and provide "back" and "forward" methods
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  */
 
- elFinder.prototype.history = function(fm) {
 
- 		var self = this,
 
- 		/**
 
- 		 * Update history on "open" event?
 
- 		 *
 
- 		 * @type Boolean
 
- 		 */
 
- 		update = true,
 
- 		/**
 
- 		 * Directories hashes storage
 
- 		 *
 
- 		 * @type Array
 
- 		 */
 
- 		history = [],
 
- 		/**
 
- 		 * Current directory index in history
 
- 		 *
 
- 		 * @type Number
 
- 		 */
 
- 		current,
 
- 		/**
 
- 		 * Clear history
 
- 		 *
 
- 		 * @return void
 
- 		 */
 
- 		reset = function() {
 
- 			history = [fm.cwd().hash];
 
- 			current = 0;
 
- 			update  = true;
 
- 		},
 
- 		/**
 
- 		 * Browser native history object
 
- 		 */
 
- 		nativeHistory = (fm.options.useBrowserHistory && window.history && window.history.pushState)? window.history : null,
 
- 		/**
 
- 		 * Open prev/next folder
 
- 		 *
 
- 		 * @Boolen  open next folder?
 
- 		 * @return jQuery.Deferred
 
- 		 */
 
- 		go = function(fwd) {
 
- 			if ((fwd && self.canForward()) || (!fwd && self.canBack())) {
 
- 				update = false;
 
- 				return fm.exec('open', history[fwd ? ++current : --current]).fail(reset);
 
- 			}
 
- 			return $.Deferred().reject();
 
- 		},
 
- 		/**
 
- 		 * Sets the native history.
 
- 		 *
 
- 		 * @param String thash target hash
 
- 		 */
 
- 		setNativeHistory = function(thash) {
 
- 			if (nativeHistory && (! nativeHistory.state || nativeHistory.state.thash !== thash)) {
 
- 				nativeHistory.pushState({thash: thash}, null, location.pathname + location.search + (thash? '#elf_' + thash : ''));
 
- 			}
 
- 		};
 
- 	
 
- 	/**
 
- 	 * Return true if there is previous visited directories
 
- 	 *
 
- 	 * @return Boolen
 
- 	 */
 
- 	this.canBack = function() {
 
- 		return current > 0;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return true if can go forward
 
- 	 *
 
- 	 * @return Boolen
 
- 	 */
 
- 	this.canForward = function() {
 
- 		return current < history.length - 1;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Go back
 
- 	 *
 
- 	 * @return void
 
- 	 */
 
- 	this.back = go;
 
- 	
 
- 	/**
 
- 	 * Go forward
 
- 	 *
 
- 	 * @return void
 
- 	 */
 
- 	this.forward = function() {
 
- 		return go(true);
 
- 	};
 
- 	
 
- 	// bind to elfinder events
 
- 	fm.bind('init', function() {
 
- 		if (nativeHistory && !nativeHistory.state) {
 
- 			setNativeHistory(fm.startDir());
 
- 		}
 
- 	})
 
- 	.open(function() {
 
- 		var l = history.length,
 
- 			cwd = fm.cwd().hash;
 
- 		if (update) {
 
- 			current >= 0 && l > current + 1 && history.splice(current+1);
 
- 			history[history.length-1] != cwd && history.push(cwd);
 
- 			current = history.length - 1;
 
- 		}
 
- 		update = true;
 
- 		setNativeHistory(cwd);
 
- 	})
 
- 	.reload(fm.options.reloadClearHistory && reset);
 
- 	
 
- };
 
- /*
 
-  * File: /js/elFinder.command.js
 
-  */
 
- /**
 
-  * elFinder command prototype
 
-  *
 
-  * @type  elFinder.command
 
-  * @author  Dmitry (dio) Levashov
 
-  */
 
- elFinder.prototype.command = function(fm) {
 
- 		/**
 
- 	 * elFinder instance
 
- 	 *
 
- 	 * @type  elFinder
 
- 	 */
 
- 	this.fm = fm;
 
- 	
 
- 	/**
 
- 	 * Command name, same as class name
 
- 	 *
 
- 	 * @type  String
 
- 	 */
 
- 	this.name = '';
 
- 	
 
- 	/**
 
- 	 * Dialog class name
 
- 	 *
 
- 	 * @type  String
 
- 	 */
 
- 	this.dialogClass = '';
 
- 	/**
 
- 	 * Command icon class name with out 'elfinder-button-icon-'
 
- 	 * Use this.name if it is empty
 
- 	 *
 
- 	 * @type  String
 
- 	 */
 
- 	this.className = '';
 
- 	/**
 
- 	 * Short command description
 
- 	 *
 
- 	 * @type  String
 
- 	 */
 
- 	this.title = '';
 
- 	
 
- 	/**
 
- 	 * Linked(Child) commands name
 
- 	 * They are loaded together when tthis command is loaded.
 
- 	 * 
 
- 	 * @type  Array
 
- 	 */
 
- 	this.linkedCmds = [];
 
- 	
 
- 	/**
 
- 	 * Current command state
 
- 	 *
 
- 	 * @example
 
- 	 * this.state = -1; // command disabled
 
- 	 * this.state = 0;  // command enabled
 
- 	 * this.state = 1;  // command active (for example "fullscreen" command while elfinder in fullscreen mode)
 
- 	 * @default -1
 
- 	 * @type  Number
 
- 	 */
 
- 	this.state = -1;
 
- 	
 
- 	/**
 
- 	 * If true, command can not be disabled by connector.
 
- 	 * @see this.update()
 
- 	 *
 
- 	 * @type  Boolen
 
- 	 */
 
- 	this.alwaysEnabled = false;
 
- 	
 
- 	/**
 
- 	 * Do not change dirctory on removed current work directory
 
- 	 * 
 
- 	 * @type  Boolen
 
- 	 */
 
- 	this.noChangeDirOnRemovedCwd = false;
 
- 	
 
- 	/**
 
- 	 * If true, this means command was disabled by connector.
 
- 	 * @see this.update()
 
- 	 *
 
- 	 * @type  Boolen
 
- 	 */
 
- 	this._disabled = false;
 
- 	
 
- 	/**
 
- 	 * If true, this command is disabled on serach results
 
- 	 * 
 
- 	 * @type  Boolean
 
- 	 */
 
- 	this.disableOnSearch = false;
 
- 	
 
- 	/**
 
- 	 * Call update() when event select fired
 
- 	 * 
 
- 	 * @type  Boolean
 
- 	 */
 
- 	this.updateOnSelect = true;
 
- 	
 
- 	/**
 
- 	 * Sync toolbar button title on change
 
- 	 * 
 
- 	 * @type  Boolean
 
- 	 */
 
- 	this.syncTitleOnChange = false;
 
- 	/**
 
- 	 * Keep display of the context menu when command execution
 
- 	 * 
 
- 	 * @type  Boolean
 
- 	 */
 
- 	this.keepContextmenu = false;
 
- 	
 
- 	/**
 
- 	 * elFinder events defaults handlers.
 
- 	 * Inside handlers "this" is current command object
 
- 	 *
 
- 	 * @type  Object
 
- 	 */
 
- 	this._handlers = {
 
- 		enable  : function() { this.update(void(0), this.value); },
 
- 		disable : function() { this.update(-1, this.value); },
 
- 		'open reload load sync'    : function() { 
 
- 			this._disabled = !(this.alwaysEnabled || this.fm.isCommandEnabled(this.name));
 
- 			this.update(void(0), this.value);
 
- 			this.change(); 
 
- 		}
 
- 	};
 
- 	
 
- 	/**
 
- 	 * elFinder events handlers.
 
- 	 * Inside handlers "this" is current command object
 
- 	 *
 
- 	 * @type  Object
 
- 	 */
 
- 	this.handlers = {};
 
- 	
 
- 	/**
 
- 	 * Shortcuts
 
- 	 *
 
- 	 * @type  Array
 
- 	 */
 
- 	this.shortcuts = [];
 
- 	
 
- 	/**
 
- 	 * Command options
 
- 	 *
 
- 	 * @type  Object
 
- 	 */
 
- 	this.options = {ui : 'button'};
 
- 	
 
- 	/**
 
- 	 * Callback functions on `change` event
 
- 	 * 
 
- 	 * @type  Array
 
- 	 */
 
- 	this.listeners = [];
 
- 	/**
 
- 	 * Prepare object -
 
- 	 * bind events and shortcuts
 
- 	 *
 
- 	 * @return void
 
- 	 */
 
- 	this.setup = function(name, opts) {
 
- 		var self = this,
 
- 			fm   = this.fm,
 
- 			setCallback = function(s) {
 
- 				var cb = s.callback || function(e) {
 
- 							fm.exec(self.name, void(0), {
 
- 							_userAction: true,
 
- 							_currentType: 'shortcut'
 
- 						});
 
- 					};
 
- 				s.callback = function(e) {
 
- 					var enabled, checks = {};
 
- 					if (self.enabled()) {
 
- 						if (fm.searchStatus.state < 2) {
 
- 							enabled = fm.isCommandEnabled(self.name);
 
- 						} else {
 
- 							$.each(fm.selected(), function(i, h) {
 
- 								if (fm.optionsByHashes[h]) {
 
- 									checks[h] = true;
 
- 								} else {
 
- 									$.each(fm.volOptions, function(id) {
 
- 										if (!checks[id] && h.indexOf(id) === 0) {
 
- 											checks[id] = true;
 
- 											return false;
 
- 										}
 
- 									});
 
- 								}
 
- 							});
 
- 							$.each(checks, function(h) {
 
- 								enabled = fm.isCommandEnabled(self.name, h);
 
- 								if (! enabled) {
 
- 									return false;
 
- 								}
 
- 							});
 
- 						}
 
- 						if (enabled) {
 
- 							self.event = e;
 
- 							cb.call(self);
 
- 							delete self.event;
 
- 						}
 
- 					}
 
- 				};
 
- 			},
 
- 			i, s, sc;
 
- 		this.name      = name;
 
- 		this.title     = fm.messages['cmd'+name] ? fm.i18n('cmd'+name)
 
- 		               : ((this.extendsCmd && fm.messages['cmd'+this.extendsCmd]) ? fm.i18n('cmd'+this.extendsCmd) : name);
 
- 		this.options   = Object.assign({}, this.options, opts);
 
- 		this.listeners = [];
 
- 		this.dialogClass = 'elfinder-dialog-' + name;
 
- 		if (opts.shortcuts) {
 
- 			if (typeof opts.shortcuts === 'function') {
 
- 				sc = opts.shortcuts(this.fm, this.shortcuts);
 
- 			} else if (Array.isArray(opts.shortcuts)) {
 
- 				sc = opts.shortcuts;
 
- 			}
 
- 			this.shortcuts = sc || [];
 
- 		}
 
- 		if (this.updateOnSelect) {
 
- 			this._handlers.select = function() { this.update(void(0), this.value); };
 
- 		}
 
- 		$.each(Object.assign({}, self._handlers, self.handlers), function(cmd, handler) {
 
- 			fm.bind(cmd, $.proxy(handler, self));
 
- 		});
 
- 		for (i = 0; i < this.shortcuts.length; i++) {
 
- 			s = this.shortcuts[i];
 
- 			setCallback(s);
 
- 			!s.description && (s.description = this.title);
 
- 			fm.shortcut(s);
 
- 		}
 
- 		if (this.disableOnSearch) {
 
- 			fm.bind('search searchend', function() {
 
- 				self._disabled = this.type === 'search'? true : ! (this.alwaysEnabled || fm.isCommandEnabled(name));
 
- 				self.update(void(0), self.value);
 
- 			});
 
- 		}
 
- 		this.init();
 
- 	};
 
- 	/**
 
- 	 * Command specific init stuffs
 
- 	 *
 
- 	 * @return void
 
- 	 */
 
- 	this.init = function() {};
 
- 	/**
 
- 	 * Exec command
 
- 	 *
 
- 	 * @param  Array         target files hashes
 
- 	 * @param  Array|Object  command value
 
- 	 * @return $.Deferred
 
- 	 */
 
- 	this.exec = function(files, opts) { 
 
- 		return $.Deferred().reject(); 
 
- 	};
 
- 	
 
- 	this.getUndo = function(opts, resData) {
 
- 		return false;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return true if command disabled.
 
- 	 *
 
- 	 * @return Boolen
 
- 	 */
 
- 	this.disabled = function() {
 
- 		return this.state < 0;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return true if command enabled.
 
- 	 *
 
- 	 * @return Boolen
 
- 	 */
 
- 	this.enabled = function() {
 
- 		return this.state > -1;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return true if command active.
 
- 	 *
 
- 	 * @return Boolen
 
- 	 */
 
- 	this.active = function() {
 
- 		return this.state > 0;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return current command state.
 
- 	 * Must be overloaded in most commands
 
- 	 *
 
- 	 * @return Number
 
- 	 */
 
- 	this.getstate = function() {
 
- 		return -1;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Update command state/value
 
- 	 * and rize 'change' event if smth changed
 
- 	 *
 
- 	 * @param  Number  new state or undefined to auto update state
 
- 	 * @param  mixed   new value
 
- 	 * @return void
 
- 	 */
 
- 	this.update = function(s, v) {
 
- 		var state = this.state,
 
- 			value = this.value;
 
- 		if (this._disabled && this.fm.searchStatus === 0) {
 
- 			this.state = -1;
 
- 		} else {
 
- 			this.state = s !== void(0) ? s : this.getstate();
 
- 		}
 
- 		this.value = v;
 
- 		
 
- 		if (state != this.state || value != this.value) {
 
- 			this.change();
 
- 		}
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Bind handler / fire 'change' event.
 
- 	 *
 
- 	 * @param  Function|undefined  event callback
 
- 	 * @return void
 
- 	 */
 
- 	this.change = function(c) {
 
- 		var cmd, i;
 
- 		
 
- 		if (typeof(c) === 'function') {
 
- 			this.listeners.push(c);			
 
- 		} else {
 
- 			for (i = 0; i < this.listeners.length; i++) {
 
- 				cmd = this.listeners[i];
 
- 				try {
 
- 					cmd(this.state, this.value);
 
- 				} catch (e) {
 
- 					this.fm.debug('error', e);
 
- 				}
 
- 			}
 
- 		}
 
- 		return this;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * With argument check given files hashes and return list of existed files hashes.
 
- 	 * Without argument return selected files hashes.
 
- 	 *
 
- 	 * @param  Array|String|void  hashes
 
- 	 * @return Array
 
- 	 */
 
- 	this.hashes = function(hashes) {
 
- 		return hashes
 
- 			? $.grep(Array.isArray(hashes) ? hashes : [hashes], function(hash) { return fm.file(hash) ? true : false; })
 
- 			: fm.selected();
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return only existed files from given fils hashes | selected files
 
- 	 *
 
- 	 * @param  Array|String|void  hashes
 
- 	 * @return Array
 
- 	 */
 
- 	this.files = function(hashes) {
 
- 		var fm = this.fm;
 
- 		
 
- 		return hashes
 
- 			? $.map(Array.isArray(hashes) ? hashes : [hashes], function(hash) { return fm.file(hash) || null; })
 
- 			: fm.selectedFiles();
 
- 	};
 
- 	/**
 
- 	 * Wrapper to fm.dialog()
 
- 	 *
 
- 	 * @param  String|DOMElement  content
 
- 	 * @param  Object             options
 
- 	 * @return Object             jQuery element object
 
- 	 */
 
- 	this.fmDialog = function(content, options) {
 
- 		if (options.cssClass) {
 
- 			options.cssClass += ' ' + this.dialogClass;
 
- 		} else {
 
- 			options.cssClass = this.dialogClass;
 
- 		}
 
- 		return this.fm.dialog(content, options);
 
- 	};
 
- };
 
- /*
 
-  * File: /js/elFinder.resources.js
 
-  */
 
- /**
 
-  * elFinder resources registry.
 
-  * Store shared data
 
-  *
 
-  * @type Object
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- elFinder.prototype.resources = {
 
- 	'class' : {
 
- 		hover       : 'ui-state-hover',
 
- 		active      : 'ui-state-active',
 
- 		disabled    : 'ui-state-disabled',
 
- 		draggable   : 'ui-draggable',
 
- 		droppable   : 'ui-droppable',
 
- 		adroppable  : 'elfinder-droppable-active',
 
- 		cwdfile     : 'elfinder-cwd-file',
 
- 		cwd         : 'elfinder-cwd',
 
- 		tree        : 'elfinder-tree',
 
- 		treeroot    : 'elfinder-navbar-root',
 
- 		navdir      : 'elfinder-navbar-dir',
 
- 		navdirwrap  : 'elfinder-navbar-dir-wrapper',
 
- 		navarrow    : 'elfinder-navbar-arrow',
 
- 		navsubtree  : 'elfinder-navbar-subtree',
 
- 		navcollapse : 'elfinder-navbar-collapsed',
 
- 		navexpand   : 'elfinder-navbar-expanded',
 
- 		treedir     : 'elfinder-tree-dir',
 
- 		placedir    : 'elfinder-place-dir',
 
- 		searchbtn   : 'elfinder-button-search',
 
- 		editing     : 'elfinder-to-editing',
 
- 		preventback : 'elfinder-prevent-back',
 
- 		tabstab     : 'ui-state-default ui-tabs-tab ui-corner-top ui-tab',
 
- 		tabsactive  : 'ui-tabs-active ui-state-active'
 
- 	},
 
- 	tpl : {
 
- 		perms      : '<span class="elfinder-perms"/>',
 
- 		lock       : '<span class="elfinder-lock"/>',
 
- 		symlink    : '<span class="elfinder-symlink"/>',
 
- 		navicon    : '<span class="elfinder-nav-icon"/>',
 
- 		navspinner : '<span class="elfinder-spinner elfinder-navbar-spinner"/>',
 
- 		navdir     : '<div class="elfinder-navbar-wrapper{root}"><span id="{id}" class="ui-corner-all elfinder-navbar-dir {cssclass}"><span class="elfinder-navbar-arrow"/><span class="elfinder-navbar-icon" {style}/>{symlink}{permissions}{name}</span><div class="elfinder-navbar-subtree" style="display:none"/></div>',
 
- 		placedir   : '<div class="elfinder-navbar-wrapper"><span id="{id}" class="ui-corner-all elfinder-navbar-dir {cssclass}" title="{title}"><span class="elfinder-navbar-arrow"/><span class="elfinder-navbar-icon" {style}/>{symlink}{permissions}{name}</span><div class="elfinder-navbar-subtree" style="display:none"/></div>'
 
- 		
 
- 	},
 
- 	// mimes.text will be overwritten with connector config if `textMimes` is included in initial response
 
- 	// @see php/elFInder.class.php `public static $textMimes`
 
- 	mimes : {
 
- 		text : [
 
- 			'application/dash+xml',
 
- 			'application/docbook+xml',
 
- 			'application/javascript',
 
- 			'application/json',
 
- 			'application/plt',
 
- 			'application/sat',
 
- 			'application/sql',
 
- 			'application/step',
 
- 			'application/vnd.hp-hpgl',
 
- 			'application/x-awk',
 
- 			'application/x-config',
 
- 			'application/x-csh',
 
- 			'application/x-empty',
 
- 			'application/x-mpegurl',
 
- 			'application/x-perl',
 
- 			'application/x-php',
 
- 			'application/x-web-config',
 
- 			'application/xhtml+xml',
 
- 			'application/xml',
 
- 			'audio/x-mp3-playlist',
 
- 			'image/cgm',
 
- 			'image/svg+xml',
 
- 			'image/vnd.dxf',
 
- 			'model/iges'
 
- 		]
 
- 	},
 
- 	
 
- 	mixin : {
 
- 		make : function() {
 
- 						var self = this,
 
- 				fm   = this.fm,
 
- 				cmd  = this.name,
 
- 				req  = this.requestCmd || cmd,
 
- 				wz   = fm.getUI('workzone'),
 
- 				org  = (this.origin && this.origin === 'navbar')? 'tree' : 'cwd',
 
- 				ui   = fm.getUI(org),
 
- 				tree = (org === 'tree'),
 
- 				find = tree? 'navHash2Id' : 'cwdHash2Id',
 
- 				tarea= (! tree && fm.storage('view') != 'list'),
 
- 				sel  = fm.selected(),
 
- 				move = this.move || false,
 
- 				empty= wz.hasClass('elfinder-cwd-wrapper-empty'),
 
- 				unselect = function() {
 
- 					requestAnimationFrame(function() {
 
- 						input && input.trigger('blur');
 
- 					});
 
- 				},
 
- 				rest = function(){
 
- 					if (!overlay.is(':hidden')) {
 
- 						overlay.elfinderoverlay('hide').off('click close', cancel);
 
- 					}
 
- 					pnode.removeClass('ui-front')
 
- 						.css('position', '')
 
- 						.off('unselect.'+fm.namespace, unselect);
 
- 					if (tarea) {
 
- 						nnode && nnode.css('max-height', '');
 
- 					} else if (!tree) {
 
- 						pnode.css('width', '')
 
- 							.parent('td').css('overflow', '');
 
- 					}
 
- 				}, colwidth,
 
- 				dfrd = $.Deferred()
 
- 					.fail(function(error) {
 
- 						dstCls && dst.attr('class', dstCls);
 
- 						empty && wz.addClass('elfinder-cwd-wrapper-empty');
 
- 						if (sel) {
 
- 							move && fm.trigger('unlockfiles', {files: sel});
 
- 							fm.clipboard([]);
 
- 							fm.trigger('selectfiles', { files: sel });
 
- 						}
 
- 						error && fm.error(error);
 
- 					})
 
- 					.always(function() {
 
- 						rest();
 
- 						cleanup();
 
- 						fm.enable().unbind('open', openCallback).trigger('resMixinMake');
 
- 					}),
 
- 				id    = 'tmp_'+parseInt(Math.random()*100000),
 
- 				phash = this.data && this.data.target? this.data.target : (tree? fm.file(sel[0]).hash : fm.cwd().hash),
 
- 				date = new Date(),
 
- 				file   = {
 
- 					hash  : id,
 
- 					phash : phash,
 
- 					name  : fm.uniqueName(this.prefix, phash),
 
- 					mime  : this.mime,
 
- 					read  : true,
 
- 					write : true,
 
- 					date  : 'Today '+date.getHours()+':'+date.getMinutes(),
 
- 					move  : move
 
- 				},
 
- 				data = this.data || {},
 
- 				node = ui.trigger('create.'+fm.namespace, file).find('#'+fm[find](id)),
 
- 				nnode, pnode,
 
- 				overlay = fm.getUI('overlay'),
 
- 				cleanup = function() {
 
- 					if (node && node.length) {
 
- 						input.off();
 
- 						node.hide();
 
- 						fm.unselectfiles({files : [id]}).unbind('resize', resize);
 
- 						requestAnimationFrame(function() {
 
- 							if (tree) {
 
- 								node.closest('.elfinder-navbar-wrapper').remove();
 
- 							} else {
 
- 								node.remove();
 
- 							}
 
- 						});
 
- 					}
 
- 				},
 
- 				cancel = function(e) { 
 
- 					if (!overlay.is(':hidden')) {
 
- 						pnode.css('z-index', '');
 
- 					}
 
- 					if (! inError) {
 
- 						cleanup();
 
- 						dfrd.reject();
 
- 						if (e) {
 
- 							e.stopPropagation();
 
- 							e.preventDefault();
 
- 						}
 
- 					}
 
- 				},
 
- 				input = $(tarea? '<textarea/>' : '<input type="text"/>')
 
- 					.on('keyup text', function(){
 
- 						if (tarea) {
 
- 							this.style.height = '1px';
 
- 							this.style.height = this.scrollHeight + 'px';
 
- 						} else if (colwidth) {
 
- 							this.style.width = colwidth + 'px';
 
- 							if (this.scrollWidth > colwidth) {
 
- 								this.style.width = this.scrollWidth + 10 + 'px';
 
- 							}
 
- 						}
 
- 					})
 
- 					.on('keydown', function(e) {
 
- 						e.stopImmediatePropagation();
 
- 						if (e.keyCode == $.ui.keyCode.ESCAPE) {
 
- 							dfrd.reject();
 
- 						} else if (e.keyCode == $.ui.keyCode.ENTER) {
 
- 							input.trigger('blur');
 
- 						}
 
- 					})
 
- 					.on('mousedown click dblclick', function(e) {
 
- 						e.stopPropagation();
 
- 						if (e.type === 'dblclick') {
 
- 							e.preventDefault();
 
- 						}
 
- 					})
 
- 					.on('blur', function() {
 
- 						var name   = $.trim(input.val()),
 
- 							parent = input.parent(),
 
- 							valid  = true,
 
- 							cut;
 
- 						if (!overlay.is(':hidden')) {
 
- 							pnode.css('z-index', '');
 
- 						}
 
- 						if (name === '') {
 
- 							return cancel();
 
- 						}
 
- 						if (!inError && parent.length) {
 
- 							if (fm.options.validName && fm.options.validName.test) {
 
- 								try {
 
- 									valid = fm.options.validName.test(name);
 
- 								} catch(e) {
 
- 									valid = false;
 
- 								}
 
- 							}
 
- 							if (!name || name === '.' || name === '..' || !valid) {
 
- 								inError = true;
 
- 								fm.error(file.mime === 'directory'? 'errInvDirname' : 'errInvName', {modal: true, close: function(){setTimeout(select, 120);}});
 
- 								return false;
 
- 							}
 
- 							if (fm.fileByName(name, phash)) {
 
- 								inError = true;
 
- 								fm.error(['errExists', name], {modal: true, close: function(){setTimeout(select, 120);}});
 
- 								return false;
 
- 							}
 
- 							cut = (sel && move)? fm.exec('cut', sel) : null;
 
- 							$.when(cut)
 
- 							.done(function() {
 
- 								var toast   = {},
 
- 									nextAct = {};
 
- 								
 
- 								rest();
 
- 								input.hide().before($('<span>').text(name));
 
- 								fm.lockfiles({files : [id]});
 
- 								fm.request({
 
- 										data        : Object.assign({cmd : req, name : name, target : phash}, data || {}), 
 
- 										notify      : {type : req, cnt : 1},
 
- 										preventFail : true,
 
- 										syncOnFail  : true,
 
- 										navigate    : {toast : toast},
 
- 									})
 
- 									.fail(function(error) {
 
- 										fm.unlockfiles({files : [id]});
 
- 										inError = true;
 
- 										input.show().prev().remove();
 
- 										fm.error(error, {
 
- 											modal: true,
 
- 											close: function() {
 
- 												if (Array.isArray(error) && $.inArray('errUploadMime', error) !== -1) {
 
- 													dfrd.notify('errUploadMime').reject();
 
- 												} else {
 
- 													setTimeout(select, 120);
 
- 												}
 
- 											}
 
- 										});
 
- 									})
 
- 									.done(function(data) {
 
- 										if (data && data.added && data.added[0]) {
 
- 											var item    = data.added[0],
 
- 												dirhash = item.hash,
 
- 												newItem = ui.find('#'+fm[find](dirhash)),
 
- 												acts    = {
 
- 													'directory' : { cmd: 'open', msg: 'cmdopendir' },
 
- 													'text'      : { cmd: 'edit', msg: 'cmdedit' },
 
- 													'default'   : { cmd: 'open', msg: 'cmdopen' }
 
- 												},
 
- 												tmpMimes;
 
- 											if (sel && move) {
 
- 												fm.one(req+'done', function() {
 
- 													fm.exec('paste', dirhash);
 
- 												});
 
- 											}
 
- 											if (!move) {
 
- 												if (fm.mimeIsText(item.mime) && !fm.mimesCanMakeEmpty[item.mime] && fm.mimeTypes[item.mime]) {
 
- 													fm.trigger('canMakeEmptyFile', {mimes: [item.mime], unshift: true});
 
- 													tmpMimes = {};
 
- 													tmpMimes[item.mime] = fm.mimeTypes[item.mime];
 
- 													fm.storage('mkfileTextMimes', Object.assign(tmpMimes, fm.storage('mkfileTextMimes') || {}));
 
- 												}
 
- 												Object.assign(nextAct, nextAction || acts[item.mime] || acts[item.mime.split('/')[0]] || acts[(fm.mimesCanMakeEmpty[item.mime] || $.inArray(item.mime, fm.resources.mimes.text) !== -1) ? 'text' : 'none'] || acts['default']);
 
- 												Object.assign(toast, nextAct.cmd ? {
 
- 													incwd    : {msg: fm.i18n(['complete', fm.i18n('cmd'+cmd)]), action: nextAct},
 
- 													inbuffer : {msg: fm.i18n(['complete', fm.i18n('cmd'+cmd)]), action: nextAct}
 
- 												} : {
 
- 													inbuffer : {msg: fm.i18n(['complete', fm.i18n('cmd'+cmd)])}
 
- 												});
 
- 											}
 
- 										}
 
- 										dfrd.resolve(data);
 
- 									});
 
- 							})
 
- 							.fail(function() {
 
- 								dfrd.reject();
 
- 							});
 
- 						}
 
- 					})
 
- 					.on('dragenter dragleave dragover drop', function(e) {
 
- 						// stop bubbling to prevent upload with native drop event
 
- 						e.stopPropagation();
 
- 					}),
 
- 				select = function() {
 
- 					var name = fm.splitFileExtention(input.val())[0];
 
- 					if (!inError && fm.UA.Mobile && !fm.UA.iOS) { // since iOS has a bug? (z-index not effect) so disable it
 
- 						overlay.on('click close', cancel).elfinderoverlay('show');
 
- 						pnode.css('z-index', overlay.css('z-index') + 1);
 
- 					}
 
- 					inError = false;
 
- 					! fm.enabled() && fm.enable();
 
- 					input.trigger('focus').trigger('select');
 
- 					input[0].setSelectionRange && input[0].setSelectionRange(0, name.length);
 
- 				},
 
- 				resize = function() {
 
- 					node.trigger('scrolltoview', {blink : false});
 
- 				},
 
- 				openCallback = function() {
 
- 					dfrd && (dfrd.state() === 'pending') && dfrd.reject();
 
- 				},
 
- 				inError = false,
 
- 				nextAction,
 
- 				// for tree
 
- 				dst, dstCls, collapsed, expanded, arrow, subtree;
 
- 			if (!fm.isCommandEnabled(req, phash) || !node.length) {
 
- 				return dfrd.reject();
 
- 			}
 
- 			if ($.isPlainObject(self.nextAction)){
 
- 				nextAction = Object.assign({}, self.nextAction);
 
- 			}
 
- 			
 
- 			if (tree) {
 
- 				dst = $('#'+fm[find](phash));
 
- 				collapsed = fm.res('class', 'navcollapse');
 
- 				expanded  = fm.res('class', 'navexpand');
 
- 				arrow = fm.res('class', 'navarrow');
 
- 				subtree = fm.res('class', 'navsubtree');
 
- 				
 
- 				node.closest('.'+subtree).show();
 
- 				if (! dst.hasClass(collapsed)) {
 
- 					dstCls = dst.attr('class');
 
- 					dst.addClass(collapsed+' '+expanded+' elfinder-subtree-loaded');
 
- 				}
 
- 				if (dst.is('.'+collapsed+':not(.'+expanded+')')) {
 
- 					dst.children('.'+arrow).trigger('click').data('dfrd').done(function() {
 
- 						if (input.val() === file.name) {
 
- 							input.val(fm.uniqueName(self.prefix, phash)).trigger('select').trigger('focus');
 
- 						}
 
- 					});
 
- 				}
 
- 				nnode = node.contents().filter(function(){ return this.nodeType==3 && $(this).parent().attr('id') === fm.navHash2Id(file.hash); });
 
- 				pnode = nnode.parent();
 
- 				nnode.replaceWith(input.val(file.name));
 
- 			} else {
 
- 				empty && wz.removeClass('elfinder-cwd-wrapper-empty');
 
- 				nnode = node.find('.elfinder-cwd-filename');
 
- 				pnode = nnode.parent();
 
- 				if (tarea) {
 
- 					nnode.css('max-height', 'none');
 
- 				} else {
 
- 					colwidth = pnode.width();
 
- 					pnode.width(colwidth - 15)
 
- 						.parent('td').css('overflow', 'visible');
 
- 				}
 
- 				nnode.empty().append(input.val(file.name));
 
- 			}
 
- 			pnode.addClass('ui-front')
 
- 				.css('position', 'relative')
 
- 				.on('unselect.'+fm.namespace, unselect);
 
- 			
 
- 			fm.bind('resize', resize).one('open', openCallback);
 
- 			
 
- 			input.trigger('keyup');
 
- 			select();
 
- 			return dfrd;
 
- 		}
 
- 	},
 
- 	blink: function(elm, mode) {
 
- 				var acts = {
 
- 			slowonce : function(){elm.hide().delay(250).fadeIn(750).delay(500).fadeOut(3500);},
 
- 			lookme   : function(){elm.show().fadeOut(500).fadeIn(750);}
 
- 		}, func;
 
- 		mode = mode || 'slowonce';
 
- 		
 
- 		func = acts[mode] || acts['lookme'];
 
- 		
 
- 		elm.stop(true, true);
 
- 		func();
 
- 	}
 
- };
 
- /*
 
-  * File: /js/jquery.dialogelfinder.js
 
-  */
 
- /**
 
-  * @class dialogelfinder - open elFinder in dialog window
 
-  *
 
-  * @param  Object  elFinder options with dialog options
 
-  * @example
 
-  * $(selector).dialogelfinder({
 
-  *     // some elfinder options
 
-  *     title          : 'My files', // dialog title, default = "Files"
 
-  *     width          : 850,        // dialog width, default 840
 
-  *     autoOpen       : false,      // if false - dialog will not be opened after init, default = true
 
-  *     destroyOnClose : true        // destroy elFinder on close dialog, default = false
 
-  * })
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.dialogelfinder = function(opts) {
 
- 		var position = 'elfinderPosition',
 
- 		destroy  = 'elfinderDestroyOnClose',
 
- 		node;
 
- 	
 
- 	this.not('.elfinder').each(function() {
 
- 		
 
- 		var doc     = $(document),
 
- 			toolbar = $('<div class="ui-widget-header dialogelfinder-drag ui-corner-top">'+(opts.title || 'Files')+'</div>'),
 
- 			button  = $('<a href="#" class="dialogelfinder-drag-close ui-corner-all"><span class="ui-icon ui-icon-closethick"> </span></a>')
 
- 				.appendTo(toolbar)
 
- 				.on('click', function(e) {
 
- 					e.preventDefault();
 
- 					
 
- 					node.dialogelfinder('close');
 
- 				}),
 
- 			node    = $(this).addClass('dialogelfinder')
 
- 				.css('position', 'absolute')
 
- 				.hide()
 
- 				.appendTo('body')
 
- 				.draggable({
 
- 					handle : '.dialogelfinder-drag',
 
- 					containment : 'window',
 
- 					stop : function() {
 
- 						node.trigger('resize');
 
- 						elfinder.trigger('resize');
 
- 					}
 
- 				})
 
- 				.elfinder(opts)
 
- 				.prepend(toolbar),
 
- 			elfinder = node.elfinder('instance');
 
- 		
 
- 		
 
- 		node.width(parseInt(node.width()) || 840) // fix width if set to "auto"
 
- 			.data(destroy, !!opts.destroyOnClose)
 
- 			.find('.elfinder-toolbar').removeClass('ui-corner-top');
 
- 		
 
- 		opts.position && node.data(position, opts.position);
 
- 		
 
- 		opts.autoOpen !== false && $(this).dialogelfinder('open');
 
- 	});
 
- 	
 
- 	if (opts == 'open') {
 
- 		var node = $(this),
 
- 			pos  = node.data(position) || {
 
- 				top  : parseInt($(document).scrollTop() + ($(window).height() < node.height() ? 2 : ($(window).height() - node.height())/2)),
 
- 				left : parseInt($(document).scrollLeft() + ($(window).width() < node.width()  ? 2 : ($(window).width()  - node.width())/2))
 
- 			};
 
- 		if (node.is(':hidden')) {
 
- 			node.addClass('ui-front').css(pos).show().trigger('resize');
 
- 			setTimeout(function() {
 
- 				// fix resize icon position and make elfinder active
 
- 				node.trigger('resize').trigger('mousedown');
 
- 			}, 200);
 
- 		}
 
- 	} else if (opts == 'close') {
 
- 		node = $(this).removeClass('ui-front');
 
- 			
 
- 		if (node.is(':visible')) {
 
- 			!!node.data(destroy)
 
- 				? node.elfinder('destroy').remove()
 
- 				: node.elfinder('close');
 
- 		}
 
- 	} else if (opts == 'instance') {
 
- 		return $(this).getElFinder();
 
- 	}
 
- 	return this;
 
- };
 
- /*
 
-  * File: /js/i18n/elfinder.en.js
 
-  */
 
- /**
 
-  * English translation
 
-  * @author Troex Nevelin <troex@fury.scancode.ru>
 
-  * @author Naoki Sawada <hypweb+elfinder@gmail.com>
 
-  * @version 2018-10-19
 
-  */
 
- // elfinder.en.js is integrated into elfinder.(full|min).js by jake build
 
- if (typeof elFinder === 'function' && elFinder.prototype.i18) {
 
- 	elFinder.prototype.i18.en = {
 
- 		translator : 'Troex Nevelin <troex@fury.scancode.ru>, Naoki Sawada <hypweb+elfinder@gmail.com>',
 
- 		language   : 'English',
 
- 		direction  : 'ltr',
 
- 		dateFormat : 'M d, Y h:i A', // will show like: Aug 24, 2018 04:39 PM
 
- 		fancyDateFormat : '$1 h:i A', // will show like: Today 04:39 PM
 
- 		nonameDateFormat : 'ymd-His', // noname upload will show like: 180824-163916
 
- 		messages   : {
 
- 			/********************************** errors **********************************/
 
- 			'error'                : 'Error',
 
- 			'errUnknown'           : 'Unknown error.',
 
- 			'errUnknownCmd'        : 'Unknown command.',
 
- 			'errJqui'              : 'Invalid jQuery UI configuration. Selectable, draggable and droppable components must be included.',
 
- 			'errNode'              : 'elFinder requires DOM Element to be created.',
 
- 			'errURL'               : 'Invalid elFinder configuration! URL option is not set.',
 
- 			'errAccess'            : 'Access denied.',
 
- 			'errConnect'           : 'Unable to connect to backend.',
 
- 			'errAbort'             : 'Connection aborted.',
 
- 			'errTimeout'           : 'Connection timeout.',
 
- 			'errNotFound'          : 'Backend not found.',
 
- 			'errResponse'          : 'Invalid backend response.',
 
- 			'errConf'              : 'Invalid backend configuration.',
 
- 			'errJSON'              : 'PHP JSON module not installed.',
 
- 			'errNoVolumes'         : 'Readable volumes not available.',
 
- 			'errCmdParams'         : 'Invalid parameters for command "$1".',
 
- 			'errDataNotJSON'       : 'Data is not JSON.',
 
- 			'errDataEmpty'         : 'Data is empty.',
 
- 			'errCmdReq'            : 'Backend request requires command name.',
 
- 			'errOpen'              : 'Unable to open "$1".',
 
- 			'errNotFolder'         : 'Object is not a folder.',
 
- 			'errNotFile'           : 'Object is not a file.',
 
- 			'errRead'              : 'Unable to read "$1".',
 
- 			'errWrite'             : 'Unable to write into "$1".',
 
- 			'errPerm'              : 'Permission denied.',
 
- 			'errLocked'            : '"$1" is locked and can not be renamed, moved or removed.',
 
- 			'errExists'            : 'Item named "$1" already exists.',
 
- 			'errInvName'           : 'Invalid file name.',
 
- 			'errInvDirname'        : 'Invalid folder name.',  // from v2.1.24 added 12.4.2017
 
- 			'errFolderNotFound'    : 'Folder not found.',
 
- 			'errFileNotFound'      : 'File not found.',
 
- 			'errTrgFolderNotFound' : 'Target folder "$1" not found.',
 
- 			'errPopup'             : 'Browser prevented opening popup window. To open file enable it in browser options.',
 
- 			'errMkdir'             : 'Unable to create folder "$1".',
 
- 			'errMkfile'            : 'Unable to create file "$1".',
 
- 			'errRename'            : 'Unable to rename "$1".',
 
- 			'errCopyFrom'          : 'Copying files from volume "$1" not allowed.',
 
- 			'errCopyTo'            : 'Copying files to volume "$1" not allowed.',
 
- 			'errMkOutLink'         : 'Unable to create a link to outside the volume root.', // from v2.1 added 03.10.2015
 
- 			'errUpload'            : 'Upload error.',  // old name - errUploadCommon
 
- 			'errUploadFile'        : 'Unable to upload "$1".', // old name - errUpload
 
- 			'errUploadNoFiles'     : 'No files found for upload.',
 
- 			'errUploadTotalSize'   : 'Data exceeds the maximum allowed size.', // old name - errMaxSize
 
- 			'errUploadFileSize'    : 'File exceeds maximum allowed size.', //  old name - errFileMaxSize
 
- 			'errUploadMime'        : 'File type not allowed.',
 
- 			'errUploadTransfer'    : '"$1" transfer error.',
 
- 			'errUploadTemp'        : 'Unable to make temporary file for upload.', // from v2.1 added 26.09.2015
 
- 			'errNotReplace'        : 'Object "$1" already exists at this location and can not be replaced by object with another type.', // new
 
- 			'errReplace'           : 'Unable to replace "$1".',
 
- 			'errSave'              : 'Unable to save "$1".',
 
- 			'errCopy'              : 'Unable to copy "$1".',
 
- 			'errMove'              : 'Unable to move "$1".',
 
- 			'errCopyInItself'      : 'Unable to copy "$1" into itself.',
 
- 			'errRm'                : 'Unable to remove "$1".',
 
- 			'errTrash'             : 'Unable into trash.', // from v2.1.24 added 30.4.2017
 
- 			'errRmSrc'             : 'Unable remove source file(s).',
 
- 			'errExtract'           : 'Unable to extract files from "$1".',
 
- 			'errArchive'           : 'Unable to create archive.',
 
- 			'errArcType'           : 'Unsupported archive type.',
 
- 			'errNoArchive'         : 'File is not archive or has unsupported archive type.',
 
- 			'errCmdNoSupport'      : 'Backend does not support this command.',
 
- 			'errReplByChild'       : 'The folder "$1" can\'t be replaced by an item it contains.',
 
- 			'errArcSymlinks'       : 'For security reason denied to unpack archives contains symlinks or files with not allowed names.', // edited 24.06.2012
 
- 			'errArcMaxSize'        : 'Archive files exceeds maximum allowed size.',
 
- 			'errResize'            : 'Unable to resize "$1".',
 
- 			'errResizeDegree'      : 'Invalid rotate degree.',  // added 7.3.2013
 
- 			'errResizeRotate'      : 'Unable to rotate image.',  // added 7.3.2013
 
- 			'errResizeSize'        : 'Invalid image size.',  // added 7.3.2013
 
- 			'errResizeNoChange'    : 'Image size not changed.',  // added 7.3.2013
 
- 			'errUsupportType'      : 'Unsupported file type.',
 
- 			'errNotUTF8Content'    : 'File "$1" is not in UTF-8 and cannot be edited.',  // added 9.11.2011
 
- 			'errNetMount'          : 'Unable to mount "$1".', // added 17.04.2012
 
- 			'errNetMountNoDriver'  : 'Unsupported protocol.',     // added 17.04.2012
 
- 			'errNetMountFailed'    : 'Mount failed.',         // added 17.04.2012
 
- 			'errNetMountHostReq'   : 'Host required.', // added 18.04.2012
 
- 			'errSessionExpires'    : 'Your session has expired due to inactivity.',
 
- 			'errCreatingTempDir'   : 'Unable to create temporary directory: "$1"',
 
- 			'errFtpDownloadFile'   : 'Unable to download file from FTP: "$1"',
 
- 			'errFtpUploadFile'     : 'Unable to upload file to FTP: "$1"',
 
- 			'errFtpMkdir'          : 'Unable to create remote directory on FTP: "$1"',
 
- 			'errArchiveExec'       : 'Error while archiving files: "$1"',
 
- 			'errExtractExec'       : 'Error while extracting files: "$1"',
 
- 			'errNetUnMount'        : 'Unable to unmount.', // from v2.1 added 30.04.2012
 
- 			'errConvUTF8'          : 'Not convertible to UTF-8', // from v2.1 added 08.04.2014
 
- 			'errFolderUpload'      : 'Try the modern browser, If you\'d like to upload the folder.', // from v2.1 added 26.6.2015
 
- 			'errSearchTimeout'     : 'Timed out while searching "$1". Search result is partial.', // from v2.1 added 12.1.2016
 
- 			'errReauthRequire'     : 'Re-authorization is required.', // from v2.1.10 added 24.3.2016
 
- 			'errMaxTargets'        : 'Max number of selectable items is $1.', // from v2.1.17 added 17.10.2016
 
- 			'errRestore'           : 'Unable to restore from the trash. Can\'t identify the restore destination.', // from v2.1.24 added 3.5.2017
 
- 			'errEditorNotFound'    : 'Editor not found to this file type.', // from v2.1.25 added 23.5.2017
 
- 			'errServerError'       : 'Error occurred on the server side.', // from v2.1.25 added 16.6.2017
 
- 			'errEmpty'             : 'Unable to empty folder "$1".', // from v2.1.25 added 22.6.2017
 
- 			/******************************* commands names ********************************/
 
- 			'cmdarchive'   : 'Create archive',
 
- 			'cmdback'      : 'Back',
 
- 			'cmdcopy'      : 'Copy',
 
- 			'cmdcut'       : 'Cut',
 
- 			'cmddownload'  : 'Download',
 
- 			'cmdduplicate' : 'Duplicate',
 
- 			'cmdedit'      : 'Edit file',
 
- 			'cmdextract'   : 'Extract files from archive',
 
- 			'cmdforward'   : 'Forward',
 
- 			'cmdgetfile'   : 'Select files',
 
- 			'cmdhelp'      : 'About this software',
 
- 			'cmdhome'      : 'Root',
 
- 			'cmdinfo'      : 'Get info',
 
- 			'cmdmkdir'     : 'New folder',
 
- 			'cmdmkdirin'   : 'Into New Folder', // from v2.1.7 added 19.2.2016
 
- 			'cmdmkfile'    : 'New file',
 
- 			'cmdopen'      : 'Open',
 
- 			'cmdpaste'     : 'Paste',
 
- 			'cmdquicklook' : 'Preview',
 
- 			'cmdreload'    : 'Reload',
 
- 			'cmdrename'    : 'Rename',
 
- 			'cmdrm'        : 'Delete',
 
- 			'cmdtrash'     : 'Into trash', //from v2.1.24 added 29.4.2017
 
- 			'cmdrestore'   : 'Restore', //from v2.1.24 added 3.5.2017
 
- 			'cmdsearch'    : 'Find files',
 
- 			'cmdup'        : 'Go to parent folder',
 
- 			'cmdupload'    : 'Upload files',
 
- 			'cmdview'      : 'View',
 
- 			'cmdresize'    : 'Resize & Rotate',
 
- 			'cmdsort'      : 'Sort',
 
- 			'cmdnetmount'  : 'Mount network volume', // added 18.04.2012
 
- 			'cmdnetunmount': 'Unmount', // from v2.1 added 30.04.2012
 
- 			'cmdplaces'    : 'To Places', // added 28.12.2014
 
- 			'cmdchmod'     : 'Change mode', // from v2.1 added 20.6.2015
 
- 			'cmdopendir'   : 'Open a folder', // from v2.1 added 13.1.2016
 
- 			'cmdcolwidth'  : 'Reset column width', // from v2.1.13 added 12.06.2016
 
- 			'cmdfullscreen': 'Full Screen', // from v2.1.15 added 03.08.2016
 
- 			'cmdmove'      : 'Move', // from v2.1.15 added 21.08.2016
 
- 			'cmdempty'     : 'Empty the folder', // from v2.1.25 added 22.06.2017
 
- 			'cmdundo'      : 'Undo', // from v2.1.27 added 31.07.2017
 
- 			'cmdredo'      : 'Redo', // from v2.1.27 added 31.07.2017
 
- 			'cmdpreference': 'Preferences', // from v2.1.27 added 03.08.2017
 
- 			'cmdselectall' : 'Select all', // from v2.1.28 added 15.08.2017
 
- 			'cmdselectnone': 'Select none', // from v2.1.28 added 15.08.2017
 
- 			'cmdselectinvert': 'Invert selection', // from v2.1.28 added 15.08.2017
 
- 			'cmdopennew'   : 'Open in new window', // from v2.1.38 added 3.4.2018
 
- 			'cmdhide'      : 'Hide (Preference)', // from v2.1.41 added 24.7.2018
 
- 			/*********************************** buttons ***********************************/
 
- 			'btnClose'  : 'Close',
 
- 			'btnSave'   : 'Save',
 
- 			'btnRm'     : 'Remove',
 
- 			'btnApply'  : 'Apply',
 
- 			'btnCancel' : 'Cancel',
 
- 			'btnNo'     : 'No',
 
- 			'btnYes'    : 'Yes',
 
- 			'btnMount'  : 'Mount',  // added 18.04.2012
 
- 			'btnApprove': 'Goto $1 & approve', // from v2.1 added 26.04.2012
 
- 			'btnUnmount': 'Unmount', // from v2.1 added 30.04.2012
 
- 			'btnConv'   : 'Convert', // from v2.1 added 08.04.2014
 
- 			'btnCwd'    : 'Here',      // from v2.1 added 22.5.2015
 
- 			'btnVolume' : 'Volume',    // from v2.1 added 22.5.2015
 
- 			'btnAll'    : 'All',       // from v2.1 added 22.5.2015
 
- 			'btnMime'   : 'MIME Type', // from v2.1 added 22.5.2015
 
- 			'btnFileName':'Filename',  // from v2.1 added 22.5.2015
 
- 			'btnSaveClose': 'Save & Close', // from v2.1 added 12.6.2015
 
- 			'btnBackup' : 'Backup', // fromv2.1 added 28.11.2015
 
- 			'btnRename'    : 'Rename',      // from v2.1.24 added 6.4.2017
 
- 			'btnRenameAll' : 'Rename(All)', // from v2.1.24 added 6.4.2017
 
- 			'btnPrevious' : 'Prev ($1/$2)', // from v2.1.24 added 11.5.2017
 
- 			'btnNext'     : 'Next ($1/$2)', // from v2.1.24 added 11.5.2017
 
- 			'btnSaveAs'   : 'Save As', // from v2.1.25 added 24.5.2017
 
- 			/******************************** notifications ********************************/
 
- 			'ntfopen'     : 'Open folder',
 
- 			'ntffile'     : 'Open file',
 
- 			'ntfreload'   : 'Reload folder content',
 
- 			'ntfmkdir'    : 'Creating folder',
 
- 			'ntfmkfile'   : 'Creating files',
 
- 			'ntfrm'       : 'Delete items',
 
- 			'ntfcopy'     : 'Copy items',
 
- 			'ntfmove'     : 'Move items',
 
- 			'ntfprepare'  : 'Checking existing items',
 
- 			'ntfrename'   : 'Rename files',
 
- 			'ntfupload'   : 'Uploading files',
 
- 			'ntfdownload' : 'Downloading files',
 
- 			'ntfsave'     : 'Save files',
 
- 			'ntfarchive'  : 'Creating archive',
 
- 			'ntfextract'  : 'Extracting files from archive',
 
- 			'ntfsearch'   : 'Searching files',
 
- 			'ntfresize'   : 'Resizing images',
 
- 			'ntfsmth'     : 'Doing something',
 
- 			'ntfloadimg'  : 'Loading image',
 
- 			'ntfnetmount' : 'Mounting network volume', // added 18.04.2012
 
- 			'ntfnetunmount': 'Unmounting network volume', // from v2.1 added 30.04.2012
 
- 			'ntfdim'      : 'Acquiring image dimension', // added 20.05.2013
 
- 			'ntfreaddir'  : 'Reading folder infomation', // from v2.1 added 01.07.2013
 
- 			'ntfurl'      : 'Getting URL of link', // from v2.1 added 11.03.2014
 
- 			'ntfchmod'    : 'Changing file mode', // from v2.1 added 20.6.2015
 
- 			'ntfpreupload': 'Verifying upload file name', // from v2.1 added 31.11.2015
 
- 			'ntfzipdl'    : 'Creating a file for download', // from v2.1.7 added 23.1.2016
 
- 			'ntfparents'  : 'Getting path infomation', // from v2.1.17 added 2.11.2016
 
- 			'ntfchunkmerge': 'Processing the uploaded file', // from v2.1.17 added 2.11.2016
 
- 			'ntftrash'    : 'Doing throw in the trash', // from v2.1.24 added 2.5.2017
 
- 			'ntfrestore'  : 'Doing restore from the trash', // from v2.1.24 added 3.5.2017
 
- 			'ntfchkdir'   : 'Checking destination folder', // from v2.1.24 added 3.5.2017
 
- 			'ntfundo'     : 'Undoing previous operation', // from v2.1.27 added 31.07.2017
 
- 			'ntfredo'     : 'Redoing previous undone', // from v2.1.27 added 31.07.2017
 
- 			'ntfchkcontent' : 'Checking contents', // from v2.1.41 added 3.8.2018
 
- 			/*********************************** volumes *********************************/
 
- 			'volume_Trash' : 'Trash', //from v2.1.24 added 29.4.2017
 
- 			/************************************ dates **********************************/
 
- 			'dateUnknown' : 'unknown',
 
- 			'Today'       : 'Today',
 
- 			'Yesterday'   : 'Yesterday',
 
- 			'msJan'       : 'Jan',
 
- 			'msFeb'       : 'Feb',
 
- 			'msMar'       : 'Mar',
 
- 			'msApr'       : 'Apr',
 
- 			'msMay'       : 'May',
 
- 			'msJun'       : 'Jun',
 
- 			'msJul'       : 'Jul',
 
- 			'msAug'       : 'Aug',
 
- 			'msSep'       : 'Sep',
 
- 			'msOct'       : 'Oct',
 
- 			'msNov'       : 'Nov',
 
- 			'msDec'       : 'Dec',
 
- 			'January'     : 'January',
 
- 			'February'    : 'February',
 
- 			'March'       : 'March',
 
- 			'April'       : 'April',
 
- 			'May'         : 'May',
 
- 			'June'        : 'June',
 
- 			'July'        : 'July',
 
- 			'August'      : 'August',
 
- 			'September'   : 'September',
 
- 			'October'     : 'October',
 
- 			'November'    : 'November',
 
- 			'December'    : 'December',
 
- 			'Sunday'      : 'Sunday',
 
- 			'Monday'      : 'Monday',
 
- 			'Tuesday'     : 'Tuesday',
 
- 			'Wednesday'   : 'Wednesday',
 
- 			'Thursday'    : 'Thursday',
 
- 			'Friday'      : 'Friday',
 
- 			'Saturday'    : 'Saturday',
 
- 			'Sun'         : 'Sun',
 
- 			'Mon'         : 'Mon',
 
- 			'Tue'         : 'Tue',
 
- 			'Wed'         : 'Wed',
 
- 			'Thu'         : 'Thu',
 
- 			'Fri'         : 'Fri',
 
- 			'Sat'         : 'Sat',
 
- 			/******************************** sort variants ********************************/
 
- 			'sortname'          : 'by name',
 
- 			'sortkind'          : 'by kind',
 
- 			'sortsize'          : 'by size',
 
- 			'sortdate'          : 'by date',
 
- 			'sortFoldersFirst'  : 'Folders first',
 
- 			'sortperm'          : 'by permission', // from v2.1.13 added 13.06.2016
 
- 			'sortmode'          : 'by mode',       // from v2.1.13 added 13.06.2016
 
- 			'sortowner'         : 'by owner',      // from v2.1.13 added 13.06.2016
 
- 			'sortgroup'         : 'by group',      // from v2.1.13 added 13.06.2016
 
- 			'sortAlsoTreeview'  : 'Also Treeview',  // from v2.1.15 added 01.08.2016
 
- 			/********************************** new items **********************************/
 
- 			'untitled file.txt' : 'NewFile.txt', // added 10.11.2015
 
- 			'untitled folder'   : 'NewFolder',   // added 10.11.2015
 
- 			'Archive'           : 'NewArchive',  // from v2.1 added 10.11.2015
 
- 			'untitled file'     : 'NewFile.$1',  // from v2.1.41 added 6.8.2018
 
- 			'extentionfile'     : '$1: File',    // from v2.1.41 added 6.8.2018
 
- 			'extentiontype'     : '$1: $2',      // from v2.1.43 added 17.10.2018
 
- 			/********************************** messages **********************************/
 
- 			'confirmReq'      : 'Confirmation required',
 
- 			'confirmRm'       : 'Are you sure you want to permanently remove items?<br/>This cannot be undone!',
 
- 			'confirmRepl'     : 'Replace old file with new one? (If it contains folders, it will be merged. To backup and replace, select Backup.)',
 
- 			'confirmRest'     : 'Replace existing item with the item in trash?', // fromv2.1.24 added 5.5.2017
 
- 			'confirmConvUTF8' : 'Not in UTF-8<br/>Convert to UTF-8?<br/>Contents become UTF-8 by saving after conversion.', // from v2.1 added 08.04.2014
 
- 			'confirmNonUTF8'  : 'Character encoding of this file couldn\'t be detected. It need to temporarily convert to UTF-8 for editting.<br/>Please select character encoding of this file.', // from v2.1.19 added 28.11.2016
 
- 			'confirmNotSave'  : 'It has been modified.<br/>Losing work if you do not save changes.', // from v2.1 added 15.7.2015
 
- 			'confirmTrash'    : 'Are you sure you want to move items to trash bin?', //from v2.1.24 added 29.4.2017
 
- 			'apllyAll'        : 'Apply to all',
 
- 			'name'            : 'Name',
 
- 			'size'            : 'Size',
 
- 			'perms'           : 'Permissions',
 
- 			'modify'          : 'Modified',
 
- 			'kind'            : 'Kind',
 
- 			'read'            : 'read',
 
- 			'write'           : 'write',
 
- 			'noaccess'        : 'no access',
 
- 			'and'             : 'and',
 
- 			'unknown'         : 'unknown',
 
- 			'selectall'       : 'Select all items',
 
- 			'selectfiles'     : 'Select item(s)',
 
- 			'selectffile'     : 'Select first item',
 
- 			'selectlfile'     : 'Select last item',
 
- 			'viewlist'        : 'List view',
 
- 			'viewicons'       : 'Icons view',
 
- 			'viewSmall'       : 'Small icons', // from v2.1.39 added 22.5.2018
 
- 			'viewMedium'      : 'Medium icons', // from v2.1.39 added 22.5.2018
 
- 			'viewLarge'       : 'Large icons', // from v2.1.39 added 22.5.2018
 
- 			'viewExtraLarge'  : 'Extra large icons', // from v2.1.39 added 22.5.2018
 
- 			'places'          : 'Places',
 
- 			'calc'            : 'Calculate',
 
- 			'path'            : 'Path',
 
- 			'aliasfor'        : 'Alias for',
 
- 			'locked'          : 'Locked',
 
- 			'dim'             : 'Dimensions',
 
- 			'files'           : 'Files',
 
- 			'folders'         : 'Folders',
 
- 			'items'           : 'Items',
 
- 			'yes'             : 'yes',
 
- 			'no'              : 'no',
 
- 			'link'            : 'Link',
 
- 			'searcresult'     : 'Search results',
 
- 			'selected'        : 'selected items',
 
- 			'about'           : 'About',
 
- 			'shortcuts'       : 'Shortcuts',
 
- 			'help'            : 'Help',
 
- 			'webfm'           : 'Web file manager',
 
- 			'ver'             : 'Version',
 
- 			'protocolver'     : 'protocol version',
 
- 			'homepage'        : 'Project home',
 
- 			'docs'            : 'Documentation',
 
- 			'github'          : 'Fork us on GitHub',
 
- 			'twitter'         : 'Follow us on Twitter',
 
- 			'facebook'        : 'Join us on Facebook',
 
- 			'team'            : 'Team',
 
- 			'chiefdev'        : 'chief developer',
 
- 			'developer'       : 'developer',
 
- 			'contributor'     : 'contributor',
 
- 			'maintainer'      : 'maintainer',
 
- 			'translator'      : 'translator',
 
- 			'icons'           : 'Icons',
 
- 			'dontforget'      : 'and don\'t forget to take your towel',
 
- 			'shortcutsof'     : 'Shortcuts disabled',
 
- 			'dropFiles'       : 'Drop files here',
 
- 			'or'              : 'or',
 
- 			'selectForUpload' : 'Select files',
 
- 			'moveFiles'       : 'Move items',
 
- 			'copyFiles'       : 'Copy items',
 
- 			'restoreFiles'    : 'Restore items', // from v2.1.24 added 5.5.2017
 
- 			'rmFromPlaces'    : 'Remove from places',
 
- 			'aspectRatio'     : 'Aspect ratio',
 
- 			'scale'           : 'Scale',
 
- 			'width'           : 'Width',
 
- 			'height'          : 'Height',
 
- 			'resize'          : 'Resize',
 
- 			'crop'            : 'Crop',
 
- 			'rotate'          : 'Rotate',
 
- 			'rotate-cw'       : 'Rotate 90 degrees CW',
 
- 			'rotate-ccw'      : 'Rotate 90 degrees CCW',
 
- 			'degree'          : '°',
 
- 			'netMountDialogTitle' : 'Mount network volume', // added 18.04.2012
 
- 			'protocol'            : 'Protocol', // added 18.04.2012
 
- 			'host'                : 'Host', // added 18.04.2012
 
- 			'port'                : 'Port', // added 18.04.2012
 
- 			'user'                : 'User', // added 18.04.2012
 
- 			'pass'                : 'Password', // added 18.04.2012
 
- 			'confirmUnmount'      : 'Are you sure to unmount $1?',  // from v2.1 added 30.04.2012
 
- 			'dropFilesBrowser': 'Drop or Paste files from browser', // from v2.1 added 30.05.2012
 
- 			'dropPasteFiles'  : 'Drop files, Paste URLs or images(clipboard) here', // from v2.1 added 07.04.2014
 
- 			'encoding'        : 'Encoding', // from v2.1 added 19.12.2014
 
- 			'locale'          : 'Locale',   // from v2.1 added 19.12.2014
 
- 			'searchTarget'    : 'Target: $1',                // from v2.1 added 22.5.2015
 
- 			'searchMime'      : 'Search by input MIME Type', // from v2.1 added 22.5.2015
 
- 			'owner'           : 'Owner', // from v2.1 added 20.6.2015
 
- 			'group'           : 'Group', // from v2.1 added 20.6.2015
 
- 			'other'           : 'Other', // from v2.1 added 20.6.2015
 
- 			'execute'         : 'Execute', // from v2.1 added 20.6.2015
 
- 			'perm'            : 'Permission', // from v2.1 added 20.6.2015
 
- 			'mode'            : 'Mode', // from v2.1 added 20.6.2015
 
- 			'emptyFolder'     : 'Folder is empty', // from v2.1.6 added 30.12.2015
 
- 			'emptyFolderDrop' : 'Folder is empty\\A Drop to add items', // from v2.1.6 added 30.12.2015
 
- 			'emptyFolderLTap' : 'Folder is empty\\A Long tap to add items', // from v2.1.6 added 30.12.2015
 
- 			'quality'         : 'Quality', // from v2.1.6 added 5.1.2016
 
- 			'autoSync'        : 'Auto sync',  // from v2.1.6 added 10.1.2016
 
- 			'moveUp'          : 'Move up',  // from v2.1.6 added 18.1.2016
 
- 			'getLink'         : 'Get URL link', // from v2.1.7 added 9.2.2016
 
- 			'selectedItems'   : 'Selected items ($1)', // from v2.1.7 added 2.19.2016
 
- 			'folderId'        : 'Folder ID', // from v2.1.10 added 3.25.2016
 
- 			'offlineAccess'   : 'Allow offline access', // from v2.1.10 added 3.25.2016
 
- 			'reAuth'          : 'To re-authenticate', // from v2.1.10 added 3.25.2016
 
- 			'nowLoading'      : 'Now loading...', // from v2.1.12 added 4.26.2016
 
- 			'openMulti'       : 'Open multiple files', // from v2.1.12 added 5.14.2016
 
- 			'openMultiConfirm': 'You are trying to open the $1 files. Are you sure you want to open in browser?', // from v2.1.12 added 5.14.2016
 
- 			'emptySearch'     : 'Search results is empty in search target.', // from v2.1.12 added 5.16.2016
 
- 			'editingFile'     : 'It is editing a file.', // from v2.1.13 added 6.3.2016
 
- 			'hasSelected'     : 'You have selected $1 items.', // from v2.1.13 added 6.3.2016
 
- 			'hasClipboard'    : 'You have $1 items in the clipboard.', // from v2.1.13 added 6.3.2016
 
- 			'incSearchOnly'   : 'Incremental search is only from the current view.', // from v2.1.13 added 6.30.2016
 
- 			'reinstate'       : 'Reinstate', // from v2.1.15 added 3.8.2016
 
- 			'complete'        : '$1 complete', // from v2.1.15 added 21.8.2016
 
- 			'contextmenu'     : 'Context menu', // from v2.1.15 added 9.9.2016
 
- 			'pageTurning'     : 'Page turning', // from v2.1.15 added 10.9.2016
 
- 			'volumeRoots'     : 'Volume roots', // from v2.1.16 added 16.9.2016
 
- 			'reset'           : 'Reset', // from v2.1.16 added 1.10.2016
 
- 			'bgcolor'         : 'Background color', // from v2.1.16 added 1.10.2016
 
- 			'colorPicker'     : 'Color picker', // from v2.1.16 added 1.10.2016
 
- 			'8pxgrid'         : '8px Grid', // from v2.1.16 added 4.10.2016
 
- 			'enabled'         : 'Enabled', // from v2.1.16 added 4.10.2016
 
- 			'disabled'        : 'Disabled', // from v2.1.16 added 4.10.2016
 
- 			'emptyIncSearch'  : 'Search results is empty in current view.\\A Press [Enter] to expand search target.', // from v2.1.16 added 5.10.2016
 
- 			'emptyLetSearch'  : 'First letter search results is empty in current view.', // from v2.1.23 added 24.3.2017
 
- 			'textLabel'       : 'Text label', // from v2.1.17 added 13.10.2016
 
- 			'minsLeft'        : '$1 mins left', // from v2.1.17 added 13.11.2016
 
- 			'openAsEncoding'  : 'Reopen with selected encoding', // from v2.1.19 added 2.12.2016
 
- 			'saveAsEncoding'  : 'Save with the selected encoding', // from v2.1.19 added 2.12.2016
 
- 			'selectFolder'    : 'Select folder', // from v2.1.20 added 13.12.2016
 
- 			'firstLetterSearch': 'First letter search', // from v2.1.23 added 24.3.2017
 
- 			'presets'         : 'Presets', // from v2.1.25 added 26.5.2017
 
- 			'tooManyToTrash'  : 'It\'s too many items so it can\'t into trash.', // from v2.1.25 added 9.6.2017
 
- 			'TextArea'        : 'TextArea', // from v2.1.25 added 14.6.2017
 
- 			'folderToEmpty'   : 'Empty the folder "$1".', // from v2.1.25 added 22.6.2017
 
- 			'filderIsEmpty'   : 'There are no items in a folder "$1".', // from v2.1.25 added 22.6.2017
 
- 			'preference'      : 'Preference', // from v2.1.26 added 28.6.2017
 
- 			'language'        : 'Language', // from v2.1.26 added 28.6.2017
 
- 			'clearBrowserData': 'Initialize the settings saved in this browser', // from v2.1.26 added 28.6.2017
 
- 			'toolbarPref'     : 'Toolbar settings', // from v2.1.27 added 2.8.2017
 
- 			'charsLeft'       : '... $1 chars left.',  // from v2.1.29 added 30.8.2017
 
- 			'sum'             : 'Sum', // from v2.1.29 added 28.9.2017
 
- 			'roughFileSize'   : 'Rough file size', // from v2.1.30 added 2.11.2017
 
- 			'autoFocusDialog' : 'Focus on the element of dialog with mouseover',  // from v2.1.30 added 2.11.2017
 
- 			'select'          : 'Select', // from v2.1.30 added 23.11.2017
 
- 			'selectAction'    : 'Action when select file', // from v2.1.30 added 23.11.2017
 
- 			'useStoredEditor' : 'Open with the editor used last time', // from v2.1.30 added 23.11.2017
 
- 			'selectinvert'    : 'Invert selection', // from v2.1.30 added 25.11.2017
 
- 			'renameMultiple'  : 'Are you sure you want to rename $1 selected items like $2?<br/>This cannot be undone!', // from v2.1.31 added 4.12.2017
 
- 			'batchRename'     : 'Batch rename', // from v2.1.31 added 8.12.2017
 
- 			'plusNumber'      : '+ Number', // from v2.1.31 added 8.12.2017
 
- 			'asPrefix'        : 'Add prefix', // from v2.1.31 added 8.12.2017
 
- 			'asSuffix'        : 'Add suffix', // from v2.1.31 added 8.12.2017
 
- 			'changeExtention' : 'Change extention', // from v2.1.31 added 8.12.2017
 
- 			'columnPref'      : 'Columns settings (List view)', // from v2.1.32 added 6.2.2018
 
- 			'reflectOnImmediate' : 'All changes will reflect immediately to the archive.', // from v2.1.33 added 2.3.2018
 
- 			'reflectOnUnmount'   : 'Any changes will not reflect until un-mount this volume.', // from v2.1.33 added 2.3.2018
 
- 			'unmountChildren' : 'The following volume(s) mounted on this volume also unmounted. Are you sure to unmount it?', // from v2.1.33 added 5.3.2018
 
- 			'selectionInfo'   : 'Selection Info', // from v2.1.33 added 7.3.2018
 
- 			'hashChecker'     : 'Algorithms to show the file hash', // from v2.1.33 added 10.3.2018
 
- 			'infoItems'       : 'Info Items (Selection Info Panel)', // from v2.1.38 added 28.3.2018
 
- 			'pressAgainToExit': 'Press again to exit.', // from v2.1.38 added 1.4.2018
 
- 			'toolbar'         : 'Toolbar', // from v2.1.38 added 4.4.2018
 
- 			'workspace'       : 'Work Space', // from v2.1.38 added 4.4.2018
 
- 			'dialog'          : 'Dialog', // from v2.1.38 added 4.4.2018
 
- 			'all'             : 'All', // from v2.1.38 added 4.4.2018
 
- 			'iconSize'        : 'Icon Size (Icons view)', // from v2.1.39 added 7.5.2018
 
- 			'editorMaximized' : 'Open the maximized editor window', // from v2.1.40 added 30.6.2018
 
- 			'editorConvNoApi' : 'Because conversion by API is not currently available, please convert on the website.', //from v2.1.40 added 8.7.2018
 
- 			'editorConvNeedUpload' : 'After conversion, you must be upload with the item URL or a downloaded file to save the converted file.', //from v2.1.40 added 8.7.2018
 
- 			'convertOn'       : 'Convert on the site of $1', // from v2.1.40 added 10.7.2018
 
- 			'integrations'    : 'Integrations', // from v2.1.40 added 11.7.2018
 
- 			'integrationWith' : 'This elFinder has the following external services integrated. Please check the terms of use, privacy policy, etc. before using it.', // from v2.1.40 added 11.7.2018
 
- 			'showHidden'      : 'Show hidden items', // from v2.1.41 added 24.7.2018
 
- 			'hideHidden'      : 'Hide hidden items', // from v2.1.41 added 24.7.2018
 
- 			'toggleHidden'    : 'Show/Hide hidden items', // from v2.1.41 added 24.7.2018
 
- 			'makefileTypes'   : 'File types to enable with "New file"', // from v2.1.41 added 7.8.2018
 
- 			'typeOfTextfile'  : 'Type of the Text file', // from v2.1.41 added 7.8.2018
 
- 			'add'             : 'Add', // from v2.1.41 added 7.8.2018
 
- 			'theme'           : 'Theme', // from v2.1.43 added 19.10.2018
 
- 			'default'         : 'Default', // from v2.1.43 added 19.10.2018
 
- 			'description'     : 'Description', // from v2.1.43 added 19.10.2018
 
- 			'website'         : 'Website', // from v2.1.43 added 19.10.2018
 
- 			'author'          : 'Author', // from v2.1.43 added 19.10.2018
 
- 			'email'           : 'Email', // from v2.1.43 added 19.10.2018
 
- 			'license'         : 'License', // from v2.1.43 added 19.10.2018
 
- 			/********************************** mimetypes **********************************/
 
- 			'kindUnknown'     : 'Unknown',
 
- 			'kindRoot'        : 'Volume Root', // from v2.1.16 added 16.10.2016
 
- 			'kindFolder'      : 'Folder',
 
- 			'kindSelects'     : 'Selections', // from v2.1.29 added 29.8.2017
 
- 			'kindAlias'       : 'Alias',
 
- 			'kindAliasBroken' : 'Broken alias',
 
- 			// applications
 
- 			'kindApp'         : 'Application',
 
- 			'kindPostscript'  : 'Postscript document',
 
- 			'kindMsOffice'    : 'Microsoft Office document',
 
- 			'kindMsWord'      : 'Microsoft Word document',
 
- 			'kindMsExcel'     : 'Microsoft Excel document',
 
- 			'kindMsPP'        : 'Microsoft Powerpoint presentation',
 
- 			'kindOO'          : 'Open Office document',
 
- 			'kindAppFlash'    : 'Flash application',
 
- 			'kindPDF'         : 'Portable Document Format (PDF)',
 
- 			'kindTorrent'     : 'Bittorrent file',
 
- 			'kind7z'          : '7z archive',
 
- 			'kindTAR'         : 'TAR archive',
 
- 			'kindGZIP'        : 'GZIP archive',
 
- 			'kindBZIP'        : 'BZIP archive',
 
- 			'kindXZ'          : 'XZ archive',
 
- 			'kindZIP'         : 'ZIP archive',
 
- 			'kindRAR'         : 'RAR archive',
 
- 			'kindJAR'         : 'Java JAR file',
 
- 			'kindTTF'         : 'True Type font',
 
- 			'kindOTF'         : 'Open Type font',
 
- 			'kindRPM'         : 'RPM package',
 
- 			// texts
 
- 			'kindText'        : 'Text document',
 
- 			'kindTextPlain'   : 'Plain text',
 
- 			'kindPHP'         : 'PHP source',
 
- 			'kindCSS'         : 'Cascading style sheet',
 
- 			'kindHTML'        : 'HTML document',
 
- 			'kindJS'          : 'Javascript source',
 
- 			'kindRTF'         : 'Rich Text Format',
 
- 			'kindC'           : 'C source',
 
- 			'kindCHeader'     : 'C header source',
 
- 			'kindCPP'         : 'C++ source',
 
- 			'kindCPPHeader'   : 'C++ header source',
 
- 			'kindShell'       : 'Unix shell script',
 
- 			'kindPython'      : 'Python source',
 
- 			'kindJava'        : 'Java source',
 
- 			'kindRuby'        : 'Ruby source',
 
- 			'kindPerl'        : 'Perl script',
 
- 			'kindSQL'         : 'SQL source',
 
- 			'kindXML'         : 'XML document',
 
- 			'kindAWK'         : 'AWK source',
 
- 			'kindCSV'         : 'Comma separated values',
 
- 			'kindDOCBOOK'     : 'Docbook XML document',
 
- 			'kindMarkdown'    : 'Markdown text', // added 20.7.2015
 
- 			// images
 
- 			'kindImage'       : 'Image',
 
- 			'kindBMP'         : 'BMP image',
 
- 			'kindJPEG'        : 'JPEG image',
 
- 			'kindGIF'         : 'GIF Image',
 
- 			'kindPNG'         : 'PNG Image',
 
- 			'kindTIFF'        : 'TIFF image',
 
- 			'kindTGA'         : 'TGA image',
 
- 			'kindPSD'         : 'Adobe Photoshop image',
 
- 			'kindXBITMAP'     : 'X bitmap image',
 
- 			'kindPXM'         : 'Pixelmator image',
 
- 			// media
 
- 			'kindAudio'       : 'Audio media',
 
- 			'kindAudioMPEG'   : 'MPEG audio',
 
- 			'kindAudioMPEG4'  : 'MPEG-4 audio',
 
- 			'kindAudioMIDI'   : 'MIDI audio',
 
- 			'kindAudioOGG'    : 'Ogg Vorbis audio',
 
- 			'kindAudioWAV'    : 'WAV audio',
 
- 			'AudioPlaylist'   : 'MP3 playlist',
 
- 			'kindVideo'       : 'Video media',
 
- 			'kindVideoDV'     : 'DV movie',
 
- 			'kindVideoMPEG'   : 'MPEG movie',
 
- 			'kindVideoMPEG4'  : 'MPEG-4 movie',
 
- 			'kindVideoAVI'    : 'AVI movie',
 
- 			'kindVideoMOV'    : 'Quick Time movie',
 
- 			'kindVideoWM'     : 'Windows Media movie',
 
- 			'kindVideoFlash'  : 'Flash movie',
 
- 			'kindVideoMKV'    : 'Matroska movie',
 
- 			'kindVideoOGG'    : 'Ogg movie'
 
- 		}
 
- 	};
 
- }
 
- /*
 
-  * File: /js/ui/button.js
 
-  */
 
- /**
 
-  * @class  elFinder toolbar button widget.
 
-  * If command has variants - create menu
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.elfinderbutton = function(cmd) {
 
- 		return this.each(function() {
 
- 		
 
- 		var c        = 'class',
 
- 			fm       = cmd.fm,
 
- 			disabled = fm.res(c, 'disabled'),
 
- 			active   = fm.res(c, 'active'),
 
- 			hover    = fm.res(c, 'hover'),
 
- 			item     = 'elfinder-button-menu-item',
 
- 			selected = 'elfinder-button-menu-item-selected',
 
- 			menu,
 
- 			text     = $('<span class="elfinder-button-text">'+cmd.title+'</span>'),
 
- 			prvCname = 'elfinder-button-icon-' + (cmd.className? cmd.className : cmd.name),
 
- 			button   = $(this).addClass('ui-state-default elfinder-button')
 
- 				.attr('title', cmd.title)
 
- 				.append('<span class="elfinder-button-icon ' + prvCname + '"/>', text)
 
- 				.on('mouseenter mouseleave', function(e) { !button.hasClass(disabled) && button[e.type == 'mouseleave' ? 'removeClass' : 'addClass'](hover);})
 
- 				.on('click', function(e) { 
 
- 					if (!button.hasClass(disabled)) {
 
- 						if (menu && cmd.variants.length >= 1) {
 
- 							// close other menus
 
- 							menu.is(':hidden') && fm.getUI().click();
 
- 							e.stopPropagation();
 
- 							menu.css(getMenuOffset()).slideToggle({
 
- 								duration: 100,
 
- 								done: function(e) {
 
- 									fm[menu.is(':visible')? 'toFront' : 'toHide'](menu);
 
- 								}
 
- 							});
 
- 						} else {
 
- 							fm.exec(cmd.name, getSelected(), {_userAction: true, _currentType: 'toolbar', _currentNode: button });
 
- 						}
 
- 						
 
- 					}
 
- 				}),
 
- 			hideMenu = function() {
 
- 				fm.toHide(menu);
 
- 			},
 
- 			getMenuOffset = function() {
 
- 				var fmNode = fm.getUI(),
 
- 					baseOffset = fm.getUI().offset(),
 
- 					buttonOffset = fmNode.offset();
 
- 				return {
 
- 					top : buttonOffset.top - baseOffset.top,
 
- 					left : buttonOffset.left - baseOffset.left,
 
- 					maxHeight : fmNode.height() - 40
 
- 				};
 
- 			},
 
- 			getSelected = function() {
 
- 				var sel = fm.selected(),
 
- 					cwd;
 
- 				if (!sel.length) {
 
- 					if (cwd = fm.cwd()) {
 
- 						sel = [ fm.cwd().hash ];
 
- 					} else {
 
- 						sel = void(0);
 
- 					}
 
- 				}
 
- 				return sel;
 
- 			},
 
- 			tm;
 
- 			
 
- 		text.hide();
 
- 		
 
- 		// set self button object to cmd object
 
- 		cmd.button = button;
 
- 		
 
- 		// if command has variants create menu
 
- 		if (Array.isArray(cmd.variants)) {
 
- 			button.addClass('elfinder-menubutton');
 
- 			
 
- 			menu = $('<div class="ui-front ui-widget ui-widget-content elfinder-button-menu ui-corner-all"/>')
 
- 				.hide()
 
- 				.appendTo(fm.getUI())
 
- 				.on('mouseenter mouseleave', '.'+item, function() { $(this).toggleClass(hover); })
 
- 				.on('click', '.'+item, function(e) {
 
- 					var opts = $(this).data('value');
 
- 					e.preventDefault();
 
- 					e.stopPropagation();
 
- 					button.removeClass(hover);
 
- 					fm.toHide(menu);
 
- 					if (typeof opts === 'undefined') {
 
- 						opts = {};
 
- 					}
 
- 					if (typeof opts === 'object') {
 
- 						opts._userAction = true;
 
- 					}
 
- 					fm.exec(cmd.name, getSelected(), opts);
 
- 				})
 
- 				.on('close', hideMenu);
 
- 			fm.bind('disable select', hideMenu).getUI().on('click', hideMenu);
 
- 			
 
- 			cmd.change(function() {
 
- 				menu.html('');
 
- 				$.each(cmd.variants, function(i, variant) {
 
- 					menu.append($('<div class="'+item+'">'+variant[1]+'</div>').data('value', variant[0]).addClass(variant[0] == cmd.value ? selected : ''));
 
- 				});
 
- 			});
 
- 		}	
 
- 			
 
- 		cmd.change(function() {
 
- 			var cName;
 
- 			tm && cancelAnimationFrame(tm);
 
- 			tm = requestAnimationFrame(function() {
 
- 				if (cmd.disabled()) {
 
- 					button.removeClass(active+' '+hover).addClass(disabled);
 
- 				} else {
 
- 					button.removeClass(disabled);
 
- 					button[cmd.active() ? 'addClass' : 'removeClass'](active);
 
- 				}
 
- 				if (cmd.syncTitleOnChange) {
 
- 					cName = 'elfinder-button-icon-' + (cmd.className? cmd.className : cmd.name);
 
- 					if (prvCname !== cName) {
 
- 						button.children('.elfinder-button-icon').removeClass(prvCname).addClass(cName);
 
- 						prvCname = cName;
 
- 					}
 
- 					text.html(cmd.title);
 
- 					button.attr('title', cmd.title);
 
- 				}
 
- 			});
 
- 		})
 
- 		.change();
 
- 	});
 
- };
 
- /*
 
-  * File: /js/ui/contextmenu.js
 
-  */
 
- /**
 
-  * @class  elFinder contextmenu
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.elfindercontextmenu = function(fm) {
 
- 		return this.each(function() {
 
- 		var self   = $(this),
 
- 			cmItem = 'elfinder-contextmenu-item',
 
- 			smItem = 'elfinder-contextsubmenu-item',
 
- 			exIcon = 'elfinder-contextmenu-extra-icon',
 
- 			cHover = fm.res('class', 'hover'),
 
- 			dragOpt = {
 
- 				distance: 8,
 
- 				start: function() {
 
- 					menu.data('drag', true).data('touching') && menu.find('.'+cHover).removeClass(cHover);
 
- 				},
 
- 				stop: function() {
 
- 					menu.data('draged', true).removeData('drag');
 
- 				}
 
- 			},
 
- 			menu = $(this).addClass('touch-punch ui-helper-reset ui-front ui-widget ui-state-default ui-corner-all elfinder-contextmenu elfinder-contextmenu-'+fm.direction)
 
- 				.hide()
 
- 				.on('touchstart', function(e) {
 
- 					menu.data('touching', true).children().removeClass(cHover);
 
- 				})
 
- 				.on('touchend', function(e) {
 
- 					menu.removeData('touching');
 
- 				})
 
- 				.on('mouseenter mouseleave', '.'+cmItem, function(e) {
 
- 					$(this).toggleClass(cHover, (e.type === 'mouseenter' || (! menu.data('draged') && menu.data('submenuKeep'))? true : false));
 
- 					if (menu.data('draged') && menu.data('submenuKeep')) {
 
- 						menu.find('.elfinder-contextmenu-sub:visible').parent().addClass(cHover);
 
- 					}
 
- 				})
 
- 				.on('mouseenter mouseleave', '.'+exIcon, function(e) {
 
- 					$(this).parent().toggleClass(cHover, e.type === 'mouseleave');
 
- 				})
 
- 				.on('mouseenter mouseleave', '.'+cmItem+',.'+smItem, function(e) {
 
- 					var setIndex = function(target, sub) {
 
- 						$.each(sub? subnodes : nodes, function(i, n) {
 
- 							if (target[0] === n) {
 
- 								(sub? subnodes : nodes)._cur = i;
 
- 								if (sub) {
 
- 									subselected = target;
 
- 								} else {
 
- 									selected = target;
 
- 								}
 
- 								return false;
 
- 							}
 
- 						});
 
- 					};
 
- 					if (e.originalEvent) {
 
- 						var target = $(this),
 
- 							unHover = function() {
 
- 								if (selected && !selected.children('div.elfinder-contextmenu-sub:visible').length) {
 
- 									selected.removeClass(cHover);
 
- 								}
 
- 							};
 
- 						if (e.type === 'mouseenter') {
 
- 							// mouseenter
 
- 							if (target.hasClass(smItem)) {
 
- 								// submenu
 
- 								if (subselected) {
 
- 									subselected.removeClass(cHover);
 
- 								}
 
- 								if (selected) {
 
- 									subnodes = selected.find('div.'+smItem);
 
- 								}
 
- 								setIndex(target, true);
 
- 							} else {
 
- 								// menu
 
- 								unHover();
 
- 								setIndex(target);
 
- 							}
 
- 						} else {
 
- 							// mouseleave
 
- 							if (target.hasClass(smItem)) {
 
- 								//submenu
 
- 								subselected = null;
 
- 								subnodes = null;
 
- 							} else {
 
- 								// menu
 
- 								unHover();
 
- 								(function(sel) {
 
- 									setTimeout(function() {
 
- 										if (sel === selected) {
 
- 											selected = null;
 
- 										}
 
- 									}, 250);
 
- 								})(selected);
 
- 							}
 
- 						}
 
- 					}
 
- 				})
 
- 				.on('contextmenu', function(){return false;})
 
- 				.on('mouseup', function() {
 
- 					setTimeout(function() {
 
- 						menu.removeData('draged');
 
- 					}, 100);
 
- 				})
 
- 				.draggable(dragOpt),
 
- 			ltr = fm.direction === 'ltr',
 
- 			subpos = ltr? 'left' : 'right',
 
- 			types = Object.assign({}, fm.options.contextmenu),
 
- 			tpl     = '<div class="'+cmItem+'{className}"><span class="elfinder-button-icon {icon} elfinder-contextmenu-icon"{style}/><span>{label}</span></div>',
 
- 			item = function(label, icon, callback, opts) {
 
- 				var className = '',
 
- 					style = '',
 
- 					iconClass = '',
 
- 					v, pos;
 
- 				if (opts) {
 
- 					if (opts.className) {
 
- 						className = ' ' + opts.className;
 
- 					}
 
- 					if (opts.iconClass) {
 
- 						iconClass = opts.iconClass;
 
- 						icon = '';
 
- 					}
 
- 					if (opts.iconImg) {
 
- 						v = opts.iconImg.split(/ +/);
 
- 						pos = v[1] && v[2]? fm.escape(v[1] + 'px ' + v[2] + 'px') : '';
 
- 						style = ' style="background:url(\''+fm.escape(v[0])+'\') '+(pos? pos : '0 0')+' no-repeat;'+(pos? '' : 'posbackground-size:contain;')+'"';
 
- 					}
 
- 				}
 
- 				return $(tpl.replace('{icon}', icon ? 'elfinder-button-icon-'+icon : (iconClass? iconClass : ''))
 
- 						.replace('{label}', label)
 
- 						.replace('{style}', style)
 
- 						.replace('{className}', className))
 
- 					.on('click', function(e) {
 
- 						e.stopPropagation();
 
- 						e.preventDefault();
 
- 						callback();
 
- 					});
 
- 			},
 
- 			urlIcon = function(iconUrl) {
 
- 				var v = iconUrl.split(/ +/),
 
- 					pos = v[1] && v[2]? (v[1] + 'px ' + v[2] + 'px') : '';
 
- 				return {
 
- 					backgroundImage: 'url("'+v[0]+'")',
 
- 					backgroundRepeat: 'no-repeat',
 
- 					backgroundPosition: pos? pos : '',
 
- 					backgroundSize: pos? '' : 'contain'
 
- 				};
 
- 			},
 
- 			base, cwd,
 
- 			nodes, selected, subnodes, subselected, autoSyncStop, subHoverTm,
 
- 			autoToggle = function() {
 
- 				var evTouchStart = 'touchstart.contextmenuAutoToggle';
 
- 				menu.data('hideTm') && clearTimeout(menu.data('hideTm'));
 
- 				if (menu.is(':visible')) {
 
- 					menu.on('touchstart', function(e) {
 
- 						if (e.originalEvent.touches.length > 1) {
 
- 							return;
 
- 						}
 
- 						menu.stop();
 
- 						fm.toFront(menu);
 
- 						menu.data('hideTm') && clearTimeout(menu.data('hideTm'));
 
- 					})
 
- 					.data('hideTm', setTimeout(function() {
 
- 						if (menu.is(':visible')) {
 
- 							cwd.find('.elfinder-cwd-file').off(evTouchStart);
 
- 							cwd.find('.elfinder-cwd-file.ui-selected')
 
- 							.one(evTouchStart, function(e) {
 
- 								if (e.originalEvent.touches.length > 1) {
 
- 									return;
 
- 								}
 
- 								var tgt = $(e.target);
 
- 								if (menu.first().length && !tgt.is('input:checkbox') && !tgt.hasClass('elfinder-cwd-select')) {
 
- 									e.stopPropagation();
 
- 									//e.preventDefault();
 
- 									open(e.originalEvent.touches[0].pageX, e.originalEvent.touches[0].pageY);
 
- 									cwd.data('longtap', true)
 
- 									tgt.one('touchend', function() {
 
- 										setTimeout(function() {
 
- 											cwd.removeData('longtap');
 
- 										}, 80);
 
- 									});
 
- 									return;
 
- 								}
 
- 								cwd.find('.elfinder-cwd-file').off(evTouchStart);
 
- 							})
 
- 							.one('unselect.'+fm.namespace, function() {
 
- 								cwd.find('.elfinder-cwd-file').off(evTouchStart);
 
- 							});
 
- 							menu.fadeOut({
 
- 								duration: 300,
 
- 								fail: function() {
 
- 									menu.css('opacity', '1').show();
 
- 								},
 
- 								done: function() {
 
- 									fm.toHide(menu);
 
- 								}
 
- 							});
 
- 						}
 
- 					}, 4500));
 
- 				}
 
- 			},
 
- 			
 
- 			keyEvts = function(e) {
 
- 				var code = e.keyCode,
 
- 					ESC = $.ui.keyCode.ESCAPE,
 
- 					ENT = $.ui.keyCode.ENTER,
 
- 					LEFT = $.ui.keyCode.LEFT,
 
- 					RIGHT = $.ui.keyCode.RIGHT,
 
- 					UP = $.ui.keyCode.UP,
 
- 					DOWN = $.ui.keyCode.DOWN,
 
- 					subent = fm.direction === 'ltr'? RIGHT : LEFT,
 
- 					sublev = subent === RIGHT? LEFT : RIGHT;
 
- 				
 
- 				if ($.inArray(code, [ESC, ENT, LEFT, RIGHT, UP, DOWN]) !== -1) {
 
- 					e.preventDefault();
 
- 					e.stopPropagation();
 
- 					e.stopImmediatePropagation();
 
- 					if (code == ESC || code === sublev) {
 
- 						if (selected && subnodes && subselected) {
 
- 							subselected.trigger('mouseleave').trigger('submenuclose');
 
- 							selected.addClass(cHover);
 
- 							subnodes = null;
 
- 							subselected = null;
 
- 						} else {
 
- 							code == ESC && close();
 
- 						}
 
- 					} else if (code == UP || code == DOWN) {
 
- 						if (subnodes) {
 
- 							if (subselected) {
 
- 								subselected.trigger('mouseleave');
 
- 							}
 
- 							if (code == DOWN && (! subselected || subnodes.length <= ++subnodes._cur)) {
 
- 								subnodes._cur = 0;
 
- 							} else if (code == UP && (! subselected || --subnodes._cur < 0)) {
 
- 								subnodes._cur = subnodes.length - 1;
 
- 							}
 
- 							subselected = subnodes.eq(subnodes._cur).trigger('mouseenter');
 
- 						} else {
 
- 							subnodes = null;
 
- 							if (selected) {
 
- 								selected.trigger('mouseleave');
 
- 							}
 
- 							if (code == DOWN && (! selected || nodes.length <= ++nodes._cur)) {
 
- 								nodes._cur = 0;
 
- 							} else if (code == UP && (! selected || --nodes._cur < 0)) {
 
- 								nodes._cur = nodes.length - 1;
 
- 							}
 
- 							selected = nodes.eq(nodes._cur).addClass(cHover);
 
- 						}
 
- 					} else if (selected && (code == ENT || code === subent)) {
 
- 						if (selected.hasClass('elfinder-contextmenu-group')) {
 
- 							if (subselected) {
 
- 								code == ENT && subselected.click();
 
- 							} else {
 
- 								selected.trigger('mouseenter');
 
- 								subnodes = selected.find('div.'+smItem);
 
- 								subnodes._cur = 0;
 
- 								subselected = subnodes.first().addClass(cHover);
 
- 							}
 
- 						} else {
 
- 							code == ENT && selected.click();
 
- 						}
 
- 					}
 
- 				}
 
- 			},
 
- 			
 
- 			open = function(x, y, css) {
 
- 				var width      = menu.outerWidth(),
 
- 					height     = menu.outerHeight(),
 
- 					bstyle     = base.attr('style'),
 
- 					bpos       = base.offset(),
 
- 					bwidth     = base.width(),
 
- 					bheight    = base.height(),
 
- 					mw         = fm.UA.Mobile? 40 : 2,
 
- 					mh         = fm.UA.Mobile? 20 : 2,
 
- 					x          = x - (bpos? bpos.left : 0),
 
- 					y          = y - (bpos? bpos.top : 0),
 
- 					css        = Object.assign(css || {}, {
 
- 						top  : Math.max(0, y + mh + height < bheight ? y + mh : y - (y + height - bheight)),
 
- 						left : Math.max(0, (x < width + mw || x + mw + width < bwidth)? x + mw : x - mw - width),
 
- 						opacity : '1'
 
- 					}),
 
- 					evts;
 
- 				autoSyncStop = true;
 
- 				fm.autoSync('stop');
 
- 				base.width(bwidth);
 
- 				menu.stop().removeAttr('style').css(css);
 
- 				fm.toFront(menu);
 
- 				menu.show();
 
- 				base.attr('style', bstyle);
 
- 				
 
- 				css[subpos] = parseInt(menu.width());
 
- 				menu.find('.elfinder-contextmenu-sub').css(css);
 
- 				if (fm.UA.iOS) {
 
- 					$('div.elfinder div.overflow-scrolling-touch').css('-webkit-overflow-scrolling', 'auto');
 
- 				}
 
- 				
 
- 				selected = null;
 
- 				subnodes = null;
 
- 				subselected = null;
 
- 				$(document).on('keydown.' + fm.namespace, keyEvts);
 
- 				evts = $._data(document).events;
 
- 				if (evts && evts.keydown) {
 
- 					evts.keydown.unshift(evts.keydown.pop());
 
- 				}
 
- 				
 
- 				fm.UA.Mobile && autoToggle();
 
- 				
 
- 				requestAnimationFrame(function() {
 
- 					fm.getUI().one('click.' + fm.namespace, close);
 
- 				});
 
- 			},
 
- 			
 
- 			close = function() {
 
- 				fm.getUI().off('click.' + fm.namespace, close);
 
- 				$(document).off('keydown.' + fm.namespace, keyEvts);
 
- 				currentType = currentTargets = null;
 
- 				
 
- 				if (menu.is(':visible') || menu.children().length) {
 
- 					fm.toHide(menu.removeAttr('style').empty().removeData('submenuKeep'));
 
- 					try {
 
- 						if (! menu.draggable('instance')) {
 
- 							menu.draggable(dragOpt);
 
- 						}
 
- 					} catch(e) {
 
- 						if (! menu.hasClass('ui-draggable')) {
 
- 							menu.draggable(dragOpt);
 
- 						}
 
- 					}
 
- 					if (menu.data('prevNode')) {
 
- 						menu.data('prevNode').after(menu);
 
- 						menu.removeData('prevNode');
 
- 					}
 
- 					fm.trigger('closecontextmenu');
 
- 					if (fm.UA.iOS) {
 
- 						$('div.elfinder div.overflow-scrolling-touch').css('-webkit-overflow-scrolling', 'touch');
 
- 					}
 
- 				}
 
- 				
 
- 				autoSyncStop && fm.searchStatus.state < 1 && ! fm.searchStatus.ininc && fm.autoSync();
 
- 				autoSyncStop = false;
 
- 			},
 
- 			
 
- 			create = function(type, targets) {
 
- 				var sep    = false,
 
- 					insSep = false,
 
- 					disabled = [],
 
- 					isCwd = type === 'cwd',
 
- 					selcnt = 0,
 
- 					cmdMap;
 
- 				currentType = type;
 
- 				currentTargets = targets;
 
- 				
 
- 				// get current uiCmdMap option
 
- 				if (!(cmdMap = fm.option('uiCmdMap', isCwd? void(0) : targets[0]))) {
 
- 					cmdMap = {};
 
- 				}
 
- 				
 
- 				if (!isCwd) {
 
- 					disabled = fm.getDisabledCmds(targets);
 
- 				}
 
- 				
 
- 				selcnt = fm.selected().length;
 
- 				if (selcnt > 1) {
 
- 					menu.append('<div class="ui-corner-top ui-widget-header elfinder-contextmenu-header"><span>'
 
- 					 + fm.i18n('selectedItems', ''+selcnt)
 
- 					 + '</span></div>');
 
- 				}
 
- 				
 
- 				nodes = $();
 
- 				$.each(types[type]||[], function(i, name) {
 
- 					var cmd, cmdName, useMap, node, submenu, hover;
 
- 					
 
- 					if (name === '|') {
 
- 						if (sep) {
 
- 							insSep = true;
 
- 						}
 
- 						return;
 
- 					}
 
- 					
 
- 					if (cmdMap[name]) {
 
- 						cmdName = cmdMap[name];
 
- 						useMap = true;
 
- 					} else {
 
- 						cmdName = name;
 
- 					}
 
- 					cmd = fm.getCommand(cmdName);
 
- 					if (cmd && !isCwd && (!fm.searchStatus.state || !cmd.disableOnSearch)) {
 
- 						cmd.__disabled = cmd._disabled;
 
- 						cmd._disabled = !(cmd.alwaysEnabled || (fm._commands[cmdName] ? $.inArray(name, disabled) === -1 && (!useMap || !disabled[cmdName]) : false));
 
- 						$.each(cmd.linkedCmds, function(i, n) {
 
- 							var c;
 
- 							if (c = fm.getCommand(n)) {
 
- 								c.__disabled = c._disabled;
 
- 								c._disabled = !(c.alwaysEnabled || (fm._commands[n] ? !disabled[n] : false));
 
- 							}
 
- 						});
 
- 					}
 
- 					if (cmd && !cmd._disabled && cmd.getstate(targets) != -1) {
 
- 						if (cmd.variants) {
 
- 							if (!cmd.variants.length) {
 
- 								return;
 
- 							}
 
- 							node = item(cmd.title, cmd.className? cmd.className : cmd.name, function(){}, cmd.contextmenuOpts);
 
- 							
 
- 							submenu = $('<div class="ui-front ui-corner-all elfinder-contextmenu-sub"/>')
 
- 								.hide()
 
- 								.css('max-height', fm.getUI().height() - 30)
 
- 								.appendTo(node.append('<span class="elfinder-contextmenu-arrow"/>'));
 
- 							
 
- 							hover = function(show){
 
- 								if (! show) {
 
- 									submenu.hide();
 
- 								} else {
 
- 									var bstyle = base.attr('style');
 
- 									base.width(base.width());
 
- 									// top: '-1000px' to prevent visible scrollbar of window with the elFinder option `height: '100%'`
 
- 									submenu.css({ top: '-1000px', left: 'auto', right: 'auto' });
 
- 									var nodeOffset = node.offset(),
 
- 										nodeleft   = nodeOffset.left,
 
- 										nodetop    = nodeOffset.top,
 
- 										nodewidth  = node.outerWidth(),
 
- 										width      = submenu.outerWidth(true),
 
- 										height     = submenu.outerHeight(true),
 
- 										baseOffset = base.offset(),
 
- 										wwidth     = baseOffset.left + base.width(),
 
- 										wheight    = baseOffset.top + base.height(),
 
- 										cltr       = ltr, 
 
- 										x          = nodewidth,
 
- 										y, over;
 
- 	
 
- 									if (ltr) {
 
- 										over = (nodeleft + nodewidth + width) - wwidth;
 
- 										if (over > 10) {
 
- 											if (nodeleft > width - 5) {
 
- 												x = x - 5;
 
- 												cltr = false;
 
- 											} else {
 
- 												if (!fm.UA.Mobile) {
 
- 													x = nodewidth - over;
 
- 												}
 
- 											}
 
- 										}
 
- 									} else {
 
- 										over = width - nodeleft;
 
- 										if (over > 0) {
 
- 											if ((nodeleft + nodewidth + width - 15) < wwidth) {
 
- 												x = x - 5;
 
- 												cltr = true;
 
- 											} else {
 
- 												if (!fm.UA.Mobile) {
 
- 													x = nodewidth - over;
 
- 												}
 
- 											}
 
- 										}
 
- 									}
 
- 									over = (nodetop + 5 + height) - wheight;
 
- 									y = (over > 0 && nodetop < wheight)? 5 - over : (over > 0? 30 - height : 5);
 
- 	
 
- 									menu.find('.elfinder-contextmenu-sub:visible').hide();
 
- 									submenu.css({
 
- 										top : y,
 
- 										left : cltr? x : 'auto',
 
- 										right: cltr? 'auto' : x,
 
- 										overflowY: 'auto'
 
- 									}).show();
 
- 									base.attr('style', bstyle);
 
- 								}
 
- 							};
 
- 							
 
- 							node.addClass('elfinder-contextmenu-group')
 
- 								.on('mouseleave', '.elfinder-contextmenu-sub', function(e) {
 
- 									if (! menu.data('draged')) {
 
- 										menu.removeData('submenuKeep');
 
- 									}
 
- 								})
 
- 								.on('submenuclose', '.elfinder-contextmenu-sub', function(e) {
 
- 									hover(false);
 
- 								})
 
- 								.on('click', '.'+smItem, function(e){
 
- 									var opts, $this;
 
- 									e.stopPropagation();
 
- 									if (! menu.data('draged')) {
 
- 										$this = $(this);
 
- 										if (!cmd.keepContextmenu) {
 
- 											menu.hide();
 
- 										} else {
 
- 											$this.removeClass(cHover);
 
- 											node.addClass(cHover);
 
- 										}
 
- 										opts = $this.data('exec');
 
- 										if (typeof opts === 'undefined') {
 
- 											opts = {};
 
- 										}
 
- 										if (typeof opts === 'object') {
 
- 											opts._userAction = true;
 
- 											opts._currentType = type;
 
- 											opts._currentNode = $this;
 
- 										}
 
- 										!cmd.keepContextmenu && close();
 
- 										fm.exec(cmd.name, targets, opts);
 
- 									}
 
- 								})
 
- 								.on('touchend', function(e) {
 
- 									if (! menu.data('drag')) {
 
- 										hover(true);
 
- 										menu.data('submenuKeep', true);
 
- 									}
 
- 								})
 
- 								.on('mouseenter mouseleave', function(e){
 
- 									if (! menu.data('touching')) {
 
- 										if (node.data('timer')) {
 
- 											clearTimeout(node.data('timer'));
 
- 											node.removeData('timer');
 
- 										}
 
- 										if (!$(e.target).closest('.elfinder-contextmenu-sub', menu).length) {
 
- 											if (e.type === 'mouseleave') {
 
- 												if (! menu.data('submenuKeep')) {
 
- 													node.data('timer', setTimeout(function() {
 
- 														node.removeData('timer');
 
- 														hover(false);
 
- 													}, 250));
 
- 												}
 
- 											} else {
 
- 												node.data('timer', setTimeout(function() {
 
- 													node.removeData('timer');
 
- 													hover(true);
 
- 												}, nodes.find('div.elfinder-contextmenu-sub:visible').length? 250 : 0));
 
- 											}
 
- 										}
 
- 									}
 
- 								});
 
- 							
 
- 							$.each(cmd.variants, function(i, variant) {
 
- 								var item = variant === '|' ? '<div class="elfinder-contextmenu-separator"/>' :
 
- 									$('<div class="'+cmItem+' '+smItem+'"><span>'+variant[1]+'</span></div>').data('exec', variant[0]),
 
- 									iconClass, icon;
 
- 								if (typeof variant[2] !== 'undefined') {
 
- 									icon = $('<span/>').addClass('elfinder-button-icon elfinder-contextmenu-icon');
 
- 									if (! /\//.test(variant[2])) {
 
- 										icon.addClass('elfinder-button-icon-'+variant[2]);
 
- 									} else {
 
- 										icon.css(urlIcon(variant[2]));
 
- 									}
 
- 									item.prepend(icon).addClass(smItem+'-icon');
 
- 								}
 
- 								submenu.append(item);
 
- 							});
 
- 								
 
- 						} else {
 
- 							node = item(cmd.title, cmd.className? cmd.className : cmd.name, function() {
 
- 								if (! menu.data('draged')) {
 
- 									!cmd.keepContextmenu && close();
 
- 									fm.exec(cmd.name, targets, {_userAction: true, _currentType: type, _currentNode: node});
 
- 								}
 
- 							}, cmd.contextmenuOpts);
 
- 							if (cmd.extra && cmd.extra.node) {
 
- 								$('<span class="elfinder-button-icon elfinder-button-icon-'+(cmd.extra.icon || '')+' '+exIcon+'"/>')
 
- 									.append(cmd.extra.node).appendTo(node);
 
- 								$(cmd.extra.node).trigger('ready', {targets: targets});
 
- 							} else {
 
- 								node.remove('.'+exIcon);
 
- 							}
 
- 						}
 
- 						
 
- 						if (cmd.extendsCmd) {
 
- 							node.children('span.elfinder-button-icon').addClass('elfinder-button-icon-' + cmd.extendsCmd);
 
- 						}
 
- 						
 
- 						if (insSep) {
 
- 							menu.append('<div class="elfinder-contextmenu-separator"/>');
 
- 						}
 
- 						menu.append(node);
 
- 						sep = true;
 
- 						insSep = false;
 
- 					}
 
- 					
 
- 					if (cmd && typeof cmd.__disabled !== 'undefined') {
 
- 						cmd._disabled = cmd.__disabled;
 
- 						delete cmd.__disabled;
 
- 						$.each(cmd.linkedCmds, function(i, n) {
 
- 							var c;
 
- 							if (c = fm.getCommand(n)) {
 
- 								c._disabled = c.__disabled;
 
- 								delete c.__disabled;
 
- 							}
 
- 						});
 
- 					}
 
- 				});
 
- 				nodes = menu.children('div.'+cmItem);
 
- 			},
 
- 			
 
- 			createFromRaw = function(raw) {
 
- 				currentType = 'raw';
 
- 				$.each(raw, function(i, data) {
 
- 					var node;
 
- 					
 
- 					if (data === '|') {
 
- 						menu.append('<div class="elfinder-contextmenu-separator"/>');
 
- 					} else if (data.label && typeof data.callback == 'function') {
 
- 						node = item(data.label, data.icon, function() {
 
- 							if (! menu.data('draged')) {
 
- 								!data.remain && close();
 
- 								data.callback();
 
- 							}
 
- 						}, data.options || null);
 
- 						menu.append(node);
 
- 					}
 
- 				});
 
- 				nodes = menu.children('div.'+cmItem);
 
- 			},
 
- 			
 
- 			currentType = null,
 
- 			currentTargets = null;
 
- 		
 
- 		fm.one('load', function() {
 
- 			base = fm.getUI();
 
- 			cwd = fm.getUI('cwd');
 
- 			fm.bind('contextmenu', function(e) {
 
- 				var data = e.data,
 
- 					css = {},
 
- 					prevNode;
 
- 				if (data.type && data.type !== 'files') {
 
- 					cwd.trigger('unselectall');
 
- 				}
 
- 				close();
 
- 				if (data.type && data.targets) {
 
- 					fm.trigger('contextmenucreate', data);
 
- 					create(data.type, data.targets);
 
- 					fm.trigger('contextmenucreatedone', data);
 
- 				} else if (data.raw) {
 
- 					createFromRaw(data.raw);
 
- 				}
 
- 				if (menu.children().length) {
 
- 					prevNode = data.prevNode || null;
 
- 					if (prevNode) {
 
- 						menu.data('prevNode', menu.prev());
 
- 						prevNode.after(menu);
 
- 					}
 
- 					if (data.fitHeight) {
 
- 						css = {maxHeight: Math.min(fm.getUI().height(), $(window).height()), overflowY: 'auto'};
 
- 						menu.draggable('destroy').removeClass('ui-draggable');
 
- 					}
 
- 					open(data.x, data.y, css);
 
- 					// call opened callback function
 
- 					if (data.opened && typeof data.opened === 'function') {
 
- 						data.opened.call(menu);
 
- 					}
 
- 				}
 
- 			})
 
- 			.one('destroy', function() { menu.remove(); })
 
- 			.bind('disable', close)
 
- 			.bind('select', function(e){
 
- 				(currentType === 'files' && (!e.data || e.data.selected.toString() !== currentTargets.toString())) && close();
 
- 			});
 
- 		})
 
- 		.shortcut({
 
- 			pattern     : fm.OS === 'mac' ? 'ctrl+m' : 'contextmenu shift+f10',
 
- 			description : 'contextmenu',
 
- 			callback    : function(e) {
 
- 				e.stopPropagation();
 
- 				e.preventDefault();
 
- 				$(document).one('contextmenu.' + fm.namespace, function(e) {
 
- 					e.preventDefault();
 
- 					e.stopPropagation();
 
- 				});
 
- 				var sel = fm.selected(),
 
- 					type, targets, pos, elm;
 
- 				
 
- 				if (sel.length) {
 
- 					type = 'files';
 
- 					targets = sel;
 
- 					elm = $('#'+fm.cwdHash2Id(sel[0]));
 
- 				} else {
 
- 					type = 'cwd';
 
- 					targets = [ fm.cwd().hash ];
 
- 					pos = fm.getUI('workzone').offset();
 
- 				}
 
- 				if (! elm || ! elm.length) {
 
- 					elm = fm.getUI('workzone');
 
- 				}
 
- 				pos = elm.offset();
 
- 				pos.top += (elm.height() / 2);
 
- 				pos.left += (elm.width() / 2);
 
- 				fm.trigger('contextmenu', {
 
- 					'type'    : type,
 
- 					'targets' : targets,
 
- 					'x'       : pos.left,
 
- 					'y'       : pos.top
 
- 				});
 
- 			}
 
- 		});
 
- 		
 
- 	});
 
- 	
 
- };
 
- /*
 
-  * File: /js/ui/cwd.js
 
-  */
 
- /**
 
-  * elFinder current working directory ui.
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.elfindercwd = function(fm, options) {
 
- 		this.not('.elfinder-cwd').each(function() {
 
- 		// fm.time('cwdLoad');
 
- 		
 
- 		var mobile = fm.UA.Mobile,
 
- 			list = fm.viewType == 'list',
 
- 			undef = 'undefined',
 
- 			/**
 
- 			 * Select event full name
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			evtSelect = 'select.'+fm.namespace,
 
- 			
 
- 			/**
 
- 			 * Unselect event full name
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			evtUnselect = 'unselect.'+fm.namespace,
 
- 			
 
- 			/**
 
- 			 * Disable event full name
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			evtDisable = 'disable.'+fm.namespace,
 
- 			
 
- 			/**
 
- 			 * Disable event full name
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			evtEnable = 'enable.'+fm.namespace,
 
- 			
 
- 			c = 'class',
 
- 			/**
 
- 			 * File css class
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			clFile       = fm.res(c, 'cwdfile'),
 
- 			
 
- 			/**
 
- 			 * Selected css class
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			fileSelector = '.'+clFile,
 
- 			
 
- 			/**
 
- 			 * Selected css class
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			clSelected = 'ui-selected',
 
- 			
 
- 			/**
 
- 			 * Disabled css class
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			clDisabled = fm.res(c, 'disabled'),
 
- 			
 
- 			/**
 
- 			 * Draggable css class
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			clDraggable = fm.res(c, 'draggable'),
 
- 			
 
- 			/**
 
- 			 * Droppable css class
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			clDroppable = fm.res(c, 'droppable'),
 
- 			
 
- 			/**
 
- 			 * Hover css class
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			clHover     = fm.res(c, 'hover'),
 
- 			/**
 
- 			 * Active css class
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			clActive     = fm.res(c, 'active'),
 
- 			/**
 
- 			 * Hover css class
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			clDropActive = fm.res(c, 'adroppable'),
 
- 			/**
 
- 			 * Css class for temporary nodes (for mkdir/mkfile) commands
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			clTmp = clFile+'-tmp',
 
- 			/**
 
- 			 * Select checkbox css class
 
- 			 * 
 
- 			 * @type String
 
- 			 */
 
- 			clSelChk = 'elfinder-cwd-selectchk',
 
- 			/**
 
- 			 * Number of thumbnails to load in one request (new api only)
 
- 			 *
 
- 			 * @type Number
 
- 			 **/
 
- 			tmbNum = fm.options.loadTmbs > 0 ? fm.options.loadTmbs : 5,
 
- 			
 
- 			/**
 
- 			 * Current search query.
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			query = '',
 
- 			/**
 
- 			 * Currect clipboard(cut) hashes as object key
 
- 			 * 
 
- 			 * @type Object
 
- 			 */
 
- 			clipCuts = {},
 
- 			/**
 
- 			 * Parents hashes of cwd
 
- 			 *
 
- 			 * @type Array
 
- 			 */
 
- 			cwdParents = [],
 
- 			
 
- 			/**
 
- 			 * cwd current hashes
 
- 			 * 
 
- 			 * @type Array
 
- 			 */
 
- 			cwdHashes = [],
 
- 			/**
 
- 			 * incsearch current hashes
 
- 			 * 
 
- 			 * @type Array
 
- 			 */
 
- 			incHashes = void 0,
 
- 			/**
 
- 			 * Custom columns name and order
 
- 			 *
 
- 			 * @type Array
 
- 			 */
 
- 			customCols = [],
 
- 			/**
 
- 			 * Current clicked element id of first time for dblclick
 
- 			 * 
 
- 			 * @type String
 
- 			 */
 
- 			curClickId = '',
 
- 			/**
 
- 			 * Custom columns builder
 
- 			 *
 
- 			 * @type Function
 
- 			 */
 
- 			customColsBuild = function() {
 
- 				var cols = '';
 
- 				for (var i = 0; i < customCols.length; i++) {
 
- 					cols += '<td class="elfinder-col-'+customCols[i]+'">{' + customCols[i] + '}</td>';
 
- 				}
 
- 				return cols;
 
- 			},
 
- 			/**
 
- 			 * Make template.row from customCols
 
- 			 *
 
- 			 * @type Function
 
- 			 */
 
- 			makeTemplateRow = function() {
 
- 				return '<tr id="{id}" class="'+clFile+' {permsclass} {dirclass}" title="{tooltip}"{css}><td class="elfinder-col-name"><div class="elfinder-cwd-file-wrapper"><span class="elfinder-cwd-icon {mime}"{style}/>{marker}<span class="elfinder-cwd-filename">{name}</span></div>'+selectCheckbox+'</td>'+customColsBuild()+'</tr>';
 
- 			},
 
- 			
 
- 			selectCheckbox = ($.map(options.showSelectCheckboxUA, function(t) {return (fm.UA[t] || t.match(/^all$/i))? true : null;}).length)? '<div class="elfinder-cwd-select"><input type="checkbox" class="'+clSelChk+'"></div>' : '',
 
- 			colResizing = false,
 
- 			
 
- 			colWidth = null,
 
- 			/**
 
- 			 * File templates
 
- 			 *
 
- 			 * @type Object
 
- 			 **/
 
- 			templates = {
 
- 				icon : '<div id="{id}" class="'+clFile+' {permsclass} {dirclass} ui-corner-all" title="{tooltip}"><div class="elfinder-cwd-file-wrapper ui-corner-all"><div class="elfinder-cwd-icon {mime} ui-corner-all" unselectable="on"{style}/>{marker}</div><div class="elfinder-cwd-filename" title="{nametitle}">{name}</div>'+selectCheckbox+'</div>',
 
- 				row  : ''
 
- 			},
 
- 			
 
- 			permsTpl = fm.res('tpl', 'perms'),
 
- 			
 
- 			lockTpl = fm.res('tpl', 'lock'),
 
- 			
 
- 			symlinkTpl = fm.res('tpl', 'symlink'),
 
- 			
 
- 			/**
 
- 			 * Template placeholders replacement rules
 
- 			 *
 
- 			 * @type Object
 
- 			 **/
 
- 			replacement = {
 
- 				id : function(f) {
 
- 					return fm.cwdHash2Id(f.hash);
 
- 				},
 
- 				name : function(f) {
 
- 					var name = fm.escape(f.i18 || f.name);
 
- 					!list && (name = name.replace(/([_.])/g, '​$1'));
 
- 					return name;
 
- 				},
 
- 				nametitle : function(f) {
 
- 					return fm.escape(f.i18 || f.name);
 
- 				},
 
- 				permsclass : function(f) {
 
- 					return fm.perms2class(f);
 
- 				},
 
- 				perm : function(f) {
 
- 					return fm.formatPermissions(f);
 
- 				},
 
- 				dirclass : function(f) {
 
- 					var cName = f.mime == 'directory' ? 'directory' : '';
 
- 					f.isroot && (cName += ' isroot');
 
- 					f.csscls && (cName += ' ' + fm.escape(f.csscls));
 
- 					options.getClass && (cName += ' ' + options.getClass(f));
 
- 					return cName;
 
- 				},
 
- 				style : function(f) {
 
- 					return f.icon? fm.getIconStyle(f) : '';
 
- 				},
 
- 				mime : function(f) {
 
- 					var cName = fm.mime2class(f.mime);
 
- 					f.icon && (cName += ' elfinder-cwd-bgurl');
 
- 					return cName;
 
- 				},
 
- 				size : function(f) {
 
- 					return (f.mime === 'directory' && !f.size)? '-' : fm.formatSize(f.size);
 
- 				},
 
- 				date : function(f) {
 
- 					return fm.formatDate(f);
 
- 				},
 
- 				kind : function(f) {
 
- 					return fm.mime2kind(f);
 
- 				},
 
- 				mode : function(f) {
 
- 					return f.perm? fm.formatFileMode(f.perm) : '';
 
- 				},
 
- 				modestr : function(f) {
 
- 					return f.perm? fm.formatFileMode(f.perm, 'string') : '';
 
- 				},
 
- 				modeoct : function(f) {
 
- 					return f.perm? fm.formatFileMode(f.perm, 'octal') : '';
 
- 				},
 
- 				modeboth : function(f) {
 
- 					return f.perm? fm.formatFileMode(f.perm, 'both') : '';
 
- 				},
 
- 				marker : function(f) {
 
- 					return (f.alias || f.mime == 'symlink-broken' ? symlinkTpl : '')+(!f.read || !f.write ? permsTpl : '')+(f.locked ? lockTpl : '');
 
- 				},
 
- 				tooltip : function(f) {
 
- 					var title = fm.formatDate(f) + (f.size > 0 ? ' ('+fm.formatSize(f.size)+')' : ''),
 
- 						info  = '';
 
- 					if (query && f.path) {
 
- 						info = fm.escape(f.path.replace(/\/[^\/]*$/, ''));
 
- 					} else {
 
- 						info = f.tooltip? fm.escape(f.tooltip).replace(/\r/g, '
') : '';
 
- 					}
 
- 					if (list) {
 
- 						info += (info? '
' : '') + fm.escape(f.i18 || f.name);
 
- 					}
 
- 					return info? info + '
' + title : title;
 
- 				}
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Type badge CSS added flag
 
- 			 * 
 
- 			 * @type Object
 
- 			 */
 
- 			addedBadges = {},
 
- 			
 
- 			/**
 
- 			 * Type badge style sheet element
 
- 			 * 
 
- 			 * @type Object
 
- 			 */
 
- 			addBadgeStyleSheet,
 
- 			
 
- 			/**
 
- 			 * Add type badge CSS into 'head'
 
- 			 * 
 
- 			 * @type Fundtion
 
- 			 */
 
- 			addBadgeStyle = function(mime, name) {
 
- 				var sel, ext, type;
 
- 				if (mime && ! addedBadges[mime]) {
 
- 					if (typeof addBadgeStyleSheet === 'undefined') {
 
- 						if ($('#elfinderAddBadgeStyle'+fm.namespace).length) {
 
- 							$('#elfinderAddBadgeStyle'+fm.namespace).remove();
 
- 						}
 
- 						addBadgeStyleSheet = $('<style id="addBadgeStyle'+fm.namespace+'"/>').insertBefore($('head').children(':first')).get(0).sheet || null;
 
- 					}
 
- 					if (addBadgeStyleSheet) {
 
- 						mime = mime.toLowerCase();
 
- 						type = mime.split('/');
 
- 						ext = fm.escape(fm.mimeTypes[mime] || (name.replace(/.bac?k$/i, '').match(/\.([^.]+)$/) || ['',''])[1]);
 
- 						if (ext) {
 
- 							sel = '.elfinder-cwd-icon-' + type[0].replace(/(\.|\+)/g, '-');
 
- 							if (typeof type[1] !== 'undefined') {
 
- 								sel += '.elfinder-cwd-icon-' + type[1].replace(/(\.|\+)/g, '-');
 
- 							}
 
- 							try {
 
- 								addBadgeStyleSheet.insertRule(sel + ':before{content:"' + ext.toLowerCase() + '"}', 0);
 
- 							} catch(e) {}
 
- 						}
 
- 						addedBadges[mime] = true;
 
- 					}
 
- 				}
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Return file html
 
- 			 *
 
- 			 * @param  Object  file info
 
- 			 * @return String
 
- 			 **/
 
- 			itemhtml = function(f) {
 
- 				f.mime && f.mime !== 'directory' && !addedBadges[f.mime] && addBadgeStyle(f.mime, f.name);
 
- 				return templates[list ? 'row' : 'icon']
 
- 						.replace(/\{([a-z0-9_]+)\}/g, function(s, e) { 
 
- 							return replacement[e] ? replacement[e](f, fm) : (f[e] ? f[e] : ''); 
 
- 						});
 
- 			},
 
- 			
 
- 			/**
 
- 			 * jQueery node that will be selected next
 
- 			 * 
 
- 			 * @type Object jQuery node
 
- 			 */
 
- 			selectedNext = $(),
 
- 			
 
- 			/**
 
- 			 * Flag. Required for msie to avoid unselect files on dragstart
 
- 			 *
 
- 			 * @type Boolean
 
- 			 **/
 
- 			selectLock = false,
 
- 			
 
- 			/**
 
- 			 * Move selection to prev/next file
 
- 			 *
 
- 			 * @param String  move direction
 
- 			 * @param Boolean append to current selection
 
- 			 * @return void
 
- 			 * @rise select			
 
- 			 */
 
- 			select = function(keyCode, append) {
 
- 				var code     = $.ui.keyCode,
 
- 					prev     = keyCode == code.LEFT || keyCode == code.UP,
 
- 					sel      = cwd.find('[id].'+clSelected),
 
- 					selector = prev ? 'first:' : 'last',
 
- 					s, n, sib, top, left;
 
- 				function sibling(n, direction) {
 
- 					return n[direction+'All']('[id]:not(.'+clDisabled+'):not(.elfinder-cwd-parent):first');
 
- 				}
 
- 				
 
- 				if (sel.length) {
 
- 					s = sel.filter(prev ? ':first' : ':last');
 
- 					sib = sibling(s, prev ? 'prev' : 'next');
 
- 					
 
- 					if (!sib.length) {
 
- 						// there is no sibling on required side - do not move selection
 
- 						n = s;
 
- 					} else if (list || keyCode == code.LEFT || keyCode == code.RIGHT) {
 
- 						// find real prevoius file
 
- 						n = sib;
 
- 					} else {
 
- 						// find up/down side file in icons view
 
- 						top = s.position().top;
 
- 						left = s.position().left;
 
- 						n = s;
 
- 						if (prev) {
 
- 							do {
 
- 								n = n.prev('[id]');
 
- 							} while (n.length && !(n.position().top < top && n.position().left <= left));
 
- 							if (n.hasClass(clDisabled)) {
 
- 								n = sibling(n, 'next');
 
- 							}
 
- 						} else {
 
- 							do {
 
- 								n = n.next('[id]');
 
- 							} while (n.length && !(n.position().top > top && n.position().left >= left));
 
- 							
 
- 							if (n.hasClass(clDisabled)) {
 
- 								n = sibling(n, 'prev');
 
- 							}
 
- 							// there is row before last one - select last file
 
- 							if (!n.length) {
 
- 								sib = cwd.find('[id]:not(.'+clDisabled+'):last');
 
- 								if (sib.position().top > top) {
 
- 									n = sib;
 
- 								}
 
- 							}
 
- 						}
 
- 					}
 
- 					// !append && unselectAll();
 
- 				} else {
 
- 					if (selectedNext.length) {
 
- 						n = prev? selectedNext.prev() : selectedNext;
 
- 					} else {
 
- 						// there are no selected file - select first/last one
 
- 						n = cwd.find('[id]:not(.'+clDisabled+'):not(.elfinder-cwd-parent):'+(prev ? 'last' : 'first'));
 
- 					}
 
- 				}
 
- 				
 
- 				if (n && n.length && !n.hasClass('elfinder-cwd-parent')) {
 
- 					if (s && append) {
 
- 						// append new files to selected
 
- 						n = s.add(s[prev ? 'prevUntil' : 'nextUntil']('#'+n.attr('id'))).add(n);
 
- 					} else {
 
- 						// unselect selected files
 
- 						sel.trigger(evtUnselect);
 
- 					}
 
- 					// select file(s)
 
- 					n.trigger(evtSelect);
 
- 					// set its visible
 
- 					scrollToView(n.filter(prev ? ':first' : ':last'));
 
- 					// update cache/view
 
- 					trigger();
 
- 				}
 
- 			},
 
- 			
 
- 			selectedFiles = {},
 
- 			
 
- 			selectFile = function(hash) {
 
- 				$('#'+fm.cwdHash2Id(hash)).trigger(evtSelect);
 
- 			},
 
- 			
 
- 			allSelected = false,
 
- 			
 
- 			selectAll = function() {
 
- 				var phash = fm.cwd().hash;
 
- 				selectCheckbox && selectAllCheckbox.find('input').prop('checked', true);
 
- 				fm.lazy(function() {
 
- 					var files;
 
- 					if (fm.maxTargets && (incHashes || cwdHashes).length > fm.maxTargets) {
 
- 						unselectAll({ notrigger: true });
 
- 						files = $.map(incHashes || cwdHashes, function(hash) { return fm.file(hash) || null; });
 
- 						files = files.slice(0, fm.maxTargets);
 
- 						selectedFiles = {};
 
- 						$.each(files, function(i, v) {
 
- 							selectedFiles[v.hash] = true;
 
- 							$('#'+fm.cwdHash2Id(v.hash)).trigger(evtSelect);
 
- 						});
 
- 						fm.toast({mode: 'warning', msg: fm.i18n(['errMaxTargets', fm.maxTargets])});
 
- 					} else {
 
- 						cwd.find('[id]:not(.'+clSelected+'):not(.elfinder-cwd-parent)').trigger(evtSelect);
 
- 						selectedFiles = fm.arrayFlip(incHashes || cwdHashes, true);
 
- 					}
 
- 					trigger();
 
- 					selectCheckbox && selectAllCheckbox.data('pending', false);
 
- 				}, 0, {repaint: true});
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Unselect all files
 
- 			 *
 
- 			 * @param  Object  options
 
- 			 * @return void
 
- 			 */
 
- 			unselectAll = function(opts) {
 
- 				var o = opts || {};
 
- 				selectCheckbox && selectAllCheckbox.find('input').prop('checked', false);
 
- 				if (Object.keys(selectedFiles).length) {
 
- 					selectLock = false;
 
- 					selectedFiles = {};
 
- 					cwd.find('[id].'+clSelected).trigger(evtUnselect);
 
- 					selectCheckbox && cwd.find('input:checkbox.'+clSelChk).prop('checked', false);
 
- 				}
 
- 				!o.notrigger && trigger();
 
- 				selectCheckbox && selectAllCheckbox.data('pending', false);
 
- 				cwd.removeClass('elfinder-cwd-allselected');
 
- 			},
 
- 			
 
- 			selectInvert = function() {
 
- 				var invHashes = {};
 
- 				if (allSelected) {
 
- 					unselectAll();
 
- 				} else if (! Object.keys(selectedFiles).length) {
 
- 					selectAll();
 
- 				} else {
 
- 					$.each((incHashes || cwdHashes), function(i, h) {
 
- 						var itemNode = $('#'+fm.cwdHash2Id(h));
 
- 						if (! selectedFiles[h]) {
 
- 							invHashes[h] = true;
 
- 							itemNode.length && itemNode.trigger(evtSelect);
 
- 						} else {
 
- 							itemNode.length && itemNode.trigger(evtUnselect);
 
- 						}
 
- 					});
 
- 					selectedFiles = invHashes;
 
- 					trigger();
 
- 				}
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Return selected files hashes list
 
- 			 *
 
- 			 * @return Array
 
- 			 */
 
- 			selected = function() {
 
- 				return Object.keys(selectedFiles);
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Last selected node id
 
- 			 * 
 
- 			 * @type String|Void
 
- 			 */
 
- 			lastSelect = void 0,
 
- 			
 
- 			/**
 
- 			 * Fire elfinder "select" event and pass selected files to it
 
- 			 *
 
- 			 * @return void
 
- 			 */
 
- 			trigger = function() {
 
- 				var selected = Object.keys(selectedFiles),
 
- 					opts = {
 
- 						selected : selected,
 
- 						origin : 'cwd'
 
- 					};
 
- 				
 
- 				if (oldSchoolItem && (selected.length > 1 || selected[0] !== fm.cwdId2Hash(
 
- 					oldSchoolItem.attr('id'))) && oldSchoolItem.hasClass(clSelected)) {
 
- 					oldSchoolItem.trigger(evtUnselect);
 
- 				}
 
- 				allSelected = selected.length && (selected.length === (incHashes || cwdHashes).length) && (!fm.maxTargets || selected.length <= fm.maxTargets);
 
- 				if (selectCheckbox) {
 
- 					selectAllCheckbox.find('input').prop('checked', allSelected);
 
- 					cwd[allSelected? 'addClass' : 'removeClass']('elfinder-cwd-allselected');
 
- 				}
 
- 				if (allSelected) {
 
- 					opts.selectall = true;
 
- 				} else if (! selected.length) {
 
- 					opts.unselectall = true;
 
- 				}
 
- 				fm.trigger('select', opts);
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Scroll file to set it visible
 
- 			 *
 
- 			 * @param DOMElement  file/dir node
 
- 			 * @return void
 
- 			 */
 
- 			scrollToView = function(o, blink) {
 
- 				if (! o.length) {
 
- 					return;
 
- 				}
 
- 				var ftop    = o.position().top,
 
- 					fheight = o.outerHeight(true),
 
- 					wtop    = wrapper.scrollTop(),
 
- 					wheight = wrapper.get(0).clientHeight,
 
- 					thheight = tableHeader? tableHeader.outerHeight(true) : 0;
 
- 				if (ftop + thheight + fheight > wtop + wheight) {
 
- 					wrapper.scrollTop(parseInt(ftop + thheight + fheight - wheight));
 
- 				} else if (ftop < wtop) {
 
- 					wrapper.scrollTop(ftop);
 
- 				}
 
- 				list && wrapper.scrollLeft(0);
 
- 				!!blink && fm.resources.blink(o, 'lookme');
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Files we get from server but not show yet
 
- 			 *
 
- 			 * @type Array
 
- 			 **/
 
- 			buffer = [],
 
- 			
 
- 			/**
 
- 			 * Extra data of buffer
 
- 			 *
 
- 			 * @type Object
 
- 			 **/
 
- 			bufferExt = {},
 
- 			
 
- 			/**
 
- 			 * Return index of elements with required hash in buffer 
 
- 			 *
 
- 			 * @param String  file hash
 
- 			 * @return Number
 
- 			 */
 
- 			index = function(hash) {
 
- 				var l = buffer.length;
 
- 				
 
- 				while (l--) {
 
- 					if (buffer[l].hash == hash) {
 
- 						return l;
 
- 					}
 
- 				}
 
- 				return -1;
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Scroll start event name
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			scrollStartEvent = 'elfscrstart',
 
- 			
 
- 			/**
 
- 			 * Scroll stop event name
 
- 			 *
 
- 			 * @type String
 
- 			 **/
 
- 			scrollEvent = 'elfscrstop',
 
- 			
 
- 			scrolling = false,
 
- 			
 
- 			/**
 
- 			 * jQuery UI selectable option
 
- 			 * 
 
- 			 * @type Object
 
- 			 */
 
- 			selectableOption = {
 
- 				disabled   : true,
 
- 				filter     : '[id]:first',
 
- 				stop       : trigger,
 
- 				delay      : 250,
 
- 				appendTo   : 'body',
 
- 				autoRefresh: false,
 
- 				selected   : function(e, ui) { $(ui.selected).trigger(evtSelect); },
 
- 				unselected : function(e, ui) { $(ui.unselected).trigger(evtUnselect); }
 
- 			},
 
- 			
 
- 			/**
 
- 			 * hashes of items displayed in current view
 
- 			 * 
 
- 			 * @type Object  ItemHash => DomId
 
- 			 */
 
- 			inViewHashes = {},
 
- 			
 
- 			/**
 
- 			 * Processing when the current view is changed (On open, search, scroll, resize etc.)
 
- 			 * 
 
- 			 * @return void
 
- 			 */
 
- 			wrapperRepaint = function(init, recnt) {
 
- 				var firstNode = (list? cwd.find('tbody:first') : cwd).children('[id]:first');
 
- 				if (!firstNode.length) {
 
- 					return;
 
- 				}
 
- 				var selectable = cwd.data('selectable'),
 
- 					rec = (function() {
 
- 						var wos = wrapper.offset(),
 
- 							w = $(window),
 
- 							x = (firstNode.width() / 2) * (!list && options.oldSchool? 3 : 1),
 
- 							l = wos.left - w.scrollLeft() + (fm.direction === 'ltr'? x : wrapper.width() - x),
 
- 							t = wos.top - w.scrollTop() + 10 + (list? (bufferExt.itemH * (options.oldSchool? 2 : 1)) || (fm.UA.Touch? 36 : 24) : 0);
 
- 						return {left: Math.max(0, Math.round(l)), top: Math.max(0, Math.round(t))};
 
- 					})(),
 
- 					tgt = init? firstNode : $(document.elementFromPoint(rec.left , rec.top)),
 
- 					ids = {},
 
- 					tmbs = {},
 
- 					multi = 5,
 
- 					cnt = Math.ceil((bufferExt.hpi? Math.ceil((wz.data('rectangle').height / bufferExt.hpi) * 1.5) : showFiles) / multi),
 
- 					chk = function() {
 
- 						var id, hash, file, i;
 
- 						for (i = 0; i < multi; i++) {
 
- 							id = tgt.attr('id');
 
- 							if (id) {
 
- 								bufferExt.getTmbs = [];
 
- 								hash = fm.cwdId2Hash(id);
 
- 								inViewHashes[hash] = id;
 
- 								// for tmbs
 
- 								if (bufferExt.attachTmbs[hash]) {
 
- 									tmbs[hash] = bufferExt.attachTmbs[hash];
 
- 								}
 
- 								// for selectable
 
- 								selectable && (ids[id] = true);
 
- 							}
 
- 							// next node
 
- 							tgt = tgt.next();
 
- 							if (!tgt.length) {
 
- 								break;
 
- 							}
 
- 						}
 
- 					},
 
- 					done = function() {
 
- 						var idsArr;
 
- 						if (cwd.data('selectable')) {
 
- 							Object.assign(ids, selectedFiles);
 
- 							idsArr = Object.keys(ids);
 
- 							if (idsArr.length) {
 
- 								selectableOption.filter = '#'+idsArr.join(', #');
 
- 								cwd.selectable('enable').selectable('option', {filter : selectableOption.filter}).selectable('refresh');
 
- 							}
 
- 						}
 
- 						if (Object.keys(tmbs).length) {
 
- 							bufferExt.getTmbs = [];
 
- 							attachThumbnails(tmbs);
 
- 						}
 
- 					},
 
- 					setTarget = function() {
 
- 						if (!tgt.hasClass(clFile)) {
 
- 							tgt = tgt.closest(fileSelector);
 
- 						}
 
- 					},
 
- 					arr, widget;
 
- 				
 
- 				inViewHashes = {};
 
- 				selectable && cwd.selectable('option', 'disabled');
 
- 				
 
- 				if (tgt.length) {
 
- 					if (!tgt.hasClass(clFile) && !tgt.closest(fileSelector).length) {
 
- 						// dialog, serach button etc.
 
- 						widget = fm.getUI().find('.ui-dialog:visible,.ui-widget:visible');
 
- 						if (widget.length) {
 
- 							widget.hide();
 
- 							tgt = $(document.elementFromPoint(rec.left , rec.top));
 
- 							widget.show();
 
- 						} else {
 
- 							widget = null;
 
- 						}
 
- 					}
 
- 					setTarget();
 
- 					if (!tgt.length) {
 
- 						// try search 5px down
 
- 						widget && widget.hide();
 
- 						tgt = $(document.elementFromPoint(rec.left , rec.top + 5));
 
- 						widget && widget.show();
 
- 						setTarget();
 
- 					}
 
- 				}
 
- 				if (tgt.length) {
 
- 					if (tgt.attr('id')) {
 
- 						if (init) {
 
- 							for (var i = 0; i < cnt; i++) {
 
- 								chk();
 
- 								if (! tgt.length) {
 
- 									break;
 
- 								}
 
- 							}
 
- 							done();
 
- 						} else {
 
- 							bufferExt.repaintJob && bufferExt.repaintJob.state() === 'pending' && bufferExt.repaintJob.reject();
 
- 							arr = new Array(cnt);
 
- 							bufferExt.repaintJob = fm.asyncJob(function() {
 
- 								chk();
 
- 								if (! tgt.length) {
 
- 									done();
 
- 									bufferExt.repaintJob && bufferExt.repaintJob.state() === 'pending' && bufferExt.repaintJob.reject();
 
- 								}
 
- 							}, arr).done(done);
 
- 						}
 
- 					}
 
- 				} else if (init && bufferExt.renderd) {
 
- 					// In initial request, cwd DOM not renderd so doing lazy check
 
- 					recnt = recnt || 0;
 
- 					if (recnt < 10) { // Prevent infinite loop
 
- 						requestAnimationFrame(function() {
 
- 							wrapperRepaint(init, ++recnt);
 
- 						});
 
- 					}
 
- 				}
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Item node of oldScholl ".."
 
- 			 */
 
- 			oldSchoolItem = null,
 
- 			/**
 
- 			 * display parent folder with ".." name
 
- 			 * 
 
- 			 * @param  String  phash
 
- 			 * @return void
 
- 			 */
 
- 			oldSchool = function(p) {
 
- 				var phash = fm.cwd().phash,
 
- 					pdir  = fm.file(phash) || null,
 
- 					set   = function(pdir) {
 
- 						if (pdir) {
 
- 							oldSchoolItem = $(itemhtml($.extend(true, {}, pdir, {name : '..', i18 : '..', mime : 'directory'})))
 
- 								.addClass('elfinder-cwd-parent')
 
- 								.on('dblclick', function() {
 
- 									var hash = fm.cwdId2Hash(this.id);
 
- 									fm.trigger('select', {selected : [hash]}).exec('open', hash);
 
- 								});
 
- 							(list ? oldSchoolItem.children('td:first') : oldSchoolItem).children('.elfinder-cwd-select').remove();
 
- 							(list ? cwd.find('tbody') : cwd).prepend(oldSchoolItem);
 
- 						}
 
- 					};
 
- 				if (pdir) {
 
- 					set(pdir);
 
- 				} else {
 
- 					if (fm.getUI('tree').length) {
 
- 						fm.one('parents', function() {
 
- 							set(fm.file(phash) || null);
 
- 							wrapper.trigger(scrollEvent);
 
- 						});
 
- 					} else {
 
- 						fm.request({
 
- 							data : {cmd : 'parents', target : fm.cwd().hash},
 
- 							preventFail : true
 
- 						})
 
- 						.done(function(data) {
 
- 							set(fm.file(phash) || null);
 
- 							wrapper.trigger(scrollEvent);
 
- 						});
 
- 					}
 
- 				}
 
- 			},
 
- 			
 
- 			showFiles = fm.options.showFiles,
 
- 			
 
- 			/**
 
- 			 * Cwd scroll event handler.
 
- 			 * Lazy load - append to cwd not shown files
 
- 			 *
 
- 			 * @return void
 
- 			 */
 
- 			render = function() {
 
- 				if (bufferExt.rendering || (bufferExt.renderd && ! buffer.length)) {
 
- 					return;
 
- 				}
 
- 				var place = (list ? cwd.children('table').children('tbody') : cwd),
 
- 					phash,
 
- 					chk,
 
- 					// created document fragment for jQuery >= 1.12, 2.2, 3.0
 
- 					// see Studio-42/elFinder#1544 @ github
 
- 					docFlag = $.htmlPrefilter? true : false,
 
- 					tempDom = docFlag? $(document.createDocumentFragment()) : $('<div/>'),
 
- 					go      = function(o){
 
- 						var over  = o || null,
 
- 							html  = [],
 
- 							dirs  = false,
 
- 							atmb  = {},
 
- 							stmb  = (fm.option('tmbUrl') === 'self'),
 
- 							init  = bufferExt.renderd? false : true,
 
- 							files, locks, selected;
 
- 						
 
- 						files = buffer.splice(0, showFiles + (over || 0) / (bufferExt.hpi || 1));
 
- 						bufferExt.renderd += files.length;
 
- 						if (! buffer.length) {
 
- 							bottomMarker.hide();
 
- 							wrapper.off(scrollEvent, render);
 
- 						}
 
- 						
 
- 						locks = [];
 
- 						html = $.map(files, function(f) {
 
- 							if (f.hash && f.name) {
 
- 								if (f.mime == 'directory') {
 
- 									dirs = true;
 
- 								}
 
- 								if ((f.tmb && (f.tmb != 1 || f.size > 0)) || (stmb && f.mime.indexOf('image/') === 0)) {
 
- 									atmb[f.hash] = f.tmb || 'self';
 
- 								}
 
- 								clipCuts[f.hash] && locks.push(f.hash);
 
- 								return itemhtml(f);
 
- 							}
 
- 							return null;
 
- 						});
 
- 						// html into temp node
 
- 						tempDom.empty().append(html.join(''));
 
- 						
 
- 						// make directory droppable
 
- 						dirs && !mobile && makeDroppable(tempDom);
 
- 						
 
- 						// check selected items
 
- 						selected = [];
 
- 						if (Object.keys(selectedFiles).length) {
 
- 							tempDom.find('[id]:not(.'+clSelected+'):not(.elfinder-cwd-parent)').each(function() {
 
- 								selectedFiles[fm.cwdId2Hash(this.id)] && selected.push($(this));
 
- 							});
 
- 						}
 
- 						
 
- 						// append to cwd
 
- 						place.append(docFlag? tempDom : tempDom.children());
 
- 						
 
- 						// trigger select
 
- 						if (selected.length) {
 
- 							$.each(selected, function(i, n) { n.trigger(evtSelect); });
 
- 							trigger();
 
- 						}
 
- 						
 
- 						locks.length && fm.trigger('lockfiles', {files: locks});
 
- 						!bufferExt.hpi && bottomMarkerShow(place, files.length);
 
- 						
 
- 						if (list) {
 
- 							// show thead
 
- 							cwd.find('thead').show();
 
- 							// fixed table header
 
- 							fixTableHeader({fitWidth: ! colWidth});
 
- 						}
 
- 						
 
- 						if (Object.keys(atmb).length) {
 
- 							Object.assign(bufferExt.attachTmbs, atmb);
 
- 						}
 
- 						
 
- 						if (init) {
 
- 							if (! mobile && ! cwd.data('selectable')) {
 
- 								// make files selectable
 
- 								cwd.selectable(selectableOption).data('selectable', true);
 
- 							}
 
- 							wrapperRepaint(true);
 
- 						}
 
- 						! scrolling && wrapper.trigger(scrollEvent);
 
- 					};
 
- 				
 
- 				if (! bufferExt.renderd) {
 
- 					// first time to go()
 
- 					bufferExt.rendering = true;
 
- 					// scroll top on dir load to avoid scroll after page reload
 
- 					wrapper.scrollTop(0);
 
- 					phash = fm.cwd().phash;
 
- 					go();
 
- 					if (options.oldSchool) {
 
- 						if (phash && !query) {
 
- 							oldSchool(phash);
 
- 						} else {
 
- 							oldSchoolItem = $();
 
- 						}
 
- 					}
 
- 					if (list) {
 
- 						colWidth && setColwidth();
 
- 						fixTableHeader({fitWidth: true});
 
- 					}
 
- 					bufferExt.itemH = (list? place.find('tr:first') : place.find('[id]:first')).outerHeight(true);
 
- 					fm.trigger('cwdrender');
 
- 					bufferExt.rendering = false;
 
- 				}
 
- 				if (! bufferExt.rendering && buffer.length) {
 
- 					// next go()
 
- 					if ((chk = (wrapper.height() + wrapper.scrollTop() + fm.options.showThreshold + bufferExt.row) - (bufferExt.renderd * bufferExt.hpi)) > 0) {
 
- 						bufferExt.rendering = true;
 
- 						fm.lazy(function() {
 
- 							go(chk);
 
- 							bufferExt.rendering = false;
 
- 						});
 
- 					} else {
 
- 						!fm.enabled() && resize();
 
- 					}
 
- 				} else {
 
- 					resize();
 
- 				}
 
- 			},
 
- 			
 
- 			// fixed table header jQuery object
 
- 			tableHeader = null,
 
- 			// Is UA support CSS sticky
 
- 			cssSticky = fm.UA.CSS.positionSticky && fm.UA.CSS.widthMaxContent,
 
- 			
 
- 			// To fixed table header colmun
 
- 			fixTableHeader = function(optsArg) {
 
- 				if (! options.listView.fixedHeader) {
 
- 					return;
 
- 				}
 
- 				var setPos = function() {
 
- 					var val, pos;
 
- 					pos = (fm.direction === 'ltr')? 'left' : 'right';
 
- 					val = ((fm.direction === 'ltr')? wrapper.scrollLeft() : table.outerWidth(true) - wrapper.width() - wrapper.scrollLeft()) * -1;
 
- 					if (base.css(pos) !== val) {
 
- 						base.css(pos, val);
 
- 					}
 
- 				},
 
- 				opts = optsArg || {},
 
- 				cnt, base, table, htable, thead, tbody, hheight, htr, btr, htd, btd, htw, btw, init;
 
- 				
 
- 				tbody = cwd.find('tbody');
 
- 				btr = tbody.children('tr:first');
 
- 				if (btr.length && btr.is(':visible')) {
 
- 					table = tbody.parent();
 
- 					if (! tableHeader) {
 
- 						init = true;
 
- 						tbody.addClass('elfinder-cwd-fixheader');
 
- 						thead = cwd.find('thead').attr('id', fm.namespace+'-cwd-thead');
 
- 						htr = thead.children('tr:first');
 
- 						hheight = htr.outerHeight(true);
 
- 						cwd.css('margin-top', hheight - parseInt(table.css('padding-top')));
 
- 						if (cssSticky) {
 
- 							tableHeader = $('<div class="elfinder-table-header-sticky"/>').addClass(cwd.attr('class')).append($('<table/>').append(thead));
 
- 							cwd.after(tableHeader);
 
- 							wrapper.on('resize.fixheader', function(e) {
 
- 								e.stopPropagation();
 
- 								fixTableHeader({fitWidth: true});
 
- 							});
 
- 						} else {
 
- 							base = $('<div/>').addClass(cwd.attr('class')).append($('<table/>').append(thead));
 
- 							tableHeader = $('<div/>').addClass(wrapper.attr('class') + ' elfinder-cwd-fixheader')
 
- 								.removeClass('ui-droppable native-droppable')
 
- 								.css(wrapper.position())
 
- 								.css({ height: hheight, width: cwd.outerWidth() })
 
- 								.append(base);
 
- 							if (fm.direction === 'rtl') {
 
- 								tableHeader.css('left', (wrapper.data('width') - wrapper.width()) + 'px');
 
- 							}
 
- 							setPos();
 
- 							wrapper.after(tableHeader)
 
- 								.on('scroll.fixheader resize.fixheader', function(e) {
 
- 									setPos();
 
- 									if (e.type === 'resize') {
 
- 										e.stopPropagation();
 
- 										tableHeader.css(wrapper.position());
 
- 										wrapper.data('width', wrapper.css('overflow', 'hidden').width());
 
- 										wrapper.css('overflow', 'auto');
 
- 										fixTableHeader();
 
- 									}
 
- 								});
 
- 						}
 
- 					} else {
 
- 						thead = $('#'+fm.namespace+'-cwd-thead');
 
- 						htr = thead.children('tr:first');
 
- 					}
 
- 					
 
- 					if (init || opts.fitWidth || Math.abs(btr.outerWidth() - htr.outerWidth()) > 2) {
 
- 						cnt = customCols.length + 1;
 
- 						for (var i = 0; i < cnt; i++) {
 
- 							htd = htr.children('td:eq('+i+')');
 
- 							btd = btr.children('td:eq('+i+')');
 
- 							htw = htd.width();
 
- 							btw = btd.width();
 
- 							if (typeof htd.data('delta') === 'undefined') {
 
- 								htd.data('delta', (htd.outerWidth() - htw) - (btd.outerWidth() - btw));
 
- 							}
 
- 							btw -= htd.data('delta');
 
- 							if (! init && ! opts.fitWidth && htw === btw) {
 
- 								break;
 
- 							}
 
- 							htd.css('width', btw + 'px');
 
- 						}
 
- 					}
 
- 					
 
- 					if (!cssSticky) {
 
- 						tableHeader.data('widthTimer') && cancelAnimationFrame(tableHeader.data('widthTimer'));
 
- 						tableHeader.data('widthTimer', requestAnimationFrame(function() {
 
- 							if (tableHeader) {
 
- 								tableHeader.css('width', mBoard.width() + 'px');
 
- 								if (fm.direction === 'rtl') {
 
- 									tableHeader.css('left', (wrapper.data('width') - wrapper.width()) + 'px');
 
- 								}
 
- 							}
 
- 						}));
 
- 					}
 
- 				}
 
- 			},
 
- 			
 
- 			// Set colmun width
 
- 			setColwidth = function() {
 
- 				if (list && colWidth) {
 
- 					var cl = 'elfinder-cwd-colwidth',
 
- 					first = cwd.find('tr[id]:first'),
 
- 					former;
 
- 					if (! first.hasClass(cl)) {
 
- 						former = cwd.find('tr.'+cl);
 
- 						former.removeClass(cl).find('td').css('width', '');
 
- 						first.addClass(cl);
 
- 						cwd.find('table:first').css('table-layout', 'fixed');
 
- 						$.each($.merge(['name'], customCols), function(i, k) {
 
- 							var w = colWidth[k] || first.find('td.elfinder-col-'+k).width();
 
- 							first.find('td.elfinder-col-'+k).width(w);
 
- 						});
 
- 					}
 
- 				}
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Droppable options for cwd.
 
- 			 * Drop target is `wrapper`
 
- 			 * Do not add class on childs file over
 
- 			 *
 
- 			 * @type Object
 
- 			 */
 
- 			droppable = Object.assign({}, fm.droppable, {
 
- 				over : function(e, ui) {
 
- 					var dst    = $(this),
 
- 						helper = ui.helper,
 
- 						ctr    = (e.shiftKey || e.ctrlKey || e.metaKey),
 
- 						hash, status, inParent;
 
- 					e.stopPropagation();
 
- 					helper.data('dropover', helper.data('dropover') + 1);
 
- 					dst.data('dropover', true);
 
- 					if (helper.data('namespace') !== fm.namespace || ! fm.insideWorkzone(e.pageX, e.pageY)) {
 
- 						dst.removeClass(clDropActive);
 
- 						helper.removeClass('elfinder-drag-helper-move elfinder-drag-helper-plus');
 
- 						return;
 
- 					}
 
- 					if (dst.hasClass(fm.res(c, 'cwdfile'))) {
 
- 						hash = fm.cwdId2Hash(dst.attr('id'));
 
- 						dst.data('dropover', hash);
 
- 					} else {
 
- 						hash = fm.cwd().hash;
 
- 						fm.cwd().write && dst.data('dropover', hash);
 
- 					}
 
- 					inParent = (fm.file(helper.data('files')[0]).phash === hash);
 
- 					if (dst.data('dropover') === hash) {
 
- 						$.each(helper.data('files'), function(i, h) {
 
- 							if (h === hash || (inParent && !ctr && !helper.hasClass('elfinder-drag-helper-plus'))) {
 
- 								dst.removeClass(clDropActive);
 
- 								return false; // break $.each
 
- 							}
 
- 						});
 
- 					} else {
 
- 						dst.removeClass(clDropActive);
 
- 					}
 
- 					if (helper.data('locked') || inParent) {
 
- 						status = 'elfinder-drag-helper-plus';
 
- 					} else {
 
- 						status = 'elfinder-drag-helper-move';
 
- 						if (ctr) {
 
- 							status += ' elfinder-drag-helper-plus';
 
- 						}
 
- 					}
 
- 					dst.hasClass(clDropActive) && helper.addClass(status);
 
- 					requestAnimationFrame(function(){ dst.hasClass(clDropActive) && helper.addClass(status); });
 
- 				},
 
- 				out : function(e, ui) {
 
- 					var helper = ui.helper;
 
- 					e.stopPropagation();
 
- 					helper.removeClass('elfinder-drag-helper-move elfinder-drag-helper-plus').data('dropover', Math.max(helper.data('dropover') - 1, 0));
 
- 					$(this).removeData('dropover')
 
- 					       .removeClass(clDropActive);
 
- 				},
 
- 				deactivate : function() {
 
- 					$(this).removeData('dropover')
 
- 					       .removeClass(clDropActive);
 
- 				},
 
- 				drop : function(e, ui) {
 
- 					unselectAll({ notrigger: true });
 
- 					fm.droppable.drop.call(this, e, ui);
 
- 				}
 
- 			}),
 
- 			
 
- 			/**
 
- 			 * Make directory droppable
 
- 			 *
 
- 			 * @return void
 
- 			 */
 
- 			makeDroppable = function(place) {
 
- 				place = place? place : (list ? cwd.find('tbody') : cwd);
 
- 				var targets = place.children('.directory:not(.'+clDroppable+',.elfinder-na,.elfinder-ro)');
 
- 				if (fm.isCommandEnabled('paste')) {
 
- 					targets.droppable(droppable);
 
- 				}
 
- 				if (fm.isCommandEnabled('upload')) {
 
- 					targets.addClass('native-droppable');
 
- 				}
 
- 				
 
- 				place.children('.isroot').each(function(i, n) {
 
- 					var $n   = $(n),
 
- 						hash = fm.cwdId2Hash(n.id);
 
- 					
 
- 					if (fm.isCommandEnabled('paste', hash)) {
 
- 						if (! $n.hasClass(clDroppable+',elfinder-na,elfinder-ro')) {
 
- 							$n.droppable(droppable);
 
- 						}
 
- 					} else {
 
- 						if ($n.hasClass(clDroppable)) {
 
- 							$n.droppable('destroy');
 
- 						}
 
- 					}
 
- 					if (fm.isCommandEnabled('upload', hash)) {
 
- 						if (! $n.hasClass('native-droppable,elfinder-na,elfinder-ro')) {
 
- 							$n.addClass('native-droppable');
 
- 						}
 
- 					} else {
 
- 						if ($n.hasClass('native-droppable')) {
 
- 							$n.removeClass('native-droppable');
 
- 						}
 
- 					}
 
- 				});
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Preload required thumbnails and on load add css to files.
 
- 			 * Return false if required file is not visible yet (in buffer) -
 
- 			 * required for old api to stop loading thumbnails.
 
- 			 *
 
- 			 * @param  Object  file hash -> thumbnail map
 
- 			 * @param  Bool    reload
 
- 			 * @return void
 
- 			 */
 
- 			attachThumbnails = function(tmbs, reload) {
 
- 				var attach = function(node, tmb) {
 
- 						$('<img/>')
 
- 							.on('load', function() {
 
- 								node.find('.elfinder-cwd-icon').addClass(tmb.className).css('background-image', "url('"+tmb.url+"')");
 
- 							})
 
- 							.attr('src', tmb.url);
 
- 					},
 
- 					chk  = function(hash, tmb) {
 
- 						var node = $('#'+fm.cwdHash2Id(hash)),
 
- 							file, tmbObj, reloads = [];
 
- 	
 
- 						if (node.length) {
 
- 							if (tmb != '1') {
 
- 								file = fm.file(hash);
 
- 								if (file.tmb !== tmb) {
 
- 									file.tmb = tmb;
 
- 								}
 
- 								tmbObj = fm.tmb(file);
 
- 								if (reload) {
 
- 									node.find('.elfinder-cwd-icon').addClass(tmbObj.className).css('background-image', "url('"+tmbObj.url+"')");
 
- 								} else {
 
- 									attach(node, tmbObj);
 
- 								}
 
- 								delete bufferExt.attachTmbs[hash];
 
- 							} else {
 
- 								if (reload) {
 
- 									loadThumbnails([hash]);
 
- 								} else if (! bufferExt.tmbLoading[hash]) {
 
- 									bufferExt.getTmbs.push(hash);
 
- 								}
 
- 							}
 
- 						}
 
- 					};
 
- 				if ($.isPlainObject(tmbs) && Object.keys(tmbs).length) {
 
- 					Object.assign(bufferExt.attachTmbs, tmbs);
 
- 					$.each(tmbs, chk);
 
- 					if (! reload && bufferExt.getTmbs.length && ! Object.keys(bufferExt.tmbLoading).length) {
 
- 						loadThumbnails();
 
- 					}
 
- 				}
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Load thumbnails from backend.
 
- 			 *
 
- 			 * @param  Array|void reloads  hashes list for reload thumbnail items
 
- 			 * @return void
 
- 			 */
 
- 			loadThumbnails = function(reloads) {
 
- 				var tmbs = [],
 
- 					reload = false;
 
- 				
 
- 				if (fm.oldAPI) {
 
- 					fm.request({
 
- 						data : {cmd : 'tmb', current : fm.cwd().hash},
 
- 						preventFail : true
 
- 					})
 
- 					.done(function(data) {
 
- 						if (data.images && Object.keys(data.images).length) {
 
- 							attachThumbnails(data.images);
 
- 						}
 
- 						if (data.tmb) {
 
- 							loadThumbnails();
 
- 						}
 
- 					});
 
- 					return;
 
- 				} 
 
- 				if (reloads) {
 
- 					reload = true;
 
- 					tmbs = reloads.splice(0, tmbNum);
 
- 				} else {
 
- 					tmbs = bufferExt.getTmbs.splice(0, tmbNum);
 
- 				}
 
- 				if (tmbs.length) {
 
- 					if (reload || inViewHashes[tmbs[0]] || inViewHashes[tmbs[tmbs.length-1]]) {
 
- 						$.each(tmbs, function(i, h) {
 
- 							bufferExt.tmbLoading[h] = true;
 
- 						});
 
- 						fm.request({
 
- 							data : {cmd : 'tmb', targets : tmbs},
 
- 							preventFail : true
 
- 						})
 
- 						.done(function(data) {
 
- 							var errs = [],
 
- 								resLen;
 
- 							if (data.images) {
 
- 								if (resLen = Object.keys(data.images).length) {
 
- 									if (resLen < tmbs.length) {
 
- 										$.each(tmbs, function(i, h) {
 
- 											if (! data.images[h]) {
 
- 												errs.push(h);
 
- 											}
 
- 										});
 
- 									}
 
- 									attachThumbnails(data.images, reload);
 
- 								} else {
 
- 									errs = tmbs;
 
- 								}
 
- 								// unset error items from bufferExt.attachTmbs
 
- 								if (errs.length) {
 
- 									$.each(errs, function(i, h) {
 
- 										delete bufferExt.attachTmbs[h];
 
- 									});
 
- 								}
 
- 							}
 
- 							if (reload) {
 
- 								if (reloads.length) {
 
- 									loadThumbnails(reloads);
 
- 								}
 
- 							}
 
- 						})
 
- 						.always(function() {
 
- 							bufferExt.tmbLoading = {};
 
- 							if (! reload && bufferExt.getTmbs.length) {
 
- 								loadThumbnails();
 
- 							}
 
- 						});
 
- 					}
 
- 				}
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Add new files to cwd/buffer
 
- 			 *
 
- 			 * @param  Array  new files
 
- 			 * @return void
 
- 			 */
 
- 			add = function(files, mode) {
 
- 				var place    = list ? cwd.find('tbody') : cwd,
 
- 					l        = files.length, 
 
- 					atmb     = {},
 
- 					findNode = function(file) {
 
- 						var pointer = cwd.find('[id]:first'), file2;
 
- 						while (pointer.length) {
 
- 							file2 = fm.file(fm.cwdId2Hash(pointer.attr('id')));
 
- 							if (!pointer.hasClass('elfinder-cwd-parent') && file2 && fm.compare(file, file2) < 0) {
 
- 								return pointer;
 
- 							}
 
- 							pointer = pointer.next('[id]');
 
- 						}
 
- 					},
 
- 					findIndex = function(file) {
 
- 						var l = buffer.length, i;
 
- 						
 
- 						for (i =0; i < l; i++) {
 
- 							if (fm.compare(file, buffer[i]) < 0) {
 
- 								return i;
 
- 							}
 
- 						}
 
- 						return l || -1;
 
- 					},
 
- 					// created document fragment for jQuery >= 1.12, 2.2, 3.0
 
- 					// see Studio-42/elFinder#1544 @ github
 
- 					docFlag = $.htmlPrefilter? true : false,
 
- 					tempDom = docFlag? $(document.createDocumentFragment()) : $('<div/>'),
 
- 					file, hash, node, nodes, ndx, stmb;
 
- 				if (l > showFiles) {
 
- 					// re-render for performance tune
 
- 					content();
 
- 					selectedFiles = fm.arrayFlip($.map(files, function(f) { return f.hash; }), true);
 
- 					trigger();
 
- 				} else {
 
- 					// add the item immediately
 
- 					l && wz.removeClass('elfinder-cwd-wrapper-empty');
 
- 					
 
- 					// Self thumbnail
 
- 					stmb = (fm.option('tmbUrl') === 'self');
 
- 					
 
- 					while (l--) {
 
- 						file = files[l];
 
- 						hash = file.hash;
 
- 						
 
- 						if ($('#'+fm.cwdHash2Id(hash)).length) {
 
- 							continue;
 
- 						}
 
- 						
 
- 						if ((node = findNode(file)) && ! node.length) {
 
- 							node = null;
 
- 						}
 
- 						if (! node && (ndx = findIndex(file)) >= 0) {
 
- 							buffer.splice(ndx, 0, file);
 
- 						} else {
 
- 							tempDom.empty().append(itemhtml(file));
 
- 							(file.mime === 'directory') && !mobile && makeDroppable(tempDom);
 
- 							nodes = docFlag? tempDom : tempDom.children();
 
- 							if (node) {
 
- 								node.before(nodes);
 
- 							} else {
 
- 								place.append(nodes);
 
- 							}
 
- 						}
 
- 						
 
- 						if ($('#'+fm.cwdHash2Id(hash)).length) {
 
- 							if ((file.tmb && (file.tmb != 1 || file.size > 0)) || (stmb && file.mime.indexOf('image/') === 0)) {
 
- 								atmb[hash] = file.tmb || 'self';
 
- 							}
 
- 						}
 
- 					}
 
- 	
 
- 					if (list) {
 
- 						setColwidth();
 
- 						fixTableHeader({fitWidth: ! colWidth});
 
- 					}
 
- 					bottomMarkerShow(place);
 
- 					if (Object.keys(atmb).length) {
 
- 						Object.assign(bufferExt.attachTmbs, atmb);
 
- 					}
 
- 				}
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Remove files from cwd/buffer
 
- 			 *
 
- 			 * @param  Array  files hashes
 
- 			 * @return void
 
- 			 */
 
- 			remove = function(files) {
 
- 				var l = files.length,
 
- 					inSearch = fm.searchStatus.state > 1,
 
- 					curCmd = fm.getCommand(fm.currentReqCmd) || {},
 
- 					hash, n, ndx, found;
 
- 				// removed cwd
 
- 				if (!fm.cwd().hash && !curCmd.noChangeDirOnRemovedCwd) {
 
- 					$.each(cwdParents.reverse(), function(i, h) {
 
- 						if (fm.file(h)) {
 
- 							found = true;
 
- 							fm.one(fm.currentReqCmd + 'done', function() {
 
- 								!fm.cwd().hash && fm.exec('open', h);
 
- 							});
 
- 							return false;
 
- 						}
 
- 					});
 
- 					// fallback to fm.roots[0]
 
- 					!found && !fm.cwd().hash && fm.exec('open', fm.roots[Object.keys(fm.roots)[0]]);
 
- 					return;
 
- 				}
 
- 				
 
- 				while (l--) {
 
- 					hash = files[l];
 
- 					if ((n = $('#'+fm.cwdHash2Id(hash))).length) {
 
- 						try {
 
- 							n.remove();
 
- 							--bufferExt.renderd;
 
- 						} catch(e) {
 
- 							fm.debug('error', e);
 
- 						}
 
- 					} else if ((ndx = index(hash)) !== -1) {
 
- 						buffer.splice(ndx, 1);
 
- 					}
 
- 					selectedFiles[hash] && delete selectedFiles[hash];
 
- 					if (inSearch) {
 
- 						if ((ndx = $.inArray(hash, cwdHashes)) !== -1) {
 
- 							cwdHashes.splice(ndx, 1);
 
- 						}
 
- 					}
 
- 				}
 
- 				
 
- 				inSearch && fm.trigger('cwdhasheschange', cwdHashes);
 
- 				
 
- 				if (list) {
 
- 					setColwidth();
 
- 					fixTableHeader({fitWidth: ! colWidth});
 
- 				}
 
- 			},
 
- 			
 
- 			customColsNameBuild = function() {
 
- 				var name = '',
 
- 				customColsName = '';
 
- 				for (var i = 0; i < customCols.length; i++) {
 
- 					name = fm.getColumnName(customCols[i]);
 
- 					customColsName +='<td class="elfinder-cwd-view-th-'+customCols[i]+' sortable-item">'+name+'</td>';
 
- 				}
 
- 				return customColsName;
 
- 			},
 
- 			
 
- 			setItemBoxSize = function(boxSize) {
 
- 				var place, elm;
 
- 				if (!boxSize.height) {
 
- 					place = (list ? cwd.find('tbody') : cwd);
 
- 					elm = place.find(list? 'tr:first' : '[id]:first');
 
- 					boxSize.height = elm.outerHeight(true);
 
- 					if (!list) {
 
- 						boxSize.width = elm.outerWidth(true);
 
- 					}
 
- 				}
 
- 			},
 
- 			bottomMarkerShow = function(cur, cnt) {
 
- 				var place = cur || (list ? cwd.find('tbody') : cwd),
 
- 					boxSize = itemBoxSize[fm.viewType],
 
- 					col = 1,
 
- 					row;
 
- 				if (buffer.length > 0) {
 
- 					if (!bufferExt.hpi) {
 
- 						setItemBoxSize(boxSize);
 
- 						if (! list) {
 
- 							col = Math.floor(place.width() / boxSize.width);
 
- 							bufferExt.row = boxSize.height;
 
- 							bufferExt.hpi = bufferExt.row / col;
 
- 						} else {
 
- 							bufferExt.row = bufferExt.hpi = boxSize.height;
 
- 						}
 
- 					} else if (!list) {
 
- 						col = Math.floor(place.width() / boxSize.width);
 
- 					}
 
- 					row = Math.ceil((buffer.length + (cnt || 0)) / col);
 
- 					if (list && tableHeader) {
 
- 						++row;
 
- 					}
 
- 					bottomMarker.css({top: (bufferExt.row * row) + 'px'}).show();
 
- 				}
 
- 			},
 
- 			
 
- 			wrapperContextMenu = {
 
- 				contextmenu : function(e) {
 
- 					e.preventDefault();
 
- 					if (cwd.data('longtap') !== void(0)) {
 
- 						e.stopPropagation();
 
- 						return;
 
- 					}
 
- 					fm.trigger('contextmenu', {
 
- 						'type'    : 'cwd',
 
- 						'targets' : [fm.cwd().hash],
 
- 						'x'       : e.pageX,
 
- 						'y'       : e.pageY
 
- 					});
 
- 				},
 
- 				touchstart : function(e) {
 
- 					if (e.originalEvent.touches.length > 1) {
 
- 						return;
 
- 					}
 
- 					if (cwd.data('longtap') !== false) {
 
- 						wrapper.data('touching', {x: e.originalEvent.touches[0].pageX, y: e.originalEvent.touches[0].pageY});
 
- 						cwd.data('tmlongtap', setTimeout(function(){
 
- 							// long tap
 
- 							cwd.data('longtap', true);
 
- 							fm.trigger('contextmenu', {
 
- 								'type'    : 'cwd',
 
- 								'targets' : [fm.cwd().hash],
 
- 								'x'       : wrapper.data('touching').x,
 
- 								'y'       : wrapper.data('touching').y
 
- 							});
 
- 						}, 500));
 
- 					}
 
- 					cwd.data('longtap', null);
 
- 				},
 
- 				touchend : function(e) {
 
- 					if (e.type === 'touchmove') {
 
- 						if (! wrapper.data('touching') ||
 
- 								( Math.abs(wrapper.data('touching').x - e.originalEvent.touches[0].pageX)
 
- 								+ Math.abs(wrapper.data('touching').y - e.originalEvent.touches[0].pageY)) > 4) {
 
- 							wrapper.data('touching', null);
 
- 						}
 
- 					} else {
 
- 						setTimeout(function() {
 
- 							cwd.removeData('longtap');
 
- 						}, 80);
 
- 					}
 
- 					clearTimeout(cwd.data('tmlongtap'));
 
- 				},
 
- 				click : function(e) {
 
- 					if (cwd.data('longtap')) {
 
- 						e.preventDefault();
 
- 						e.stopPropagation();
 
- 					}
 
- 				}
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Update directory content
 
- 			 *
 
- 			 * @return void
 
- 			 */
 
- 			content = function() {
 
- 				fm.lazy(function() {
 
- 					var phash, emptyMethod, thtr;
 
- 					wz.append(selectAllCheckbox).removeClass('elfinder-cwd-wrapper-empty elfinder-search-result elfinder-incsearch-result elfinder-letsearch-result');
 
- 					if (fm.searchStatus.state > 1 || fm.searchStatus.ininc) {
 
- 						wz.addClass('elfinder-search-result' + (fm.searchStatus.ininc? ' elfinder-'+(query.substr(0,1) === '/' ? 'let':'inc')+'search-result' : ''));
 
- 					}
 
- 					
 
- 					// abort attachThumbJob
 
- 					bufferExt.attachThumbJob && bufferExt.attachThumbJob._abort();
 
- 					
 
- 					// destroy selectable for GC
 
- 					cwd.data('selectable') && cwd.selectable('disable').selectable('destroy').removeData('selectable');
 
- 					
 
- 					// notify cwd init
 
- 					fm.trigger('cwdinit');
 
- 					
 
- 					selectedNext = $();
 
- 					try {
 
- 						// to avoid problem with draggable
 
- 						cwd.empty();
 
- 					} catch (e) {
 
- 						cwd.html('');
 
- 					}
 
- 					
 
- 					if (tableHeader) {
 
- 						wrapper.off('scroll.fixheader resize.fixheader');
 
- 						tableHeader.remove();
 
- 						tableHeader = null;
 
- 					}
 
- 					cwd.removeClass('elfinder-cwd-view-icons elfinder-cwd-view-list')
 
- 						.addClass('elfinder-cwd-view-'+(list ? 'list' :'icons'))
 
- 						.attr('style', '')
 
- 						.css('height', 'auto');
 
- 					bottomMarker.hide();
 
- 					wrapper[list ? 'addClass' : 'removeClass']('elfinder-cwd-wrapper-list')._padding = parseInt(wrapper.css('padding-top')) + parseInt(wrapper.css('padding-bottom'));
 
- 					if (fm.UA.iOS) {
 
- 						wrapper.removeClass('overflow-scrolling-touch').addClass('overflow-scrolling-touch');
 
- 					}
 
- 					if (list) {
 
- 						cwd.html('<table><thead/><tbody/></table>');
 
- 						thtr = $('<tr class="ui-state-default"><td class="elfinder-cwd-view-th-name">'+fm.getColumnName('name')+'</td>'+customColsNameBuild()+'</tr>');
 
- 						cwd.find('thead').hide().append(thtr).find('td:first').append(selectAllCheckbox);
 
- 						if ($.fn.sortable) {
 
- 							thtr.addClass('touch-punch touch-punch-keep-default')
 
- 								.sortable({
 
- 								axis: 'x',
 
- 								distance: 8,
 
- 								items: '> .sortable-item',
 
- 								start: function(e, ui) {
 
- 									$(ui.item[0]).data('dragging', true);
 
- 									ui.placeholder
 
- 										.width(ui.helper.removeClass('ui-state-hover').width())
 
- 										.removeClass('ui-state-active')
 
- 										.addClass('ui-state-hover')
 
- 										.css('visibility', 'visible');
 
- 								},
 
- 								update: function(e, ui){
 
- 									var target = $(ui.item[0]).attr('class').split(' ')[0].replace('elfinder-cwd-view-th-', ''),
 
- 										prev, done;
 
- 									customCols = $.map($(this).children(), function(n) {
 
- 										var name = $(n).attr('class').split(' ')[0].replace('elfinder-cwd-view-th-', '');
 
- 										if (! done) {
 
- 											if (target === name) {
 
- 												done = true;
 
- 											} else {
 
- 												prev = name;
 
- 											}
 
- 										}
 
- 										return (name === 'name')? null : name;
 
- 									});
 
- 									templates.row = makeTemplateRow();
 
- 									fm.storage('cwdCols', customCols);
 
- 									prev = '.elfinder-col-'+prev+':first';
 
- 									target = '.elfinder-col-'+target+':first';
 
- 									fm.lazy(function() {
 
- 										cwd.find('tbody tr').each(function() {
 
- 											var $this = $(this);
 
- 											$this.children(prev).after($this.children(target));
 
- 										});
 
- 									});
 
- 								},
 
- 								stop: function(e, ui) {
 
- 									setTimeout(function() {
 
- 										$(ui.item[0]).removeData('dragging');
 
- 									}, 100);
 
- 								}
 
- 							});
 
- 						}
 
- 						thtr.find('td').addClass('touch-punch').resizable({
 
- 							handles: fm.direction === 'ltr'? 'e' : 'w',
 
- 							start: function(e, ui) {
 
- 								var target = cwd.find('td.elfinder-col-'
 
- 									+ ui.element.attr('class').split(' ')[0].replace('elfinder-cwd-view-th-', '')
 
- 									+ ':first');
 
- 								
 
- 								ui.element
 
- 									.data('dragging', true)
 
- 									.data('resizeTarget', target)
 
- 									.data('targetWidth', target.width());
 
- 								colResizing = true;
 
- 								if (cwd.find('table').css('table-layout') !== 'fixed') {
 
- 									cwd.find('tbody tr:first td').each(function() {
 
- 										$(this).width($(this).width());
 
- 									});
 
- 									cwd.find('table').css('table-layout', 'fixed');
 
- 								}
 
- 							},
 
- 							resize: function(e, ui) {
 
- 								ui.element.data('resizeTarget').width(ui.element.data('targetWidth') - (ui.originalSize.width - ui.size.width));
 
- 							},
 
- 							stop : function(e, ui) {
 
- 								colResizing = false;
 
- 								fixTableHeader({fitWidth: true});
 
- 								colWidth = {};
 
- 								cwd.find('tbody tr:first td').each(function() {
 
- 									var name = $(this).attr('class').split(' ')[0].replace('elfinder-col-', '');
 
- 									colWidth[name] = $(this).width();
 
- 								});
 
- 								fm.storage('cwdColWidth', colWidth);
 
- 								setTimeout(function() {
 
- 									ui.element.removeData('dragging');
 
- 								}, 100);
 
- 							}
 
- 						})
 
- 						.find('.ui-resizable-handle').addClass('ui-icon ui-icon-grip-dotted-vertical');
 
- 					}
 
- 					buffer = $.map(incHashes || cwdHashes, function(hash) { return fm.file(hash) || null; });
 
- 					
 
- 					buffer = fm.sortFiles(buffer);
 
- 					
 
- 					if (incHashes) {
 
- 						incHashes = $.map(buffer, function(f) { return f.hash; });
 
- 					} else {
 
- 						cwdHashes = $.map(buffer, function(f) { return f.hash; });
 
- 					}
 
- 					
 
- 					bufferExt = {
 
- 						renderd: 0,
 
- 						attachTmbs: {},
 
- 						getTmbs: [],
 
- 						tmbLoading: {},
 
- 						lazyOpts: { tm : 0 }
 
- 					};
 
- 					
 
- 					wz[(buffer.length < 1) ? 'addClass' : 'removeClass']('elfinder-cwd-wrapper-empty');
 
- 					wrapper.off(scrollEvent, render).on(scrollEvent, render).trigger(scrollEvent);
 
- 					
 
- 					// set droppable
 
- 					if (!fm.cwd().write) {
 
- 						wrapper.removeClass('native-droppable')
 
- 						       .droppable('disable')
 
- 						       .removeClass('ui-state-disabled'); // for old jQueryUI see https://bugs.jqueryui.com/ticket/5974
 
- 					} else {
 
- 						wrapper[fm.isCommandEnabled('upload')? 'addClass' : 'removeClass']('native-droppable');
 
- 						wrapper.droppable(fm.isCommandEnabled('paste')? 'enable' : 'disable');
 
- 					}
 
- 				});
 
- 			},
 
- 			
 
- 			/**
 
- 			 * CWD node itself
 
- 			 *
 
- 			 * @type JQuery
 
- 			 **/
 
- 			cwd = $(this)
 
- 				.addClass('ui-helper-clearfix elfinder-cwd')
 
- 				.attr('unselectable', 'on')
 
- 				// fix ui.selectable bugs and add shift+click support 
 
- 				.on('click.'+fm.namespace, fileSelector, function(e) {
 
- 					var p    = this.id ? $(this) : $(this).parents('[id]:first'),
 
- 						tgt  = $(e.target),
 
- 						prev,
 
- 						next,
 
- 						pl,
 
- 						nl,
 
- 						sib;
 
- 					if (selectCheckbox && (tgt.is('input:checkbox.'+clSelChk) || tgt.hasClass('elfinder-cwd-select'))) {
 
- 						e.stopPropagation();
 
- 						e.preventDefault();
 
- 						p.trigger(p.hasClass(clSelected) ? evtUnselect : evtSelect);
 
- 						trigger();
 
- 						requestAnimationFrame(function() {
 
- 							tgt.prop('checked', p.hasClass(clSelected));
 
- 						});
 
- 						return;
 
- 					}
 
- 					if (cwd.data('longtap') || tgt.hasClass('elfinder-cwd-nonselect')) {
 
- 						e.stopPropagation();
 
- 						return;
 
- 					}
 
- 					if (!curClickId) {
 
- 						curClickId = p.attr('id');
 
- 						setTimeout(function() {
 
- 							curClickId = '';
 
- 						}, 500);
 
- 					}
 
- 					
 
- 					if (e.shiftKey) {
 
- 						prev = p.prevAll(lastSelect || '.'+clSelected+':first');
 
- 						next = p.nextAll(lastSelect || '.'+clSelected+':first');
 
- 						pl   = prev.length;
 
- 						nl   = next.length;
 
- 					}
 
- 					if (e.shiftKey && (pl || nl)) {
 
- 						sib = pl ? p.prevUntil('#'+prev.attr('id')) : p.nextUntil('#'+next.attr('id'));
 
- 						sib.add(p).trigger(evtSelect);
 
- 					} else if (e.ctrlKey || e.metaKey) {
 
- 						p.trigger(p.hasClass(clSelected) ? evtUnselect : evtSelect);
 
- 					} else {
 
- 						if (wrapper.data('touching') && p.hasClass(clSelected)) {
 
- 							wrapper.data('touching', null);
 
- 							fm.dblclick({file : fm.cwdId2Hash(this.id)});
 
- 							return;
 
- 						} else {
 
- 							unselectAll({ notrigger: true });
 
- 							p.trigger(evtSelect);
 
- 						}
 
- 					}
 
- 					trigger();
 
- 				})
 
- 				// call fm.open()
 
- 				.on('dblclick.'+fm.namespace, fileSelector, function(e) {
 
- 					if (curClickId) {
 
- 						var hash = fm.cwdId2Hash(curClickId);
 
- 						e.stopPropagation();
 
- 						if (this.id !== curClickId) {
 
- 							$(this).trigger(evtUnselect);
 
- 							$('#'+curClickId).trigger(evtSelect);
 
- 							trigger();
 
- 						}
 
- 						fm.dblclick({file : hash});
 
- 					}
 
- 				})
 
- 				// for touch device
 
- 				.on('touchstart.'+fm.namespace, fileSelector, function(e) {
 
- 					if (e.originalEvent.touches.length > 1) {
 
- 						return;
 
- 					}
 
- 					var p   = this.id ? $(this) : $(this).parents('[id]:first'),
 
- 						tgt = $(e.target),
 
- 						nodeName = e.target.nodeName,
 
- 						sel;
 
- 					
 
- 					if ((nodeName === 'INPUT' && e.target.type === 'text') || nodeName === 'TEXTAREA' || tgt.hasClass('elfinder-cwd-nonselect')) {
 
- 						e.stopPropagation();
 
- 						return;
 
- 					}
 
- 					
 
- 					// now name editing
 
- 					if (p.find('input:text,textarea').length) {
 
- 						e.stopPropagation();
 
- 						e.preventDefault();
 
- 						return;
 
- 					}
 
- 					
 
- 					wrapper.data('touching', {x: e.originalEvent.touches[0].pageX, y: e.originalEvent.touches[0].pageY});
 
- 					if (selectCheckbox && (tgt.is('input:checkbox.'+clSelChk) || tgt.hasClass('elfinder-cwd-select'))) {
 
- 						return;
 
- 					}
 
- 					
 
- 					sel = p.prevAll('.'+clSelected+':first').length +
 
- 					      p.nextAll('.'+clSelected+':first').length;
 
- 					cwd.data('longtap', null);
 
- 					if (Object.keys(selectedFiles).length
 
- 						||
 
- 						(list && e.target.nodeName !== 'TD')
 
- 						||
 
- 						(!list && this !== e.target)
 
- 					) {
 
- 						cwd.data('longtap', false);
 
- 						p.addClass(clHover);
 
- 						p.data('tmlongtap', setTimeout(function(){
 
- 							// long tap
 
- 							cwd.data('longtap', true);
 
- 							p.trigger(evtSelect);
 
- 							trigger();
 
- 							fm.trigger('contextmenu', {
 
- 								'type'    : 'files',
 
- 								'targets' : fm.selected(),
 
- 								'x'       : e.originalEvent.touches[0].pageX,
 
- 								'y'       : e.originalEvent.touches[0].pageY
 
- 							});
 
- 						}, 500));
 
- 					}
 
- 				})
 
- 				.on('touchmove.'+fm.namespace+' touchend.'+fm.namespace, fileSelector, function(e) {
 
- 					var tgt = $(e.target),
 
- 						p;
 
- 					if (selectCheckbox && (tgt.is('input:checkbox.'+clSelChk) || tgt.hasClass('elfinder-cwd-select'))) {
 
- 						return;
 
- 					}
 
- 					if (e.target.nodeName == 'INPUT' || e.target.nodeName == 'TEXTAREA') {
 
- 						e.stopPropagation();
 
- 						return;
 
- 					}
 
- 					p = this.id ? $(this) : $(this).parents('[id]:first');
 
- 					clearTimeout(p.data('tmlongtap'));
 
- 					if (e.type === 'touchmove') {
 
- 						wrapper.data('touching', null);
 
- 						p.removeClass(clHover);
 
- 					} else {
 
- 						if (wrapper.data('touching') && !cwd.data('longtap') && p.hasClass(clSelected)) {
 
- 							e.preventDefault();
 
- 							wrapper.data('touching', null);
 
- 							fm.dblclick({file : fm.cwdId2Hash(this.id)});
 
- 						}
 
- 						setTimeout(function() {
 
- 							cwd.removeData('longtap');
 
- 						}, 80);
 
- 					}
 
- 				})
 
- 				// attach draggable
 
- 				.on('mouseenter.'+fm.namespace, fileSelector, function(e) {
 
- 					if (scrolling) { return; }
 
- 					var $this = $(this), helper = null;
 
- 					if (!mobile && !$this.data('dragRegisted') && !$this.hasClass(clTmp) && !$this.hasClass(clDraggable) && !$this.hasClass(clDisabled)) {
 
- 						$this.data('dragRegisted', true);
 
- 						if (!fm.isCommandEnabled('copy', fm.searchStatus.state > 1 || $this.hasClass('isroot')? fm.cwdId2Hash($this.attr('id')) : void 0)) {
 
- 							return;
 
- 						}
 
- 						$this.on('mousedown', function(e) {
 
- 							// shiftKey or altKey + drag start for HTML5 native drag function
 
- 							// Note: can no use shiftKey with the Google Chrome 
 
- 							var metaKey = e.shiftKey || e.altKey,
 
- 								disable = false;
 
- 							if (metaKey && !fm.UA.IE && cwd.data('selectable')) {
 
- 								// destroy jQuery-ui selectable while trigger native drag
 
- 								cwd.selectable('disable').selectable('destroy').removeData('selectable');
 
- 								requestAnimationFrame(function(){
 
- 									cwd.selectable(selectableOption).selectable('option', {disabled: false}).selectable('refresh').data('selectable', true);
 
- 								});
 
- 							}
 
- 							$this.removeClass('ui-state-disabled');
 
- 							if (metaKey) {
 
- 								$this.draggable('option', 'disabled', true).attr('draggable', 'true');
 
- 							} else {
 
- 								if (!$this.hasClass(clSelected)) {
 
- 									if (list) {
 
- 										disable = $(e.target).closest('span,tr').is('tr');
 
- 									} else {
 
- 										disable = $(e.target).hasClass('elfinder-cwd-file');
 
- 									}
 
- 								}
 
- 								if (disable) {
 
- 									$this.draggable('option', 'disabled', true);
 
- 								} else {
 
- 									$this.draggable('option', 'disabled', false)
 
- 										  .removeAttr('draggable')
 
- 									      .draggable('option', 'cursorAt', {left: 50 - parseInt($(e.currentTarget).css('margin-left')), top: 47});
 
- 								}
 
- 							}
 
- 						})
 
- 						.on('dragstart', function(e) {
 
- 							var dt = e.dataTransfer || e.originalEvent.dataTransfer || null;
 
- 							helper = null;
 
- 							if (dt && !fm.UA.IE) {
 
- 								var p = this.id ? $(this) : $(this).parents('[id]:first'),
 
- 									elm   = $('<span>'),
 
- 									url   = '',
 
- 									durl  = null,
 
- 									murl  = null,
 
- 									files = [],
 
- 									icon  = function(f) {
 
- 										var mime = f.mime, i, tmb = fm.tmb(f);
 
- 										i = '<div class="elfinder-cwd-icon elfinder-cwd-icon-drag '+fm.mime2class(mime)+' ui-corner-all"/>';
 
- 										if (tmb) {
 
- 											i = $(i).addClass(tmb.className).css('background-image', "url('"+tmb.url+"')").get(0).outerHTML;
 
- 										}
 
- 										return i;
 
- 									}, l, geturl = [];
 
- 								p.trigger(evtSelect);
 
- 								trigger();
 
- 								$.each(selectedFiles, function(v){
 
- 									var file = fm.file(v),
 
- 										furl = file.url;
 
- 									if (file && file.mime !== 'directory') {
 
- 										if (!furl) {
 
- 											furl = fm.url(file.hash);
 
- 										} else if (furl == '1') {
 
- 											geturl.push(v);
 
- 											return true;
 
- 										}
 
- 										if (furl) {
 
- 											furl = fm.convAbsUrl(furl);
 
- 											files.push(v);
 
- 											$('<a>').attr('href', furl).text(furl).appendTo(elm);
 
- 											url += furl + "\n";
 
- 											if (!durl) {
 
- 												durl = file.mime + ':' + file.name + ':' + furl;
 
- 											}
 
- 											if (!murl) {
 
- 												murl = furl + "\n" + file.name;
 
- 											}
 
- 										}
 
- 									}
 
- 								});
 
- 								if (geturl.length) {
 
- 									$.each(geturl, function(i, v){
 
- 										var rfile = fm.file(v);
 
- 										rfile.url = '';
 
- 										fm.request({
 
- 											data : {cmd : 'url', target : v},
 
- 											notify : {type : 'url', cnt : 1},
 
- 											preventDefault : true
 
- 										})
 
- 										.always(function(data) {
 
- 											rfile.url = data.url? data.url : '1';
 
- 										});
 
- 									});
 
- 									return false;
 
- 								} else if (url) {
 
- 									if (dt.setDragImage) {
 
- 										helper = $('<div class="elfinder-drag-helper html5-native"></div>').append(icon(fm.file(files[0]))).appendTo($(document.body));
 
- 										if ((l = files.length) > 1) {
 
- 											helper.append(icon(fm.file(files[l-1])) + '<span class="elfinder-drag-num">'+l+'</span>');
 
- 										}
 
- 										dt.setDragImage(helper.get(0), 50, 47);
 
- 									}
 
- 									dt.effectAllowed = 'copyLink';
 
- 									dt.setData('DownloadURL', durl);
 
- 									dt.setData('text/x-moz-url', murl);
 
- 									dt.setData('text/uri-list', url);
 
- 									dt.setData('text/plain', url);
 
- 									dt.setData('text/html', elm.html());
 
- 									dt.setData('elfinderfrom', window.location.href + fm.cwd().hash);
 
- 									dt.setData('elfinderfrom:' + dt.getData('elfinderfrom'), '');
 
- 								} else {
 
- 									return false;
 
- 								}
 
- 							}
 
- 						})
 
- 						.on('dragend', function(e){
 
- 							unselectAll({ notrigger: true });
 
- 							helper && helper.remove();
 
- 						})
 
- 						.draggable(fm.draggable);
 
- 					}
 
- 				})
 
- 				// add hover class to selected file
 
- 				.on(evtSelect, fileSelector, function(e) {
 
- 					var $this = $(this),
 
- 						id    = fm.cwdId2Hash($this.attr('id'));
 
- 					
 
- 					if (!selectLock && !$this.hasClass(clDisabled)) {
 
- 						lastSelect = '#'+ this.id;
 
- 						$this.addClass(clSelected).children().addClass(clHover).find('input:checkbox.'+clSelChk).prop('checked', true);
 
- 						if (! selectedFiles[id]) {
 
- 							selectedFiles[id] = true;
 
- 						}
 
- 						// will be selected next
 
- 						selectedNext = cwd.find('[id].'+clSelected+':last').next();
 
- 					}
 
- 				})
 
- 				// remove hover class from unselected file
 
- 				.on(evtUnselect, fileSelector, function(e) {
 
- 					var $this = $(this), 
 
- 						id    = fm.cwdId2Hash($this.attr('id'));
 
- 					
 
- 					if (!selectLock) {
 
- 						$this.removeClass(clSelected).children().removeClass(clHover).find('input:checkbox.'+clSelChk).prop('checked', false);
 
- 						if (cwd.hasClass('elfinder-cwd-allselected')) {
 
- 							selectCheckbox && selectAllCheckbox.children('input').prop('checked', false);
 
- 							cwd.removeClass('elfinder-cwd-allselected');
 
- 						}
 
- 						selectedFiles[id] && delete selectedFiles[id];
 
- 					}
 
- 					
 
- 				})
 
- 				// disable files wich removing or moving
 
- 				.on(evtDisable, fileSelector, function() {
 
- 					var $this  = $(this).removeClass(clHover+' '+clSelected).addClass(clDisabled), 
 
- 						child  = $this.children(),
 
- 						target = (list ? $this : child.find('div.elfinder-cwd-file-wrapper,div.elfinder-cwd-filename'));
 
- 					
 
- 					child.removeClass(clHover+' '+clSelected);
 
- 					
 
- 					$this.hasClass(clDroppable) && $this.droppable('disable');
 
- 					target.hasClass(clDraggable) && target.draggable('disable');
 
- 				})
 
- 				// if any files was not removed/moved - unlock its
 
- 				.on(evtEnable, fileSelector, function() {
 
- 					var $this  = $(this).removeClass(clDisabled), 
 
- 						target = list ? $this : $this.children('div.elfinder-cwd-file-wrapper,div.elfinder-cwd-filename');
 
- 					
 
- 					$this.hasClass(clDroppable) && $this.droppable('enable');	
 
- 					target.hasClass(clDraggable) && target.draggable('enable');
 
- 				})
 
- 				.on('scrolltoview', fileSelector, function(e, data) {
 
- 					scrollToView($(this), (data && typeof data.blink !== 'undefined')? data.blink : true);
 
- 				})
 
- 				.on('mouseenter.'+fm.namespace+' mouseleave.'+fm.namespace, fileSelector, function(e) {
 
- 					var enter = (e.type === 'mouseenter');
 
- 					if (enter && (scrolling || fm.UA.Mobile)) { return; }
 
- 					fm.trigger('hover', {hash : fm.cwdId2Hash($(this).attr('id')), type : e.type});
 
- 					$(this).toggleClass(clHover, (e.type == 'mouseenter'));
 
- 				})
 
- 				// for file contextmenu
 
- 				.on('mouseenter.'+fm.namespace+' mouseleave.'+fm.namespace, '.elfinder-cwd-file-wrapper,.elfinder-cwd-filename', function(e) {
 
- 					var enter = (e.type === 'mouseenter');
 
- 					if (enter && scrolling) { return; }
 
- 					$(this).closest(fileSelector).children('.elfinder-cwd-file-wrapper,.elfinder-cwd-filename').toggleClass(clActive, (e.type == 'mouseenter'));
 
- 				})
 
- 				.on('contextmenu.'+fm.namespace, function(e) {
 
- 					var file = $(e.target).closest(fileSelector);
 
- 					
 
- 					if (file.get(0) === e.target && !selectedFiles[fm.cwdId2Hash(file.get(0).id)]) {
 
- 						return;
 
- 					}
 
- 					// now filename editing
 
- 					if (file.find('input:text,textarea').length) {
 
- 						e.stopPropagation();
 
- 						return;
 
- 					}
 
- 					
 
- 					if (file.length && (e.target.nodeName != 'TD' || selectedFiles[fm.cwdId2Hash(file.get(0).id)])) {
 
- 						e.stopPropagation();
 
- 						e.preventDefault();
 
- 						if (!file.hasClass(clDisabled) && !wrapper.data('touching')) {
 
- 							if (!file.hasClass(clSelected)) {
 
- 								unselectAll({ notrigger: true });
 
- 								file.trigger(evtSelect);
 
- 								trigger();
 
- 							}
 
- 							fm.trigger('contextmenu', {
 
- 								'type'    : 'files',
 
- 								'targets' : fm.selected(),
 
- 								'x'       : e.pageX,
 
- 								'y'       : e.pageY
 
- 							});
 
- 						}
 
- 						
 
- 					}
 
- 				})
 
- 				// unselect all on cwd click
 
- 				.on('click.'+fm.namespace, function(e) {
 
- 					if (e.target === this && ! cwd.data('longtap')) {
 
- 						!e.shiftKey && !e.ctrlKey && !e.metaKey && unselectAll();
 
- 					}
 
- 				})
 
- 				// prepend fake file/dir
 
- 				.on('create.'+fm.namespace, function(e, f) {
 
- 					var parent = list ? cwd.find('tbody') : cwd,
 
- 						p = parent.find('.elfinder-cwd-parent'),
 
- 						lock = f.move || false,
 
- 						file = $(itemhtml(f)).addClass(clTmp),
 
- 						selected = fm.selected();
 
- 						
 
- 					if (selected.length) {
 
- 						lock && fm.trigger('lockfiles', {files: selected});
 
- 					} else {
 
- 						unselectAll();
 
- 					}
 
- 					if (p.length) {
 
- 						p.after(file);
 
- 					} else {
 
- 						parent.prepend(file);
 
- 					}
 
- 					
 
- 					setColwidth();
 
- 					wrapper.scrollTop(0).scrollLeft(0);
 
- 				})
 
- 				// unselect all selected files
 
- 				.on('unselectall', unselectAll)
 
- 				.on('selectfile', function(e, id) {
 
- 					$('#'+fm.cwdHash2Id(id)).trigger(evtSelect);
 
- 					trigger();
 
- 				})
 
- 				.on('colwidth', function() {
 
- 					if (list) {
 
- 						cwd.find('table').css('table-layout', '')
 
- 							.find('td').css('width', '');
 
- 						fixTableHeader({fitWidth: true});
 
- 						fm.storage('cwdColWidth', colWidth = null);
 
- 					}
 
- 				})
 
- 				.on('iconpref', function(e, data) {
 
- 					cwd.removeClass(function(i, cName) {
 
- 						return (cName.match(/\belfinder-cwd-size\S+/g) || []).join(' ');
 
- 					});
 
- 					iconSize = data? (parseInt(data.size) || 0) : 0;
 
- 					if (!list) {
 
- 						if (iconSize > 0) {
 
- 							cwd.addClass('elfinder-cwd-size' + iconSize);
 
- 						}
 
- 						if (bufferExt.renderd) {
 
- 							requestAnimationFrame(function() {
 
- 								itemBoxSize.icons = {};
 
- 								bufferExt.hpi = null;
 
- 								bottomMarkerShow(cwd, bufferExt.renderd);
 
- 								wrapperRepaint();
 
- 							});
 
- 						}
 
- 					}
 
- 				})
 
- 				// Change icon size with mouse wheel event
 
- 				.on('onwheel' in document ? 'wheel' : 'mousewheel', function(e) {
 
- 					var tm, size, delta;
 
- 					if (!list && ((e.ctrlKey && !e.metaKey) || (!e.ctrlKey && e.metaKey))) {
 
- 						e.stopPropagation();
 
- 						e.preventDefault();
 
- 						tm = cwd.data('wheelTm');
 
- 						if (typeof tm !== 'undefined') {
 
- 							clearTimeout(tm);
 
- 							cwd.data('wheelTm', setTimeout(function() {
 
- 								cwd.removeData('wheelTm');
 
- 							}, 200));
 
- 						} else {
 
- 							cwd.data('wheelTm', false);
 
- 							size = iconSize || 0;
 
- 							delta = e.originalEvent.deltaY ? e.originalEvent.deltaY : -(e.originalEvent.wheelDelta);
 
- 							if (delta > 0) {
 
- 								if (iconSize > 0) {
 
- 									size = iconSize - 1;
 
- 								}
 
- 							} else {
 
- 								if (iconSize < options.iconsView.sizeMax) {
 
- 									size = iconSize + 1;
 
- 								}
 
- 							}
 
- 							if (size !== iconSize) {
 
- 								fm.storage('iconsize', size);
 
- 								cwd.trigger('iconpref', {size: size});
 
- 							}
 
- 						}
 
- 					}
 
- 				}),
 
- 			wrapper = $('<div class="elfinder-cwd-wrapper"/>')
 
- 				// make cwd itself droppable for folders from nav panel
 
- 				.droppable(Object.assign({}, droppable, {autoDisable: false}))
 
- 				.on('contextmenu.'+fm.namespace, wrapperContextMenu.contextmenu)
 
- 				.on('touchstart.'+fm.namespace, wrapperContextMenu.touchstart)
 
- 				.on('touchmove.'+fm.namespace+' touchend.'+fm.namespace, wrapperContextMenu.touchend)
 
- 				.on('click.'+fm.namespace, wrapperContextMenu.click)
 
- 				.on('scroll.'+fm.namespace, function() {
 
- 					if (! scrolling) {
 
- 						cwd.data('selectable') && cwd.selectable('disable');
 
- 						wrapper.trigger(scrollStartEvent);
 
- 					}
 
- 					scrolling = true;
 
- 					bufferExt.scrtm && cancelAnimationFrame(bufferExt.scrtm);
 
- 					if (bufferExt.scrtm && Math.abs((bufferExt.scrolltop || 0) - (bufferExt.scrolltop = (this.scrollTop || $(this).scrollTop()))) < 5) {
 
- 						bufferExt.scrtm = 0;
 
- 						wrapper.trigger(scrollEvent);
 
- 					}
 
- 					bufferExt.scrtm = requestAnimationFrame(function() {
 
- 						bufferExt.scrtm = 0;
 
- 						wrapper.trigger(scrollEvent);
 
- 					});
 
- 				})
 
- 				.on(scrollEvent, function() {
 
- 					scrolling = false;
 
- 					wrapperRepaint();
 
- 				}),
 
- 			
 
- 			bottomMarker = $('<div> </div>')
 
- 				.css({position: 'absolute', width: '1px', height: '1px'})
 
- 				.hide(),
 
- 			
 
- 			selectAllCheckbox = selectCheckbox? $('<div class="elfinder-cwd-selectall"><input type="checkbox"/></div>')
 
- 				.attr('title', fm.i18n('selectall'))
 
- 				.on('touchstart mousedown click', function(e) {
 
- 					e.stopPropagation();
 
- 					e.preventDefault();
 
- 					if ($(this).data('pending') || e.type === 'click') {
 
- 						return false;
 
- 					}
 
- 					selectAllCheckbox.data('pending', true);
 
- 					if (cwd.hasClass('elfinder-cwd-allselected')) {
 
- 						selectAllCheckbox.find('input').prop('checked', false);
 
- 						requestAnimationFrame(function() {
 
- 							unselectAll();
 
- 						});
 
- 					} else {
 
- 						selectAll();
 
- 					}
 
- 				}) : $(),
 
- 			
 
- 			restm = null,
 
- 			resize = function(init) {
 
- 				var initHeight = function() {
 
- 					if (typeof bufferExt.renderd !== 'undefined') {
 
- 						var h = 0;
 
- 						wrapper.siblings('div.elfinder-panel:visible').each(function() {
 
- 							h += $(this).outerHeight(true);
 
- 						});
 
- 						wrapper.height(wz.height() - h - wrapper._padding);
 
- 					}
 
- 				};
 
- 				
 
- 				init && initHeight();
 
- 				
 
- 				restm && cancelAnimationFrame(restm);
 
- 				restm = requestAnimationFrame(function(){
 
- 					!init && initHeight();
 
- 					var wph, cwdoh;
 
- 					// fix cwd height if it less then wrapper
 
- 					cwd.css('height', 'auto');
 
- 					wph = wrapper[0].clientHeight - parseInt(wrapper.css('padding-top')) - parseInt(wrapper.css('padding-bottom')) - parseInt(cwd.css('margin-top')),
 
- 					cwdoh = cwd.outerHeight(true);
 
- 					if (cwdoh < wph) {
 
- 						cwd.height(wph);
 
- 					}
 
- 				});
 
- 				
 
- 				list && ! colResizing && (init? wrapper.trigger('resize.fixheader') : fixTableHeader());
 
- 				
 
- 				wrapperRepaint();
 
- 			},
 
- 			
 
- 			// elfinder node
 
- 			parent = $(this).parent().on('resize', resize),
 
- 			
 
- 			// workzone node 
 
- 			wz = parent.children('.elfinder-workzone').append(wrapper.append(this).append(bottomMarker)),
 
- 			
 
- 			// message board
 
- 			mBoard = $('<div class="elfinder-cwd-message-board"/>').insertAfter(cwd),
 
- 			// Volume expires
 
- 			vExpires = $('<div class="elfinder-cwd-expires" />'),
 
- 			vExpiresTm,
 
- 			showVolumeExpires = function() {
 
- 				var remain, sec, int;
 
- 				vExpiresTm && clearTimeout(vExpiresTm);
 
- 				if (curVolId && fm.volumeExpires[curVolId]) {
 
- 					sec = fm.volumeExpires[curVolId] - ((+new Date()) / 1000);
 
- 					int = (sec % 60) + 0.1;
 
- 					remain = Math.floor(sec / 60);
 
- 					vExpires.html(fm.i18n(['minsLeft', remain])).show();
 
- 					if (remain) {
 
- 						vExpiresTm = setTimeout(showVolumeExpires, int * 1000);
 
- 					}
 
- 				}
 
- 			},
 
- 			// each item box size
 
- 			itemBoxSize = {
 
- 				icons : {},
 
- 				list : {}
 
- 			},
 
- 			// has UI tree
 
- 			hasUiTree,
 
- 			// Icon size of icons view
 
- 			iconSize,
 
- 			// Current volume id
 
- 			curVolId,
 
- 			
 
- 			winScrTm;
 
- 		// IE < 11 not support CSS `pointer-events: none`
 
- 		if (!fm.UA.ltIE10) {
 
- 			mBoard.append($('<div class="elfinder-cwd-trash" />').html(fm.i18n('volume_Trash')))
 
- 			      .append(vExpires);
 
- 		}
 
- 		// setup by options
 
- 		replacement = Object.assign(replacement, options.replacement || {});
 
- 		
 
- 		try {
 
- 			colWidth = fm.storage('cwdColWidth')? fm.storage('cwdColWidth') : null;
 
- 		} catch(e) {
 
- 			colWidth = null;
 
- 		}
 
- 		
 
- 		// setup costomCols
 
- 		fm.bind('columnpref', function(e) {
 
- 			var opts = e.data || {};
 
- 			if (customCols = fm.storage('cwdCols')) {
 
- 				customCols = $.grep(customCols, function(n) {
 
- 					return (options.listView.columns.indexOf(n) !== -1)? true : false;
 
- 				});
 
- 				if (options.listView.columns.length > customCols.length) {
 
- 					$.each(options.listView.columns, function(i, n) {
 
- 						if (customCols.indexOf(n) === -1) {
 
- 							customCols.push(n);
 
- 						}
 
- 					});
 
- 				}
 
- 			} else {
 
- 				customCols = options.listView.columns;
 
- 			}
 
- 			// column names array that hidden
 
- 			var columnhides = fm.storage('columnhides') || null;
 
- 			if (columnhides && Object.keys(columnhides).length)
 
- 			customCols = $.grep(customCols, function(n) {
 
- 				return columnhides[n]? false : true;
 
- 			});
 
- 			// make template with customCols
 
- 			templates.row = makeTemplateRow();
 
- 			// repaint if need it
 
- 			list && opts.repaint && content();
 
- 		}).trigger('columnpref');
 
- 		if (mobile) {
 
- 			// for iOS5 bug
 
- 			$('body').on('touchstart touchmove touchend', function(e){});
 
- 		}
 
- 		
 
- 		selectCheckbox && cwd.addClass('elfinder-has-checkbox');
 
- 		
 
- 		$(window).on('scroll.'+fm.namespace, function() {
 
- 			winScrTm && cancelAnimationFrame(winScrTm);
 
- 			winScrTm = requestAnimationFrame(function() {
 
- 				wrapper.trigger(scrollEvent);
 
- 			});
 
- 		});
 
- 		
 
- 		$(document).on('keydown.'+fm.namespace, function(e) {
 
- 			if (e.keyCode == $.ui.keyCode.ESCAPE) {
 
- 				if (! fm.getUI().find('.ui-widget:visible').length) {
 
- 					unselectAll();
 
- 				}
 
- 			}
 
- 		});
 
- 		
 
- 		fm
 
- 			.one('init', function(){
 
- 				var style = document.createElement('style'),
 
- 				sheet, node, base, resizeTm, iconSize, i = 0;
 
- 				if (document.head) {
 
- 					document.head.appendChild(style);
 
- 					sheet = style.sheet;
 
- 					sheet.insertRule('.elfinder-cwd-wrapper-empty .elfinder-cwd:not(.elfinder-table-header-sticky):after{ content:"'+fm.i18n('emptyFolder')+'" }', i++);
 
- 					sheet.insertRule('.elfinder-cwd-wrapper-empty .native-droppable .elfinder-cwd:not(.elfinder-table-header-sticky):after{ content:"'+fm.i18n('emptyFolder'+(mobile? 'LTap' : 'Drop'))+'" }', i++);
 
- 					sheet.insertRule('.elfinder-cwd-wrapper-empty .ui-droppable-disabled .elfinder-cwd:not(.elfinder-table-header-sticky):after{ content:"'+fm.i18n('emptyFolder')+'" }', i++);
 
- 					sheet.insertRule('.elfinder-cwd-wrapper-empty.elfinder-search-result .elfinder-cwd:not(.elfinder-table-header-sticky):after{ content:"'+fm.i18n('emptySearch')+'" }', i++);
 
- 					sheet.insertRule('.elfinder-cwd-wrapper-empty.elfinder-search-result.elfinder-incsearch-result .elfinder-cwd:not(.elfinder-table-header-sticky):after{ content:"'+fm.i18n('emptyIncSearch')+'" }', i++);
 
- 					sheet.insertRule('.elfinder-cwd-wrapper-empty.elfinder-search-result.elfinder-letsearch-result .elfinder-cwd:not(.elfinder-table-header-sticky):after{ content:"'+fm.i18n('emptyLetSearch')+'" }', i++);
 
- 				}
 
- 				if (iconSize = fm.storage('iconsize') || 0) {
 
- 					cwd.trigger('iconpref', {size: iconSize});
 
- 				}
 
- 				if (! mobile) {
 
- 					fm.one('open', function() {
 
- 						sheet && fm.zIndex && sheet.insertRule('.ui-selectable-helper{z-index:'+fm.zIndex+';}', i++);
 
- 					});
 
- 					base = $('<div style="position:absolute"/>');
 
- 					node = fm.getUI();
 
- 					node.on('resize', function(e, data) {
 
- 						var offset;
 
- 						e.preventDefault();
 
- 						e.stopPropagation();
 
- 						if (data && data.fullscreen) {
 
- 							offset = node.offset();
 
- 							if (data.fullscreen === 'on') {
 
- 								base.css({top:offset.top * -1 , left:offset.left * -1 }).appendTo(node);
 
- 								selectableOption.appendTo = base;
 
- 							} else {
 
- 								base.detach();
 
- 								selectableOption.appendTo = 'body';
 
- 							}
 
- 							cwd.data('selectable') && cwd.selectable('option', {appendTo : selectableOption.appendTo});
 
- 						}
 
- 					});
 
- 				}
 
- 				hasUiTree = fm.getUI('tree').length;
 
- 			})
 
- 			.bind('enable', function() {
 
- 				resize();
 
- 			})
 
- 			.bind('request.open', function() {
 
- 				bufferExt.getTmbs = [];
 
- 			})
 
- 			.one('open', function() {
 
- 				if (fm.maxTargets) {
 
- 					tmbNum = Math.min(fm.maxTargets, tmbNum);
 
- 				}
 
- 			})
 
- 			.bind('open add remove searchend', function() {
 
- 				var phash = fm.cwd().hash,
 
- 					type = this.type;
 
- 				if (type === 'open' || type === 'searchend' || fm.searchStatus.state < 2) {
 
- 					cwdHashes = $.map(fm.files(phash), function(f) { return f.hash; });
 
- 					fm.trigger('cwdhasheschange', cwdHashes);
 
- 				}
 
- 				if (type === 'open') {
 
- 					var inTrash = function() {
 
- 							var isIn = false;
 
- 							$.each(cwdParents, function(i, h) {
 
- 								if (fm.trashes[h]) {
 
- 									isIn = true;
 
- 									return false;
 
- 								}
 
- 							});
 
- 							return isIn;
 
- 						},
 
- 						req = phash?
 
- 							(! fm.file(phash) || hasUiTree?
 
- 								(! hasUiTree?
 
- 									fm.request({
 
- 										data: {
 
- 											cmd    : 'parents',
 
- 											target : fm.cwd().hash
 
- 										},
 
- 										preventFail : true
 
- 									}) : (function() {
 
- 										var dfd = $.Deferred();
 
- 										fm.one('treesync', function(e) {
 
- 											e.data.always(function() {
 
- 												dfd.resolve();
 
- 											});
 
- 										});
 
- 										return dfd;
 
- 									})()
 
- 								) : null
 
- 							) : null,
 
- 						cwdObj = fm.cwd();
 
- 					// add/remove volume id class
 
- 					if (cwdObj.volumeid !== curVolId) {
 
- 						vExpires.empty().hide();
 
- 						if (curVolId) {
 
- 							wrapper.removeClass('elfinder-cwd-wrapper-' + curVolId);
 
- 						}
 
- 						curVolId = cwdObj.volumeid;
 
- 						showVolumeExpires();
 
- 						wrapper.addClass('elfinder-cwd-wrapper-' + curVolId);
 
- 					}
 
- 					// add/remove trash class
 
- 					$.when(req).done(function() {
 
- 						cwdParents = fm.parents(cwdObj.hash);
 
- 						wrapper[inTrash()? 'addClass':'removeClass']('elfinder-cwd-wrapper-trash');
 
- 					});
 
- 					incHashes = void 0;
 
- 					unselectAll({ notrigger: true });
 
- 					content();
 
- 				}
 
- 			})
 
- 			.bind('search', function(e) {
 
- 				cwdHashes = $.map(e.data.files, function(f) { return f.hash; });
 
- 				fm.trigger('cwdhasheschange', cwdHashes);
 
- 				incHashes = void 0;
 
- 				fm.searchStatus.ininc = false;
 
- 				content();
 
- 				fm.autoSync('stop');
 
- 			})
 
- 			.bind('searchend', function(e) {
 
- 				if (query || incHashes) {
 
- 					query = '';
 
- 					if (incHashes) {
 
- 						fm.trigger('incsearchend', e.data);
 
- 					} else {
 
- 						if (!e.data || !e.data.noupdate) {
 
- 							content();
 
- 						}
 
- 					}
 
- 				}
 
- 				fm.autoSync();
 
- 			})
 
- 			.bind('searchstart', function(e) {
 
- 				unselectAll();
 
- 				query = e.data.query;
 
- 			})
 
- 			.bind('incsearchstart', function(e) {
 
- 				selectedFiles = {};
 
- 				fm.lazy(function() {
 
- 					// incremental search
 
- 					var regex, q, fst = '';
 
- 					q = query = e.data.query || '';
 
- 					if (q) {
 
- 						if (q.substr(0,1) === '/') {
 
- 							q = q.substr(1);
 
- 							fst = '^';
 
- 						}
 
- 						regex = new RegExp(fst + q.replace(/([\\*\;\.\?\[\]\{\}\(\)\^\$\-\|])/g, '\\$1'), 'i');
 
- 						incHashes = $.grep(cwdHashes, function(hash) {
 
- 							var file = fm.file(hash);
 
- 							return (file && (file.name.match(regex) || (file.i18 && file.i18.match(regex))))? true : false;
 
- 						});
 
- 						fm.trigger('incsearch', { hashes: incHashes, query: q })
 
- 							.searchStatus.ininc = true;
 
- 						content();
 
- 						fm.autoSync('stop');
 
- 					} else {
 
- 						fm.trigger('incsearchend');
 
- 					}
 
- 				});
 
- 			})
 
- 			.bind('incsearchend', function(e) {
 
- 				query = '';
 
- 				fm.searchStatus.ininc = false;
 
- 				incHashes = void 0;
 
- 				if (!e.data || !e.data.noupdate) {
 
- 					content();
 
- 				}
 
- 				fm.autoSync();
 
- 			})
 
- 			.bind('sortchange', function() {
 
- 				var lastScrollLeft = wrapper.scrollLeft(),
 
- 					allsel = cwd.hasClass('elfinder-cwd-allselected');
 
- 				
 
- 				content();
 
- 				fm.one('cwdrender', function() {
 
- 					wrapper.scrollLeft(lastScrollLeft);
 
- 					if (allsel) {
 
- 						selectedFiles = fm.arrayFlip(incHashes || cwdHashes, true);
 
- 					}
 
- 					(allsel || Object.keys(selectedFiles).length) && trigger();
 
- 				});
 
- 			})
 
- 			.bind('viewchange', function() {
 
- 				var l      = fm.storage('view') == 'list',
 
- 					allsel = cwd.hasClass('elfinder-cwd-allselected');
 
- 				
 
- 				if (l != list) {
 
- 					list = l;
 
- 					fm.viewType = list? 'list' : 'icons';
 
- 					if (iconSize) {
 
- 						fm.one('cwdinit', function() {
 
- 							cwd.trigger('iconpref', {size: iconSize});
 
- 						});
 
- 					}
 
- 					content();
 
- 					resize();
 
- 					if (allsel) {
 
- 						cwd.addClass('elfinder-cwd-allselected');
 
- 						selectAllCheckbox.find('input').prop('checked', true);
 
- 					}
 
- 					Object.keys(selectedFiles).length && trigger();
 
- 				}
 
- 			})
 
- 			.bind('wzresize', function() {
 
- 				var place = list ? cwd.find('tbody') : cwd,
 
- 					cwdOffset;
 
- 				resize(true);
 
- 				if (bufferExt.hpi) {
 
- 					bottomMarkerShow(place, place.find('[id]').length);
 
- 				}
 
- 				
 
- 				cwdOffset = cwd.offset();
 
- 				wz.data('rectangle', Object.assign(
 
- 					{
 
- 						width: wz.width(),
 
- 						height: wz.height(),
 
- 						cwdEdge: (fm.direction === 'ltr')? cwdOffset.left : cwdOffset.left + cwd.width()
 
- 					},
 
- 					wz.offset())
 
- 				);
 
- 				
 
- 				bufferExt.itemH = (list? place.find('tr:first') : place.find('[id]:first')).outerHeight(true);
 
- 			})
 
- 			.bind('changeclipboard', function(e) {
 
- 				clipCuts = {};
 
- 				if (e.data && e.data.clipboard && e.data.clipboard.length) {
 
- 					$.each(e.data.clipboard, function(i, f) {
 
- 						if (f.cut) {
 
- 							clipCuts[f.hash] = true;
 
- 						}
 
- 					});
 
- 				}
 
- 			})
 
- 			.bind('resMixinMake', function() {
 
- 				setColwidth();
 
- 			})
 
- 			.bind('tmbreload', function(e) {
 
- 				var imgs = {},
 
- 					files = (e.data && e.data.files)? e.data.files : null;
 
- 				
 
- 				$.each(files, function(i, f) {
 
- 					if (f.tmb && f.tmb != '1') {
 
- 						imgs[f.hash] = f.tmb;
 
- 					}
 
- 				});
 
- 				if (Object.keys(imgs).length) {
 
- 					attachThumbnails(imgs, true);
 
- 				}
 
- 			})
 
- 			.add(function(e) {
 
- 				var regex = query? new RegExp(query.replace(/([\\*\;\.\?\[\]\{\}\(\)\^\$\-\|])/g, '\\$1'), 'i') : null,
 
- 					mime  = fm.searchStatus.mime,
 
- 					inSearch = fm.searchStatus.state > 1,
 
- 					phash = inSearch && fm.searchStatus.target? fm.searchStatus.target : fm.cwd().hash,
 
- 					curPath = fm.path(phash),
 
- 					inTarget = function(f) {
 
- 						var res, parents, path;
 
- 						res = (f.phash === phash);
 
- 						if (!res && inSearch) {
 
- 							path = f.path || fm.path(f.hash);
 
- 							res = (curPath && path.indexOf(curPath) === 0);
 
- 							if (! res && fm.searchStatus.mixed) {
 
- 								res = $.grep(fm.searchStatus.mixed, function(vid) { return f.hash.indexOf(vid) === 0? true : false; }).length? true : false;
 
- 							}
 
- 						}
 
- 						if (res && inSearch) {
 
- 							if (mime) {
 
- 								res = (f.mime.indexOf(mime) === 0);
 
- 							} else {
 
- 								res = (f.name.match(regex) || (f.i18 && f.i18.match(regex)))? true : false;
 
- 							}
 
- 						}
 
- 						return res;
 
- 					},
 
- 					files = $.grep(e.data.added || [], function(f) { return inTarget(f)? true : false ;});
 
- 				add(files);
 
- 				if (fm.searchStatus.state === 2) {
 
- 					$.each(files, function(i, f) {
 
- 						if ($.inArray(f.hash, cwdHashes) === -1) {
 
- 							cwdHashes.push(f.hash);
 
- 						}
 
- 					});
 
- 					fm.trigger('cwdhasheschange', cwdHashes);
 
- 				}
 
- 				list && resize();
 
- 				wrapper.trigger(scrollEvent);
 
- 			})
 
- 			.change(function(e) {
 
- 				var phash = fm.cwd().hash,
 
- 					sel   = fm.selected(),
 
- 					files, added;
 
- 				if (query) {
 
- 					$.each(e.data.changed || [], function(i, file) {
 
- 						if ($('#'+fm.cwdHash2Id(file.hash)).length) {
 
- 							remove([file.hash]);
 
- 							add([file], 'change');
 
- 							$.inArray(file.hash, sel) !== -1 && selectFile(file.hash);
 
- 							added = true;
 
- 						}
 
- 					});
 
- 				} else {
 
- 					$.each($.grep(e.data.changed || [], function(f) { return f.phash == phash ? true : false; }), function(i, file) {
 
- 						if ($('#'+fm.cwdHash2Id(file.hash)).length) {
 
- 							remove([file.hash]);
 
- 							add([file], 'change');
 
- 							$.inArray(file.hash, sel) !== -1 && selectFile(file.hash);
 
- 							added = true;
 
- 						}
 
- 					});
 
- 				}
 
- 				
 
- 				if (added) {
 
- 					fm.trigger('cwdhasheschange', cwdHashes);
 
- 					list && resize();
 
- 					wrapper.trigger(scrollEvent);
 
- 				}
 
- 				
 
- 				trigger();
 
- 			})
 
- 			.remove(function(e) {
 
- 				var place = list ? cwd.find('tbody') : cwd;
 
- 				remove(e.data.removed || []);
 
- 				trigger();
 
- 				if (buffer.length < 1 && place.children(fileSelector).length < 1) {
 
- 					wz.addClass('elfinder-cwd-wrapper-empty');
 
- 					selectCheckbox && selectAllCheckbox.find('input').prop('checked', false);
 
- 					bottomMarker.hide();
 
- 					wrapper.off(scrollEvent, render);
 
- 					resize();
 
- 				} else {
 
- 					bottomMarkerShow(place);
 
- 					wrapper.trigger(scrollEvent);
 
- 				}
 
- 			})
 
- 			// select dragged file if no selected, disable selectable
 
- 			.dragstart(function(e) {
 
- 				var target = $(e.data.target),
 
- 					oe     = e.data.originalEvent;
 
- 				if (target.hasClass(clFile)) {
 
- 					
 
- 					if (!target.hasClass(clSelected)) {
 
- 						!(oe.ctrlKey || oe.metaKey || oe.shiftKey) && unselectAll({ notrigger: true });
 
- 						target.trigger(evtSelect);
 
- 						trigger();
 
- 					}
 
- 				}
 
- 				
 
- 				cwd.removeClass(clDisabled).data('selectable') && cwd.selectable('disable');
 
- 				selectLock = true;
 
- 			})
 
- 			// enable selectable
 
- 			.dragstop(function() {
 
- 				cwd.data('selectable') && cwd.selectable('enable');
 
- 				selectLock = false;
 
- 			})
 
- 			.bind('lockfiles unlockfiles selectfiles unselectfiles', function(e) {
 
- 				var events = {
 
- 						lockfiles     : evtDisable ,
 
- 						unlockfiles   : evtEnable ,
 
- 						selectfiles   : evtSelect,
 
- 						unselectfiles : evtUnselect },
 
- 					event  = events[e.type],
 
- 					files  = e.data.files || [],
 
- 					l      = files.length,
 
- 					helper = e.data.helper || $(),
 
- 					parents, ctr, add;
 
- 				if (l > 0) {
 
- 					parents = fm.parents(files[0]);
 
- 				}
 
- 				if (event === evtSelect || event === evtUnselect) {
 
- 					add  = (event === evtSelect),
 
- 					$.each(files, function(i, hash) {
 
- 						var all = cwd.hasClass('elfinder-cwd-allselected');
 
- 						if (! selectedFiles[hash]) {
 
- 							add && (selectedFiles[hash] = true);
 
- 						} else {
 
- 							if (all) {
 
- 								selectCheckbox && selectAllCheckbox.children('input').prop('checked', false);
 
- 								cwd.removeClass('elfinder-cwd-allselected');
 
- 								all = false;
 
- 							}
 
- 							! add && delete selectedFiles[hash];
 
- 						}
 
- 					});
 
- 				}
 
- 				if (!helper.data('locked')) {
 
- 					while (l--) {
 
- 						try {
 
- 							$('#'+fm.cwdHash2Id(files[l])).trigger(event);
 
- 						} catch(e) {}
 
- 					}
 
- 					! e.data.inselect && trigger();
 
- 				}
 
- 				if (wrapper.data('dropover') && parents.indexOf(wrapper.data('dropover')) !== -1) {
 
- 					ctr = e.type !== 'lockfiles';
 
- 					helper.toggleClass('elfinder-drag-helper-plus', ctr);
 
- 					wrapper.toggleClass(clDropActive, ctr);
 
- 				}
 
- 			})
 
- 			// select new files after some actions
 
- 			.bind('mkdir mkfile duplicate upload rename archive extract paste multiupload', function(e) {
 
- 				if (e.type == 'upload' && e.data._multiupload) return;
 
- 				var phash = fm.cwd().hash, files;
 
- 				
 
- 				unselectAll({ notrigger: true });
 
- 				$.each((e.data.added || []).concat(e.data.changed || []), function(i, file) { 
 
- 					file && file.phash == phash && selectFile(file.hash);
 
- 				});
 
- 				trigger();
 
- 			})
 
- 			.shortcut({
 
- 				pattern     :'ctrl+a', 
 
- 				description : 'selectall',
 
- 				callback    : selectAll
 
- 			})
 
- 			.shortcut({
 
- 				pattern     :'ctrl+shift+i', 
 
- 				description : 'selectinvert',
 
- 				callback    : selectInvert
 
- 			})
 
- 			.shortcut({
 
- 				pattern     : 'left right up down shift+left shift+right shift+up shift+down',
 
- 				description : 'selectfiles',
 
- 				type        : 'keydown' , //fm.UA.Firefox || fm.UA.Opera ? 'keypress' : 'keydown',
 
- 				callback    : function(e) { select(e.keyCode, e.shiftKey); }
 
- 			})
 
- 			.shortcut({
 
- 				pattern     : 'home',
 
- 				description : 'selectffile',
 
- 				callback    : function(e) { 
 
- 					unselectAll({ notrigger: true });
 
- 					scrollToView(cwd.find('[id]:first').trigger(evtSelect));
 
- 					trigger();
 
- 				}
 
- 			})
 
- 			.shortcut({
 
- 				pattern     : 'end',
 
- 				description : 'selectlfile',
 
- 				callback    : function(e) { 
 
- 					unselectAll({ notrigger: true });
 
- 					scrollToView(cwd.find('[id]:last').trigger(evtSelect)) ;
 
- 					trigger();
 
- 				}
 
- 			})
 
- 			.shortcut({
 
- 				pattern     : 'page_up',
 
- 				description : 'pageTurning',
 
- 				callback    : function(e) {
 
- 					if (bufferExt.itemH) {
 
- 						wrapper.scrollTop(
 
- 							Math.round(
 
- 								wrapper.scrollTop()
 
- 								- (Math.floor((wrapper.height() + (list? bufferExt.itemH * -1 : 16)) / bufferExt.itemH)) * bufferExt.itemH
 
- 							)
 
- 						);
 
- 					}
 
- 				}
 
- 			}).shortcut({
 
- 				pattern     : 'page_down',
 
- 				description : 'pageTurning',
 
- 				callback    : function(e) { 
 
- 					if (bufferExt.itemH) {
 
- 						wrapper.scrollTop(
 
- 							Math.round(
 
- 								wrapper.scrollTop()
 
- 								+ (Math.floor((wrapper.height() + (list? bufferExt.itemH * -1 : 16)) / bufferExt.itemH)) * bufferExt.itemH
 
- 							)
 
- 						);
 
- 					}
 
- 				}
 
- 			});
 
- 		
 
- 	});
 
- 	
 
- 	// fm.timeEnd('cwdLoad')
 
- 	
 
- 	return this;
 
- };
 
- /*
 
-  * File: /js/ui/dialog.js
 
-  */
 
- /**
 
-  * @class  elFinder dialog
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.elfinderdialog = function(opts, fm) {
 
- 		var platformWin = (window.navigator.platform.indexOf('Win') != -1),
 
- 		delta       = {},
 
- 		syncSize    = { enabled: false, width: false, height: false, defaultSize: null },
 
- 		fitSize     = function(dialog) {
 
- 			var opts, node;
 
- 			if (syncSize.enabled) {
 
- 				node = fm.options.dialogContained? elfNode : $(window);
 
- 				opts = {
 
- 					maxWidth : syncSize.width?  node.width() - delta.width  : null,
 
- 					maxHeight: syncSize.height? node.height() - delta.height : null
 
- 				};
 
- 				Object.assign(restoreStyle, opts);
 
- 				dialog.css(opts).trigger('resize');
 
- 				if (dialog.data('hasResizable') && (dialog.resizable('option', 'maxWidth') < opts.maxWidth || dialog.resizable('option', 'maxHeight') < opts.maxHeight)) {
 
- 					dialog.resizable('option', opts);
 
- 				}
 
- 			}
 
- 		},
 
- 		syncFunc    = function(e) {
 
- 			var dialog = e.data;
 
- 			syncTm && cancelAnimationFrame(syncTm);
 
- 			syncTm = requestAnimationFrame(function() {
 
- 				var opts, offset;
 
- 				if (syncSize.enabled) {
 
- 					fitSize(dialog);
 
- 				}
 
- 			});
 
- 		},
 
- 		checkEditing = function() {
 
- 			var cldialog = 'elfinder-dialog',
 
- 				dialogs = elfNode.children('.' + cldialog + '.' + fm.res('class', 'editing') + ':visible');
 
- 			fm[dialogs.length? 'disable' : 'enable']();
 
- 		},
 
- 		propagationEvents = {},
 
- 		syncTm, dialog, elfNode, restoreStyle;
 
- 	
 
- 	if (fm && fm.ui) {
 
- 		elfNode = fm.getUI();
 
- 	} else {
 
- 		elfNode = this.closest('.elfinder');
 
- 		if (! fm) {
 
- 			fm = elfNode.elfinder('instance');
 
- 		}
 
- 	}
 
- 	
 
- 	if (typeof opts  === 'string') {
 
- 		if ((dialog = this.closest('.ui-dialog')).length) {
 
- 			if (opts === 'open') {
 
- 				if (dialog.css('display') === 'none') {
 
- 					// Need dialog.show() and hide() to detect elements size in open() callbacks
 
- 					dialog.trigger('posinit').show().trigger('open').hide();
 
- 					dialog.fadeIn(120, function() {
 
- 						fm.trigger('dialogopened', {dialog: dialog});
 
- 					});
 
- 				}
 
- 			} else if (opts === 'close' || opts === 'destroy') {
 
- 				dialog.stop(true);
 
- 				if (dialog.is(':visible') || elfNode.is(':hidden')) {
 
- 					dialog.trigger('close');
 
- 					fm.trigger('dialogclosed', {dialog: dialog});
 
- 				}
 
- 				if (opts === 'destroy') {
 
- 					dialog.remove();
 
- 					fm.trigger('dialogremoved', {dialog: dialog});
 
- 				}
 
- 			} else if (opts === 'toTop') {
 
- 				dialog.trigger('totop');
 
- 				fm.trigger('dialogtotoped', {dialog: dialog});
 
- 			} else if (opts === 'posInit') {
 
- 				dialog.trigger('posinit');
 
- 				fm.trigger('dialogposinited', {dialog: dialog});
 
- 			} else if (opts === 'tabstopsInit') {
 
- 				dialog.trigger('tabstopsInit');
 
- 				fm.trigger('dialogtabstopsinited', {dialog: dialog});
 
- 			} else if (opts === 'checkEditing') {
 
- 				checkEditing();
 
- 			}
 
- 		}
 
- 		return this;
 
- 	}
 
- 	
 
- 	opts = Object.assign({}, $.fn.elfinderdialog.defaults, opts);
 
- 	
 
- 	if (opts.allowMinimize && opts.allowMinimize === 'auto') {
 
- 		opts.allowMinimize = this.find('textarea,input').length? true : false; 
 
- 	}
 
- 	opts.openMaximized = opts.allowMinimize && opts.openMaximized;
 
- 	if (opts.headerBtnPos && opts.headerBtnPos === 'auto') {
 
- 		opts.headerBtnPos = platformWin? 'right' : 'left';
 
- 	}
 
- 	if (opts.headerBtnOrder && opts.headerBtnOrder === 'auto') {
 
- 		opts.headerBtnOrder = platformWin? 'close:maximize:minimize' : 'close:minimize:maximize';
 
- 	}
 
- 	
 
- 	if (opts.modal && opts.allowMinimize) {
 
- 		opts.allowMinimize = false;
 
- 	}
 
- 	
 
- 	if (fm.options.dialogContained) {
 
- 		syncSize.width = syncSize.height = syncSize.enabled = true;
 
- 	} else {
 
- 		syncSize.width = (opts.maxWidth === 'window');
 
- 		syncSize.height = (opts.maxHeight === 'window');
 
- 		if (syncSize.width || syncSize.height) {
 
- 			syncSize.enabled = true;
 
- 		}
 
- 	}
 
- 	propagationEvents = fm.arrayFlip(opts.propagationEvents, true);
 
- 	
 
- 	this.filter(':not(.ui-dialog-content)').each(function() {
 
- 		var self       = $(this).addClass('ui-dialog-content ui-widget-content'),
 
- 			clactive   = 'elfinder-dialog-active',
 
- 			cldialog   = 'elfinder-dialog',
 
- 			clnotify   = 'elfinder-dialog-notify',
 
- 			clhover    = 'ui-state-hover',
 
- 			cltabstop  = 'elfinder-tabstop',
 
- 			cl1stfocus = 'elfinder-focus',
 
- 			clmodal    = 'elfinder-dialog-modal',
 
- 			id         = parseInt(Math.random()*1000000),
 
- 			titlebar   = $('<div class="ui-dialog-titlebar ui-widget-header ui-corner-top ui-helper-clearfix"><span class="elfinder-dialog-title">'+opts.title+'</span></div>'),
 
- 			buttonset  = $('<div class="ui-dialog-buttonset"/>'),
 
- 			buttonpane = $('<div class=" ui-helper-clearfix ui-dialog-buttonpane ui-widget-content"/>')
 
- 				.append(buttonset),
 
- 			btnWidth   = 0,
 
- 			btnCnt     = 0,
 
- 			tabstops   = $(),
 
- 			evCover    = $('<div style="width:100%;height:100%;position:absolute;top:0px;left:0px;"/>').hide(),
 
- 			numberToTel = function() {
 
- 				if (opts.optimizeNumber) {
 
- 					dialog.find('input[type=number]').each(function() {
 
- 						$(this).attr('inputmode', 'numeric');
 
- 						$(this).attr('pattern', '[0-9]*');
 
- 					});
 
- 				}
 
- 			},
 
- 			tabstopsInit = function() {
 
- 				tabstops = dialog.find('.'+cltabstop);
 
- 				if (tabstops.length) {
 
- 					tabstops.attr('tabindex', '-1');
 
- 					if (! tabstops.filter('.'+cl1stfocus).length) {
 
- 						buttonset.children('.'+cltabstop+':'+(platformWin? 'first' : 'last')).addClass(cl1stfocus);
 
- 					}
 
- 				}
 
- 			},
 
- 			tabstopNext = function(cur) {
 
- 				var elms = tabstops.filter(':visible:enabled'),
 
- 					node = cur? null : elms.filter('.'+cl1stfocus+':first');
 
- 					
 
- 				if (! node || ! node.length) {
 
- 					node = elms.first();
 
- 				}
 
- 				if (cur) {
 
- 					$.each(elms, function(i, elm) {
 
- 						if (elm === cur && elms[i+1]) {
 
- 							node = elms.eq(i+1);
 
- 							return false;
 
- 						}
 
- 					});
 
- 				}
 
- 				return node;
 
- 			},
 
- 			tabstopPrev = function(cur) {
 
- 				var elms = tabstops.filter(':visible:enabled'),
 
- 					node = elms.last();
 
- 				$.each(elms, function(i, elm) {
 
- 					if (elm === cur && elms[i-1]) {
 
- 						node = elms.eq(i-1);
 
- 						return false;
 
- 					}
 
- 				});
 
- 				return node;
 
- 			},
 
- 			makeHeaderBtn = function() {
 
- 				$.each(opts.headerBtnOrder.split(':').reverse(), function(i, v) {
 
- 					headerBtns[v] && headerBtns[v]();
 
- 				});
 
- 				if (platformWin) {
 
- 					titlebar.children('.elfinder-titlebar-button').addClass('elfinder-titlebar-button-right');
 
- 				}
 
- 			},
 
- 			headerBtns = {
 
- 				close: function() {
 
- 					titlebar.prepend($('<span class="ui-widget-header ui-dialog-titlebar-close ui-corner-all elfinder-titlebar-button"><span class="ui-icon ui-icon-closethick"/></span>')
 
- 						.on('mousedown', function(e) {
 
- 							e.preventDefault();
 
- 							e.stopPropagation();
 
- 							self.elfinderdialog('close');
 
- 						})
 
- 					);
 
- 				},
 
- 				maximize: function() {
 
- 					if (opts.allowMaximize) {
 
- 						dialog.on('resize', function(e, data) {
 
- 							var full, elm;
 
- 							e.preventDefault();
 
- 							e.stopPropagation();
 
- 							if (data && data.maximize) {
 
- 								elm = titlebar.find('.elfinder-titlebar-full');
 
- 								full = (data.maximize === 'on');
 
- 								elm.children('span.ui-icon')
 
- 									.toggleClass('ui-icon-plusthick', ! full)
 
- 									.toggleClass('ui-icon-arrowreturnthick-1-s', full);
 
- 								if (full) {
 
- 									try {
 
- 										dialog.hasClass('ui-draggable') && dialog.draggable('disable');
 
- 										dialog.hasClass('ui-resizable') && dialog.resizable('disable');
 
- 									} catch(e) {}
 
- 									self.css('width', '100%').css('height', dialog.height() - dialog.children('.ui-dialog-titlebar').outerHeight(true) - buttonpane.outerHeight(true));
 
- 								} else {
 
- 									self.attr('style', elm.data('style'));
 
- 									elm.removeData('style');
 
- 									posCheck();
 
- 									try {
 
- 										dialog.hasClass('ui-draggable') && dialog.draggable('enable');
 
- 										dialog.hasClass('ui-resizable') && dialog.resizable('enable');
 
- 									} catch(e) {}
 
- 								}
 
- 								dialog.trigger('resize', {init: true});
 
- 							}
 
- 						});
 
- 						titlebar.prepend($('<span class="ui-widget-header ui-corner-all elfinder-titlebar-button elfinder-titlebar-full"><span class="ui-icon ui-icon-plusthick"/></span>')
 
- 							.on('mousedown', function(e) {
 
- 								var elm = $(this);
 
- 								e.preventDefault();
 
- 								e.stopPropagation();
 
- 								if (!dialog.hasClass('elfinder-maximized') && typeof elm.data('style') === 'undefined') {
 
- 									self.height(self.height());
 
- 									elm.data('style', self.attr('style') || '');
 
- 								}
 
- 								fm.toggleMaximize(dialog);
 
- 								typeof(opts.maximize) === 'function' && opts.maximize.call(self[0]);
 
- 							})
 
- 						);
 
- 					}
 
- 					
 
- 				},
 
- 				minimize: function() {
 
- 					var btn, mnode, doffset;
 
- 					if (opts.allowMinimize) {
 
- 						btn = $('<span class="ui-widget-header ui-corner-all elfinder-titlebar-button elfinder-titlebar-minimize"><span class="ui-icon ui-icon-minusthick"/></span>')
 
- 							.on('mousedown', function(e) {
 
- 								var $this = $(this),
 
- 									tray = fm.getUI('bottomtray'),
 
- 									dumStyle = { width: 70, height: 24 },
 
- 									dum = $('<div/>').css(dumStyle).addClass(dialog.get(0).className + ' elfinder-dialog-minimized'),
 
- 									pos = {};
 
- 								
 
- 								e.preventDefault();
 
- 								e.stopPropagation();
 
- 								if (!dialog.data('minimized')) {
 
- 									// minimize
 
- 									doffset = dialog.data('minimized', true).position();
 
- 									mnode = dialog.clone().on('mousedown', function() {
 
- 										$this.trigger('mousedown');
 
- 									}).removeClass('ui-draggable ui-resizable elfinder-frontmost');
 
- 									tray.append(dum);
 
- 									Object.assign(pos, dum.offset(), dumStyle);
 
- 									dum.remove();
 
- 									mnode.height(dialog.height()).children('.ui-dialog-content:first').empty();
 
- 									fm.toHide(dialog.before(mnode));
 
- 									mnode.children('.ui-dialog-content:first,.ui-dialog-buttonpane,.ui-resizable-handle').remove();
 
- 									mnode.find('.elfinder-titlebar-minimize,.elfinder-titlebar-full').remove();
 
- 									mnode.find('.ui-dialog-titlebar-close').on('mousedown', function(e) {
 
- 										e.stopPropagation();
 
- 										e.preventDefault();
 
- 										mnode.remove();
 
- 										dialog.show();
 
- 										self.elfinderdialog('close');
 
- 									});
 
- 									mnode.animate(pos, function() {
 
- 										mnode.attr('style', '')
 
- 										.css({ maxWidth: dialog.width() })
 
- 										.addClass('elfinder-dialog-minimized')
 
- 										.appendTo(tray);
 
- 										checkEditing();
 
- 										typeof(opts.minimize) === 'function' && opts.minimize.call(self[0]);
 
- 									});
 
- 								} else {
 
- 									//restore
 
- 									dialog.removeData('minimized').before(mnode.css(Object.assign({'position': 'absolute'}, mnode.offset())));
 
- 									fm.toFront(mnode);
 
- 									mnode.animate(Object.assign({ width: dialog.width(), height: dialog.height() }, doffset), function() {
 
- 										dialog.show();
 
- 										fm.toFront(dialog);
 
- 										mnode.remove();
 
- 										posCheck();
 
- 										checkEditing();
 
- 										dialog.trigger('resize', {init: true});
 
- 										typeof(opts.minimize) === 'function' && opts.minimize.call(self[0]);
 
- 									});
 
- 								}
 
- 							});
 
- 						titlebar.on('dblclick', function(e) {
 
- 							$(this).children('.elfinder-titlebar-minimize').trigger('mousedown');
 
- 						}).prepend(btn);
 
- 						dialog.on('togleminimize', function() {
 
- 							btn.trigger('mousedown');
 
- 						});
 
- 					}
 
- 				}
 
- 			},
 
- 			dialog = $('<div class="ui-front ui-dialog ui-widget ui-widget-content ui-corner-all ui-draggable std42-dialog touch-punch '+cldialog+' '+opts.cssClass+'"/>')
 
- 				.hide()
 
- 				.append(self)
 
- 				.appendTo(elfNode)
 
- 				.draggable({
 
- 					containment : fm.options.dialogContained? elfNode : null,
 
- 					handle : '.ui-dialog-titlebar',
 
- 					start : function() {
 
- 						evCover.show();
 
- 					},
 
- 					drag : function(e, ui) {
 
- 						var top = ui.offset.top,
 
- 							left = ui.offset.left;
 
- 						if (top < 0) {
 
- 							ui.position.top = ui.position.top - top;
 
- 						}
 
- 						if (left < 0) {
 
- 							ui.position.left = ui.position.left - left;
 
- 						}
 
- 						if (fm.options.dialogContained) {
 
- 							ui.position.top < 0 && (ui.position.top = 0);
 
- 							ui.position.left < 0 && (ui.position.left = 0);
 
- 						}
 
- 					},
 
- 					stop : function(e, ui) {
 
- 						evCover.hide();
 
- 						dialog.css({height : opts.height});
 
- 						self.data('draged', true);
 
- 					}
 
- 				})
 
- 				.css({
 
- 					width     : opts.width,
 
- 					height    : opts.height,
 
- 					minWidth  : opts.minWidth,
 
- 					minHeight : opts.minHeight,
 
- 					maxWidth  : opts.maxWidth,
 
- 					maxHeight : opts.maxHeight
 
- 				})
 
- 				.on('touchstart touchmove touchend click dblclick mouseup mouseenter mouseleave mouseout mouseover mousemove', function(e) {
 
- 					// stopPropagation of user action events
 
- 					!propagationEvents[e.type] && e.stopPropagation();
 
- 				})
 
- 				.on('mousedown', function(e) {
 
- 					!propagationEvents[e.type] && e.stopPropagation();
 
- 					requestAnimationFrame(function() {
 
- 						if (dialog.is(':visible') && !dialog.hasClass('elfinder-frontmost')) {
 
- 							toFocusNode = $(':focus');
 
- 							if (!toFocusNode.length) {
 
- 								toFocusNode = void(0);
 
- 							}
 
- 							dialog.trigger('totop');
 
- 						}
 
- 					});
 
- 				})
 
- 				.on('open', function() {
 
- 					dialog.data('margin-y', self.outerHeight(true) - self.height());
 
- 					if (syncSize.enabled) {
 
- 						if (opts.height && opts.height !== 'auto') {
 
- 							dialog.trigger('resize', {init: true});
 
- 						}
 
- 						if (!syncSize.defaultSize) {
 
- 							syncSize.defaultSize = { width: self.width(), height: self.height() };
 
- 						}
 
- 						fitSize(dialog);
 
- 						dialog.trigger('resize').trigger('posinit');
 
- 						elfNode.on('resize.'+fm.namespace, dialog, syncFunc);
 
- 					}
 
- 					
 
- 					if (!dialog.hasClass(clnotify)) {
 
- 						elfNode.children('.'+cldialog+':visible:not(.'+clnotify+')').each(function() {
 
- 							var d     = $(this),
 
- 								top   = parseInt(d.css('top')),
 
- 								left  = parseInt(d.css('left')),
 
- 								_top  = parseInt(dialog.css('top')),
 
- 								_left = parseInt(dialog.css('left')),
 
- 								ct    = Math.abs(top - _top) < 10,
 
- 								cl    = Math.abs(left - _left) < 10;
 
- 							if (d[0] != dialog[0] && (ct || cl)) {
 
- 								dialog.css({
 
- 									top  : ct ? (top + 10) : _top,
 
- 									left : cl ? (left + 10) : _left
 
- 								});
 
- 							}
 
- 						});
 
- 					} 
 
- 					
 
- 					if (dialog.data('modal')) {
 
- 						dialog.addClass(clmodal);
 
- 						fm.getUI('overlay').elfinderoverlay('show');
 
- 					}
 
- 					
 
- 					dialog.trigger('totop');
 
- 					
 
- 					opts.openMaximized && fm.toggleMaximize(dialog);
 
- 					fm.trigger('dialogopen', {dialog: dialog});
 
- 					typeof(opts.open) == 'function' && $.proxy(opts.open, self[0])();
 
- 					
 
- 					if (opts.closeOnEscape) {
 
- 						$(document).on('keydown.'+id, function(e) {
 
- 							if (e.keyCode == $.ui.keyCode.ESCAPE && dialog.hasClass('elfinder-frontmost')) {
 
- 								self.elfinderdialog('close');
 
- 							}
 
- 						});
 
- 					}
 
- 					dialog.hasClass(fm.res('class', 'editing')) && checkEditing();
 
- 				})
 
- 				.on('close', function(e) {
 
- 					var dialogs, dfd;
 
- 					
 
- 					if (opts.beforeclose && typeof opts.beforeclose === 'function') {
 
- 						dfd = opts.beforeclose();
 
- 						if (!dfd || !dfd.promise) {
 
- 							dfd = !dfd? $.Deferred().reject() : $.Deferred().resolve();
 
- 						}
 
- 					} else {
 
- 						dfd = $.Deferred().resolve();
 
- 					}
 
- 					
 
- 					dfd.done(function() {
 
- 						syncSize.enabled && elfNode.off('resize.'+fm.namespace, syncFunc);
 
- 						
 
- 						if (opts.closeOnEscape) {
 
- 							$(document).off('keyup.'+id);
 
- 						}
 
- 						
 
- 						if (opts.allowMaximize) {
 
- 							fm.toggleMaximize(dialog, false);
 
- 						}
 
- 						
 
- 						fm.toHide(dialog);
 
- 						dialog.data('modal') && fm.getUI('overlay').elfinderoverlay('hide');
 
- 						
 
- 						if (typeof(opts.close) == 'function') {
 
- 							$.proxy(opts.close, self[0])();
 
- 						}
 
- 						if (opts.destroyOnClose && dialog.parent().length) {
 
- 							dialog.hide().remove();
 
- 						}
 
- 						
 
- 						// get focus to next dialog
 
- 						dialogs = elfNode.children('.'+cldialog+':visible');
 
- 						
 
- 						dialog.hasClass(fm.res('class', 'editing')) && checkEditing();
 
- 					});
 
- 				})
 
- 				.on('totop frontmost', function() {
 
- 					var s = fm.storage('autoFocusDialog');
 
- 					
 
- 					dialog.data('focusOnMouseOver', s? (s > 0) : fm.options.uiOptions.dialog.focusOnMouseOver);
 
- 					
 
- 					if (dialog.data('minimized')) {
 
- 						titlebar.children('.elfinder-titlebar-minimize').trigger('mousedown');
 
- 					}
 
- 					
 
- 					if (!dialog.data('modal') && fm.getUI('overlay').is(':visible')) {
 
- 						fm.getUI('overlay').before(dialog);
 
- 					} else {
 
- 						fm.toFront(dialog);
 
- 					}
 
- 					elfNode.children('.'+cldialog+':not(.'+clmodal+')').removeClass(clactive);
 
- 					dialog.addClass(clactive);
 
- 					! fm.UA.Mobile && (toFocusNode || tabstopNext()).trigger('focus');
 
- 					toFocusNode = void(0);
 
- 				})
 
- 				.on('posinit', function() {
 
- 					var css = opts.position,
 
- 						nodeOffset, minTop, minLeft, outerSize, win, winSize, nodeFull;
 
- 					if (dialog.hasClass('elfinder-maximized')) {
 
- 						return;
 
- 					}
 
- 					if (! css && ! dialog.data('resizing')) {
 
- 						nodeFull = elfNode.hasClass('elfinder-fullscreen');
 
- 						dialog.css(nodeFull? {
 
- 							maxWidth  : '100%',
 
- 							maxHeight : '100%',
 
- 							overflow   : 'auto'
 
- 						} : restoreStyle);
 
- 						if (fm.UA.Mobile && !nodeFull && dialog.data('rotated') === fm.UA.Rotated) {
 
- 							return;
 
- 						}
 
- 						dialog.data('rotated', fm.UA.Rotated);
 
- 						win = $(window);
 
- 						nodeOffset = elfNode.offset();
 
- 						outerSize = {
 
- 							width : dialog.outerWidth(true),
 
- 							height: dialog.outerHeight(true)
 
- 						};
 
- 						outerSize.right = nodeOffset.left + outerSize.width;
 
- 						outerSize.bottom = nodeOffset.top + outerSize.height;
 
- 						winSize = {
 
- 							scrLeft: win.scrollLeft(),
 
- 							scrTop : win.scrollTop(),
 
- 							width  : win.width(),
 
- 							height : win.height()
 
- 						};
 
- 						winSize.right = winSize.scrLeft + winSize.width;
 
- 						winSize.bottom = winSize.scrTop + winSize.height;
 
- 						
 
- 						if (fm.options.dialogContained || nodeFull) {
 
- 							minTop = 0;
 
- 							minLeft = 0;
 
- 						} else {
 
- 							minTop = nodeOffset.top * -1 + winSize.scrTop;
 
- 							minLeft = nodeOffset.left * -1 + winSize.scrLeft;
 
- 						}
 
- 						css = {
 
- 							top  : outerSize.height >= winSize.height? minTop  : Math.max(minTop, parseInt((elfNode.height() - outerSize.height)/2 - 42)),
 
- 							left : outerSize.width  >= winSize.width ? minLeft : Math.max(minLeft, parseInt((elfNode.width() - outerSize.width)/2))
 
- 						};
 
- 						if (outerSize.right + css.left > winSize.right) {
 
- 							css.left = Math.max(minLeft, winSize.right - outerSize.right);
 
- 						}
 
- 						if (outerSize.bottom + css.top > winSize.bottom) {
 
- 							css.top = Math.max(minTop, winSize.bottom - outerSize.bottom);
 
- 						}
 
- 					}
 
- 					if (opts.absolute) {
 
- 						css.position = 'absolute';
 
- 					}
 
- 					css && dialog.css(css);
 
- 				})
 
- 				.on('resize', function(e, data) {
 
- 					var oh = 0, init = data && data.init, h, minH;
 
- 					if ((data && (data.minimize || data.maxmize)) || dialog.data('minimized')) {
 
- 						return;
 
- 					}
 
- 					e.stopPropagation();
 
- 					e.preventDefault();
 
- 					dialog.children('.ui-widget-header,.ui-dialog-buttonpane').each(function() {
 
- 						oh += $(this).outerHeight(true);
 
- 					});
 
- 					if (!init && syncSize.enabled && !e.originalEvent && !dialog.hasClass('elfinder-maximized')) {
 
- 						h = Math.min(syncSize.defaultSize.height, Math.max(parseInt(dialog.css('max-height')), parseInt(dialog.css('min-height'))) - oh - dialog.data('margin-y'));
 
- 					} else {
 
- 						h = dialog.height() - oh - dialog.data('margin-y');
 
- 					}
 
- 					self.height(h);
 
- 					if (init) {
 
- 						return;
 
- 					}
 
- 					posCheck();
 
- 					minH = self.height();
 
- 					minH = (h < minH)? (minH + oh + dialog.data('margin-y')) : opts.minHeight;
 
- 					dialog.css('min-height', minH);
 
- 					dialog.data('hasResizable') && dialog.resizable('option', { minHeight: minH });
 
- 					if (typeof(opts.resize) === 'function') {
 
- 						$.proxy(opts.resize, self[0])(e, data);
 
- 					}
 
- 				})
 
- 				.on('tabstopsInit', tabstopsInit)
 
- 				.on('focus', '.'+cltabstop, function() {
 
- 					$(this).addClass(clhover).parent('label').addClass(clhover);
 
- 					this.id && $(this).parent().find('label[for='+this.id+']').addClass(clhover);
 
- 				})
 
- 				.on('click', 'select.'+cltabstop, function() {
 
- 					var node = $(this);
 
- 					node.data('keepFocus')? node.removeData('keepFocus') : node.data('keepFocus', true);
 
- 				})
 
- 				.on('blur', '.'+cltabstop, function() {
 
- 					$(this).removeClass(clhover).removeData('keepFocus').parent('label').removeClass(clhover);
 
- 					this.id && $(this).parent().find('label[for='+this.id+']').removeClass(clhover);
 
- 				})
 
- 				.on('mouseenter mouseleave', '.'+cltabstop+',label', function(e) {
 
- 					var $this = $(this), labelfor;
 
- 					if (this.nodeName === 'LABEL') {
 
- 						if (!$this.children('.'+cltabstop).length && (!(labelfor = $this.attr('for')) || !$('#'+labelfor).hasClass(cltabstop))) {
 
- 							return;
 
- 						}
 
- 					}
 
- 					if (opts.btnHoverFocus && dialog.data('focusOnMouseOver')) {
 
- 						if (e.type === 'mouseenter' && ! $(':focus').data('keepFocus')) {
 
- 							$this.trigger('focus');
 
- 						}
 
- 					} else {
 
- 						$this.toggleClass(clhover, e.type == 'mouseenter');
 
- 					}
 
- 				})
 
- 				.on('keydown', '.'+cltabstop, function(e) {
 
- 					var $this = $(this),
 
- 						esc, move, moveTo;
 
- 					if ($this.is(':focus')) {
 
- 						esc = e.keyCode === $.ui.keyCode.ESCAPE;
 
- 						if (e.keyCode === $.ui.keyCode.ENTER) {
 
- 							e.preventDefault();
 
- 							$this.trigger('click');
 
- 						}  else if (((e.keyCode === $.ui.keyCode.TAB) && e.shiftKey) || e.keyCode === $.ui.keyCode.LEFT || e.keyCode == $.ui.keyCode.UP) {
 
- 							move = 'prev';
 
- 						}  else if (e.keyCode === $.ui.keyCode.TAB || e.keyCode == $.ui.keyCode.RIGHT || e.keyCode == $.ui.keyCode.DOWN) {
 
- 							move = 'next';
 
- 						}
 
- 						if (move
 
- 								&&
 
- 							(
 
- 								($this.is('textarea') && !(e.ctrlKey || e.metaKey))
 
- 									||
 
- 								($this.is('select,span.ui-slider-handle') && e.keyCode !== $.ui.keyCode.TAB)
 
- 									||
 
- 								($this.is('input:not(:checkbox,:radio)') && (!(e.ctrlKey || e.metaKey) && e.keyCode === $.ui.keyCode[move === 'prev'? 'LEFT':'RIGHT']))
 
- 							)
 
- 						) {
 
- 							e.stopPropagation();
 
- 							return;
 
- 						}
 
- 						if (!esc) {
 
- 							e.stopPropagation();
 
- 						} else if ($this.is('input:not(:checkbox,:radio),textarea')) {
 
- 							if ($this.val() !== '') {
 
- 								$this.val('');
 
- 								e.stopPropagation();
 
- 							}
 
- 						}
 
- 						if (move) {
 
- 							e.preventDefault();
 
- 							(move === 'prev'? tabstopPrev : tabstopNext)(this).trigger('focus');
 
- 						}
 
- 					}
 
- 				})
 
- 				.data({modal: opts.modal}),
 
- 			posCheck = function() {
 
- 				var node = fm.getUI(),
 
- 					pos;
 
- 				if (node.hasClass('elfinder-fullscreen')) {
 
- 					pos = dialog.position();
 
- 					dialog.css('top', Math.max(Math.min(Math.max(pos.top, 0), node.height() - 100), 0));
 
- 					dialog.css('left', Math.max(Math.min(Math.max(pos.left, 0), node.width() - 200), 0));
 
- 				}
 
- 			},
 
- 			maxSize, toFocusNode;
 
- 		
 
- 		dialog.prepend(titlebar);
 
- 		makeHeaderBtn();
 
- 		$.each(opts.buttons, function(name, cb) {
 
- 			var button = $('<button type="button" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only '
 
- 					+'elfinder-btncnt-'+(btnCnt++)+' '
 
- 					+cltabstop
 
- 					+'"><span class="ui-button-text">'+name+'</span></button>')
 
- 				.on('click', $.proxy(cb, self[0]));
 
- 			if (cb._cssClass) {
 
- 				button.addClass(cb._cssClass);
 
- 			}
 
- 			if (platformWin) {
 
- 				buttonset.append(button);
 
- 			} else {
 
- 				buttonset.prepend(button);
 
- 			}
 
- 		});
 
- 		
 
- 		if (buttonset.children().length) {
 
- 			dialog.append(buttonpane);
 
- 			
 
- 			dialog.show();
 
- 			buttonpane.find('button').each(function(i, btn) {
 
- 				btnWidth += $(btn).outerWidth(true);
 
- 			});
 
- 			dialog.hide();
 
- 			btnWidth += 20;
 
- 			
 
- 			if (dialog.width() < btnWidth) {
 
- 				dialog.width(btnWidth);
 
- 			}
 
- 		}
 
- 		
 
- 		dialog.append(evCover);
 
- 		
 
- 		if (syncSize.enabled) {
 
- 			delta.width = dialog.outerWidth(true) - dialog.width() + ((dialog.outerWidth() - dialog.width()) / 2);
 
- 			delta.height = dialog.outerHeight(true) - dialog.height() + ((dialog.outerHeight() - dialog.height()) / 2);
 
- 		}
 
- 		
 
- 		if (fm.options.dialogContained) {
 
- 			maxSize = {
 
- 				maxWidth: elfNode.width() - delta.width,
 
- 				maxHeight: elfNode.height() - delta.height
 
- 			};
 
- 			opts.maxWidth = opts.maxWidth? Math.min(maxSize.maxWidth, opts.maxWidth) : maxSize.maxWidth;
 
- 			opts.maxHeight = opts.maxHeight? Math.min(maxSize.maxHeight, opts.maxHeight) : maxSize.maxHeight;
 
- 			dialog.css(maxSize);
 
- 		}
 
- 		
 
- 		restoreStyle = {
 
- 			maxWidth  : dialog.css('max-width'),
 
- 			maxHeight : dialog.css('max-height'),
 
- 			overflow   : dialog.css('overflow')
 
- 		};
 
- 		
 
- 		if (opts.resizable) {
 
- 			dialog.resizable({
 
- 				minWidth   : opts.minWidth,
 
- 				minHeight  : opts.minHeight,
 
- 				maxWidth   : opts.maxWidth,
 
- 				maxHeight  : opts.maxHeight,
 
- 				start      : function() {
 
- 					evCover.show();
 
- 					if (dialog.data('resizing') !== true && dialog.data('resizing')) {
 
- 						clearTimeout(dialog.data('resizing'));
 
- 					}
 
- 					dialog.data('resizing', true);
 
- 				},
 
- 				stop       : function(e, ui) {
 
- 					evCover.hide();
 
- 					dialog.data('resizing', setTimeout(function() {
 
- 						dialog.data('resizing', false);
 
- 					}, 200));
 
- 					if (syncSize.enabled) {
 
- 						syncSize.defaultSize = { width: self.width(), height: self.height() };
 
- 					}
 
- 				}
 
- 			}).data('hasResizable', true);
 
- 		} 
 
- 		
 
- 		numberToTel();
 
- 		
 
- 		tabstopsInit();
 
- 		
 
- 		typeof(opts.create) == 'function' && $.proxy(opts.create, this)();
 
- 		
 
- 		if (opts.autoOpen) {
 
- 			if (opts.open) {
 
- 				requestAnimationFrame(function() {
 
- 					self.elfinderdialog('open');
 
- 				});
 
- 			} else {
 
- 				self.elfinderdialog('open');
 
- 			}
 
- 		}
 
- 		if (opts.resize) {
 
- 			fm.bind('themechange', function() {
 
- 				setTimeout(function() {
 
- 					dialog.data('margin-y', self.outerHeight(true) - self.height());
 
- 					dialog.trigger('resize', {init: true});
 
- 				}, 300);
 
- 			});
 
- 		}
 
- 	});
 
- 	
 
- 	return this;
 
- };
 
- $.fn.elfinderdialog.defaults = {
 
- 	cssClass  : '',
 
- 	title     : '',
 
- 	modal     : false,
 
- 	resizable : true,
 
- 	autoOpen  : true,
 
- 	closeOnEscape : true,
 
- 	destroyOnClose : false,
 
- 	buttons   : {},
 
- 	btnHoverFocus : true,
 
- 	position  : null,
 
- 	absolute  : false,
 
- 	width     : 320,
 
- 	height    : 'auto',
 
- 	minWidth  : 200,
 
- 	minHeight : 70,
 
- 	maxWidth  : null,
 
- 	maxHeight : null,
 
- 	allowMinimize : 'auto',
 
- 	allowMaximize : false,
 
- 	openMaximized : false,
 
- 	headerBtnPos : 'auto',
 
- 	headerBtnOrder : 'auto',
 
- 	optimizeNumber : true,
 
- 	propagationEvents : ['mousemove', 'mouseup']
 
- };
 
- /*
 
-  * File: /js/ui/fullscreenbutton.js
 
-  */
 
- /**
 
-  * @class  elFinder toolbar button to switch full scrren mode.
 
-  *
 
-  * @author Naoki Sawada
 
-  **/
 
- $.fn.elfinderfullscreenbutton = function(cmd) {
 
- 		return this.each(function() {
 
- 		var button = $(this).elfinderbutton(cmd),
 
- 			icon   = button.children('.elfinder-button-icon'),
 
- 			tm;
 
- 		cmd.change(function() {
 
- 			tm && cancelAnimationFrame(tm);
 
- 			tm = requestAnimationFrame(function() {
 
- 				var fullscreen = cmd.value;
 
- 				icon.addClass('elfinder-button-icon-fullscreen').toggleClass('elfinder-button-icon-unfullscreen', fullscreen);
 
- 				cmd.className = fullscreen? 'unfullscreen' : '';
 
- 			});
 
- 		});
 
- 	});
 
- };
 
- /*
 
-  * File: /js/ui/navbar.js
 
-  */
 
- /**
 
-  * @class elfindernav - elFinder container for diretories tree and places
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.elfindernavbar = function(fm, opts) {
 
- 		this.not('.elfinder-navbar').each(function() {
 
- 		var nav    = $(this).hide().addClass('ui-state-default elfinder-navbar'),
 
- 			parent = nav.css('overflow', 'hidden').parent(),
 
- 			wz     = parent.children('.elfinder-workzone').append(nav),
 
- 			ltr    = fm.direction == 'ltr',
 
- 			delta, deltaW, handle, swipeHandle, autoHide, setWidth, navdock,
 
- 			setWzRect = function() {
 
- 				var cwd = fm.getUI('cwd'),
 
- 					wz  = fm.getUI('workzone'),
 
- 					wzRect = wz.data('rectangle'),
 
- 					cwdOffset = cwd.offset();
 
- 				wz.data('rectangle', Object.assign(wzRect, { cwdEdge: (fm.direction === 'ltr')? cwdOffset.left : cwdOffset.left + cwd.width() }));
 
- 			},
 
- 			setDelta = function() {
 
- 				nav.css('overflow', 'hidden');
 
- 				delta  = Math.round(nav.outerHeight() - nav.height());
 
- 				deltaW = Math.round(navdock.outerWidth() - navdock.innerWidth());
 
- 				nav.css('overflow', 'auto');
 
- 			};
 
- 		fm.one('init', function() {
 
- 			var set = function() {
 
- 				navdock =fm.getUI('navdock');
 
- 				setDelta();
 
- 				fm.trigger('wzresize');
 
- 			};
 
- 			fm.bind('wzresize', function() {
 
- 				var navdockH = 0;
 
- 				navdock.width(nav.outerWidth() - deltaW);
 
- 				if (navdock.children().length > 1) {
 
- 					navdockH = navdock.outerHeight(true);
 
- 				}
 
- 				nav.height(wz.height() - navdockH - delta);
 
- 			});
 
- 			if (fm.cssloaded) {
 
- 				set();
 
- 			} else {
 
- 				fm.one('cssloaded', set);
 
- 			}
 
- 		})
 
- 		.one('opendone',function() {
 
- 			handle && handle.trigger('resize');
 
- 			nav.css('overflow', 'auto');
 
- 		}).bind('themechange', setDelta);
 
- 		
 
- 		if (fm.UA.Touch) {
 
- 			autoHide = fm.storage('autoHide') || {};
 
- 			if (typeof autoHide.navbar === 'undefined') {
 
- 				autoHide.navbar = (opts.autoHideUA && opts.autoHideUA.length > 0 && $.grep(opts.autoHideUA, function(v){ return fm.UA[v]? true : false; }).length);
 
- 				fm.storage('autoHide', autoHide);
 
- 			}
 
- 			
 
- 			if (autoHide.navbar) {
 
- 				fm.one('init', function() {
 
- 					if (nav.children().length) {
 
- 						fm.uiAutoHide.push(function(){ nav.stop(true, true).trigger('navhide', { duration: 'slow', init: true }); });
 
- 					}
 
- 				});
 
- 			}
 
- 			
 
- 			fm.bind('load', function() {
 
- 				if (nav.children().length) {
 
- 					swipeHandle = $('<div class="elfinder-navbar-swipe-handle"/>').hide().appendTo(wz);
 
- 					if (swipeHandle.css('pointer-events') !== 'none') {
 
- 						swipeHandle.remove();
 
- 						swipeHandle = null;
 
- 					}
 
- 				}
 
- 			});
 
- 			
 
- 			nav.on('navshow navhide', function(e, data) {
 
- 				var mode     = (e.type === 'navshow')? 'show' : 'hide',
 
- 					duration = (data && data.duration)? data.duration : 'fast',
 
- 					handleW = (data && data.handleW)? data.handleW : Math.max(50, fm.getUI().width() / 10);
 
- 				nav.stop(true, true)[mode]({
 
- 					duration: duration,
 
- 					step    : function() {
 
- 						fm.trigger('wzresize');
 
- 					},
 
- 					complete: function() {
 
- 						if (swipeHandle) {
 
- 							if (mode === 'show') {
 
- 								swipeHandle.stop(true, true).hide();
 
- 							} else {
 
- 								swipeHandle.width(handleW? handleW : '');
 
- 								fm.resources.blink(swipeHandle, 'slowonce');
 
- 							}
 
- 						}
 
- 						fm.trigger('navbar'+ mode);
 
- 						data.init && fm.trigger('uiautohide');
 
- 						setWzRect();
 
- 					}
 
- 				});
 
- 				autoHide.navbar = (mode !== 'show');
 
- 				fm.storage('autoHide', Object.assign(fm.storage('autoHide'), {navbar: autoHide.navbar}));
 
- 			}).on('touchstart', function(e) {
 
- 				if ($(this)['scroll' + (fm.direction === 'ltr'? 'Right' : 'Left')]() > 5) {
 
- 					e.originalEvent._preventSwipeX = true;
 
- 				}
 
- 			});
 
- 		}
 
- 		
 
- 		if (! fm.UA.Mobile) {
 
- 			handle = nav.resizable({
 
- 					handles : ltr ? 'e' : 'w',
 
- 					minWidth : opts.minWidth || 150,
 
- 					maxWidth : opts.maxWidth || 500,
 
- 					resize : function() {
 
- 						fm.trigger('wzresize');
 
- 					},
 
- 					stop : function(e, ui) {
 
- 						fm.storage('navbarWidth', ui.size.width);
 
- 						setWzRect();
 
- 					}
 
- 				})
 
- 				.on('resize scroll', function(e) {
 
- 					var $this = $(this),
 
- 						tm = $this.data('posinit');
 
- 					e.preventDefault();
 
- 					e.stopPropagation();
 
- 					if (! ltr && e.type === 'resize') {
 
- 						nav.css('left', 0);
 
- 					}
 
- 					tm && cancelAnimationFrame(tm);
 
- 					$this.data('posinit', requestAnimationFrame(function() {
 
- 						var offset = (fm.UA.Opera && nav.scrollLeft())? 20 : 2;
 
- 						handle.css('top', 0).css({
 
- 							top  : parseInt(nav.scrollTop())+'px',
 
- 							left : ltr ? 'auto' : parseInt(nav.scrollRight() -  offset) * -1,
 
- 							right: ltr ? parseInt(nav.scrollLeft() - offset) * -1 : 'auto'
 
- 						});
 
- 						if (e.type === 'resize') {
 
- 							fm.getUI('cwd').trigger('resize');
 
- 						}
 
- 					}));
 
- 				})
 
- 				.children('.ui-resizable-handle').addClass('ui-front');
 
- 		}
 
- 		if (setWidth = fm.storage('navbarWidth')) {
 
- 			nav.width(setWidth);
 
- 		} else {
 
- 			if (fm.UA.Mobile) {
 
- 				fm.one('cssloaded', function() {
 
- 					var set = function() {
 
- 						setWidth = nav.parent().width() / 2;
 
- 						if (nav.data('defWidth') > setWidth) {
 
- 							nav.width(setWidth);
 
- 						} else {
 
- 							nav.width(nav.data('defWidth'));
 
- 						}
 
- 						nav.data('width', nav.width());
 
- 						fm.trigger('wzresize');
 
- 					};
 
- 					nav.data('defWidth', nav.width());
 
- 					$(window).on('resize.' + fm.namespace, set);
 
- 					set();
 
- 				});
 
- 			}
 
- 		}
 
- 	});
 
- 	
 
- 	return this;
 
- };
 
- /*
 
-  * File: /js/ui/navdock.js
 
-  */
 
- /**
 
-  * @class elfindernavdock - elFinder container for preview etc at below the navbar
 
-  *
 
-  * @author Naoki Sawada
 
-  **/
 
- $.fn.elfindernavdock = function(fm, opts) {
 
- 		this.not('.elfinder-navdock').each(function() {
 
- 		var self = $(this).hide().addClass('ui-state-default elfinder-navdock touch-punch'),
 
- 			node = self.parent(),
 
- 			wz   = node.children('.elfinder-workzone').append(self),
 
- 			resize = function(to, h) {
 
- 				var curH = h || self.height(),
 
- 					diff = to - curH,
 
- 					len  = Object.keys(sizeSyncs).length,
 
- 					calc = len? diff / len : 0,
 
- 					ovf;
 
- 				if (diff) {
 
- 					ovf = self.css('overflow');
 
- 					self.css('overflow', 'hidden');
 
- 					self.height(to);
 
- 					$.each(sizeSyncs, function(id, n) {
 
- 						n.height(n.height() + calc).trigger('resize.' + fm.namespace);
 
- 					});
 
- 					fm.trigger('wzresize');
 
- 					self.css('overflow', ovf);
 
- 				}
 
- 			},
 
- 			handle = $('<div class="ui-front ui-resizable-handle ui-resizable-n"/>').appendTo(self),
 
- 			sizeSyncs = {},
 
- 			resizeFn = [],
 
- 			initMaxHeight = (parseInt(opts.initMaxHeight) || 50) / 100,
 
- 			maxHeight = (parseInt(opts.maxHeight) || 90) / 100,
 
- 			basicHeight, hasNode;
 
- 		
 
- 		
 
- 		self.data('addNode', function(cNode, opts) {
 
- 			var wzH = fm.getUI('workzone').height(),
 
- 				imaxH = wzH * initMaxHeight,
 
- 				curH, tH, mH;
 
- 			opts = Object.assign({
 
- 				first: false,
 
- 				sizeSync: true,
 
- 				init: false
 
- 			}, opts);
 
- 			if (!cNode.attr('id')) {
 
- 				cNode.attr('id', fm.namespace+'-navdock-' + (+new Date()));
 
- 			}
 
- 			opts.sizeSync && (sizeSyncs[cNode.attr('id')] = cNode);
 
- 			curH = self.height();
 
- 			tH = curH + cNode.outerHeight(true);
 
- 			
 
- 			if (opts.first) {
 
- 				handle.after(cNode);
 
- 			} else {
 
- 				self.append(cNode);
 
- 			}
 
- 			hasNode = true;
 
- 			self.resizable('enable').height(tH).show();
 
- 			
 
- 			fm.trigger('wzresize');
 
- 			
 
- 			if (opts.init) {
 
- 				mH = fm.storage('navdockHeight');
 
- 				if (mH) {
 
- 					tH = mH;
 
- 				} else {
 
- 					tH = tH > imaxH? imaxH : tH;
 
- 				}
 
- 				basicHeight = tH;
 
- 			}
 
- 			resize(Math.min(tH, wzH * maxHeight));
 
- 			
 
- 			return self;
 
- 		}).data('removeNode', function(nodeId, appendTo) {
 
- 			var cNode = $('#'+nodeId);
 
- 			delete sizeSyncs[nodeId];
 
- 			self.height(self.height() - $('#'+nodeId).outerHeight(true));
 
- 			if (appendTo) {
 
- 				if (appendTo === 'detach') {
 
- 					cNode = cNode.detach();
 
- 				} else {
 
- 					appendTo.append(cNode);
 
- 				}
 
- 			} else {
 
- 				cNode.remove();
 
- 			}
 
- 			if (self.children().length <= 1) {
 
- 				hasNode = false;
 
- 				self.resizable('disable').height(0).hide();
 
- 			}
 
- 			fm.trigger('wzresize');
 
- 			return cNode;
 
- 		});
 
- 		
 
- 		if (! opts.disabled) {
 
- 			fm.one('init', function() {
 
- 				var ovf;
 
- 				if (fm.getUI('navbar').children().not('.ui-resizable-handle').length) {
 
- 					self.data('dockEnabled', true);
 
- 					self.resizable({
 
- 						maxHeight: fm.getUI('workzone').height() * maxHeight,
 
- 						handles: { n: handle },
 
- 						start: function(e, ui) {
 
- 							ovf = self.css('overflow');
 
- 							self.css('overflow', 'hidden');
 
- 							fm.trigger('navdockresizestart', {event: e, ui: ui}, true);
 
- 						},
 
- 						resize: function(e, ui) {
 
- 							self.css('top', '');
 
- 							fm.trigger('wzresize', { inNavdockResize : true });
 
- 						},
 
- 						stop: function(e, ui) {
 
- 							fm.trigger('navdockresizestop', {event: e, ui: ui}, true);
 
- 							self.css('top', '');
 
- 							basicHeight = ui.size.height;
 
- 							fm.storage('navdockHeight', basicHeight);
 
- 							resize(basicHeight, ui.originalSize.height);
 
- 							self.css('overflow', ovf);
 
- 						}
 
- 					});
 
- 					fm.bind('wzresize', function(e) {
 
- 						var minH, maxH, h;
 
- 						if (self.is(':visible')) {
 
- 							maxH = fm.getUI('workzone').height() * maxHeight;
 
- 							if (! e.data || ! e.data.inNavdockResize) {
 
- 								h = self.height();
 
- 								if (maxH < basicHeight) {
 
- 									if (Math.abs(h - maxH) > 1) {
 
- 										resize(maxH);
 
- 									}
 
- 								} else {
 
- 									if (Math.abs(h - basicHeight) > 1) {
 
- 										resize(basicHeight);
 
- 									}
 
- 								}
 
- 							}
 
- 							self.resizable('option', 'maxHeight', maxH);
 
- 						}
 
- 					}).bind('themechange', function() {
 
- 						var oldH = Math.round(self.height());
 
- 						requestAnimationFrame(function() {
 
- 							var curH = Math.round(self.height()),
 
- 								diff = oldH - curH;
 
- 							if (diff !== 0) {
 
- 								resize(self.height(),  curH - diff);
 
- 							}
 
- 						});
 
- 					});
 
- 				}
 
- 				fm.bind('navbarshow navbarhide', function(e) {
 
- 					self[hasNode && e.type === 'navbarshow'? 'show' : 'hide']();
 
- 				});
 
- 			});
 
- 		}
 
- 	});
 
- 	return this;
 
- };
 
- /*
 
-  * File: /js/ui/overlay.js
 
-  */
 
- $.fn.elfinderoverlay = function(opts) {
 
- 		var fm = this.parent().elfinder('instance'),
 
- 		o, cnt, show, hide;
 
- 	
 
- 	this.filter(':not(.elfinder-overlay)').each(function() {
 
- 		opts = Object.assign({}, opts);
 
- 		$(this).addClass('ui-front ui-widget-overlay elfinder-overlay')
 
- 			.hide()
 
- 			.on('mousedown', function(e) {
 
- 				e.preventDefault();
 
- 				e.stopPropagation();
 
- 			})
 
- 			.data({
 
- 				cnt  : 0,
 
- 				show : typeof(opts.show) == 'function' ? opts.show : function() { },
 
- 				hide : typeof(opts.hide) == 'function' ? opts.hide : function() { }
 
- 			});
 
- 	});
 
- 	
 
- 	if (opts == 'show') {
 
- 		o    = this.eq(0);
 
- 		cnt  = o.data('cnt') + 1;
 
- 		show = o.data('show');
 
- 		fm.toFront(o);
 
- 		o.data('cnt', cnt);
 
- 		if (o.is(':hidden')) {
 
- 			o.show();
 
- 			show();
 
- 		}
 
- 	} 
 
- 	
 
- 	if (opts == 'hide') {
 
- 		o    = this.eq(0);
 
- 		cnt  = o.data('cnt') - 1;
 
- 		hide = o.data('hide');
 
- 		
 
- 		o.data('cnt', cnt);
 
- 			
 
- 		if (cnt <= 0) {
 
- 			o.hide();
 
- 			hide();
 
- 		}
 
- 	}
 
- 	
 
- 	return this;
 
- };
 
- /*
 
-  * File: /js/ui/panel.js
 
-  */
 
- $.fn.elfinderpanel = function(fm) {
 
- 		return this.each(function() {
 
- 		var panel = $(this).addClass('elfinder-panel ui-state-default ui-corner-all'),
 
- 			margin = 'margin-'+(fm.direction == 'ltr' ? 'left' : 'right');
 
- 		
 
- 		fm.one('load', function(e) {
 
- 			var navbar = fm.getUI('navbar');
 
- 			
 
- 			panel.css(margin, parseInt(navbar.outerWidth(true)));
 
- 			navbar.on('resize', function(e) {
 
- 				e.preventDefault();
 
- 				e.stopPropagation();
 
- 				panel.is(':visible') && panel.css(margin, parseInt(navbar.outerWidth(true)));
 
- 			});
 
- 		});
 
- 	});
 
- };
 
- /*
 
-  * File: /js/ui/path.js
 
-  */
 
- /**
 
-  * @class elFinder ui
 
-  * Display current folder path in statusbar.
 
-  * Click on folder name in path - open folder
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.elfinderpath = function(fm, options) {
 
- 		return this.each(function() {
 
- 		var query  = '',
 
- 			target = '',
 
- 			mimes  = [],
 
- 			place  = 'statusbar',
 
- 			clHover= fm.res('class', 'hover'),
 
- 			prefix = 'path' + (elFinder.prototype.uniqueid? elFinder.prototype.uniqueid : '') + '-',
 
- 			wzbase = $('<div class="ui-widget-header ui-helper-clearfix elfinder-workzone-path"/>'),
 
- 			path   = $(this).addClass('elfinder-path').html(' ')
 
- 				.on('mousedown', 'span.elfinder-path-dir', function(e) {
 
- 					var hash = $(this).attr('id').substr(prefix.length);
 
- 					e.preventDefault();
 
- 					if (hash != fm.cwd().hash) {
 
- 						$(this).addClass(clHover);
 
- 						if (query) {
 
- 							fm.exec('search', query, { target: hash, mime: mimes.join(' ') });
 
- 						} else {
 
- 							fm.trigger('select', {selected : [hash]}).exec('open', hash);
 
- 						}
 
- 					}
 
- 				})
 
- 				.prependTo(fm.getUI('statusbar').show()),
 
- 			roots = $('<div class="elfinder-path-roots"/>').on('click', function(e) {
 
- 				e.stopPropagation();
 
- 				e.preventDefault();
 
- 				
 
- 				var roots = $.map(fm.roots, function(h) { return fm.file(h); }),
 
- 				raw = [];
 
- 				$.each(roots, function(i, f) {
 
- 					if (! f.phash && fm.root(fm.cwd().hash, true) !== f.hash) {
 
- 						raw.push({
 
- 							label    : fm.escape(f.i18 || f.name),
 
- 							icon     : 'home',
 
- 							callback : function() { fm.exec('open', f.hash); },
 
- 							options  : {
 
- 								iconClass : f.csscls || '',
 
- 								iconImg   : f.icon   || ''
 
- 							}
 
- 						});
 
- 					}
 
- 				});
 
- 				fm.trigger('contextmenu', {
 
- 					raw: raw,
 
- 					x: e.pageX,
 
- 					y: e.pageY
 
- 				});
 
- 			}).append('<span class="elfinder-button-icon elfinder-button-icon-menu" />').appendTo(wzbase),
 
- 			render = function(cwd) {
 
- 				var dirs = [],
 
- 					names = [];
 
- 				$.each(fm.parents(cwd), function(i, hash) {
 
- 					var c = (cwd === hash)? 'elfinder-path-dir elfinder-path-cwd' : 'elfinder-path-dir',
 
- 						f = fm.file(hash),
 
- 						name = fm.escape(f.i18 || f.name);
 
- 					names.push(name);
 
- 					dirs.push('<span id="'+prefix+hash+'" class="'+c+'" title="'+names.join(fm.option('separator'))+'">'+name+'</span>');
 
- 				});
 
- 				return dirs.join('<span class="elfinder-path-other">'+fm.option('separator')+'</span>');
 
- 			},
 
- 			toWorkzone = function() {
 
- 				var prev;
 
- 				path.children('span.elfinder-path-dir').attr('style', '');
 
- 				prev = fm.direction === 'ltr'? $('#'+prefix + fm.cwd().hash).prevAll('span.elfinder-path-dir:first') : $();
 
- 				path.scrollLeft(prev.length? prev.position().left : 0);
 
- 			},
 
- 			fit = function() {
 
- 				if (fm.UA.CSS.flex) {
 
- 					return;
 
- 				}
 
- 				var dirs = path.children('span.elfinder-path-dir'),
 
- 					cnt  = dirs.length,
 
- 					m, bg = 0, ids;
 
- 				
 
- 				if (place === 'workzone' || cnt < 2) {
 
- 					dirs.attr('style', '');
 
- 					return;
 
- 				}
 
- 				path.width(path.css('max-width'));
 
- 				dirs.css({maxWidth: (100/cnt)+'%', display: 'inline-block'});
 
- 				m = path.width() - 9;
 
- 				path.children('span.elfinder-path-other').each(function() {
 
- 					m -= $(this).width();
 
- 				});
 
- 				ids = [];
 
- 				dirs.each(function(i) {
 
- 					var dir = $(this),
 
- 						w   = dir.width();
 
- 					m -= w;
 
- 					if (w < this.scrollWidth) {
 
- 						ids.push(i);
 
- 					}
 
- 				});
 
- 				path.width('');
 
- 				if (ids.length) {
 
- 					if (m > 0) {
 
- 						m = m / ids.length;
 
- 						$.each(ids, function(i, k) {
 
- 							var d = $(dirs[k]);
 
- 							d.css('max-width', d.width() + m);
 
- 						});
 
- 					}
 
- 					dirs.last().attr('style', '');
 
- 				} else {
 
- 					dirs.attr('style', '');
 
- 				}
 
- 			},
 
- 			hasUiTree, hasUiStat;
 
- 		fm.one('init', function() {
 
- 			hasUiTree = fm.getUI('tree').length;
 
- 			hasUiStat = fm.getUI('stat').length;
 
- 			if (! hasUiTree && options.toWorkzoneWithoutNavbar) {
 
- 				wzbase.append(path).insertBefore(fm.getUI('workzone'));
 
- 				place = 'workzone';
 
- 				fm.bind('open', toWorkzone)
 
- 				.one('opendone', function() {
 
- 					fm.getUI().trigger('resize');
 
- 				});
 
- 			}
 
- 		})
 
- 		.bind('open searchend parents', function() {
 
- 			var dirs = [];
 
- 			query  = '';
 
- 			target = '';
 
- 			mimes  = [];
 
- 			
 
- 			path.html(render(fm.cwd().hash));
 
- 			if (Object.keys(fm.roots).length > 1) {
 
- 				path.css('margin', '');
 
- 				roots.show();
 
- 			} else {
 
- 				path.css('margin', 0);
 
- 				roots.hide();
 
- 			}
 
- 			!hasUiStat && fit();
 
- 		})
 
- 		.bind('searchstart', function(e) {
 
- 			if (e.data) {
 
- 				query  = e.data.query || '';
 
- 				target = e.data.target || '';
 
- 				mimes  = e.data.mimes || [];
 
- 			}
 
- 		})
 
- 		.bind('search', function(e) {
 
- 			var dirs = [],
 
- 				html = '';
 
- 			if (target) {
 
- 				html = render(target);
 
- 			} else {
 
- 				html = fm.i18n('btnAll');
 
- 			}
 
- 			path.html('<span class="elfinder-path-other">'+fm.i18n('searcresult') + ': </span>' + html);
 
- 			fit();
 
- 		})
 
- 		// on swipe to navbar show/hide
 
- 		.bind('navbarshow navbarhide', function() {
 
- 			var wz = fm.getUI('workzone');
 
- 			if (this.type === 'navbarshow') {
 
- 				fm.unbind('open', toWorkzone);
 
- 				path.prependTo(fm.getUI('statusbar'));
 
- 				wzbase.detach();
 
- 				place = 'statusbar';
 
- 			} else {
 
- 				wzbase.append(path).insertBefore(wz);
 
- 				place = 'workzone';
 
- 				toWorkzone();
 
- 				fm.bind('open', toWorkzone);
 
- 			}
 
- 			fm.trigger('uiresize');
 
- 		})
 
- 		.bind('resize uistatchange', fit);
 
- 	});
 
- };
 
- /*
 
-  * File: /js/ui/places.js
 
-  */
 
- /**
 
-  * @class elFinder places/favorites ui
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  * @author Naoki Sawada
 
-  **/
 
- $.fn.elfinderplaces = function(fm, opts) {
 
- 		return this.each(function() {
 
- 		var dirs      = {},
 
- 			c         = 'class',
 
- 			navdir    = fm.res(c, 'navdir'),
 
- 			collapsed = fm.res(c, 'navcollapse'),
 
- 			expanded  = fm.res(c, 'navexpand'),
 
- 			hover     = fm.res(c, 'hover'),
 
- 			clroot    = fm.res(c, 'treeroot'),
 
- 			dropover  = fm.res(c, 'adroppable'),
 
- 			tpl       = fm.res('tpl', 'placedir'),
 
- 			ptpl      = fm.res('tpl', 'perms'),
 
- 			spinner   = $(fm.res('tpl', 'navspinner')),
 
- 			suffix    = opts.suffix? opts.suffix : '',
 
- 			key       = 'places' + suffix,
 
- 			menuTimer = null,
 
- 			/**
 
- 			 * Convert places dir node into dir hash
 
- 			 *
 
- 			 * @param  String  directory id
 
- 			 * @return String
 
- 			 **/
 
- 			id2hash   = function(id) { return id.substr(6);	},
 
- 			/**
 
- 			 * Convert places dir node into dir hash
 
- 			 *
 
- 			 * @param  String  directory id
 
- 			 * @return String
 
- 			 **/
 
- 			hash2id   = function(hash) { return 'place-'+hash; },
 
- 			
 
- 			/**
 
- 			 * Save current places state
 
- 			 *
 
- 			 * @return void
 
- 			 **/
 
- 			save      = function() {
 
- 				var hashes = [], data = {};
 
- 				
 
- 				hashes = $.map(subtree.children().find('[id]'), function(n) {
 
- 					return id2hash(n.id);
 
- 				});
 
- 				if (hashes.length) {
 
- 					$.each(hashes.reverse(), function(i, h) {
 
- 						data[h] = dirs[h];
 
- 					});
 
- 				} else {
 
- 					data = null;
 
- 				}
 
- 				
 
- 				fm.storage(key, data);
 
- 			},
 
- 			/**
 
- 			 * Init dir at places
 
- 			 *
 
- 			 * @return void
 
- 			 **/
 
- 			init = function() {
 
- 				var dat, hashes;
 
- 				key = 'places'+(opts.suffix? opts.suffix : ''),
 
- 				dirs = {};
 
- 				dat = fm.storage(key);
 
- 				if (typeof dat === 'string') {
 
- 					// old data type elFinder <= 2.1.12
 
- 					dat = $.grep(dat.split(','), function(hash) { return hash? true : false;});
 
- 					$.each(dat, function(i, d) {
 
- 						var dir = d.split('#');
 
- 						dirs[dir[0]] = dir[1]? dir[1] : dir[0];
 
- 					});
 
- 				} else if ($.isPlainObject(dat)) {
 
- 					dirs = dat;
 
- 				}
 
- 				// allow modify `dirs`
 
- 				/**
 
- 				 * example for preset places
 
- 				 * 
 
- 				 * elfinderInstance.bind('placesload', function(e, fm) {
 
- 				 * 	//if (fm.storage(e.data.storageKey) === null) { // for first time only
 
- 				 * 	if (!fm.storage(e.data.storageKey)) {           // for empty places
 
- 				 * 		e.data.dirs[targetHash] = fallbackName;     // preset folder
 
- 				 * 	}
 
- 				 * }
 
- 				 **/
 
- 				fm.trigger('placesload', {dirs: dirs, storageKey: key}, true);
 
- 				
 
- 				hashes = Object.keys(dirs);
 
- 				if (hashes.length) {
 
- 					root.prepend(spinner);
 
- 					
 
- 					fm.request({
 
- 						data : {cmd : 'info', targets : hashes},
 
- 						preventDefault : true
 
- 					})
 
- 					.done(function(data) {
 
- 						var exists = {};
 
- 						
 
- 						data.files && data.files.length && fm.cache(data.files);
 
- 						
 
- 						$.each(data.files, function(i, f) {
 
- 							var hash = f.hash;
 
- 							exists[hash] = f;
 
- 						});
 
- 						$.each(dirs, function(h, f) {
 
- 							add(exists[h] || Object.assign({notfound: true}, f));
 
- 						});
 
- 						if (fm.storage('placesState') > 0) {
 
- 							root.trigger('click');
 
- 						}
 
- 					})
 
- 					.always(function() {
 
- 						spinner.remove();
 
- 					});
 
- 				}
 
- 			},
 
- 			/**
 
- 			 * Return node for given dir object
 
- 			 *
 
- 			 * @param  Object  directory object
 
- 			 * @return jQuery
 
- 			 **/
 
- 			create    = function(dir, hash) {
 
- 				return $(tpl.replace(/\{id\}/, hash2id(dir? dir.hash : hash))
 
- 						.replace(/\{name\}/, fm.escape(dir? dir.i18 || dir.name : hash))
 
- 						.replace(/\{cssclass\}/, dir? (fm.perms2class(dir) + (dir.notfound? ' elfinder-na' : '') + (dir.csscls? ' '+dir.csscls : '')) : '')
 
- 						.replace(/\{permissions\}/, (dir && (!dir.read || !dir.write || dir.notfound))? ptpl : '')
 
- 						.replace(/\{title\}/, (dir && dir.path)? fm.escape(dir.path) : '')
 
- 						.replace(/\{symlink\}/, '')
 
- 						.replace(/\{style\}/, (dir && dir.icon)? fm.getIconStyle(dir) : ''));
 
- 			},
 
- 			/**
 
- 			 * Add new node into places
 
- 			 *
 
- 			 * @param  Object  directory object
 
- 			 * @return void
 
- 			 **/
 
- 			add = function(dir) {
 
- 				var node, hash;
 
- 				if (dir.mime !== 'directory') {
 
- 					return false;
 
- 				}
 
- 				hash = dir.hash;
 
- 				if (!fm.files().hasOwnProperty(hash)) {
 
- 					// update cache
 
- 					fm.trigger('tree', {tree: [dir]});
 
- 				}
 
- 				
 
- 				node = create(dir, hash);
 
- 				
 
- 				dirs[hash] = dir;
 
- 				subtree.prepend(node);
 
- 				root.addClass(collapsed);
 
- 				sortBtn.toggle(subtree.children().length > 1);
 
- 				
 
- 				return true;
 
- 			},
 
- 			/**
 
- 			 * Remove dir from places
 
- 			 *
 
- 			 * @param  String  directory hash
 
- 			 * @return String  removed name
 
- 			 **/
 
- 			remove = function(hash) {
 
- 				var name = null, tgt, cnt;
 
- 				if (dirs[hash]) {
 
- 					delete dirs[hash];
 
- 					tgt = $('#'+hash2id(hash));
 
- 					if (tgt.length) {
 
- 						name = tgt.text();
 
- 						tgt.parent().remove();
 
- 						cnt = subtree.children().length;
 
- 						sortBtn.toggle(cnt > 1);
 
- 						if (! cnt) {
 
- 							root.removeClass(collapsed);
 
- 							places.removeClass(expanded);
 
- 							subtree.slideToggle(false);
 
- 						}
 
- 					}
 
- 				}
 
- 				
 
- 				return name;
 
- 			},
 
- 			/**
 
- 			 * Move up dir on places
 
- 			 *
 
- 			 * @param  String  directory hash
 
- 			 * @return void
 
- 			 **/
 
- 			moveup = function(hash) {
 
- 				var self = $('#'+hash2id(hash)),
 
- 					tgt  = self.parent(),
 
- 					prev = tgt.prev('div'),
 
- 					cls  = 'ui-state-hover',
 
- 					ctm  = fm.getUI('contextmenu');
 
- 				
 
- 				menuTimer && clearTimeout(menuTimer);
 
- 				
 
- 				if (prev.length) {
 
- 					ctm.find(':first').data('placesHash', hash);
 
- 					self.addClass(cls);
 
- 					tgt.insertBefore(prev);
 
- 					prev = tgt.prev('div');
 
- 					menuTimer = setTimeout(function() {
 
- 						self.removeClass(cls);
 
- 						if (ctm.find(':first').data('placesHash') === hash) {
 
- 							ctm.hide().empty();
 
- 						}
 
- 					}, 1500);
 
- 				}
 
- 				
 
- 				if(!prev.length) {
 
- 					self.removeClass(cls);
 
- 					ctm.hide().empty();
 
- 				}
 
- 			},
 
- 			/**
 
- 			 * Update dir at places
 
- 			 *
 
- 			 * @param  Object   directory
 
- 			 * @param  String   previous hash
 
- 			 * @return Boolean
 
- 			 **/
 
- 			update = function(dir, preHash) {
 
- 				var hash = dir.hash,
 
- 					tgt  = $('#'+hash2id(preHash || hash)),
 
- 					node = create(dir, hash);
 
- 				if (tgt.length > 0) {
 
- 					tgt.parent().replaceWith(node);
 
- 					dirs[hash] = dir;
 
- 					return true;
 
- 				} else {
 
- 					return false;
 
- 				}
 
- 			},
 
- 			/**
 
- 			 * Remove all dir from places
 
- 			 *
 
- 			 * @return void
 
- 			 **/
 
- 			clear = function() {
 
- 				subtree.empty();
 
- 				root.removeClass(collapsed);
 
- 				places.removeClass(expanded);
 
- 				subtree.slideToggle(false);
 
- 			},
 
- 			/**
 
- 			 * Sort places dirs A-Z
 
- 			 *
 
- 			 * @return void
 
- 			 **/
 
- 			sort = function() {
 
- 				$.each(dirs, function(h, f) {
 
- 					var dir = fm.file(h) || f,
 
- 						node = create(dir, h),
 
- 						ret = null;
 
- 					if (!dir) {
 
- 						node.hide();
 
- 					}
 
- 					if (subtree.children().length) {
 
- 						$.each(subtree.children(), function() {
 
- 							var current =  $(this);
 
- 							if ((dir.i18 || dir.name).localeCompare(current.children('.'+navdir).text()) < 0) {
 
- 								ret = !node.insertBefore(current);
 
- 								return ret;
 
- 							}
 
- 						});
 
- 						if (ret !== null) {
 
- 							return true;
 
- 						}
 
- 					}
 
- 					!$('#'+hash2id(h)).length && subtree.append(node);
 
- 				});
 
- 				save();
 
- 			},
 
- 			// sort button
 
- 			sortBtn = $('<span class="elfinder-button-icon elfinder-button-icon-sort elfinder-places-root-icon" title="'+fm.i18n('cmdsort')+'"/>')
 
- 				.hide()
 
- 				.on('click', function(e) {
 
- 					e.stopPropagation();
 
- 					subtree.empty();
 
- 					sort();
 
- 				}
 
- 			),
 
- 			/**
 
- 			 * Node - wrapper for places root
 
- 			 *
 
- 			 * @type jQuery
 
- 			 **/
 
- 			wrapper = create({
 
- 					hash  : 'root-'+fm.namespace, 
 
- 					name  : fm.i18n(opts.name, 'places'),
 
- 					read  : true,
 
- 					write : true
 
- 				}),
 
- 			/**
 
- 			 * Places root node
 
- 			 *
 
- 			 * @type jQuery
 
- 			 **/
 
- 			root = wrapper.children('.'+navdir)
 
- 				.addClass(clroot)
 
- 				.on('click', function(e) {
 
- 					e.stopPropagation();
 
- 					if (root.hasClass(collapsed)) {
 
- 						places.toggleClass(expanded);
 
- 						subtree.slideToggle();
 
- 						fm.storage('placesState', places.hasClass(expanded)? 1 : 0);
 
- 					}
 
- 				})
 
- 				.append(sortBtn),
 
- 			/**
 
- 			 * Container for dirs
 
- 			 *
 
- 			 * @type jQuery
 
- 			 **/
 
- 			subtree = wrapper.children('.'+fm.res(c, 'navsubtree')),
 
- 			
 
- 			/**
 
- 			 * Main places container
 
- 			 *
 
- 			 * @type jQuery
 
- 			 **/
 
- 			places = $(this).addClass(fm.res(c, 'tree')+' elfinder-places ui-corner-all')
 
- 				.hide()
 
- 				.append(wrapper)
 
- 				.appendTo(fm.getUI('navbar'))
 
- 				.on('mouseenter mouseleave', '.'+navdir, function(e) {
 
- 					$(this).toggleClass('ui-state-hover', (e.type == 'mouseenter'));
 
- 				})
 
- 				.on('click', '.'+navdir, function(e) {
 
- 					var p = $(this);
 
- 					if (p.data('longtap')) {
 
- 						e.stopPropagation();
 
- 						return;
 
- 					}
 
- 					! p.hasClass('elfinder-na') && fm.exec('open', p.attr('id').substr(6));
 
- 				})
 
- 				.on('contextmenu', '.'+navdir+':not(.'+clroot+')', function(e) {
 
- 					var self = $(this),
 
- 						hash = self.attr('id').substr(6);
 
- 					
 
- 					e.preventDefault();
 
- 					fm.trigger('contextmenu', {
 
- 						raw : [{
 
- 							label    : fm.i18n('moveUp'),
 
- 							icon     : 'up',
 
- 							remain   : true,
 
- 							callback : function() { moveup(hash); save(); }
 
- 						},'|',{
 
- 							label    : fm.i18n('rmFromPlaces'),
 
- 							icon     : 'rm',
 
- 							callback : function() { remove(hash); save(); }
 
- 						}],
 
- 						'x'       : e.pageX,
 
- 						'y'       : e.pageY
 
- 					});
 
- 					
 
- 					self.addClass('ui-state-hover');
 
- 					
 
- 					fm.getUI('contextmenu').children().on('mouseenter', function() {
 
- 						self.addClass('ui-state-hover');
 
- 					});
 
- 					
 
- 					fm.bind('closecontextmenu', function() {
 
- 						self.removeClass('ui-state-hover');
 
- 					});
 
- 				})
 
- 				.droppable({
 
- 					tolerance  : 'pointer',
 
- 					accept     : '.elfinder-cwd-file-wrapper,.elfinder-tree-dir,.elfinder-cwd-file',
 
- 					hoverClass : fm.res('class', 'adroppable'),
 
- 					classes    : { // Deprecated hoverClass jQueryUI>=1.12.0
 
- 						'ui-droppable-hover': fm.res('class', 'adroppable')
 
- 					},
 
- 					over       : function(e, ui) {
 
- 						var helper = ui.helper,
 
- 							dir    = $.grep(helper.data('files'), function(h) { return (fm.file(h).mime === 'directory' && !dirs[h])? true : false; });
 
- 						e.stopPropagation();
 
- 						helper.data('dropover', helper.data('dropover') + 1);
 
- 						if (fm.insideWorkzone(e.pageX, e.pageY)) {
 
- 							if (dir.length > 0) {
 
- 								helper.addClass('elfinder-drag-helper-plus');
 
- 								fm.trigger('unlockfiles', {files : helper.data('files'), helper: helper});
 
- 							} else {
 
- 								$(this).removeClass(dropover);
 
- 							}
 
- 						}
 
- 					},
 
- 					out : function(e, ui) {
 
- 						var helper = ui.helper;
 
- 						e.stopPropagation();
 
- 						helper.removeClass('elfinder-drag-helper-move elfinder-drag-helper-plus').data('dropover', Math.max(helper.data('dropover') - 1, 0));
 
- 						$(this).removeData('dropover')
 
- 						       .removeClass(dropover);
 
- 					},
 
- 					drop       : function(e, ui) {
 
- 						var helper  = ui.helper,
 
- 							resolve = true;
 
- 						
 
- 						$.each(helper.data('files'), function(i, hash) {
 
- 							var dir = fm.file(hash);
 
- 							
 
- 							if (dir && dir.mime == 'directory' && !dirs[dir.hash]) {
 
- 								add(dir);
 
- 							} else {
 
- 								resolve = false;
 
- 							}
 
- 						});
 
- 						save();
 
- 						resolve && helper.hide();
 
- 					}
 
- 				})
 
- 				// for touch device
 
- 				.on('touchstart', '.'+navdir+':not(.'+clroot+')', function(e) {
 
- 					if (e.originalEvent.touches.length > 1) {
 
- 						return;
 
- 					}
 
- 					var hash = $(this).attr('id').substr(6),
 
- 					p = $(this)
 
- 					.addClass(hover)
 
- 					.data('longtap', null)
 
- 					.data('tmlongtap', setTimeout(function(){
 
- 						// long tap
 
- 						p.data('longtap', true);
 
- 						fm.trigger('contextmenu', {
 
- 							raw : [{
 
- 								label    : fm.i18n('rmFromPlaces'),
 
- 								icon     : 'rm',
 
- 								callback : function() { remove(hash); save(); }
 
- 							}],
 
- 							'x'       : e.originalEvent.touches[0].pageX,
 
- 							'y'       : e.originalEvent.touches[0].pageY
 
- 						});
 
- 					}, 500));
 
- 				})
 
- 				.on('touchmove touchend', '.'+navdir+':not(.'+clroot+')', function(e) {
 
- 					clearTimeout($(this).data('tmlongtap'));
 
- 					if (e.type == 'touchmove') {
 
- 						$(this).removeClass(hover);
 
- 					}
 
- 				});
 
- 		if ($.fn.sortable) {
 
- 			subtree.addClass('touch-punch')
 
- 			.sortable({
 
- 				appendTo : fm.getUI(),
 
- 				revert   : false,
 
- 				helper   : function(e) {
 
- 					var dir = $(e.target).parent();
 
- 						
 
- 					dir.children().removeClass('ui-state-hover');
 
- 					
 
- 					return $('<div class="ui-widget elfinder-place-drag elfinder-'+fm.direction+'"/>')
 
- 							.append($('<div class="elfinder-navbar"/>').show().append(dir.clone()));
 
- 				},
 
- 				stop     : function(e, ui) {
 
- 					var target = $(ui.item[0]),
 
- 						top    = places.offset().top,
 
- 						left   = places.offset().left,
 
- 						width  = places.width(),
 
- 						height = places.height(),
 
- 						x      = e.pageX,
 
- 						y      = e.pageY;
 
- 					
 
- 					if (!(x > left && x < left+width && y > top && y < y+height)) {
 
- 						remove(id2hash(target.children(':first').attr('id')));
 
- 						save();
 
- 					}
 
- 				},
 
- 				update   : function(e, ui) {
 
- 					save();
 
- 				}
 
- 			});
 
- 		}
 
- 		// "on regist" for command exec
 
- 		$(this).on('regist', function(e, files){
 
- 			var added = false;
 
- 			$.each(files, function(i, dir) {
 
- 				if (dir && dir.mime == 'directory' && !dirs[dir.hash]) {
 
- 					if (add(dir)) {
 
- 						added = true;
 
- 					}
 
- 				}
 
- 			});
 
- 			added && save();
 
- 		});
 
- 	
 
- 		// on fm load - show places and load files from backend
 
- 		fm.one('load', function() {
 
- 			var dat, hashes;
 
- 			
 
- 			if (fm.oldAPI) {
 
- 				return;
 
- 			}
 
- 			
 
- 			places.show().parent().show();
 
- 			init();
 
- 			fm.change(function(e) {
 
- 				var changed = false;
 
- 				$.each(e.data.changed, function(i, file) {
 
- 					if (dirs[file.hash]) {
 
- 						if (file.mime !== 'directory') {
 
- 							if (remove(file.hash)) {
 
- 								changed = true;
 
- 							}
 
- 						} else {
 
- 							if (update(file)) {
 
- 								changed = true;
 
- 							}
 
- 						}
 
- 					}
 
- 				});
 
- 				changed && save();
 
- 			})
 
- 			.bind('rename', function(e) {
 
- 				var changed = false;
 
- 				if (e.data.removed) {
 
- 					$.each(e.data.removed, function(i, hash) {
 
- 						if (e.data.added[i]) {
 
- 							if (update(e.data.added[i], hash)) {
 
- 								changed = true;
 
- 							}
 
- 						}
 
- 					});
 
- 				}
 
- 				changed && save();
 
- 			})
 
- 			.bind('rm paste', function(e) {
 
- 				var names = [],
 
- 					changed = false;
 
- 				if (e.data.removed) {
 
- 					$.each(e.data.removed, function(i, hash) {
 
- 						var name = remove(hash);
 
- 						name && names.push(name);
 
- 					});
 
- 				}
 
- 				if (names.length) {
 
- 					changed = true;
 
- 				}
 
- 				if (e.data.added && names.length) {
 
- 					$.each(e.data.added, function(i, file) {
 
- 						if ($.inArray(file.name, names) !== 1) {
 
- 							file.mime == 'directory' && add(file);
 
- 						}
 
- 					});
 
- 				}
 
- 				changed && save();
 
- 			})
 
- 			.bind('sync netmount', function() {
 
- 				var ev = this,
 
- 					opSuffix = opts.suffix? opts.suffix : '',
 
- 					hashes;
 
- 				
 
- 				if (ev.type === 'sync') {
 
- 					// check is change of opts.suffix
 
- 					if (suffix !== opSuffix) {
 
- 						suffix = opSuffix;
 
- 						clear();
 
- 						init();
 
- 						return;
 
- 					}
 
- 				}
 
- 				
 
- 				hashes = Object.keys(dirs);
 
- 				if (hashes.length) {
 
- 					root.prepend(spinner);
 
- 					fm.request({
 
- 						data : {cmd : 'info', targets : hashes},
 
- 						preventDefault : true
 
- 					})
 
- 					.done(function(data) {
 
- 						var exists  = {},
 
- 							updated = false,
 
- 							cwd     = fm.cwd().hash;
 
- 						$.each(data.files || [], function(i, file) {
 
- 							var hash = file.hash;
 
- 							exists[hash] = file;
 
- 							if (!fm.files().hasOwnProperty(file.hash)) {
 
- 								// update cache
 
- 								fm.trigger('tree', {tree: [file]});
 
- 							}
 
- 						});
 
- 						$.each(dirs, function(h, f) {
 
- 							if (f.notfound === Boolean(exists[h])) {
 
- 								if ((f.phash === cwd && ev.type !== 'netmount') || (exists[h] && exists[h].mime !== 'directory')) {
 
- 									if (remove(h)) {
 
- 										updated = true;
 
- 									}
 
- 								} else {
 
- 									if (update(exists[h] || Object.assign({notfound: true}, f))) {
 
- 										updated = true;
 
- 									}
 
- 								}
 
- 							} else if (exists[h] && exists[h].phash != cwd) {
 
- 								// update permission of except cwd
 
- 								update(exists[h]);
 
- 							}
 
- 						});
 
- 						updated && save();
 
- 					})
 
- 					.always(function() {
 
- 						spinner.remove();
 
- 					});
 
- 				}
 
- 			});
 
- 			
 
- 		});
 
- 		
 
- 	});
 
- };
 
- /*
 
-  * File: /js/ui/searchbutton.js
 
-  */
 
- /**
 
-  * @class  elFinder toolbar search button widget.
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.elfindersearchbutton = function(cmd) {
 
- 		return this.each(function() {
 
- 		var result = false,
 
- 			fm     = cmd.fm,
 
- 			isopts = cmd.options.incsearch || { enable: false },
 
- 			sTypes = cmd.options.searchTypes,
 
- 			id     = function(name){return fm.namespace + fm.escape(name);},
 
- 			toolbar= fm.getUI('toolbar'),
 
- 			btnCls = fm.res('class', 'searchbtn'),
 
- 			button = $(this)
 
- 				.hide()
 
- 				.addClass('ui-widget-content elfinder-button '+btnCls)
 
- 				.on('click', function(e) {
 
- 					e.stopPropagation();
 
- 				}),
 
- 			search = function() {
 
- 				input.data('inctm') && clearTimeout(input.data('inctm'));
 
- 				var val = $.trim(input.val()),
 
- 					from = !$('#' + id('SearchFromAll')).prop('checked'),
 
- 					mime = $('#' + id('SearchMime')).prop('checked'),
 
- 					type = '';
 
- 				if (from) {
 
- 					if ($('#' + id('SearchFromVol')).prop('checked')) {
 
- 						from = fm.root(fm.cwd().hash);
 
- 					} else {
 
- 						from = fm.cwd().hash;
 
- 					}
 
- 				}
 
- 				if (mime) {
 
- 					mime = val;
 
- 					val = '.';
 
- 				}
 
- 				if (typeSet) {
 
- 					type = typeSet.children('input:checked').val();
 
- 				}
 
- 				if (val) {
 
- 					input.trigger('focus');
 
- 					cmd.exec(val, from, mime, type).done(function() {
 
- 						result = true;
 
- 					}).fail(function() {
 
- 						abort();
 
- 					});
 
- 					
 
- 				} else {
 
- 					fm.trigger('searchend');
 
- 				}
 
- 			},
 
- 			abort = function() {
 
- 				input.data('inctm') && clearTimeout(input.data('inctm'));
 
- 				input.val('').trigger('blur');
 
- 				if (result || incVal) {
 
- 					result = false;
 
- 					incVal = '';
 
- 					fm.lazy(function() {
 
- 						fm.trigger('searchend');
 
- 					});
 
- 				}
 
- 			},
 
- 			incVal = '',
 
- 			input  = $('<input type="text" size="42"/>')
 
- 				.on('focus', function() {
 
- 					inFocus = true;
 
- 					incVal = '';
 
- 					button.addClass('ui-state-active');
 
- 					fm.trigger('uiresize');
 
- 					opts && opts.slideDown(function() {
 
- 						// Care for on browser window re-active
 
- 						button.addClass('ui-state-active');
 
- 						fm.toFront(opts);
 
- 					});
 
- 				})
 
- 				.on('blur', function() {
 
- 					inFocus = false;
 
- 					if (opts) {
 
- 						if (!opts.data('infocus')) {
 
- 							opts.slideUp(function() {
 
- 								button.removeClass('ui-state-active');
 
- 								fm.trigger('uiresize');
 
- 								fm.toHide(opts);
 
- 							});
 
- 						} else {
 
- 							opts.data('infocus', false);
 
- 						}
 
- 					} else {
 
- 						button.removeClass('ui-state-active');
 
- 					}
 
- 				})
 
- 				.appendTo(button)
 
- 				// to avoid fm shortcuts on arrows
 
- 				.on('keypress', function(e) {
 
- 					e.stopPropagation();
 
- 				})
 
- 				.on('keydown', function(e) {
 
- 					e.stopPropagation();
 
- 					if (e.keyCode === $.ui.keyCode.ENTER) {
 
- 						search();
 
- 					} else if (e.keyCode === $.ui.keyCode.ESCAPE) {
 
- 						e.preventDefault();
 
- 						abort();
 
- 					}
 
- 				}),
 
- 			opts, typeSet, cwdReady, inFocus;
 
- 		
 
- 		if (isopts.enable) {
 
- 			isopts.minlen = isopts.minlen || 2;
 
- 			isopts.wait = isopts.wait || 500;
 
- 			input
 
- 				.attr('title', fm.i18n('incSearchOnly'))
 
- 				.on('compositionstart', function() {
 
- 					input.data('composing', true);
 
- 				})
 
- 				.on('compositionend', function() {
 
- 					input.removeData('composing');
 
- 					input.trigger('input'); // for IE, edge
 
- 				})
 
- 				.on('input', function() {
 
- 					if (! input.data('composing')) {
 
- 						input.data('inctm') && clearTimeout(input.data('inctm'));
 
- 						input.data('inctm', setTimeout(function() {
 
- 							var val = input.val();
 
- 							if (val.length === 0 || val.length >= isopts.minlen) {
 
- 								(incVal !== val) && fm.trigger('incsearchstart', { query: val });
 
- 								incVal = val;
 
- 								if (val === '' && fm.searchStatus.state > 1 && fm.searchStatus.query) {
 
- 									input.val(fm.searchStatus.query).trigger('select');
 
- 								} 
 
- 							}
 
- 						}, isopts.wait));
 
- 					}
 
- 				});
 
- 			
 
- 			if (fm.UA.ltIE8) {
 
- 				input.on('keydown', function(e) {
 
- 						if (e.keyCode === 229) {
 
- 							input.data('imetm') && clearTimeout(input.data('imetm'));
 
- 							input.data('composing', true);
 
- 							input.data('imetm', setTimeout(function() {
 
- 								input.removeData('composing');
 
- 							}, 100));
 
- 						}
 
- 					})
 
- 					.on('keyup', function(e) {
 
- 						input.data('imetm') && clearTimeout(input.data('imetm'));
 
- 						if (input.data('composing')) {
 
- 							e.keyCode === $.ui.keyCode.ENTER && input.trigger('compositionend');
 
- 						} else {
 
- 							input.trigger('input');
 
- 						}
 
- 					});
 
- 			}
 
- 		}
 
- 		
 
- 		$('<span class="ui-icon ui-icon-search" title="'+cmd.title+'"/>')
 
- 			.appendTo(button)
 
- 			.on('mousedown', function(e) {
 
- 				e.stopPropagation();
 
- 				e.preventDefault();
 
- 				if (button.hasClass('ui-state-active')) {
 
- 					search();
 
- 				} else {
 
- 					input.trigger('focus');
 
- 				}
 
- 			});
 
- 		
 
- 		$('<span class="ui-icon ui-icon-close"/>')
 
- 			.appendTo(button)
 
- 			.on('mousedown', function(e) {
 
- 				e.stopPropagation();
 
- 				e.preventDefault();
 
- 				if (input.val() === '' && !button.hasClass('ui-state-active')) {
 
- 					input.trigger('focus');
 
- 				} else {
 
- 					abort();
 
- 				}
 
- 			});
 
- 		
 
- 		// wait when button will be added to DOM
 
- 		fm.bind('toolbarload', function(){
 
- 			var parent = button.parent();
 
- 			if (parent.length) {
 
- 				toolbar.prepend(button.show());
 
- 				parent.remove();
 
- 				// position icons for ie7
 
- 				if (fm.UA.ltIE7) {
 
- 					var icon = button.children(fm.direction == 'ltr' ? '.ui-icon-close' : '.ui-icon-search');
 
- 					icon.css({
 
- 						right : '',
 
- 						left  : parseInt(button.width())-icon.outerWidth(true)
 
- 					});
 
- 				}
 
- 			}
 
- 		});
 
- 		
 
- 		fm
 
- 			.one('init', function() {
 
- 				fm.getUI('cwd').on('touchstart click', function() {
 
- 					inFocus && input.trigger('blur');
 
- 				});
 
- 			})
 
- 			.one('open', function() {
 
- 				opts = (fm.api < 2.1)? null : $('<div class="ui-front ui-widget ui-widget-content elfinder-button-search-menu ui-corner-all"/>')
 
- 					.append(
 
- 						$('<div class="buttonset"/>')
 
- 							.append(
 
- 								$('<input id="'+id('SearchFromCwd')+'" name="serchfrom" type="radio" checked="checked"/><label for="'+id('SearchFromCwd')+'">'+fm.i18n('btnCwd')+'</label>'),
 
- 								$('<input id="'+id('SearchFromVol')+'" name="serchfrom" type="radio"/><label for="'+id('SearchFromVol')+'">'+fm.i18n('btnVolume')+'</label>'),
 
- 								$('<input id="'+id('SearchFromAll')+'" name="serchfrom" type="radio"/><label for="'+id('SearchFromAll')+'">'+fm.i18n('btnAll')+'</label>')
 
- 							),
 
- 						$('<div class="buttonset elfinder-search-type"/>')
 
- 							.append(
 
- 								$('<input id="'+id('SearchName')+'" name="serchcol" type="radio" checked="checked" value="SearchName"/><label for="'+id('SearchName')+'">'+fm.i18n('btnFileName')+'</label>')
 
- 							)
 
- 					)
 
- 					.hide()
 
- 					.appendTo(fm.getUI());
 
- 				if (opts) {
 
- 					if (sTypes) {
 
- 						typeSet = opts.find('.elfinder-search-type');
 
- 						$.each(cmd.options.searchTypes, function(i, v) {
 
- 							typeSet.append($('<input id="'+id(i)+'" name="serchcol" type="radio" value="'+fm.escape(i)+'"/><label for="'+id(i)+'">'+fm.i18n(v.name)+'</label>'));
 
- 						});
 
- 					}
 
- 					opts.find('div.buttonset').buttonset();
 
- 					$('#'+id('SearchFromAll')).next('label').attr('title', fm.i18n('searchTarget', fm.i18n('btnAll')));
 
- 					if (sTypes) {
 
- 						$.each(sTypes, function(i, v) {
 
- 							if (v.title) {
 
- 								$('#'+id(i)).next('label').attr('title', fm.i18n(v.title));
 
- 							}
 
- 						});
 
- 					}
 
- 					opts.on('mousedown', 'div.buttonset', function(e){
 
- 							e.stopPropagation();
 
- 							opts.data('infocus', true);
 
- 						})
 
- 						.on('click', 'input', function(e) {
 
- 							e.stopPropagation();
 
- 							$.trim(input.val())? search() : input.trigger('focus');
 
- 						})
 
- 						.on('close', function() {
 
- 							input.trigger('blur');
 
- 						});
 
- 				}
 
- 			})
 
- 			.bind('searchend', function() {
 
- 				input.val('');
 
- 			})
 
- 			.bind('open parents', function() {
 
- 				var dirs    = [],
 
- 					volroot = fm.file(fm.root(fm.cwd().hash));
 
- 				
 
- 				if (volroot) {
 
- 					$.each(fm.parents(fm.cwd().hash), function(i, hash) {
 
- 						dirs.push(fm.file(hash).name);
 
- 					});
 
- 		
 
- 					$('#'+id('SearchFromCwd')).next('label').attr('title', fm.i18n('searchTarget', dirs.join(fm.option('separator'))));
 
- 					$('#'+id('SearchFromVol')).next('label').attr('title', fm.i18n('searchTarget', volroot.name));
 
- 				}
 
- 			})
 
- 			.bind('open', function() {
 
- 				incVal && abort();
 
- 			})
 
- 			.bind('cwdinit', function() {
 
- 				cwdReady = false;
 
- 			})
 
- 			.bind('cwdrender',function() {
 
- 				cwdReady = true;
 
- 			})
 
- 			.bind('keydownEsc', function() {
 
- 				if (incVal && incVal.substr(0, 1) === '/') {
 
- 					incVal = '';
 
- 					input.val('');
 
- 					fm.trigger('searchend');
 
- 				}
 
- 			})
 
- 			.shortcut({
 
- 				pattern     : 'ctrl+f f3',
 
- 				description : cmd.title,
 
- 				callback    : function() { 
 
- 					input.trigger('select').trigger('focus');
 
- 				}
 
- 			})
 
- 			.shortcut({
 
- 				pattern     : 'a b c d e f g h i j k l m n o p q r s t u v w x y z dig0 dig1 dig2 dig3 dig4 dig5 dig6 dig7 dig8 dig9 num0 num1 num2 num3 num4 num5 num6 num7 num8 num9',
 
- 				description : fm.i18n('firstLetterSearch'),
 
- 				callback    : function(e) { 
 
- 					if (! cwdReady) { return; }
 
- 					
 
- 					var code = e.originalEvent.keyCode,
 
- 						next = function() {
 
- 							var sel = fm.selected(),
 
- 								key = $.ui.keyCode[(!sel.length || $('#'+fm.cwdHash2Id(sel[0])).next('[id]').length)? 'RIGHT' : 'HOME'];
 
- 							$(document).trigger($.Event('keydown', { keyCode: key, ctrlKey : false, shiftKey : false, altKey : false, metaKey : false }));
 
- 						},
 
- 						val;
 
- 					if (code >= 96 && code <= 105) {
 
- 						code -= 48;
 
- 					}
 
- 					val = '/' + String.fromCharCode(code);
 
- 					if (incVal !== val) {
 
- 						input.val(val);
 
- 						incVal = val;
 
- 						fm
 
- 							.trigger('incsearchstart', { query: val })
 
- 							.one('cwdrender', next);
 
- 					} else{
 
- 						next();
 
- 					}
 
- 				}
 
- 			});
 
- 	});
 
- };
 
- /*
 
-  * File: /js/ui/sortbutton.js
 
-  */
 
- /**
 
-  * @class  elFinder toolbar button menu with sort variants.
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.elfindersortbutton = function(cmd) {
 
- 		return this.each(function() {
 
- 		var fm       = cmd.fm,
 
- 			name     = cmd.name,
 
- 			c        = 'class',
 
- 			disabled = fm.res(c, 'disabled'),
 
- 			hover    = fm.res(c, 'hover'),
 
- 			item     = 'elfinder-button-menu-item',
 
- 			selected = item+'-selected',
 
- 			asc      = selected+'-asc',
 
- 			desc     = selected+'-desc',
 
- 			text     = $('<span class="elfinder-button-text">'+cmd.title+'</span>'),
 
- 			button   = $(this).addClass('ui-state-default elfinder-button elfinder-menubutton elfiner-button-'+name)
 
- 				.attr('title', cmd.title)
 
- 				.append('<span class="elfinder-button-icon elfinder-button-icon-'+name+'"/>', text)
 
- 				.on('mouseenter mouseleave', function(e) { !button.hasClass(disabled) && button.toggleClass(hover, e.type === 'mouseenter'); })
 
- 				.on('click', function(e) {
 
- 					if (!button.hasClass(disabled)) {
 
- 						e.stopPropagation();
 
- 						menu.is(':hidden') && fm.getUI().click();
 
- 						menu.css(getMenuOffset()).slideToggle({
 
- 							duration: 100,
 
- 							done: function(e) {
 
- 								fm[menu.is(':visible')? 'toFront' : 'toHide'](menu);
 
- 							}
 
- 						});
 
- 					}
 
- 				}),
 
- 			hide = function() { fm.toHide(menu); },
 
- 			menu = $('<div class="ui-front ui-widget ui-widget-content elfinder-button-menu ui-corner-all"/>')
 
- 				.hide()
 
- 				.appendTo(fm.getUI())
 
- 				.on('mouseenter mouseleave', '.'+item, function(e) { $(this).toggleClass(hover, e.type === 'mouseenter'); })
 
- 				.on('click', function(e) {
 
- 					e.preventDefault();
 
- 					e.stopPropagation();
 
- 				})
 
- 				.on('close', hide),
 
- 			update = function() {
 
- 				menu.children('[rel]').removeClass(selected+' '+asc+' '+desc)
 
- 					.filter('[rel="'+fm.sortType+'"]')
 
- 					.addClass(selected+' '+(fm.sortOrder == 'asc' ? asc : desc));
 
- 				menu.children('.elfinder-sort-stick').toggleClass(selected, fm.sortStickFolders);
 
- 				menu.children('.elfinder-sort-tree').toggleClass(selected, fm.sortAlsoTreeview);
 
- 			},
 
- 			getMenuOffset = function() {
 
- 				var baseOffset = fm.getUI().offset(),
 
- 					buttonOffset = button.offset();
 
- 				return {
 
- 					top : buttonOffset.top - baseOffset.top,
 
- 					left : buttonOffset.left - baseOffset.left
 
- 				};
 
- 			},
 
- 			tm;
 
- 			
 
- 		text.hide();
 
- 		
 
- 		$.each(fm.sortRules, function(name, value) {
 
- 			menu.append($('<div class="'+item+'" rel="'+name+'"><span class="ui-icon ui-icon-arrowthick-1-n"/><span class="ui-icon ui-icon-arrowthick-1-s"/>'+fm.i18n('sort'+name)+'</div>').data('type', name));
 
- 		});
 
- 		
 
- 		menu.children().on('click', function(e) {
 
- 			cmd.exec([], $(this).removeClass(hover).attr('rel'));
 
- 		});
 
- 		
 
- 		$('<div class="'+item+' '+item+'-separated elfinder-sort-ext elfinder-sort-stick"><span class="ui-icon ui-icon-check"/>'+fm.i18n('sortFoldersFirst')+'</div>')
 
- 			.appendTo(menu)
 
- 			.on('click', function() {
 
- 				cmd.exec([], 'stick');
 
- 			});
 
- 		if ($.fn.elfindertree && $.inArray('tree', fm.options.ui) !== -1) {
 
- 			$('<div class="'+item+' '+item+'-separated elfinder-sort-ext elfinder-sort-tree"><span class="ui-icon ui-icon-check"/>'+fm.i18n('sortAlsoTreeview')+'</div>')
 
- 				.appendTo(menu)
 
- 				.on('click', function() {
 
- 					cmd.exec([], 'tree');
 
- 				});
 
- 		}
 
- 		
 
- 		fm.bind('disable select', hide).getUI().on('click', hide);
 
- 			
 
- 		fm.bind('open', function() {
 
- 			menu.children('[rel]').each(function() {
 
- 				var $this = $(this);
 
- 				$this.toggle(fm.sorters[$this.attr('rel')]);
 
- 			});
 
- 		}).bind('sortchange', update);
 
- 		
 
- 		if (menu.children().length > 1) {
 
- 			cmd.change(function() {
 
- 					tm && cancelAnimationFrame(tm);
 
- 					tm = requestAnimationFrame(function() {
 
- 						button.toggleClass(disabled, cmd.disabled());
 
- 						update();
 
- 					});
 
- 				})
 
- 				.change();
 
- 		} else {
 
- 			button.addClass(disabled);
 
- 		}
 
- 	});
 
- 	
 
- };
 
- /*
 
-  * File: /js/ui/stat.js
 
-  */
 
- /**
 
-  * @class elFinder ui
 
-  * Display number of files/selected files and its size in statusbar
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.elfinderstat = function(fm) {
 
- 		return this.each(function() {
 
- 		var size       = $(this).addClass('elfinder-stat-size'),
 
- 			sel        = $('<div class="elfinder-stat-selected"/>')
 
- 				.on('click', 'a', function(e) {
 
- 					var hash = $(this).data('hash');
 
- 					e.preventDefault();
 
- 					fm.exec('opendir', [ hash ]);
 
- 				}),
 
- 			titleitems = fm.i18n('items'),
 
- 			titlesel   = fm.i18n('selected'),
 
- 			titlesize  = fm.i18n('size'),
 
- 			setstat    = function(files) {
 
- 				var c = 0, 
 
- 					s = 0,
 
- 					cwd = fm.cwd(),
 
- 					calc = true,
 
- 					hasSize = true;
 
- 				if (cwd.sizeInfo || cwd.size) {
 
- 					s = cwd.size;
 
- 					calc = false;
 
- 				}
 
- 				$.each(files, function(i, file) {
 
- 					c++;
 
- 					if (calc) {
 
- 						s += parseInt(file.size) || 0;
 
- 						if (hasSize === true && file.mime === 'directory' && !file.sizeInfo) {
 
- 							hasSize = false;
 
- 						}
 
- 					}
 
- 				});
 
- 				size.html(titleitems+': <span class="elfinder-stat-incsearch"></span>'+c+', <span class="elfinder-stat-size'+(hasSize? ' elfinder-stat-size-recursive' : '')+'">'+fm.i18n(hasSize? 'sum' : 'size')+': '+fm.formatSize(s)+'</span>')
 
- 					.attr('title', size.text());
 
- 				fm.trigger('uistatchange');
 
- 			},
 
- 			setIncsearchStat = function(data) {
 
- 				size.find('span.elfinder-stat-incsearch').html(data? data.hashes.length + ' / ' : '');
 
- 				size.attr('title', size.text());
 
- 				fm.trigger('uistatchange');
 
- 			},
 
- 			setSelect = function(files) {
 
- 				var s = 0,
 
- 					c = 0,
 
- 					dirs = [],
 
- 					path, file;
 
- 				if (files.length === 1) {
 
- 					file = files[0];
 
- 					s = file.size;
 
- 					if (fm.searchStatus.state === 2) {
 
- 						path = fm.escape(file.path? file.path.replace(/\/[^\/]*$/, '') : '..');
 
- 						dirs.push('<a href="#elf_'+file.phash+'" data-hash="'+file.hash+'" title="'+path+'">'+path+'</a>');
 
- 					}
 
- 					dirs.push(fm.escape(file.i18 || file.name));
 
- 					sel.html(dirs.join('/') + (s > 0 ? ', '+fm.formatSize(s) : ''));
 
- 				} else if (files.length) {
 
- 					$.each(files, function(i, file) {
 
- 						c++;
 
- 						s += parseInt(file.size)||0;
 
- 					});
 
- 					sel.html(c ? titlesel+': '+c+', '+titlesize+': '+fm.formatSize(s) : ' ');
 
- 				} else {
 
- 					sel.html('');
 
- 				}
 
- 				sel.attr('title', sel.text());
 
- 				fm.trigger('uistatchange');
 
- 			};
 
- 		fm.getUI('statusbar').prepend(size).append(sel).show();
 
- 		if (fm.UA.Mobile && $.fn.tooltip) {
 
- 			fm.getUI('statusbar').tooltip({
 
- 				classes: {
 
- 					'ui-tooltip': 'elfinder-ui-tooltip ui-widget-shadow'
 
- 				},
 
- 				tooltipClass: 'elfinder-ui-tooltip ui-widget-shadow',
 
- 				track: true
 
- 			});
 
- 		}
 
- 		
 
- 		fm
 
- 		.bind('cwdhasheschange', function(e) {
 
- 			setstat($.map(e.data, function(h) { return fm.file(h); }));
 
- 		})
 
- 		.change(function(e) {
 
- 			var files = e.data.changed || [],
 
- 				cwdHash = fm.cwd().hash;
 
- 			$.each(files, function() {
 
- 				if (this.hash === cwdHash) {
 
- 					if (this.size) {
 
- 						size.children('.elfinder-stat-size').addClass('elfinder-stat-size-recursive').html(fm.i18n('sum')+': '+fm.formatSize(this.size));
 
- 						size.attr('title', size.text());
 
- 					}
 
- 					return false;
 
- 				}
 
- 			});
 
- 		})
 
- 		.select(function() {
 
- 			setSelect(fm.selectedFiles());
 
- 		})
 
- 		.bind('open', function() {
 
- 			setSelect([]);
 
- 		})
 
- 		.bind('incsearch', function(e) {
 
- 			setIncsearchStat(e.data);
 
- 		})
 
- 		.bind('incsearchend', function() {
 
- 			setIncsearchStat();
 
- 		})
 
- 		;
 
- 	});
 
- };
 
- /*
 
-  * File: /js/ui/toast.js
 
-  */
 
- /**
 
-  * @class  elFinder toast
 
-  * 
 
-  * This was created inspired by the toastr. Thanks to developers of toastr.
 
-  * CodeSeven/toastr: http://johnpapa.net <https://github.com/CodeSeven/toastr>
 
-  *
 
-  * @author Naoki Sawada
 
-  **/
 
- $.fn.elfindertoast = function(opts, fm) {
 
- 		var defOpts = Object.assign({
 
- 		mode: 'success', // or 'info', 'warning' and 'error'
 
- 		msg: '',
 
- 		showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery
 
- 		showDuration: 300,
 
- 		showEasing: 'swing', //swing and linear are built into jQuery
 
- 		onShown: undefined,
 
- 		hideMethod: 'fadeOut',
 
- 		hideDuration: 1500,
 
- 		hideEasing: 'swing',
 
- 		onHidden: undefined,
 
- 		timeOut: 3000,
 
- 		extNode: undefined,
 
- 		button: undefined,
 
- 		width: undefined
 
- 	}, $.isPlainObject(fm.options.uiOptions.toast.defaults)? fm.options.uiOptions.toast.defaults : {});
 
- 	return this.each(function() {
 
- 		opts = Object.assign({}, defOpts, opts || {});
 
- 		
 
- 		var self = $(this),
 
- 			show = function(notm) {
 
- 				self.stop();
 
- 				fm.toFront(self);
 
- 				self[opts.showMethod]({
 
- 					duration: opts.showDuration,
 
- 					easing: opts.showEasing,
 
- 					complete: function() {
 
- 						opts.onShown && opts.onShown();
 
- 						if (!notm && opts.timeOut) {
 
- 							rmTm = setTimeout(rm, opts.timeOut);
 
- 						}
 
- 					}
 
- 				});
 
- 			},
 
- 			rm = function() {
 
- 				self[opts.hideMethod]({
 
- 					duration: opts.hideDuration,
 
- 					easing: opts.hideEasing,
 
- 					complete: function() {
 
- 						opts.onHidden && opts.onHidden();
 
- 						self.remove();
 
- 					}
 
- 				});
 
- 			},
 
- 			rmTm;
 
- 		
 
- 		self.on('click', function(e) {
 
- 			e.stopPropagation();
 
- 			e.preventDefault();
 
- 			rmTm && clearTimeout(rmTm);
 
- 			opts.onHidden && opts.onHidden();
 
- 			self.stop().remove();
 
- 		}).on('mouseenter mouseleave', function(e) {
 
- 			if (opts.timeOut) {
 
- 				rmTm && clearTimeout(rmTm);
 
- 				rmTm = null;
 
- 				if (e.type === 'mouseenter') {
 
- 					show(true);
 
- 				} else {
 
- 					rmTm = setTimeout(rm, opts.timeOut);
 
- 				}
 
- 			}
 
- 		}).hide().addClass('toast-' + opts.mode).append($('<div class="elfinder-toast-msg"/>').html(opts.msg.replace(/%([a-zA-Z0-9]+)%/g, function(m, m1) {
 
- 			return fm.i18n(m1);
 
- 		})));
 
- 		
 
- 		if (opts.extNode) {
 
- 			self.append(opts.extNode);
 
- 		}
 
- 		if (opts.button) {
 
- 			self.append(
 
- 				$('<button class="ui-button ui-widget ui-state-default ui-corner-all elfinder-tabstop"/>')
 
- 				.append($('<span class="ui-button-text"/>').text(fm.i18n(opts.button.text)))
 
- 				.on('mouseenter mouseleave', function(e) { 
 
- 					$(this).toggleClass('ui-state-hover', e.type == 'mouseenter');
 
- 				})
 
- 				.on('click', opts.button.click || function(){})
 
- 			);
 
- 		}
 
- 		if (opts.width) {
 
- 			self.css('max-width', opts.width);
 
- 		}
 
- 		
 
- 		show();
 
- 	});
 
- };
 
- /*
 
-  * File: /js/ui/toolbar.js
 
-  */
 
- /**
 
-  * @class  elFinder toolbar
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.elfindertoolbar = function(fm, opts) {
 
- 		this.not('.elfinder-toolbar').each(function() {
 
- 		var commands = fm._commands,
 
- 			self     = $(this).addClass('ui-helper-clearfix ui-widget-header elfinder-toolbar'),
 
- 			options  = {
 
- 				// default options
 
- 				displayTextLabel: false,
 
- 				labelExcludeUA: ['Mobile'],
 
- 				autoHideUA: ['Mobile'],
 
- 				showPreferenceButton: 'none'
 
- 			},
 
- 			filter   = function(opts) {
 
- 				return $.grep(opts, function(v) {
 
- 					if ($.isPlainObject(v)) {
 
- 						options = Object.assign(options, v);
 
- 						return false;
 
- 					}
 
- 					return true;
 
- 				});
 
- 			},
 
- 			render = function(disabled){
 
- 				var name,cmdPref;
 
- 				
 
- 				$.each(buttons, function(i, b) { b.detach(); });
 
- 				self.empty();
 
- 				l = panels.length;
 
- 				while (l--) {
 
- 					if (panels[l]) {
 
- 						panel = $('<div class="ui-widget-content ui-corner-all elfinder-buttonset"/>');
 
- 						i = panels[l].length;
 
- 						while (i--) {
 
- 							name = panels[l][i];
 
- 							if ((!disabled || !disabled[name]) && (cmd = commands[name])) {
 
- 								button = 'elfinder'+cmd.options.ui;
 
- 								if (! buttons[name] && $.fn[button]) {
 
- 									buttons[name] = $('<div/>')[button](cmd);
 
- 								}
 
- 								if (buttons[name]) {
 
- 									buttons[name].children('.elfinder-button-text')[textLabel? 'show' : 'hide']();
 
- 									panel.prepend(buttons[name]);
 
- 								}
 
- 							}
 
- 						}
 
- 						
 
- 						panel.children().length && self.prepend(panel);
 
- 						panel.children(':gt(0)').before('<span class="ui-widget-content elfinder-toolbar-button-separator"/>');
 
- 					}
 
- 				}
 
- 				
 
- 				if (cmdPref = commands['preference']) {
 
- 					//cmdPref.state = !self.children().length? 0 : -1;
 
- 					if (options.showPreferenceButton === 'always' || (!self.children().length && options.showPreferenceButton === 'auto')) {
 
- 						//cmdPref.state = 0;
 
- 						panel = $('<div class="ui-widget-content ui-corner-all elfinder-buttonset"/>');
 
- 						name = 'preference';
 
- 						button = 'elfinder'+cmd.options.ui;
 
- 						buttons[name] = $('<div/>')[button](cmdPref);
 
- 						buttons[name].children('.elfinder-button-text')[textLabel? 'show' : 'hide']();
 
- 						panel.prepend(buttons[name]);
 
- 						self.append(panel);
 
- 					}
 
- 				}
 
- 				
 
- 				(! self.data('swipeClose') && self.children().length)? self.show() : self.hide();
 
- 				prevHeight = self[0].clientHeight;
 
- 				fm.trigger('toolbarload').trigger('uiresize');
 
- 			},
 
- 			buttons = {},
 
- 			panels   = filter(opts || []),
 
- 			dispre   = null,
 
- 			uiCmdMapPrev = '',
 
- 			prevHeight = 0,
 
- 			contextRaw = [],
 
- 			l, i, cmd, panel, button, swipeHandle, autoHide, textLabel, resizeTm;
 
- 		
 
- 		// normalize options
 
- 		options.showPreferenceButton = options.showPreferenceButton.toLowerCase();
 
- 		
 
- 		if (options.displayTextLabel !== 'none') {
 
- 			// correction of options.displayTextLabel
 
- 			textLabel = fm.storage('toolbarTextLabel');
 
- 			if (textLabel === null) {
 
- 				textLabel = (options.displayTextLabel && (! options.labelExcludeUA || ! options.labelExcludeUA.length || ! $.grep(options.labelExcludeUA, function(v){ return fm.UA[v]? true : false; }).length));
 
- 			} else {
 
- 				textLabel = (textLabel == 1);
 
- 			}
 
- 			contextRaw.push({
 
- 				label    : fm.i18n('textLabel'),
 
- 				icon     : 'text',
 
- 				callback : function() {
 
- 					textLabel = ! textLabel;
 
- 					self.css('height', '').find('.elfinder-button-text')[textLabel? 'show':'hide']();
 
- 					fm.trigger('uiresize').storage('toolbarTextLabel', textLabel? '1' : '0');
 
- 				},
 
- 			});
 
- 		}
 
- 		if (options.preferenceInContextmenu && commands['preference']) {
 
- 			contextRaw.push({
 
- 				label    : fm.i18n('toolbarPref'),
 
- 				icon     : 'preference',
 
- 				callback : function() {
 
- 					fm.exec('preference', void(0), {tab: 'toolbar'});
 
- 				}
 
- 			});
 
- 		}
 
- 		// add contextmenu
 
- 		if (contextRaw.length) {
 
- 			self.on('contextmenu', function(e) {
 
- 					e.stopPropagation();
 
- 					e.preventDefault();
 
- 					fm.trigger('contextmenu', {
 
- 						raw: contextRaw,
 
- 						x: e.pageX,
 
- 						y: e.pageY
 
- 					});
 
- 				}).on('touchstart', function(e) {
 
- 					if (e.originalEvent.touches.length > 1) {
 
- 						return;
 
- 					}
 
- 					self.data('tmlongtap') && clearTimeout(self.data('tmlongtap'));
 
- 					self.removeData('longtap')
 
- 						.data('longtap', {x: e.originalEvent.touches[0].pageX, y: e.originalEvent.touches[0].pageY})
 
- 						.data('tmlongtap', setTimeout(function() {
 
- 							self.removeData('longtapTm')
 
- 								.trigger({
 
- 									type: 'contextmenu',
 
- 									pageX: self.data('longtap').x,
 
- 									pageY: self.data('longtap').y
 
- 								})
 
- 								.data('longtap', {longtap: true});
 
- 						}, 500));
 
- 				}).on('touchmove touchend', function(e) {
 
- 					if (self.data('tmlongtap')) {
 
- 						if (e.type === 'touchend' ||
 
- 								( Math.abs(self.data('longtap').x - e.originalEvent.touches[0].pageX)
 
- 								+ Math.abs(self.data('longtap').y - e.originalEvent.touches[0].pageY)) > 4)
 
- 						clearTimeout(self.data('tmlongtap'));
 
- 						self.removeData('longtapTm');
 
- 					}
 
- 				}).on('click', function(e) {
 
- 					if (self.data('longtap') && self.data('longtap').longtap) {
 
- 						e.stopImmediatePropagation();
 
- 						e.preventDefault();
 
- 					}
 
- 				}).on('touchend click', '.elfinder-button', function(e) {
 
- 					if (self.data('longtap') && self.data('longtap').longtap) {
 
- 						e.stopImmediatePropagation();
 
- 						e.preventDefault();
 
- 					}
 
- 				}
 
- 			);
 
- 		}
 
- 		self.prev().length && self.parent().prepend(this);
 
- 		
 
- 		render();
 
- 		
 
- 		fm.bind('open sync select toolbarpref', function() {
 
- 			var disabled = Object.assign({}, fm.option('disabledFlip')),
 
- 				userHides = fm.storage('toolbarhides'),
 
- 				doRender, sel, disabledKeys;
 
- 			
 
- 			if (! userHides && Array.isArray(options.defaultHides)) {
 
- 				userHides = {};
 
- 				$.each(options.defaultHides, function() {
 
- 					userHides[this] = true;
 
- 				});
 
- 				fm.storage('toolbarhides', userHides);
 
- 			}
 
- 			if (this.type === 'select') {
 
- 				if (fm.searchStatus.state < 2) {
 
- 					return;
 
- 				}
 
- 				sel = fm.selected();
 
- 				if (sel.length) {
 
- 					disabled = fm.getDisabledCmds(sel, true);
 
- 				}
 
- 			}
 
- 			
 
- 			$.each(userHides, function(n) {
 
- 				if (!disabled[n]) {
 
- 					disabled[n] = true;
 
- 				}
 
- 			});
 
- 			
 
- 			if (Object.keys(fm.commandMap).length) {
 
- 				$.each(fm.commandMap, function(from, to){
 
- 					if (to === 'hidden') {
 
- 						disabled[from] = true;
 
- 					}
 
- 				});
 
- 			}
 
- 			
 
- 			disabledKeys = Object.keys(disabled);
 
- 			if (!dispre || dispre.toString() !== disabledKeys.sort().toString()) {
 
- 				render(disabledKeys.length? disabled : null);
 
- 				doRender = true;
 
- 			}
 
- 			dispre = disabledKeys.sort();
 
- 			if (doRender || uiCmdMapPrev !== JSON.stringify(fm.commandMap)) {
 
- 				uiCmdMapPrev = JSON.stringify(fm.commandMap);
 
- 				if (! doRender) {
 
- 					// reset toolbar
 
- 					$.each($('div.elfinder-button'), function(){
 
- 						var origin = $(this).data('origin');
 
- 						if (origin) {
 
- 							$(this).after(origin).detach();
 
- 						}
 
- 					});
 
- 				}
 
- 				if (Object.keys(fm.commandMap).length) {
 
- 					$.each(fm.commandMap, function(from, to){
 
- 						var cmd = fm._commands[to],
 
- 							button = cmd? 'elfinder'+cmd.options.ui : null,
 
- 							btn;
 
- 						if (button && $.fn[button]) {
 
- 							btn = buttons[from];
 
- 							if (btn) {
 
- 								if (! buttons[to] && $.fn[button]) {
 
- 									buttons[to] = $('<div/>')[button](cmd);
 
- 									if (buttons[to]) {
 
- 										buttons[to].children('.elfinder-button-text')[textLabel? 'show' : 'hide']();
 
- 										if (cmd.extendsCmd) {
 
- 											buttons[to].children('span.elfinder-button-icon').addClass('elfinder-button-icon-' + cmd.extendsCmd);
 
- 										}
 
- 									}
 
- 								}
 
- 								if (buttons[to]) {
 
- 									btn.after(buttons[to]);
 
- 									buttons[to].data('origin', btn.detach());
 
- 								}
 
- 							}
 
- 						}
 
- 					});
 
- 				}
 
- 			}
 
- 		}).bind('resize', function(e) {
 
- 			resizeTm && cancelAnimationFrame(resizeTm);
 
- 			resizeTm = requestAnimationFrame(function() {
 
- 				var h = self[0].clientHeight;
 
- 				if (prevHeight !== h) {
 
- 					prevHeight = h;
 
- 					fm.trigger('uiresize');
 
- 				}
 
- 			});
 
- 		});
 
- 		
 
- 		if (fm.UA.Touch) {
 
- 			autoHide = fm.storage('autoHide') || {};
 
- 			if (typeof autoHide.toolbar === 'undefined') {
 
- 				autoHide.toolbar = (options.autoHideUA && options.autoHideUA.length > 0 && $.grep(options.autoHideUA, function(v){ return fm.UA[v]? true : false; }).length);
 
- 				fm.storage('autoHide', autoHide);
 
- 			}
 
- 			
 
- 			if (autoHide.toolbar) {
 
- 				fm.one('init', function() {
 
- 					fm.uiAutoHide.push(function(){ self.stop(true, true).trigger('toggle', { duration: 500, init: true }); });
 
- 				});
 
- 			}
 
- 			
 
- 			fm.bind('load', function() {
 
- 				swipeHandle = $('<div class="elfinder-toolbar-swipe-handle"/>').hide().appendTo(fm.getUI());
 
- 				if (swipeHandle.css('pointer-events') !== 'none') {
 
- 					swipeHandle.remove();
 
- 					swipeHandle = null;
 
- 				}
 
- 			});
 
- 			
 
- 			self.on('toggle', function(e, data) {
 
- 				var wz    = fm.getUI('workzone'),
 
- 					toshow= self.is(':hidden'),
 
- 					wzh   = wz.height(),
 
- 					h     = self.height(),
 
- 					tbh   = self.outerHeight(true),
 
- 					delta = tbh - h,
 
- 					opt   = Object.assign({
 
- 						step: function(now) {
 
- 							wz.height(wzh + (toshow? (now + delta) * -1 : h - now));
 
- 							fm.trigger('resize');
 
- 						},
 
- 						always: function() {
 
- 							requestAnimationFrame(function() {
 
- 								self.css('height', '');
 
- 								fm.trigger('uiresize');
 
- 								if (swipeHandle) {
 
- 									if (toshow) {
 
- 										swipeHandle.stop(true, true).hide();
 
- 									} else {
 
- 										swipeHandle.height(data.handleH? data.handleH : '');
 
- 										fm.resources.blink(swipeHandle, 'slowonce');
 
- 									}
 
- 								}
 
- 								toshow && self.scrollTop('0px');
 
- 								data.init && fm.trigger('uiautohide');
 
- 							});
 
- 						}
 
- 					}, data);
 
- 				self.data('swipeClose', ! toshow).stop(true, true).animate({height : 'toggle'}, opt);
 
- 				autoHide.toolbar = !toshow;
 
- 				fm.storage('autoHide', Object.assign(fm.storage('autoHide'), {toolbar: autoHide.toolbar}));
 
- 			}).on('touchstart', function(e) {
 
- 				if (self.scrollBottom() > 5) {
 
- 					e.originalEvent._preventSwipeY = true;
 
- 				}
 
- 			});
 
- 		}
 
- 	});
 
- 	
 
- 	return this;
 
- };
 
- /*
 
-  * File: /js/ui/tree.js
 
-  */
 
- /**
 
-  * @class  elFinder folders tree
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.elfindertree = function(fm, opts) {
 
- 		var treeclass = fm.res('class', 'tree');
 
- 	
 
- 	this.not('.'+treeclass).each(function() {
 
- 		var c = 'class', mobile = fm.UA.Mobile,
 
- 			
 
- 			/**
 
- 			 * Root directory class name
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			root      = fm.res(c, 'treeroot'),
 
- 			/**
 
- 			 * Open root dir if not opened yet
 
- 			 *
 
- 			 * @type Boolean
 
- 			 */
 
- 			openRoot  = opts.openRootOnLoad,
 
- 			/**
 
- 			 * Open current work dir if not opened yet
 
- 			 *
 
- 			 * @type Boolean
 
- 			 */
 
- 			openCwd   = opts.openCwdOnOpen,
 
- 			
 
- 			/**
 
- 			 * Auto loading current directory parents and do expand their node
 
- 			 *
 
- 			 * @type Boolean
 
- 			 */
 
- 			syncTree  = openCwd || opts.syncTree,
 
- 			
 
- 			/**
 
- 			 * Subtree class name
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			subtree   = fm.res(c, 'navsubtree'),
 
- 			
 
- 			/**
 
- 			 * Directory class name
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			navdir    = fm.res(c, 'treedir'),
 
- 			
 
- 			/**
 
- 			 * Directory CSS selector
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			selNavdir = 'span.' + navdir,
 
- 			
 
- 			/**
 
- 			 * Collapsed arrow class name
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			collapsed = fm.res(c, 'navcollapse'),
 
- 			
 
- 			/**
 
- 			 * Expanded arrow class name
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			expanded  = fm.res(c, 'navexpand'),
 
- 			
 
- 			/**
 
- 			 * Class name to mark arrow for directory with already loaded children
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			loaded    = 'elfinder-subtree-loaded',
 
- 			
 
- 			/**
 
- 			 * Class name to mark need subdirs request
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			chksubdir = 'elfinder-subtree-chksubdir',
 
- 			
 
- 			/**
 
- 			 * Arraw class name
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			arrow = fm.res(c, 'navarrow'),
 
- 			
 
- 			/**
 
- 			 * Current directory class name
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			active    = fm.res(c, 'active'),
 
- 			
 
- 			/**
 
- 			 * Droppable dirs dropover class
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			dropover = fm.res(c, 'adroppable'),
 
- 			
 
- 			/**
 
- 			 * Hover class name
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			hover    = fm.res(c, 'hover'),
 
- 			
 
- 			/**
 
- 			 * Disabled dir class name
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			disabled = fm.res(c, 'disabled'),
 
- 			
 
- 			/**
 
- 			 * Draggable dir class name
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			draggable = fm.res(c, 'draggable'),
 
- 			
 
- 			/**
 
- 			 * Droppable dir  class name
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			droppable = fm.res(c, 'droppable'),
 
- 			
 
- 			/**
 
- 			 * root wrapper class
 
- 			 * 
 
- 			 * @type String
 
- 			 */
 
- 			wrapperRoot = 'elfinder-navbar-wrapper-root',
 
- 			/**
 
- 			 * Un-disabled cmd `paste` volume's root wrapper class
 
- 			 * 
 
- 			 * @type String
 
- 			 */
 
- 			pastable = 'elfinder-navbar-wrapper-pastable',
 
- 			
 
- 			/**
 
- 			 * Un-disabled cmd `upload` volume's root wrapper class
 
- 			 * 
 
- 			 * @type String
 
- 			 */
 
- 			uploadable = 'elfinder-navbar-wrapper-uploadable',
 
- 			
 
- 			/**
 
- 			 * Is position x inside Navbar
 
- 			 * 
 
- 			 * @param x Numbar
 
- 			 * 
 
- 			 * @return
 
- 			 */
 
- 			insideNavbar = function(x) {
 
- 				var left = navbar.offset().left;
 
- 					
 
- 				return left <= x && x <= left + navbar.width();
 
- 			},
 
- 			
 
- 			/**
 
- 			 * To call subdirs elements queue
 
- 			 * 
 
- 			 * @type Object
 
- 			 */
 
- 			subdirsQue = {},
 
- 			
 
- 			/**
 
- 			 * To exec subdirs elements ids
 
- 			 * 
 
- 			 */
 
- 			subdirsExecQue = [],
 
- 			
 
- 			/**
 
- 			 * Request subdirs to backend
 
- 			 * 
 
- 			 * @param id String
 
- 			 * 
 
- 			 * @return Deferred
 
- 			 */
 
- 			subdirs = function(ids) {
 
- 				var targets = [];
 
- 				$.each(ids, function(i, id) {
 
- 					subdirsQue[id] && targets.push(fm.navId2Hash(id));
 
- 					delete subdirsQue[id];
 
- 				});
 
- 				if (targets.length) {
 
- 					return fm.request({
 
- 						data: {
 
- 							cmd: 'subdirs',
 
- 							targets: targets,
 
- 							preventDefault : true
 
- 						}
 
- 					}).done(function(res) {
 
- 						if (res && res.subdirs) {
 
- 							$.each(res.subdirs, function(hash, subdirs) {
 
- 								var elm = $('#'+fm.navHash2Id(hash));
 
- 								elm.removeClass(chksubdir);
 
- 								elm[subdirs? 'addClass' : 'removeClass'](collapsed);
 
- 							});
 
- 						}
 
- 					});
 
- 				}
 
- 			},
 
- 			
 
- 			subdirsJobRes = null,
 
- 			
 
- 			/**
 
- 			 * To check target element is in window of subdirs
 
- 			 * 
 
- 			 * @return void
 
- 			 */
 
- 			checkSubdirs = function() {
 
- 				var ids = Object.keys(subdirsQue);
 
- 				if (ids.length) {
 
- 					subdirsJobRes && subdirsJobRes._abort();
 
- 					execSubdirsTm && clearTimeout(execSubdirsTm);
 
- 					subdirsExecQue = [];
 
- 					subdirsJobRes = fm.asyncJob(function(id) {
 
- 						return fm.isInWindow($('#'+id))? id : null;
 
- 					}, ids, { numPerOnce: 200 })
 
- 					.done(function(arr) {
 
- 						if (arr.length) {
 
- 							subdirsExecQue = arr;
 
- 							execSubdirs();
 
- 						}
 
- 					});
 
- 				}
 
- 			},
 
- 			
 
- 			subdirsPending = 0,
 
- 			execSubdirsTm,
 
- 			
 
- 			/**
 
- 			 * Exec subdirs as batch request
 
- 			 * 
 
- 			 * @return void
 
- 			 */
 
- 			execSubdirs = function() {
 
- 				var cnt = opts.subdirsMaxConn - subdirsPending,
 
- 					atOnce = fm.maxTargets? Math.min(fm.maxTargets, opts.subdirsAtOnce) : opts.subdirsAtOnce,
 
- 					i, ids;
 
- 				execSubdirsTm && cancelAnimationFrame(execSubdirsTm);
 
- 				if (subdirsExecQue.length) {
 
- 					if (cnt > 0) {
 
- 						for (i = 0; i < cnt; i++) {
 
- 							if (subdirsExecQue.length) {
 
- 								subdirsPending++;
 
- 								subdirs(subdirsExecQue.splice(0, atOnce)).always(function() {
 
- 									subdirsPending--;
 
- 									execSubdirs();
 
- 								});
 
- 							}
 
- 						}
 
- 					} else {
 
- 						execSubdirsTm = requestAnimationFrame(function() {
 
- 							subdirsExecQue.length && execSubdirs();
 
- 						});
 
- 					}
 
- 				}
 
- 			},
 
- 			
 
- 			drop = fm.droppable.drop,
 
- 			
 
- 			/**
 
- 			 * Droppable options
 
- 			 *
 
- 			 * @type Object
 
- 			 */
 
- 			droppableopts = $.extend(true, {}, fm.droppable, {
 
- 				// show subfolders on dropover
 
- 				over : function(e, ui) {
 
- 					var dst    = $(this),
 
- 						helper = ui.helper,
 
- 						cl     = hover+' '+dropover,
 
- 						hash, status;
 
- 					e.stopPropagation();
 
- 					helper.data('dropover', helper.data('dropover') + 1);
 
- 					dst.data('dropover', true);
 
- 					if (ui.helper.data('namespace') !== fm.namespace || ! insideNavbar(e.clientX) || ! fm.insideWorkzone(e.pageX, e.pageY)) {
 
- 						dst.removeClass(cl);
 
- 						helper.removeClass('elfinder-drag-helper-move elfinder-drag-helper-plus');
 
- 						return;
 
- 					}
 
- 					dst.addClass(hover);
 
- 					if (dst.is('.'+collapsed+':not(.'+expanded+')')) {
 
- 						dst.data('expandTimer', setTimeout(function() {
 
- 							dst.is('.'+collapsed+'.'+hover) && dst.children('.'+arrow).trigger('click');
 
- 						}, 500));
 
- 					}
 
- 					if (dst.is('.elfinder-ro,.elfinder-na')) {
 
- 						dst.removeClass(dropover);
 
- 						helper.removeClass('elfinder-drag-helper-move elfinder-drag-helper-plus');
 
- 						return;
 
- 					}
 
- 					hash = fm.navId2Hash(dst.attr('id'));
 
- 					dst.data('dropover', hash);
 
- 					$.each(ui.helper.data('files'), function(i, h) {
 
- 						if (h === hash || (fm.file(h).phash === hash && !ui.helper.hasClass('elfinder-drag-helper-plus'))) {
 
- 							dst.removeClass(cl);
 
- 							return false; // break $.each
 
- 						}
 
- 					});
 
- 					if (helper.data('locked')) {
 
- 						status = 'elfinder-drag-helper-plus';
 
- 					} else {
 
- 						status = 'elfinder-drag-helper-move';
 
- 						if (e.shiftKey || e.ctrlKey || e.metaKey) {
 
- 							status += ' elfinder-drag-helper-plus';
 
- 						}
 
- 					}
 
- 					dst.hasClass(dropover) && helper.addClass(status);
 
- 					requestAnimationFrame(function(){ dst.hasClass(dropover) && helper.addClass(status); });
 
- 				},
 
- 				out : function(e, ui) {
 
- 					var dst    = $(this),
 
- 						helper = ui.helper;
 
- 					e.stopPropagation();
 
- 					helper.removeClass('elfinder-drag-helper-move elfinder-drag-helper-plus').data('dropover', Math.max(helper.data('dropover') - 1, 0));
 
- 					dst.data('expandTimer') && clearTimeout(dst.data('expandTimer'));
 
- 					dst.removeData('dropover')
 
- 					   .removeClass(hover+' '+dropover);
 
- 				},
 
- 				deactivate : function() {
 
- 					$(this).removeData('dropover')
 
- 					       .removeClass(hover+' '+dropover);
 
- 				},
 
- 				drop : function(e, ui) {
 
- 					insideNavbar(e.clientX) && drop.call(this, e, ui);
 
- 				}
 
- 			}),
 
- 			
 
- 			spinner = $(fm.res('tpl', 'navspinner')),
 
- 			
 
- 			/**
 
- 			 * Directory html template
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			tpl = fm.res('tpl', 'navdir'),
 
- 			
 
- 			/**
 
- 			 * Permissions marker html template
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			ptpl = fm.res('tpl', 'perms'),
 
- 			
 
- 			/**
 
- 			 * Lock marker html template
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			ltpl = fm.res('tpl', 'lock'),
 
- 			
 
- 			/**
 
- 			 * Symlink marker html template
 
- 			 *
 
- 			 * @type String
 
- 			 */
 
- 			stpl = fm.res('tpl', 'symlink'),
 
- 			
 
- 			/**
 
- 			 * Directory hashes that has more pages
 
- 			 * 
 
- 			 * @type Object
 
- 			 */
 
- 			hasMoreDirs = {},
 
- 			
 
- 			/**
 
- 			 * Html template replacement methods
 
- 			 *
 
- 			 * @type Object
 
- 			 */
 
- 			replace = {
 
- 				id          : function(dir) { return fm.navHash2Id(dir.hash); },
 
- 				name        : function(dir) { return fm.escape(dir.i18 || dir.name); },
 
- 				cssclass    : function(dir) {
 
- 					var cname = (dir.phash && ! dir.isroot ? '' : root)+' '+navdir+' '+fm.perms2class(dir);
 
- 					dir.dirs && !dir.link && (cname += ' ' + collapsed) && dir.dirs == -1 && (cname += ' ' + chksubdir);
 
- 					opts.getClass && (cname += ' ' + opts.getClass(dir));
 
- 					dir.csscls && (cname += ' ' + fm.escape(dir.csscls));
 
- 					return cname;
 
- 				},
 
- 				root        : function(dir) {
 
- 					var cls = '';
 
- 					if (!dir.phash || dir.isroot) {
 
- 						cls += ' '+wrapperRoot;
 
- 						if (!dir.disabled || dir.disabled.length < 1) {
 
- 							cls += ' '+pastable+' '+uploadable;
 
- 						} else {
 
- 							if ($.inArray('paste', dir.disabled) === -1) {
 
- 								cls += ' '+pastable;
 
- 							}
 
- 							if ($.inArray('upload', dir.disabled) === -1) {
 
- 								cls += ' '+uploadable;
 
- 							}
 
- 						}
 
- 						return cls;
 
- 					} else {
 
- 						return '';
 
- 					}
 
- 				},
 
- 				permissions : function(dir) { return !dir.read || !dir.write ? ptpl : ''; },
 
- 				symlink     : function(dir) { return dir.alias ? stpl : ''; },
 
- 				style       : function(dir) { return dir.icon ? fm.getIconStyle(dir) : ''; }
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Return html for given dir
 
- 			 *
 
- 			 * @param  Object  directory
 
- 			 * @return String
 
- 			 */
 
- 			itemhtml = function(dir) {
 
- 				return tpl.replace(/(?:\{([a-z]+)\})/ig, function(m, key) {
 
- 					var res = replace[key] ? replace[key](dir) : (dir[key] || '');
 
- 					if (key === 'id' && dir.dirs == -1) {
 
- 						subdirsQue[res] = res;
 
- 					}
 
- 					return res;
 
- 				});
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Return only dirs from files list
 
- 			 *
 
- 			 * @param  Array   files list
 
- 			 * @param  Boolean do check exists
 
- 			 * @return Array
 
- 			 */
 
- 			filter = function(files, checkExists) {
 
- 				return $.map(files || [], function(f) {
 
- 					return (f.mime === 'directory' && (!checkExists || $('#'+fm.navHash2Id(f.hash)).length)) ? f : null;
 
- 				});
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Find parent subtree for required directory
 
- 			 *
 
- 			 * @param  String  dir hash
 
- 			 * @return jQuery
 
- 			 */
 
- 			findSubtree = function(hash) {
 
- 				return hash ? $('#'+fm.navHash2Id(hash)).next('.'+subtree) : tree;
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Find directory (wrapper) in required node
 
- 			 * before which we can insert new directory
 
- 			 *
 
- 			 * @param  jQuery  parent directory
 
- 			 * @param  Object  new directory
 
- 			 * @return jQuery
 
- 			 */
 
- 			findSibling = function(subtree, dir) {
 
- 				var node = subtree.children(':first'),
 
- 					info;
 
- 				while (node.length) {
 
- 					info = fm.file(fm.navId2Hash(node.children('[id]').attr('id')));
 
- 					
 
- 					if ((info = fm.file(fm.navId2Hash(node.children('[id]').attr('id')))) 
 
- 					&& compare(dir, info) < 0) {
 
- 						return node;
 
- 					}
 
- 					node = node.next();
 
- 				}
 
- 				return subtree.children('button.elfinder-navbar-pager-next');
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Add new dirs in tree
 
- 			 *
 
- 			 * @param  Array  dirs list
 
- 			 * @return void
 
- 			 */
 
- 			updateTree = function(dirs) {
 
- 				var length  = dirs.length,
 
- 					orphans = [],
 
- 					i = length,
 
- 					tgts = $(),
 
- 					done = {},
 
- 					cwd = fm.cwd(),
 
- 					append = function(parent, dirs, start, direction) {
 
- 						var hashes = {},
 
- 							curStart = 0,
 
- 							max = fm.newAPI? Math.min(10000, Math.max(10, opts.subTreeMax)) : 10000,
 
- 							setHashes = function() {
 
- 								hashes = {};
 
- 								$.each(dirs, function(i, d) {
 
- 									hashes[d.hash] = i;
 
- 								});
 
- 							},
 
- 							change = function(mode) {
 
- 								if (mode === 'prepare') {
 
- 									$.each(dirs, function(i, d) {
 
- 										d.node && parent.append(d.node.hide());
 
- 									});
 
- 								} else if (mode === 'done') {
 
- 									$.each(dirs, function(i, d) {
 
- 										d.node && d.node.detach().show();
 
- 									});
 
- 								}
 
- 							},
 
- 							update = function(e, data) {
 
- 								var i, changed;
 
- 								e.stopPropagation();
 
- 								
 
- 								if (data.select) {
 
- 									render(getStart(data.select));
 
- 									return;
 
- 								}
 
- 								
 
- 								if (data.change) {
 
- 									change(data.change);
 
- 									return;
 
- 								}
 
- 								
 
- 								if (data.removed && data.removed.length) {
 
- 									dirs = $.grep(dirs, function(d) {
 
- 										if (data.removed.indexOf(d.hash) === -1) {
 
- 											return true;
 
- 										} else {
 
- 											!changed && (changed = true);
 
- 											return false;
 
- 										}
 
- 									});
 
- 								}
 
- 								
 
- 								if (data.added && data.added.length) {
 
- 									dirs = dirs.concat($.grep(data.added, function(d) {
 
- 										if (hashes[d.hash] === void(0)) {
 
- 											!changed && (changed = true);
 
- 											return true;
 
- 										} else {
 
- 											return false;
 
- 										}
 
- 									}));
 
- 								}
 
- 								if (changed) {
 
- 									dirs.sort(compare);
 
- 									setHashes();
 
- 									render(curStart);
 
- 								}
 
- 							},
 
- 							getStart = function(target) {
 
- 								if (hashes[target] !== void(0)) {
 
- 									return Math.floor(hashes[target] / max) * max;
 
- 								}
 
- 								return void(0);
 
- 							},
 
- 							target = fm.navId2Hash(parent.prev('[id]').attr('id')),
 
- 							render = function(start, direction) {
 
- 								var html = [],
 
- 									nodes = {},
 
- 									total, page, s, parts, prev, next, prevBtn, nextBtn;
 
- 								delete hasMoreDirs[target];
 
- 								curStart = start;
 
- 								parent.off('update.'+fm.namespace, update);
 
- 								if (dirs.length > max) {
 
- 									parent.on('update.'+fm.namespace, update);
 
- 									if (start === void(0)) {
 
- 										s = 0;
 
- 										setHashes();
 
- 										start = getStart(cwd.hash);
 
- 										if (start === void(0)) {
 
- 											start = 0;
 
- 										}
 
- 									}
 
- 									parts = dirs.slice(start, start + max);
 
- 									hasMoreDirs[target] = parent;
 
- 									prev = start? Math.max(-1, start - max) : -1;
 
- 									next = (start + max >= dirs.length)? 0 : start + max;
 
- 									total = Math.ceil(dirs.length/max);
 
- 									page = Math.ceil(start/max);
 
- 								}
 
- 								$.each(parts || dirs, function(i, d) {
 
- 									html.push(itemhtml(d));
 
- 									if (d.node) {
 
- 										nodes[d.hash] = d.node;
 
- 									}
 
- 								});
 
- 								if (prev > -1) {
 
- 									prevBtn = $('<button class="elfinder-navbar-pager elfinder-navbar-pager-prev"/>')
 
- 										.text(fm.i18n('btnPrevious', page, total))
 
- 										.button({
 
- 											icons: {
 
- 												primary: "ui-icon-caret-1-n"
 
- 											}
 
- 										})
 
- 										.on('click', function(e) {
 
- 											e.preventDefault();
 
- 											e.stopPropagation();
 
- 											render(prev, 'up');
 
- 										});
 
- 								} else {
 
- 									prevBtn = $();
 
- 								}
 
- 								if (next) {
 
- 									nextBtn = $('<button class="elfinder-navbar-pager elfinder-navbar-pager-next"/>')
 
- 										.text(fm.i18n('btnNext', page + 2, total))
 
- 										.button({
 
- 											icons: {
 
- 												primary: "ui-icon-caret-1-s"
 
- 											}
 
- 										})
 
- 										.on('click', function(e) {
 
- 											e.preventDefault();
 
- 											e.stopPropagation();
 
- 											render(next, 'down');
 
- 										});
 
- 								} else {
 
- 									nextBtn = $();
 
- 								}
 
- 								detach();
 
- 								parent.empty()[parts? 'addClass' : 'removeClass']('elfinder-navbar-hasmore').append(prevBtn, html.join(''), nextBtn);
 
- 								$.each(nodes, function(h, n) {
 
- 									$('#'+fm.navHash2Id(h)).parent().replaceWith(n);
 
- 								});
 
- 								if (direction) {
 
- 									autoScroll(fm.navHash2Id(parts[direction === 'up'? parts.length - 1 : 0].hash));
 
- 								}
 
- 								! mobile && fm.lazy(function() { updateDroppable(null, parent); });
 
- 							},
 
- 							detach = function() {
 
- 								$.each(parent.children('.elfinder-navbar-wrapper'), function(i, elm) {
 
- 									var n = $(elm),
 
- 										ch = n.children('[id]:first'),
 
- 										h, c;
 
- 									if (ch.hasClass(loaded)) {
 
- 										h = fm.navId2Hash(ch.attr('id'));
 
- 										if (h && (c = hashes[h]) !== void(0)) {
 
- 											dirs[c].node = n.detach();
 
- 										}
 
- 									}
 
- 								});
 
- 							};
 
- 						
 
- 						render();
 
- 					},
 
- 					dir, html, parent, sibling, init, atonce = {}, updates = [], base, node,
 
- 					firstVol = true; // check for netmount volume
 
- 				
 
- 				while (i--) {
 
- 					dir = dirs[i];
 
- 					if (done[dir.hash] || $('#'+fm.navHash2Id(dir.hash)).length) {
 
- 						continue;
 
- 					}
 
- 					done[dir.hash] = true;
 
- 					
 
- 					if ((parent = findSubtree(dir.phash)).length) {
 
- 						if (dir.phash && ((init = !parent.children().length) || parent.hasClass('elfinder-navbar-hasmore') || (sibling = findSibling(parent, dir)).length)) {
 
- 							if (init) {
 
- 								if (!atonce[dir.phash]) {
 
- 									atonce[dir.phash] = [];
 
- 								}
 
- 								atonce[dir.phash].push(dir);
 
- 							} else {
 
- 								if (sibling) {
 
- 									node = itemhtml(dir);
 
- 									sibling.before(node);
 
- 									! mobile && (tgts = tgts.add(node));
 
- 								} else {
 
- 									updates.push(dir);
 
- 								}
 
- 							}
 
- 						} else {
 
- 							node = itemhtml(dir);
 
- 							parent[firstVol || dir.phash ? 'append' : 'prepend'](node);
 
- 							firstVol = false;
 
- 							if (!dir.phash || dir.isroot) {
 
- 								base = $('#'+fm.navHash2Id(dir.hash)).parent();
 
- 							}
 
- 							! mobile && updateDroppable(null, base);
 
- 						}
 
- 					} else {
 
- 						orphans.push(dir);
 
- 					}
 
- 				}
 
- 				// When init, html append at once
 
- 				if (Object.keys(atonce).length){
 
- 					$.each(atonce, function(p, dirs){
 
- 						var parent = findSubtree(p),
 
- 						    html   = [];
 
- 						dirs.sort(compare);
 
- 						append(parent, dirs);
 
- 					});
 
- 				}
 
- 				
 
- 				if (updates.length) {
 
- 					parent.trigger('update.' + fm.namespace, { added : updates });
 
- 				}
 
- 				
 
- 				if (orphans.length && orphans.length < length) {
 
- 					updateTree(orphans);
 
- 					return;
 
- 				} 
 
- 				
 
- 				! mobile && tgts.length && fm.lazy(function() { updateDroppable(tgts); });
 
- 				
 
- 			},
 
- 			
 
- 			/**
 
- 			 * sort function by dir.name
 
- 			 * 
 
- 			 */
 
- 			compare = function(dir1, dir2) {
 
- 				if (! fm.sortAlsoTreeview) {
 
- 					return fm.sortRules.name(dir1, dir2);
 
- 				} else {
 
- 					var asc   = fm.sortOrder == 'asc',
 
- 						type  = fm.sortType,
 
- 						rules = fm.sortRules,
 
- 						res;
 
- 					
 
- 					res = asc? rules[fm.sortType](dir1, dir2) : rules[fm.sortType](dir2, dir1);
 
- 					
 
- 					return type !== 'name' && res === 0
 
- 						? res = asc ? rules.name(dir1, dir2) : rules.name(dir2, dir1)
 
- 						: res;
 
- 				}
 
- 			},
 
- 			/**
 
- 			 * Timer ID of autoScroll
 
- 			 * 
 
- 			 * @type  Integer
 
- 			 */
 
- 			autoScrTm,
 
- 			/**
 
- 			 * Auto scroll to cwd
 
- 			 *
 
- 			 * @return Object  jQuery Deferred
 
- 			 */
 
- 			autoScroll = function(target) {
 
- 				var dfrd = $.Deferred(),
 
- 					current, parent, top, treeH, bottom, tgtTop;
 
- 				autoScrTm && clearTimeout(autoScrTm);
 
- 				autoScrTm = setTimeout(function() {
 
- 					current = $('#'+(target || fm.navHash2Id(fm.cwd().hash)));
 
- 					if (current.length) {
 
- 						// expand parents directory
 
- 						(openCwd? current : current.parent()).parents('.elfinder-navbar-wrapper').children('.'+loaded).addClass(expanded).next('.'+subtree).show();
 
- 						
 
- 						parent = tree.parent().stop(false, true);
 
- 						top = parent.offset().top;
 
- 						treeH = parent.height();
 
- 						bottom = top + treeH - current.outerHeight();
 
- 						tgtTop = current.offset().top;
 
- 						
 
- 						if (tgtTop < top || tgtTop > bottom) {
 
- 							parent.animate({
 
- 								scrollTop : parent.scrollTop() + tgtTop - top - treeH / 3
 
- 							}, {
 
- 								duration : opts.durations.autoScroll,
 
- 								complete : function() {	dfrd.resolve(); }
 
- 							});
 
- 						} else {
 
- 							dfrd.resolve();
 
- 						}
 
- 					} else {
 
- 						dfrd.reject();
 
- 					}
 
- 				}, 100);
 
- 				return dfrd;
 
- 			},
 
- 			/**
 
- 			 * Get hashes array of items of the bottom of the leaf root back from the target
 
- 			 * 
 
- 			 * @param Object elFinder item(directory) object
 
- 			 * @return Array hashes
 
- 			 */
 
- 			getEnds = function(d) {
 
- 				var cur = d || fm.cwd(),
 
- 					res = cur.hash? [ cur.hash ] : [],
 
- 					phash, root, dir;
 
- 				
 
- 				root = fm.root(cur.hash);
 
- 				dir = fm.file(root);
 
- 				while (dir && (phash = dir.phash)) {
 
- 					res.unshift(phash);
 
- 					root = fm.root(phash);
 
- 					dir = fm.file(root);
 
- 					if ($('#'+fm.navHash2Id(dir.hash)).hasClass(loaded)) {
 
- 						break;
 
- 					}
 
- 				}
 
- 				
 
- 				return res;
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Select pages back in order to display the target
 
- 			 * 
 
- 			 * @param Object elFinder item(directory) object
 
- 			 * @return Object jQuery node object of target node
 
- 			 */
 
- 			selectPages = function(current) {
 
- 				var cur = current || fm.cwd(),
 
- 					curHash = cur.hash,
 
- 					node = $('#'+fm.navHash2Id(curHash));
 
- 			
 
- 				if (!node.length) {
 
- 					while(cur && cur.phash) {
 
- 						if (hasMoreDirs[cur.phash] && !$('#'+fm.navHash2Id(cur.hash)).length) {
 
- 							hasMoreDirs[cur.phash].trigger('update.'+fm.namespace, { select : cur.hash });
 
- 						}
 
- 						cur = fm.file(cur.phash);
 
- 					}
 
- 					node = $('#'+fm.navHash2Id(curHash));
 
- 				}
 
- 				
 
- 				return node;
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Flag indicating that synchronization is currently in progress
 
- 			 * 
 
- 			 * @type Boolean
 
- 			 */
 
- 			syncing,
 
- 			/**
 
- 			 * Mark current directory as active
 
- 			 * If current directory is not in tree - load it and its parents
 
- 			 *
 
- 			 * @param Array directory objects of cwd
 
- 			 * @param Boolean do auto scroll
 
- 			 * @return Object jQuery Deferred
 
- 			 */
 
- 			sync = function(cwdDirs, aScr) {
 
- 				var cwd     = fm.cwd(),
 
- 					cwdhash = cwd.hash,
 
- 					autoScr = aScr === void(0)? syncTree : aScr,
 
- 					loadParents = function(dir) {
 
- 						var dfd  = $.Deferred(),
 
- 							reqs = [],
 
- 							ends = getEnds(dir),
 
- 							makeReq = function(cmd, h, until) {
 
- 								var data = {
 
- 										cmd    : cmd,
 
- 										target : h
 
- 									};
 
- 								if (until) {
 
- 									data.until = until;
 
- 								}
 
- 								return fm.request({
 
- 									data : data,
 
- 									preventFail : true
 
- 								});
 
- 							},
 
- 							baseHash, baseId;
 
- 						
 
- 						reqs = $.map(ends, function(h) {
 
- 							var d = fm.file(h),
 
- 								isRoot = d? fm.isRoot(d) : false,
 
- 								node = $('#'+fm.navHash2Id(h)),
 
- 								getPhash = function(h, dep) {
 
- 									var d, ph,
 
- 										depth = dep || 1;
 
- 									ph = (d = fm.file(h))? d.phash : false;
 
- 									if (ph && depth > 1) {
 
- 										return getPhash(ph, --depth);
 
- 									}
 
- 									return ph;
 
- 								},
 
- 								until,
 
- 								closest = (function() {
 
- 									var phash = getPhash(h);
 
- 									until = phash;
 
- 									while (phash) {
 
- 										if ($('#'+fm.navHash2Id(phash)).hasClass(loaded)) {
 
- 											break;
 
- 										}
 
- 										until = phash;
 
- 										phash = getPhash(phash);
 
- 									}
 
- 									if (!phash) {
 
- 										until = void(0);
 
- 										phash = fm.root(h);
 
- 									}
 
- 									return phash;
 
- 								})(),
 
- 								cmd;
 
- 							
 
- 							if (!node.hasClass(loaded) && (isRoot || !d || !$('#'+fm.navHash2Id(d.phash)).hasClass(loaded))) {
 
- 								if (isRoot || closest === getPhash(h) || closest === getPhash(h, 2)) {
 
- 									until = void(0);
 
- 									cmd = 'tree';
 
- 									if (!isRoot) {
 
- 										h = getPhash(h);
 
- 									}
 
- 								} else {
 
- 									cmd = 'parents';
 
- 								}
 
- 								if (!baseHash) {
 
- 									baseHash = (cmd === 'tree')? h : closest;
 
- 								}
 
- 								return makeReq(cmd, h, until);
 
- 							}
 
- 							return null;
 
- 						});
 
- 						
 
- 						if (reqs.length) {
 
- 							selectPages(fm.file(baseHash));
 
- 							baseId = fm.navHash2Id(baseHash);
 
- 							autoScr && autoScroll(baseId);
 
- 							baseNode = $('#'+baseId);
 
- 							spinner = $(fm.res('tpl', 'navspinner')).insertBefore(baseNode.children('.'+arrow));
 
- 							baseNode.removeClass(collapsed);
 
- 							
 
- 							$.when.apply($, reqs)
 
- 							.done(function() {
 
- 								var res = {},data, treeDirs, dirs, argLen, i;
 
- 								argLen = arguments.length;
 
- 								if (argLen > 0) {
 
- 									for (i = 0; i < argLen; i++) {
 
- 										data = arguments[i].tree || [];
 
- 										res[ends[i]] = Object.assign([], filter(data));
 
- 									}
 
- 								}
 
- 								dfd.resolve(res);
 
- 							})
 
- 							.fail(function() {
 
- 								dfd.reject();
 
- 							});
 
- 							
 
- 							return dfd;
 
- 						} else {
 
- 							return dfd.resolve();
 
- 						}
 
- 					},
 
- 					done= function(res, dfrd) {
 
- 						var open = function() {
 
- 								if (openRoot && baseNode) {
 
- 									findSubtree(baseNode.hash).show().prev(selNavdir).addClass(expanded);
 
- 									openRoot = false;
 
- 								}
 
- 								if (autoScr) {
 
- 									autoScroll().done(checkSubdirs);
 
- 								} else {
 
- 									checkSubdirs();
 
- 								}
 
- 							},
 
- 							current;
 
- 						
 
- 						if (res) {
 
- 							$.each(res, function(endHash, dirs) {
 
- 								dirs && updateTree(dirs);
 
- 								selectPages(fm.file(endHash));
 
- 								dirs && updateArrows(dirs, loaded);
 
- 							});
 
- 						}
 
- 						
 
- 						if (cwdDirs) {
 
- 							(fm.api < 2.1) && cwdDirs.push(cwd);
 
- 							updateTree(cwdDirs);
 
- 						}
 
- 						
 
- 						// set current node
 
- 						current = selectPages();
 
- 						
 
- 						if (!current.hasClass(active)) {
 
- 							tree.find(selNavdir+'.'+active).removeClass(active);
 
- 							current.addClass(active);
 
- 						}
 
- 						
 
- 						// mark as loaded to cwd parents
 
- 						current.parents('.elfinder-navbar-wrapper').children('.'+navdir).addClass(loaded);
 
- 						
 
- 						if (res) {
 
- 							fm.lazy(open).done(function() {
 
- 								dfrd.resolve();
 
- 							});
 
- 						} else {
 
- 							open();
 
- 							dfrd.resolve();
 
- 						}
 
- 					},
 
- 					rmSpinner = function(fail) {
 
- 						if (baseNode) {
 
- 							spinner.remove();
 
- 							baseNode.addClass(collapsed + (fail? '' : (' ' + loaded)));
 
- 						}
 
- 					},
 
- 					dfrd = $.Deferred(),
 
- 					baseNode, spinner;
 
- 				
 
- 				if (!$('#'+fm.navHash2Id(cwdhash)).length) {
 
- 					syncing = true;
 
- 					loadParents()
 
- 					.done(function(res) {
 
- 						done(res, dfrd);
 
- 						rmSpinner();
 
- 					})
 
- 					.fail(function() { 
 
- 						rmSpinner(true);
 
- 						dfrd.reject();
 
- 					})
 
- 					.always(function() {
 
- 						syncing = false;
 
- 					});
 
- 				} else {
 
- 					done(void(0), dfrd);
 
- 				}
 
- 				
 
- 				// trigger 'treesync' with my $.Deferred
 
- 				fm.trigger('treesync', dfrd);
 
- 				return dfrd;
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Make writable and not root dirs droppable
 
- 			 *
 
- 			 * @return void
 
- 			 */
 
- 			updateDroppable = function(target, node) {
 
- 				var limit = 100,
 
- 					next;
 
- 				
 
- 				if (!target) {
 
- 					if (!node || node.closest('div.'+wrapperRoot).hasClass(uploadable)) {
 
- 						(node || tree.find('div.'+uploadable)).find(selNavdir+':not(.elfinder-ro,.elfinder-na)').addClass('native-droppable');
 
- 					}
 
- 					if (!node || node.closest('div.'+wrapperRoot).hasClass(pastable)) {
 
- 						target = (node || tree.find('div.'+pastable)).find(selNavdir+':not(.'+droppable+')');
 
- 					} else {
 
- 						target = $();
 
- 					}
 
- 					if (node) {
 
- 						// check leaf roots
 
- 						node.children('div.'+wrapperRoot).each(function() {
 
- 							updateDroppable(null, $(this));
 
- 						});
 
- 					}
 
- 				}
 
- 				
 
- 				// make droppable on async
 
- 				if (target.length) {
 
- 					fm.asyncJob(function(elm) {
 
- 						$(elm).droppable(droppableopts);
 
- 					}, $.makeArray(target), {
 
- 						interval : 20,
 
- 						numPerOnce : 100
 
- 					});
 
- 				}
 
- 			},
 
- 			
 
- 			/**
 
- 			 * Check required folders for subfolders and update arrow classes
 
- 			 *
 
- 			 * @param  Array  folders to check
 
- 			 * @param  String css class 
 
- 			 * @return void
 
- 			 */
 
- 			updateArrows = function(dirs, cls) {
 
- 				var sel = cls == loaded
 
- 						? '.'+collapsed+':not(.'+loaded+')'
 
- 						: ':not(.'+collapsed+')';
 
- 				
 
- 				$.each(dirs, function(i, dir) {
 
- 					$('#'+fm.navHash2Id(dir.phash)+sel)
 
- 						.filter(function() { return $.grep($(this).next('.'+subtree).children(), function(n) {
 
- 							return ($(n).children().hasClass(root))? false : true;
 
- 						}).length > 0; })
 
- 						.addClass(cls);
 
- 				});
 
- 			},
 
- 			
 
- 			
 
- 			
 
- 			/**
 
- 			 * Navigation tree
 
- 			 *
 
- 			 * @type JQuery
 
- 			 */
 
- 			tree = $(this).addClass(treeclass)
 
- 				// make dirs draggable and toggle hover class
 
- 				.on('mouseenter mouseleave', selNavdir, function(e) {
 
- 					var enter = (e.type === 'mouseenter');
 
- 					if (enter && scrolling) { return; }
 
- 					var link  = $(this); 
 
- 					
 
- 					if (!link.hasClass(dropover+' '+disabled)) {
 
- 						if (!mobile && enter && !link.data('dragRegisted') && !link.hasClass(root+' '+draggable+' elfinder-na elfinder-wo')) {
 
- 							link.data('dragRegisted', true);
 
- 							if (fm.isCommandEnabled('copy', fm.navId2Hash(link.attr('id')))) {
 
- 								link.draggable(fm.draggable);
 
- 							}
 
- 						}
 
- 						link.toggleClass(hover, enter);
 
- 					}
 
- 				})
 
- 				// native drag enter
 
- 				.on('dragenter', selNavdir, function(e) {
 
- 					if (e.originalEvent.dataTransfer) {
 
- 						var dst = $(this);
 
- 						dst.addClass(hover);
 
- 						if (dst.is('.'+collapsed+':not(.'+expanded+')')) {
 
- 							dst.data('expandTimer', setTimeout(function() {
 
- 								dst.is('.'+collapsed+'.'+hover) && dst.children('.'+arrow).trigger('click');
 
- 							}, 500));
 
- 						}
 
- 					}
 
- 				})
 
- 				// native drag leave
 
- 				.on('dragleave', selNavdir, function(e) {
 
- 					if (e.originalEvent.dataTransfer) {
 
- 						var dst = $(this);
 
- 						dst.data('expandTimer') && clearTimeout(dst.data('expandTimer'));
 
- 						dst.removeClass(hover);
 
- 					}
 
- 				})
 
- 				// open dir or open subfolders in tree
 
- 				.on('click', selNavdir, function(e) {
 
- 					var link = $(this),
 
- 						hash = fm.navId2Hash(link.attr('id')),
 
- 						file = fm.file(hash);
 
- 					
 
- 					if (link.data('longtap')) {
 
- 						link.removeData('longtap');
 
- 						e.stopPropagation();
 
- 						return;
 
- 					}
 
- 					
 
- 					if (!link.hasClass(active)) {
 
- 						tree.find(selNavdir+'.'+active).removeClass(active);
 
- 						link.addClass(active);
 
- 					}
 
- 					if (hash != fm.cwd().hash && !link.hasClass(disabled)) {
 
- 						fm.exec('open', hash).done(function() {
 
- 							fm.one('opendone', function() {
 
- 								fm.select({selected: [hash], origin: 'navbar'});
 
- 							});
 
- 						});
 
- 					} else {
 
- 						if (link.hasClass(collapsed)) {
 
- 							link.children('.'+arrow).trigger('click');
 
- 						}
 
- 						fm.select({selected: [hash], origin: 'navbar'});
 
- 					}
 
- 				})
 
- 				// for touch device
 
- 				.on('touchstart', selNavdir, function(e) {
 
- 					if (e.originalEvent.touches.length > 1) {
 
- 						return;
 
- 					}
 
- 					var evt = e.originalEvent,
 
- 						p;
 
- 					
 
- 					if (e.target.nodeName === 'INPUT') {
 
- 						e.stopPropagation();
 
- 						return;
 
- 					}
 
- 					
 
- 					p = $(this).addClass(hover)
 
- 					.removeData('longtap')
 
- 					.data('tmlongtap', setTimeout(function(e){
 
- 						// long tap
 
- 						p.data('longtap', true);
 
- 						fm.trigger('contextmenu', {
 
- 							'type'    : 'navbar',
 
- 							'targets' : [fm.navId2Hash(p.attr('id'))],
 
- 							'x'       : evt.touches[0].pageX,
 
- 							'y'       : evt.touches[0].pageY
 
- 						});
 
- 					}, 500));
 
- 				})
 
- 				.on('touchmove touchend', selNavdir, function(e) {
 
- 					if (e.target.nodeName === 'INPUT') {
 
- 						e.stopPropagation();
 
- 						return;
 
- 					}
 
- 					clearTimeout($(this).data('tmlongtap'));
 
- 					if (e.type == 'touchmove') {
 
- 						$(this).removeClass(hover);
 
- 					}
 
- 				})
 
- 				// toggle subfolders in tree
 
- 				.on('click', selNavdir+'.'+collapsed+' .'+arrow, function(e) {
 
- 					var arrow = $(this),
 
- 						link  = arrow.parent(selNavdir),
 
- 						stree = link.next('.'+subtree),
 
- 						dfrd  = $.Deferred(),
 
- 						slideTH = 30, cnt;
 
- 					e.stopPropagation();
 
- 					if (link.hasClass(loaded)) {
 
- 						link.toggleClass(expanded);
 
- 						fm.lazy(function() {
 
- 							cnt = link.hasClass(expanded)? stree.children().length + stree.find('div.elfinder-navbar-subtree[style*=block]').children().length : stree.find('div:visible').length;
 
- 							if (cnt > slideTH) {
 
- 								stree.toggle();
 
- 								fm.draggingUiHelper && fm.draggingUiHelper.data('refreshPositions', 1);
 
- 								checkSubdirs();
 
- 							} else {
 
- 								stree.stop(true, true)[link.hasClass(expanded)? 'slideDown' : 'slideUp'](opts.durations.slideUpDown, function(){
 
- 									fm.draggingUiHelper && fm.draggingUiHelper.data('refreshPositions', 1);
 
- 									checkSubdirs();
 
- 								});
 
- 							}
 
- 						}).always(function() {
 
- 							dfrd.resolve();
 
- 						});
 
- 					} else {
 
- 						spinner.insertBefore(arrow);
 
- 						link.removeClass(collapsed);
 
- 						fm.request({cmd : 'tree', target : fm.navId2Hash(link.attr('id'))})
 
- 							.done(function(data) { 
 
- 								updateTree(Object.assign([], filter(data.tree))); 
 
- 								
 
- 								if (stree.children().length) {
 
- 									link.addClass(collapsed+' '+expanded);
 
- 									if (stree.children().length > slideTH) {
 
- 										stree.show();
 
- 										fm.draggingUiHelper && fm.draggingUiHelper.data('refreshPositions', 1);
 
- 										checkSubdirs();
 
- 									} else {
 
- 										stree.stop(true, true).slideDown(opts.durations.slideUpDown, function(){
 
- 											fm.draggingUiHelper && fm.draggingUiHelper.data('refreshPositions', 1);
 
- 											checkSubdirs();
 
- 										});
 
- 									}
 
- 								} 
 
- 							})
 
- 							.always(function(data) {
 
- 								spinner.remove();
 
- 								link.addClass(loaded);
 
- 								fm.one('treedone', function() {
 
- 									dfrd.resolve();
 
- 								});
 
- 							});
 
- 					}
 
- 					arrow.data('dfrd', dfrd);
 
- 				})
 
- 				.on('contextmenu', selNavdir, function(e) {
 
- 					var self = $(this);
 
- 					
 
- 					// now dirname editing
 
- 					if (self.find('input:text').length) {
 
- 						e.stopPropagation();
 
- 						return;
 
- 					}
 
- 					
 
- 					e.preventDefault();
 
- 					fm.trigger('contextmenu', {
 
- 						'type'    : 'navbar',
 
- 						'targets' : [fm.navId2Hash($(this).attr('id'))],
 
- 						'x'       : e.pageX,
 
- 						'y'       : e.pageY
 
- 					});
 
- 					
 
- 					self.addClass('ui-state-hover');
 
- 					
 
- 					fm.getUI('contextmenu').children().on('mouseenter', function() {
 
- 						self.addClass('ui-state-hover');
 
- 					});
 
- 					
 
- 					fm.bind('closecontextmenu', function() {
 
- 						self.removeClass('ui-state-hover');
 
- 					});
 
- 				})
 
- 				.on('scrolltoview', selNavdir, function(e, data) {
 
- 					var self = $(this);
 
- 					autoScroll(self.attr('id')).done(function() {
 
- 						if (!data || data.blink === 'undefined' || data.blink) {
 
- 							fm.resources.blink(self, 'lookme');
 
- 						}
 
- 					});
 
- 				})
 
- 				// prepend fake dir
 
- 				.on('create.'+fm.namespace, function(e, item) {
 
- 					var pdir = findSubtree(item.phash),
 
- 						lock = item.move || false,
 
- 						dir  = $(itemhtml(item)).addClass('elfinder-navbar-wrapper-tmp'),
 
- 						selected = fm.selected();
 
- 						
 
- 					lock && selected.length && fm.trigger('lockfiles', {files: selected});
 
- 					pdir.prepend(dir);
 
- 				}),
 
- 			scrolling = false,
 
- 			navbarScrTm,
 
- 			// move tree into navbar
 
- 			navbar = fm.getUI('navbar').append(tree).show().on('scroll', function() {
 
- 				scrolling = true;
 
- 				navbarScrTm && cancelAnimationFrame(navbarScrTm);
 
- 				navbarScrTm = requestAnimationFrame(function() {
 
- 					scrolling = false;
 
- 					checkSubdirs();
 
- 				});
 
- 			}),
 
- 			
 
- 			prevSortTreeview = fm.sortAlsoTreeview;
 
- 			
 
- 		fm.open(function(e) {
 
- 			var data = e.data,
 
- 				dirs = filter(data.files),
 
- 				contextmenu = fm.getUI('contextmenu');
 
- 			data.init && tree.empty();
 
- 			if (fm.UA.iOS) {
 
- 				navbar.removeClass('overflow-scrolling-touch').addClass('overflow-scrolling-touch');
 
- 			}
 
- 			if (dirs.length) {
 
- 				fm.lazy(function() {
 
- 					if (!contextmenu.data('cmdMaps')) {
 
- 						contextmenu.data('cmdMaps', {});
 
- 					}
 
- 					updateTree(dirs);
 
- 					updateArrows(dirs, loaded);
 
- 					sync(dirs);
 
- 				});
 
- 			} else {
 
- 				sync();
 
- 			}
 
- 		})
 
- 		// add new dirs
 
- 		.add(function(e) {
 
- 			var dirs = filter(e.data.added);
 
- 			if (dirs.length) {
 
- 				updateTree(dirs);
 
- 				updateArrows(dirs, collapsed);
 
- 			}
 
- 		})
 
- 		// update changed dirs
 
- 		.change(function(e) {
 
- 			// do ot perfome while syncing
 
- 			if (syncing) {
 
- 				return;
 
- 			}
 
- 			var dirs = filter(e.data.changed, true),
 
- 				length = dirs.length,
 
- 				l    = length,
 
- 				tgts = $(),
 
- 				changed = {},
 
- 				dir, phash, node, tmp, realParent, reqParent, realSibling, reqSibling, isExpanded, isLoaded, parent, subdirs;
 
- 			
 
- 			$.each(hasMoreDirs, function(h, node) {
 
- 				node.trigger('update.'+fm.namespace, { change: 'prepare' });
 
- 			});
 
- 			
 
- 			while (l--) {
 
- 				dir = dirs[l];
 
- 				phash = dir.phash;
 
- 				if ((node = $('#'+fm.navHash2Id(dir.hash))).length) {
 
- 					parent = node.parent();
 
- 					if (phash) {
 
- 						realParent  = node.closest('.'+subtree);
 
- 						reqParent   = findSubtree(phash);
 
- 						realSibling = node.parent().next();
 
- 						reqSibling  = findSibling(reqParent, dir);
 
- 						
 
- 						if (!reqParent.length) {
 
- 							continue;
 
- 						}
 
- 						
 
- 						if (reqParent[0] !== realParent[0] || realSibling.get(0) !== reqSibling.get(0)) {
 
- 							reqSibling.length ? reqSibling.before(parent) : reqParent.append(parent);
 
- 						}
 
- 					}
 
- 					isExpanded = node.hasClass(expanded);
 
- 					isLoaded   = node.hasClass(loaded);
 
- 					tmp        = $(itemhtml(dir));
 
- 					node.replaceWith(tmp.children(selNavdir));
 
- 					! mobile && updateDroppable(null, parent);
 
- 					
 
- 					if (dir.dirs
 
- 					&& (isExpanded || isLoaded) 
 
- 					&& (node = $('#'+fm.navHash2Id(dir.hash))) 
 
- 					&& node.next('.'+subtree).children().length) {
 
- 						isExpanded && node.addClass(expanded);
 
- 						isLoaded && node.addClass(loaded);
 
- 					}
 
- 					
 
- 					subdirs |= dir.dirs == -1;
 
- 				}
 
- 			}
 
- 			
 
- 			// to check subdirs
 
- 			if (subdirs) {
 
- 				checkSubdirs();
 
- 			}
 
- 			
 
- 			$.each(hasMoreDirs, function(h, node) {
 
- 				node.trigger('update.'+fm.namespace, { change: 'done' });
 
- 			});
 
- 			
 
- 			length && sync(void(0), false);
 
- 		})
 
- 		// remove dirs
 
- 		.remove(function(e) {
 
- 			var dirs = e.data.removed,
 
- 				l    = dirs.length,
 
- 				node, stree, removed;
 
- 			
 
- 			$.each(hasMoreDirs, function(h, node) {
 
- 				node.trigger('update.'+fm.namespace, { removed : dirs });
 
- 				node.trigger('update.'+fm.namespace, { change: 'prepare' });
 
- 			});
 
- 			while (l--) {
 
- 				if ((node = $('#'+fm.navHash2Id(dirs[l]))).length) {
 
- 					removed = true;
 
- 					stree = node.closest('.'+subtree);
 
- 					node.parent().detach();
 
- 					if (!stree.children().length) {
 
- 						stree.hide().prev(selNavdir).removeClass(collapsed+' '+expanded+' '+loaded);
 
- 					}
 
- 				}
 
- 			}
 
- 			
 
- 			removed && fm.getUI('navbar').children('.ui-resizable-handle').trigger('resize');
 
- 			
 
- 			$.each(hasMoreDirs, function(h, node) {
 
- 				node.trigger('update.'+fm.namespace, { change: 'done' });
 
- 			});
 
- 		})
 
- 		// lock/unlock dirs while moving
 
- 		.bind('lockfiles unlockfiles', function(e) {
 
- 			var lock = e.type == 'lockfiles',
 
- 				helperLocked = e.data.helper? e.data.helper.data('locked') : false,
 
- 				act  = (lock && !helperLocked) ? 'disable' : 'enable',
 
- 				dirs = $.grep(e.data.files||[], function(h) {  
 
- 					var dir = fm.file(h);
 
- 					return dir && dir.mime == 'directory' ? true : false;
 
- 				});
 
- 				
 
- 			$.each(dirs, function(i, hash) {
 
- 				var dir = $('#'+fm.navHash2Id(hash));
 
- 				
 
- 				if (dir.length && !helperLocked) {
 
- 					dir.hasClass(draggable) && dir.draggable(act);
 
- 					dir.hasClass(droppable) && dir.droppable(act);
 
- 					dir[lock ? 'addClass' : 'removeClass'](disabled);
 
- 				}
 
- 			});
 
- 		})
 
- 		.bind('sortchange', function() {
 
- 			if (fm.sortAlsoTreeview || prevSortTreeview !== fm.sortAlsoTreeview) {
 
- 				var dirs,
 
- 					ends = [],
 
- 					endsMap = {},
 
- 					endsVid = {},
 
- 					topVid = '',
 
- 					single = false,
 
- 					current;
 
- 				
 
- 				fm.lazy(function() {
 
- 					dirs = filter(fm.files());
 
- 					prevSortTreeview = fm.sortAlsoTreeview;
 
- 					
 
- 					tree.empty();
 
- 					
 
- 					// append volume roots at first
 
- 					updateTree($.map(fm.roots, function(h) {
 
- 						var dir = fm.file(h);
 
- 						return dir && !dir.phash? dir : null;
 
- 					}));
 
- 					
 
- 					if (!Object.keys(hasMoreDirs).length) {
 
- 						updateTree(dirs);
 
- 						current = selectPages();
 
- 						updateArrows(dirs, loaded);
 
- 					} else {
 
- 						ends = getEnds();
 
- 						if (ends.length > 1) {
 
- 							$.each(ends, function(i, end) {
 
- 								var vid = fm.file(fm.root(end)).volumeid; 
 
- 								if (i === 0) {
 
- 									topVid = vid;
 
- 								}
 
- 								endsVid[vid] = end;
 
- 								endsMap[end] = [];
 
- 							});
 
- 							$.each(dirs, function(i, d) {
 
- 								if (!d.volumeid) {
 
- 									single = true;
 
- 									return false;
 
- 								}
 
- 								endsMap[endsVid[d.volumeid] || endsVid[topVid]].push(d);
 
- 							});
 
- 						} else {
 
- 							single = true;
 
- 						}
 
- 						if (single) {
 
- 							$.each(ends, function(i, endHash) {
 
- 								updateTree(dirs);
 
- 								current = selectPages(fm.file(endHash));
 
- 								updateArrows(dirs, loaded);
 
- 							});
 
- 						} else {
 
- 							$.each(endsMap, function(endHash, dirs) {
 
- 								updateTree(dirs);
 
- 								current = selectPages(fm.file(endHash));
 
- 								updateArrows(dirs, loaded);
 
- 							});
 
- 						}
 
- 					}
 
- 					
 
- 					sync();
 
- 				}, 100);
 
- 			}
 
- 		});
 
- 	});
 
- 	
 
- 	return this;
 
- };
 
- /*
 
-  * File: /js/ui/uploadButton.js
 
-  */
 
- /**
 
-  * @class  elFinder toolbar's button tor upload file
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.elfinderuploadbutton = function(cmd) {
 
- 		return this.each(function() {
 
- 		var fm = cmd.fm,
 
- 			button = $(this).elfinderbutton(cmd)
 
- 				.off('click'), 
 
- 			form = $('<form/>').appendTo(button),
 
- 			input = $('<input type="file" multiple="true" title="'+cmd.fm.i18n('selectForUpload')+'"/>')
 
- 				.on('change', function() {
 
- 					var _input = $(this);
 
- 					if (_input.val()) {
 
- 						fm.exec('upload', {input : _input.remove()[0]}, void(0), fm.cwd().hash);
 
- 						input.clone(true).appendTo(form);
 
- 					} 
 
- 				})
 
- 				.on('dragover', function(e) {
 
- 					e.originalEvent.dataTransfer.dropEffect = 'copy';
 
- 				}),
 
- 			tm;
 
- 		form.append(input.clone(true));
 
- 				
 
- 		cmd.change(function() {
 
- 			tm && cancelAnimationFrame(tm);
 
- 			tm = requestAnimationFrame(function() {
 
- 				var toShow = cmd.disabled();
 
- 				if (form.is('visible')) {
 
- 					!toShow && form.hide();
 
- 				} else {
 
- 					toShow && form.show();
 
- 				}
 
- 			});
 
- 		})
 
- 		.change();
 
- 	});
 
- };
 
- /*
 
-  * File: /js/ui/viewbutton.js
 
-  */
 
- /**
 
-  * @class  elFinder toolbar button to switch current directory view.
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.elfinderviewbutton = function(cmd) {
 
- 		return this.each(function() {
 
- 		var button = $(this).elfinderbutton(cmd),
 
- 			icon   = button.children('.elfinder-button-icon'),
 
- 			text   = button.children('.elfinder-button-text'),
 
- 			tm;
 
- 		cmd.change(function() {
 
- 			tm && cancelAnimationFrame(tm);
 
- 			tm = requestAnimationFrame(function() {
 
- 				var icons = cmd.value == 'icons';
 
- 				icon.toggleClass('elfinder-button-icon-view-list', icons);
 
- 				cmd.className = icons? 'view-list' : '';
 
- 				cmd.title = cmd.fm.i18n(icons ? 'viewlist' : 'viewicons');
 
- 				button.attr('title', cmd.title);
 
- 				text.html(cmd.title);
 
- 			});
 
- 		});
 
- 	});
 
- };
 
- /*
 
-  * File: /js/ui/workzone.js
 
-  */
 
- /**
 
-  * @class elfinderworkzone - elFinder container for nav and current directory
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- $.fn.elfinderworkzone = function(fm) {
 
- 		var cl = 'elfinder-workzone';
 
- 	
 
- 	this.not('.'+cl).each(function() {
 
- 		var wz     = $(this).addClass(cl),
 
- 			prevH  = Math.round(wz.height()),
 
- 			parent = wz.parent(),
 
- 			setDelta = function() {
 
- 				wdelta = wz.outerHeight(true) - wz.height();
 
- 			},
 
- 			fitsize = function(e) {
 
- 				var height = parent.height() - wdelta,
 
- 					style  = parent.attr('style'),
 
- 					curH   = Math.round(wz.height());
 
- 	
 
- 				if (e) {
 
- 					e.preventDefault();
 
- 					e.stopPropagation();
 
- 				}
 
- 				
 
- 				parent.css('overflow', 'hidden')
 
- 					.children(':visible:not(.'+cl+')').each(function() {
 
- 						var ch = $(this);
 
- 		
 
- 						if (ch.css('position') != 'absolute' && ch.css('position') != 'fixed') {
 
- 							height -= ch.outerHeight(true);
 
- 						}
 
- 					});
 
- 				parent.attr('style', style || '');
 
- 				
 
- 				height = Math.max(0, Math.round(height));
 
- 				if (prevH !== height || curH !== height) {
 
- 					prevH  = Math.round(wz.height());
 
- 					wz.height(height);
 
- 					fm.trigger('wzresize');
 
- 				}
 
- 			},
 
- 			cssloaded = function() {
 
- 				wdelta = wz.outerHeight(true) - wz.height();
 
- 				fitsize();
 
- 			},
 
- 			wdelta;
 
- 		
 
- 		setDelta();
 
- 		parent.on('resize.' + fm.namespace, fitsize);
 
- 		fm.one('cssloaded', cssloaded)
 
- 		  .bind('uiresize', fitsize)
 
- 		  .bind('themechange', setDelta);
 
- 	});
 
- 	return this;
 
- };
 
- /*
 
-  * File: /js/commands/archive.js
 
-  */
 
- /**
 
-  * @class  elFinder command "archive"
 
-  * Archive selected files
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- elFinder.prototype.commands.archive = function() {
 
- 		var self  = this,
 
- 		fm    = self.fm,
 
- 		mimes = [],
 
- 		dfrd;
 
- 		
 
- 	this.variants = [];
 
- 	
 
- 	this.disableOnSearch = false;
 
- 	
 
- 	this.nextAction = {};
 
- 	
 
- 	/**
 
- 	 * Update mimes on open/reload
 
- 	 *
 
- 	 * @return void
 
- 	 **/
 
- 	fm.bind('open reload', function() {
 
- 		self.variants = [];
 
- 		$.each((mimes = fm.option('archivers')['create'] || []), function(i, mime) {
 
- 			self.variants.push([mime, fm.mime2kind(mime)]);
 
- 		});
 
- 		self.change();
 
- 	});
 
- 	
 
- 	this.getstate = function(select) {
 
- 		var sel = this.files(select),
 
- 			cnt = sel.length,
 
- 			chk = (cnt && ! fm.isRoot(sel[0]) && (fm.file(sel[0].phash) || {}).write && ! $.grep(sel, function(f){ return f.read ? false : true; }).length),
 
- 			cwdId;
 
- 		
 
- 		if (chk && fm.searchStatus.state > 1) {
 
- 			cwdId = fm.cwd().volumeid;
 
- 			chk = (cnt === $.grep(sel, function(f) { return f.read && f.hash.indexOf(cwdId) === 0 ? true : false; }).length);
 
- 		}
 
- 		
 
- 		return chk && !this._disabled && mimes.length && (cnt || (dfrd && dfrd.state() == 'pending')) ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes, type) {
 
- 		var files = this.files(hashes),
 
- 			cnt   = files.length,
 
- 			mime  = type || mimes[0],
 
- 			cwd   = fm.file(files[0].phash) || null,
 
- 			error = ['errArchive', 'errPerm', 'errCreatingTempDir', 'errFtpDownloadFile', 'errFtpUploadFile', 'errFtpMkdir', 'errArchiveExec', 'errExtractExec', 'errRm'],
 
- 			i, open;
 
- 		dfrd = $.Deferred().fail(function(error) {
 
- 			error && fm.error(error);
 
- 		});
 
- 		if (! (cnt && mimes.length && $.inArray(mime, mimes) !== -1)) {
 
- 			return dfrd.reject();
 
- 		}
 
- 		
 
- 		if (!cwd.write) {
 
- 			return dfrd.reject(error);
 
- 		}
 
- 		
 
- 		for (i = 0; i < cnt; i++) {
 
- 			if (!files[i].read) {
 
- 				return dfrd.reject(error);
 
- 			}
 
- 		}
 
- 		self.mime   = mime;
 
- 		self.prefix = ((cnt > 1)? 'Archive' : files[0].name) + (fm.option('archivers')['createext']? '.' + fm.option('archivers')['createext'][mime] : '');
 
- 		self.data   = {targets : self.hashes(hashes), type : mime};
 
- 		
 
- 		if (fm.cwd().hash !== cwd.hash) {
 
- 			open = fm.exec('open', cwd.hash).done(function() {
 
- 				fm.one('cwdrender', function() {
 
- 					fm.selectfiles({files : hashes});
 
- 					dfrd = $.proxy(fm.res('mixin', 'make'), self)();
 
- 				});
 
- 			});
 
- 		} else {
 
- 			fm.selectfiles({files : hashes});
 
- 			dfrd = $.proxy(fm.res('mixin', 'make'), self)();
 
- 		}
 
- 		
 
- 		return dfrd;
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/back.js
 
-  */
 
- /**
 
-  * @class  elFinder command "back"
 
-  * Open last visited folder
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- (elFinder.prototype.commands.back = function() {
 
- 		this.alwaysEnabled  = true;
 
- 	this.updateOnSelect = false;
 
- 	this.shortcuts      = [{
 
- 		pattern     : 'ctrl+left backspace'
 
- 	}];
 
- 	
 
- 	this.getstate = function() {
 
- 		return this.fm.history.canBack() ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function() {
 
- 		return this.fm.history.back();
 
- 	};
 
- }).prototype = { forceLoad : true }; // this is required command
 
- /*
 
-  * File: /js/commands/chmod.js
 
-  */
 
- /**
 
-  * @class elFinder command "chmod".
 
-  * Chmod files.
 
-  *
 
-  * @type  elFinder.command
 
-  * @author Naoki Sawada
 
-  */
 
- elFinder.prototype.commands.chmod = function() {
 
- 		this.updateOnSelect = false;
 
- 	var fm  = this.fm,
 
- 		level = {
 
- 			0 : 'owner',
 
- 			1 : 'group',
 
- 			2 : 'other'
 
- 		},
 
- 		msg = {
 
- 			read     : fm.i18n('read'),
 
- 			write    : fm.i18n('write'),
 
- 			execute  : fm.i18n('execute'),
 
- 			perm     : fm.i18n('perm'),
 
- 			kind     : fm.i18n('kind'),
 
- 			files    : fm.i18n('files')
 
- 		},
 
- 		isPerm = function(perm){
 
- 			return (!isNaN(parseInt(perm, 8) && parseInt(perm, 8) <= 511) || perm.match(/^([r-][w-][x-]){3}$/i));
 
- 		};
 
- 	this.tpl = {
 
- 		main       : '<div class="ui-helper-clearfix elfinder-info-title"><span class="elfinder-cwd-icon {class} ui-corner-all"/>{title}</div>'
 
- 					+'{dataTable}',
 
- 		itemTitle  : '<strong>{name}</strong><span id="elfinder-info-kind">{kind}</span>',
 
- 		groupTitle : '<strong>{items}: {num}</strong>',
 
- 		dataTable  : '<table id="{id}-table-perm"><tr><td>{0}</td><td>{1}</td><td>{2}</td></tr></table>'
 
- 					+'<div class="">'+msg.perm+': <input class="elfinder-tabstop elfinder-focus" id="{id}-perm" type="text" size="4" maxlength="3" value="{value}"></div>',
 
- 		fieldset   : '<fieldset id="{id}-fieldset-{level}"><legend>{f_title}{name}</legend>'
 
- 					+'<input type="checkbox" value="4" class="elfinder-tabstop" id="{id}-read-{level}-perm"{checked-r}> <label for="{id}-read-{level}-perm">'+msg.read+'</label><br>'
 
- 					+'<input type="checkbox" value="6" class="elfinder-tabstop" id="{id}-write-{level}-perm"{checked-w}> <label for="{id}-write-{level}-perm">'+msg.write+'</label><br>'
 
- 					+'<input type="checkbox" value="5" class="elfinder-tabstop" id="{id}-execute-{level}-perm"{checked-x}> <label for="{id}-execute-{level}-perm">'+msg.execute+'</label><br>'
 
- 	};
 
- 	this.shortcuts = [{
 
- 		//pattern     : 'ctrl+p'
 
- 	}];
 
- 	this.getstate = function(sel) {
 
- 		var fm = this.fm;
 
- 		sel = sel || fm.selected();
 
- 		if (sel.length == 0) {
 
- 			sel = [ fm.cwd().hash ];
 
- 		}
 
- 		return this.checkstate(this.files(sel)) ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.checkstate = function(sel) {
 
- 		var cnt = sel.length;
 
- 		if (!cnt) return false;
 
- 		var chk = $.grep(sel, function(f) {
 
- 			return (f.isowner && f.perm && isPerm(f.perm) && (cnt == 1 || f.mime != 'directory')) ? true : false;
 
- 		}).length;
 
- 		return (cnt == chk)? true : false;
 
- 	};
 
- 	this.exec = function(select) {
 
- 		var hashes  = this.hashes(select),
 
- 			files   = this.files(hashes);
 
- 		if (! files.length) {
 
- 			hashes = [ this.fm.cwd().hash ];
 
- 			files   = this.files(hashes);
 
- 		}
 
- 		var fm  = this.fm,
 
- 		dfrd    = $.Deferred().always(function() {
 
- 			fm.enable();
 
- 		}),
 
- 		tpl     = this.tpl,
 
- 		cnt     = files.length,
 
- 		file    = files[0],
 
- 		id = fm.namespace + '-perm-' + file.hash,
 
- 		view    = tpl.main,
 
- 		checked = ' checked="checked"',
 
- 		buttons = function() {
 
- 			var buttons = {};
 
- 			buttons[fm.i18n('btnApply')] = save;
 
- 			buttons[fm.i18n('btnCancel')] = function() { dialog.elfinderdialog('close'); };
 
- 			return buttons;
 
- 		},
 
- 		save = function() {
 
- 			var perm = $.trim($('#'+id+'-perm').val()),
 
- 				reqData;
 
- 			
 
- 			if (!isPerm(perm)) return false;
 
- 			
 
- 			dialog.elfinderdialog('close');
 
- 			
 
- 			reqData = {
 
- 				cmd     : 'chmod',
 
- 				targets : hashes,
 
- 				mode    : perm
 
- 			};
 
- 			fm.request({
 
- 				data : reqData,
 
- 				notify : {type : 'chmod', cnt : cnt}
 
- 			})
 
- 			.fail(function(error) {
 
- 				dfrd.reject(error);
 
- 			})
 
- 			.done(function(data) {
 
- 				if (data.changed && data.changed.length) {
 
- 					data.undo = {
 
- 						cmd : 'chmod',
 
- 						callback : function() {
 
- 							var reqs = [];
 
- 							$.each(prevVals, function(perm, hashes) {
 
- 								reqs.push(fm.request({
 
- 									data : {cmd : 'chmod', targets : hashes, mode : perm},
 
- 									notify : {type : 'undo', cnt : hashes.length}
 
- 								}));
 
- 							});
 
- 							return $.when.apply(null, reqs);
 
- 						}
 
- 					};
 
- 					data.redo = {
 
- 						cmd : 'chmod',
 
- 						callback : function() {
 
- 							return fm.request({
 
- 								data : reqData,
 
- 								notify : {type : 'redo', cnt : hashes.length}
 
- 							});
 
- 						}
 
- 					};
 
- 				}
 
- 				dfrd.resolve(data);
 
- 			});
 
- 		},
 
- 		setperm = function() {
 
- 			var perm = '';
 
- 			var _perm;
 
- 			for (var i = 0; i < 3; i++){
 
- 				_perm = 0;
 
- 				if ($("#"+id+"-read-"+level[i]+'-perm').is(':checked')) {
 
- 					_perm = (_perm | 4);
 
- 				}
 
- 				if ($("#"+id+"-write-"+level[i]+'-perm').is(':checked')) {
 
- 					_perm = (_perm | 2);
 
- 				}
 
- 				if ($("#"+id+"-execute-"+level[i]+'-perm').is(':checked')) {
 
- 					_perm = (_perm | 1);
 
- 				}
 
- 				perm += _perm.toString(8);
 
- 			}
 
- 			$('#'+id+'-perm').val(perm);
 
- 		},
 
- 		setcheck = function(perm) {
 
- 			var _perm;
 
- 			for (var i = 0; i < 3; i++){
 
- 				_perm = parseInt(perm.slice(i, i+1), 8);
 
- 				$("#"+id+"-read-"+level[i]+'-perm').prop("checked", false);
 
- 				$("#"+id+"-write-"+level[i]+'-perm').prop("checked", false);
 
- 				$("#"+id+"-execute-"+level[i]+'-perm').prop("checked", false);
 
- 				if ((_perm & 4) == 4) {
 
- 					$("#"+id+"-read-"+level[i]+'-perm').prop("checked", true);
 
- 				}
 
- 				if ((_perm & 2) == 2) {
 
- 					$("#"+id+"-write-"+level[i]+'-perm').prop("checked", true);
 
- 				}
 
- 				if ((_perm & 1) == 1) {
 
- 					$("#"+id+"-execute-"+level[i]+'-perm').prop("checked", true);
 
- 				}
 
- 			}
 
- 			setperm();
 
- 		},
 
- 		makeperm = function(files) {
 
- 			var perm = '777', ret = '', chk, _chk, _perm;
 
- 			var len = files.length;
 
- 			for (var i2 = 0; i2 < len; i2++) {
 
- 				chk = getPerm(files[i2].perm);
 
- 				if (! prevVals[chk]) {
 
- 					prevVals[chk] = [];
 
- 				}
 
- 				prevVals[chk].push(files[i2].hash);
 
- 				ret = '';
 
- 				for (var i = 0; i < 3; i++){
 
- 					_chk = parseInt(chk.slice(i, i+1), 8);
 
- 					_perm = parseInt(perm.slice(i, i+1), 8);
 
- 					if ((_chk & 4) != 4 && (_perm & 4) == 4) {
 
- 						_perm -= 4;
 
- 					}
 
- 					if ((_chk & 2) != 2 && (_perm & 2) == 2) {
 
- 						_perm -= 2;
 
- 					}
 
- 					if ((_chk & 1) != 1 && (_perm & 1) == 1) {
 
- 						_perm -= 1;
 
- 					}
 
- 					ret += _perm.toString(8);
 
- 				}
 
- 				perm = ret;
 
- 			}
 
- 			return perm;
 
- 		},
 
- 		makeName = function(name) {
 
- 			return name? ':'+name : '';
 
- 		},
 
- 		makeDataTable = function(perm, f) {
 
- 			var _perm, fieldset;
 
- 			var value = '';
 
- 			var dataTable = tpl.dataTable;
 
- 			for (var i = 0; i < 3; i++){
 
- 				_perm = parseInt(perm.slice(i, i+1), 8);
 
- 				value += _perm.toString(8);
 
- 				fieldset = tpl.fieldset.replace('{f_title}', fm.i18n(level[i])).replace('{name}', makeName(f[level[i]])).replace(/\{level\}/g, level[i]);
 
- 				dataTable = dataTable.replace('{'+i+'}', fieldset)
 
- 				                     .replace('{checked-r}', ((_perm & 4) == 4)? checked : '')
 
- 				                     .replace('{checked-w}', ((_perm & 2) == 2)? checked : '')
 
- 				                     .replace('{checked-x}', ((_perm & 1) == 1)? checked : '');
 
- 			}
 
- 			dataTable = dataTable.replace('{value}', value).replace('{valueCaption}', msg['perm']);
 
- 			return dataTable;
 
- 		},
 
- 		getPerm = function(perm){
 
- 			if (isNaN(parseInt(perm, 8))) {
 
- 				var mode_array = perm.split('');
 
- 				var a = [];
 
- 				for (var i = 0, l = mode_array.length; i < l; i++) {
 
- 					if (i === 0 || i === 3 || i === 6) {
 
- 						if (mode_array[i].match(/[r]/i)) {
 
- 							a.push(1);
 
- 						} else if (mode_array[i].match(/[-]/)) {
 
- 							a.push(0);
 
- 						}
 
- 					} else if ( i === 1 || i === 4 || i === 7) {
 
- 						 if (mode_array[i].match(/[w]/i)) {
 
- 							a.push(1);
 
- 						} else if (mode_array[i].match(/[-]/)) {
 
- 							a.push(0);
 
- 						}
 
- 					} else {
 
- 						if (mode_array[i].match(/[x]/i)) {
 
- 							a.push(1);
 
- 						} else if (mode_array[i].match(/[-]/)) {
 
- 							a.push(0);
 
- 						}
 
- 					}
 
- 				}
 
- 			
 
- 				a.splice(3, 0, ",");
 
- 				a.splice(7, 0, ",");
 
- 				var b = a.join("");
 
- 				var b_array = b.split(",");
 
- 				var c = [];
 
- 			
 
- 				for (var j = 0, m = b_array.length; j < m; j++) {
 
- 					var p = parseInt(b_array[j], 2).toString(8);
 
- 					c.push(p);
 
- 				}
 
- 				perm = c.join('');
 
- 			} else {
 
- 				perm = parseInt(perm, 8).toString(8);
 
- 			}
 
- 			return perm;
 
- 		},
 
- 		opts    = {
 
- 			title : this.title,
 
- 			width : 'auto',
 
- 			buttons : buttons(),
 
- 			close : function() { $(this).elfinderdialog('destroy'); }
 
- 		},
 
- 		dialog = fm.getUI().find('#'+id),
 
- 		prevVals = {},
 
- 		tmb = '', title, dataTable;
 
- 		if (dialog.length) {
 
- 			dialog.elfinderdialog('toTop');
 
- 			return $.Deferred().resolve();
 
- 		}
 
- 		view  = view.replace('{class}', cnt > 1 ? 'elfinder-cwd-icon-group' : fm.mime2class(file.mime));
 
- 		if (cnt > 1) {
 
- 			title = tpl.groupTitle.replace('{items}', fm.i18n('items')).replace('{num}', cnt);
 
- 		} else {
 
- 			title = tpl.itemTitle.replace('{name}', file.name).replace('{kind}', fm.mime2kind(file));
 
- 			tmb = fm.tmb(file);
 
- 		}
 
- 		dataTable = makeDataTable(makeperm(files), files.length == 1? files[0] : {});
 
- 		view = view.replace('{title}', title).replace('{dataTable}', dataTable).replace(/{id}/g, id);
 
- 		dialog = this.fmDialog(view, opts);
 
- 		dialog.attr('id', id);
 
- 		// load thumbnail
 
- 		if (tmb) {
 
- 			$('<img/>')
 
- 				.on('load', function() { dialog.find('.elfinder-cwd-icon').addClass(tmb.className).css('background-image', "url('"+tmb.url+"')"); })
 
- 				.attr('src', tmb.url);
 
- 		}
 
- 		$('#' + id + '-table-perm :checkbox').on('click', function(){setperm('perm');});
 
- 		$('#' + id + '-perm').on('keydown', function(e) {
 
- 			var c = e.keyCode;
 
- 			if (c == $.ui.keyCode.ENTER) {
 
- 				e.stopPropagation();
 
- 				save();
 
- 				return;
 
- 			}
 
- 		}).on('focus', function(e){
 
- 			$(this).trigger('select');
 
- 		}).on('keyup', function(e) {
 
- 			if ($(this).val().length == 3) {
 
- 				$(this).trigger('select');
 
- 				setcheck($(this).val());
 
- 			}
 
- 		});
 
- 		
 
- 		return dfrd;
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/colwidth.js
 
-  */
 
- /**
 
-  * @class  elFinder command "colwidth"
 
-  * CWD list table columns width to auto
 
-  *
 
-  * @author Naoki Sawada
 
-  **/
 
- elFinder.prototype.commands.colwidth = function() {
 
- 		this.alwaysEnabled = true;
 
- 	this.updateOnSelect = false;
 
- 	
 
- 	this.getstate = function() {
 
- 		return this.fm.getUI('cwd').find('table').css('table-layout') === 'fixed' ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function() {
 
- 		this.fm.getUI('cwd').trigger('colwidth');
 
- 		return $.Deferred().resolve();
 
- 	};
 
- 	
 
- };
 
- /*
 
-  * File: /js/commands/copy.js
 
-  */
 
- /**
 
-  * @class elFinder command "copy".
 
-  * Put files in filemanager clipboard.
 
-  *
 
-  * @type  elFinder.command
 
-  * @author  Dmitry (dio) Levashov
 
-  */
 
- elFinder.prototype.commands.copy = function() {
 
- 		this.shortcuts = [{
 
- 		pattern     : 'ctrl+c ctrl+insert'
 
- 	}];
 
- 	
 
- 	this.getstate = function(select) {
 
- 		var sel = this.files(select),
 
- 			cnt = sel.length;
 
- 		return cnt && $.grep(sel, function(f) { return f.read ? true : false; }).length == cnt ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes) {
 
- 		var fm   = this.fm,
 
- 			dfrd = $.Deferred()
 
- 				.fail(function(error) {
 
- 					fm.error(error);
 
- 				});
 
- 		$.each(this.files(hashes), function(i, file) {
 
- 			if (! file.read) {
 
- 				return !dfrd.reject(['errCopy', file.name, 'errPerm']);
 
- 			}
 
- 		});
 
- 		
 
- 		return dfrd.state() == 'rejected' ? dfrd : dfrd.resolve(fm.clipboard(this.hashes(hashes)));
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/cut.js
 
-  */
 
- /**
 
-  * @class elFinder command "copy".
 
-  * Put files in filemanager clipboard.
 
-  *
 
-  * @type  elFinder.command
 
-  * @author  Dmitry (dio) Levashov
 
-  */
 
- elFinder.prototype.commands.cut = function() {
 
- 		var fm = this.fm;
 
- 	
 
- 	this.shortcuts = [{
 
- 		pattern     : 'ctrl+x shift+insert'
 
- 	}];
 
- 	
 
- 	this.getstate = function(select) {
 
- 		var sel = this.files(select),
 
- 			cnt = sel.length;
 
- 		
 
- 		return cnt && $.grep(sel, function(f) { return f.read && ! f.locked && ! fm.isRoot(f) ? true : false; }).length == cnt ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes) {
 
- 		var dfrd = $.Deferred()
 
- 				.fail(function(error) {
 
- 					fm.error(error);
 
- 				});
 
- 		$.each(this.files(hashes), function(i, file) {
 
- 			if (!(file.read && ! file.locked && ! fm.isRoot(file)) ) {
 
- 				return !dfrd.reject(['errCopy', file.name, 'errPerm']);
 
- 			}
 
- 			if (file.locked) {
 
- 				return !dfrd.reject(['errLocked', file.name]);
 
- 			}
 
- 		});
 
- 		
 
- 		return dfrd.state() == 'rejected' ? dfrd : dfrd.resolve(fm.clipboard(this.hashes(hashes), true));
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/download.js
 
-  */
 
- /**
 
-  * @class elFinder command "download". 
 
-  * Download selected files.
 
-  * Only for new api
 
-  *
 
-  * @author Dmitry (dio) Levashov, dio@std42.ru
 
-  **/
 
- elFinder.prototype.commands.zipdl = function() {};
 
- elFinder.prototype.commands.download = function() {
 
- 		var self   = this,
 
- 		fm     = this.fm,
 
- 		czipdl = null,
 
- 		zipOn  = false,
 
- 		mixed  = false,
 
- 		dlntf  = false,
 
- 		cpath  = window.location.pathname || '/',
 
- 		filter = function(hashes, inExec) {
 
- 			var volumeid, mixedCmd;
 
- 			
 
- 			if (czipdl !== null) {
 
- 				if (fm.searchStatus.state > 1) {
 
- 					mixed = fm.searchStatus.mixed;
 
- 				} else if (fm.leafRoots[fm.cwd().hash]) {
 
- 					volumeid = fm.cwd().volumeid;
 
- 					$.each(hashes, function(i, h) {
 
- 						if (h.indexOf(volumeid) !== 0) {
 
- 							mixed = true;
 
- 							return false;
 
- 						}
 
- 					});
 
- 				}
 
- 				zipOn = (fm.isCommandEnabled('zipdl', hashes[0]));
 
- 			}
 
- 			if (mixed) {
 
- 				mixedCmd = czipdl? 'zipdl' : 'download';
 
- 				hashes = $.grep(hashes, function(h) {
 
- 					var f = fm.file(h),
 
- 						res = (! f || (! czipdl && f.mime === 'directory') || ! fm.isCommandEnabled(mixedCmd, h))? false : true;
 
- 					if (f && inExec && ! res) {
 
- 						$('#' + fm.cwdHash2Id(f.hash)).trigger('unselect');
 
- 					}
 
- 					return res;
 
- 				});
 
- 				if (! hashes.length) {
 
- 					return [];
 
- 				}
 
- 			} else {
 
- 				if (!fm.isCommandEnabled('download', hashes[0])) {
 
- 					return [];
 
- 				}
 
- 			}
 
- 			
 
- 			return $.grep(self.files(hashes), function(f) { 
 
- 				var res = (! f.read || (! zipOn && f.mime == 'directory')) ? false : true;
 
- 				if (inExec && ! res) {
 
- 					$('#' + fm.cwdHash2Id(f.hash)).trigger('unselect');
 
- 				}
 
- 				return res;
 
- 			});
 
- 		};
 
- 	
 
- 	this.linkedCmds = ['zipdl'];
 
- 	
 
- 	this.shortcuts = [{
 
- 		pattern     : 'shift+enter'
 
- 	}];
 
- 	
 
- 	this.getstate = function(select) {
 
- 		var sel    = this.hashes(select),
 
- 			cnt    = sel.length,
 
- 			maxReq = this.options.maxRequests || 10,
 
- 			mixed  = false,
 
- 			croot  = '';
 
- 		
 
- 		if (cnt < 1) {
 
- 			return -1;
 
- 		}
 
- 		cnt = filter(sel).length;
 
- 		
 
- 		return  (cnt && (zipOn || (cnt <= maxReq && ((!fm.UA.IE && !fm.UA.Mobile) || cnt == 1))) ? 0 : -1);
 
- 	};
 
- 	
 
- 	fm.bind('contextmenu', function(e){
 
- 		var fm = self.fm,
 
- 			helper = null,
 
- 			targets, file, link,
 
- 			getExtra = function(file) {
 
- 				var link = file.url || fm.url(file.hash);
 
- 				return {
 
- 					icon: 'link',
 
- 					node: $('<a/>')
 
- 						.attr({href: link, target: '_blank', title: fm.i18n('link')})
 
- 						.text(file.name)
 
- 						.on('mousedown click touchstart touchmove touchend contextmenu', function(e){
 
- 							e.stopPropagation();
 
- 						})
 
- 						.on('dragstart', function(e) {
 
- 							var dt = e.dataTransfer || e.originalEvent.dataTransfer || null;
 
- 							helper = null;
 
- 							if (dt) {
 
- 								var icon  = function(f) {
 
- 										var mime = f.mime, i, tmb = fm.tmb(f);
 
- 										i = '<div class="elfinder-cwd-icon '+fm.mime2class(mime)+' ui-corner-all"/>';
 
- 										if (tmb) {
 
- 											i = $(i).addClass(tmb.className).css('background-image', "url('"+tmb.url+"')").get(0).outerHTML;
 
- 										}
 
- 										return i;
 
- 									};
 
- 								dt.effectAllowed = 'copyLink';
 
- 								if (dt.setDragImage) {
 
- 									helper = $('<div class="elfinder-drag-helper html5-native">').append(icon(file)).appendTo($(document.body));
 
- 									dt.setDragImage(helper.get(0), 50, 47);
 
- 								}
 
- 								if (!fm.UA.IE) {
 
- 									dt.setData('elfinderfrom', window.location.href + file.phash);
 
- 									dt.setData('elfinderfrom:' + dt.getData('elfinderfrom'), '');
 
- 								}
 
- 							}
 
- 						})
 
- 						.on('dragend', function(e) {
 
- 							helper && helper.remove();
 
- 						})
 
- 				};
 
- 			};
 
- 		self.extra = null;
 
- 		if (e.data) {
 
- 			targets = e.data.targets || [];
 
- 			if (targets.length === 1 && (file = fm.file(targets[0])) && file.mime !== 'directory') {
 
- 				if (file.url != '1') {
 
- 					self.extra = getExtra(file);
 
- 				} else {
 
- 					// Get URL ondemand
 
- 					var node;
 
- 					self.extra = {
 
- 						icon: 'link',
 
- 						node: $('<a/>')
 
- 							.attr({href: '#', title: fm.i18n('getLink'), draggable: 'false'})
 
- 							.text(file.name)
 
- 							.on('click touchstart', function(e){
 
- 								if (e.type === 'touchstart' && e.originalEvent.touches.length > 1) {
 
- 									return;
 
- 								}
 
- 								var parent = node.parent();
 
- 								e.stopPropagation();
 
- 								e.preventDefault();
 
- 								parent.removeClass('ui-state-disabled').addClass('elfinder-button-icon-spinner');
 
- 								fm.request({
 
- 									data : {cmd : 'url', target : file.hash},
 
- 									preventDefault : true
 
- 								})
 
- 								.always(function(data) {
 
- 									parent.removeClass('elfinder-button-icon-spinner');
 
- 									if (data.url) {
 
- 										var rfile = fm.file(file.hash);
 
- 										rfile.url = data.url;
 
- 										node.replaceWith(getExtra(file).node);
 
- 									} else {
 
- 										parent.addClass('ui-state-disabled');
 
- 									}
 
- 								});
 
- 							})
 
- 					};
 
- 					node = self.extra.node;
 
- 					node.ready(function(){
 
- 						requestAnimationFrame(function(){
 
- 							node.parent().addClass('ui-state-disabled').css('pointer-events', 'auto');
 
- 						});
 
- 					});
 
- 				}
 
- 			}
 
- 		}
 
- 	}).one('open', function() {
 
- 		if (fm.api >= 2.1012) {
 
- 			czipdl = fm.getCommand('zipdl');
 
- 		}
 
- 		dlntf = fm.api > 2.1038 && !fm.isCORS;
 
- 	});
 
- 	
 
- 	this.exec = function(select) {
 
- 		var hashes  = this.hashes(select),
 
- 			fm      = this.fm,
 
- 			base    = fm.options.url,
 
- 			files   = filter(hashes, true),
 
- 			dfrd    = $.Deferred(),
 
- 			iframes = '',
 
- 			cdata   = '',
 
- 			targets = {},
 
- 			i, url,
 
- 			linkdl  = false,
 
- 			getTask = function(hashes) {
 
- 				return function() {
 
- 					var dfd = $.Deferred(),
 
- 						root = fm.file(fm.root(hashes[0])),
 
- 						single = (hashes.length === 1),
 
- 						volName = root? (root.i18 || root.name) : null,
 
- 						dir, dlName, phash;
 
- 					if (single) {
 
- 						if (dir = fm.file(hashes[0])) {
 
- 							dlName = (dir.i18 || dir.name);
 
- 						}
 
- 					} else {
 
- 						$.each(hashes, function() {
 
- 							var d = fm.file(this);
 
- 							if (d && (!phash || phash === d.phash)) {
 
- 								phash = d.phash;
 
- 							} else {
 
- 								phash = null;
 
- 								return false;
 
- 							}
 
- 						});
 
- 						if (phash && (dir = fm.file(phash))) {
 
- 							dlName = (dir.i18 || dir.name) + '-' + hashes.length;
 
- 						}
 
- 					}
 
- 					if (dlName) {
 
- 						volName = dlName;
 
- 					}
 
- 					volName && (volName = ' (' + volName + ')');
 
- 					fm.request({
 
- 						data : {cmd : 'zipdl', targets : hashes},
 
- 						notify : {type : 'zipdl', cnt : 1, hideCnt : true, msg : fm.i18n('ntfzipdl') + volName},
 
- 						cancel : true,
 
- 						eachCancel : true,
 
- 						preventDefault : true
 
- 					}).done(function(e) {
 
- 						var zipdl, dialog, btn = {}, dllink, form, iframe, m,
 
- 							uniq = 'dlw' + (+new Date());
 
- 						if (e.error) {
 
- 							fm.error(e.error);
 
- 							dfd.resolve();
 
- 						} else if (e.zipdl) {
 
- 							zipdl = e.zipdl;
 
- 							if (dlName) {
 
- 								m = fm.splitFileExtention(zipdl.name || '');
 
- 								dlName += m[1]? ('.' + m[1]) : '.zip';
 
- 							} else {
 
- 								dlName = zipdl.name;
 
- 							}
 
- 							if ((html5dl && (!fm.UA.Safari || fm.isSameOrigin(fm.options.url))) || linkdl) {
 
- 								url = fm.options.url + (fm.options.url.indexOf('?') === -1 ? '?' : '&')
 
- 								+ 'cmd=zipdl&download=1';
 
- 								$.each([hashes[0], zipdl.file, dlName, zipdl.mime], function(key, val) {
 
- 									url += '&targets%5B%5D='+encodeURIComponent(val);
 
- 								});
 
- 								$.each(fm.customData, function(key, val) {
 
- 									url += '&'+encodeURIComponent(key)+'='+encodeURIComponent(val);
 
- 								});
 
- 								url += '&'+encodeURIComponent(dlName);
 
- 								dllink = $('<a/>')
 
- 									.attr('href', url)
 
- 									.attr('download', fm.escape(dlName))
 
- 									.on('click', function() {
 
- 										dfd.resolve();
 
- 										dialog && dialog.elfinderdialog('destroy');
 
- 									});
 
- 								if (linkdl) {
 
- 									dllink.attr('target', '_blank')
 
- 										.append('<span class="elfinder-button-icon elfinder-button-icon-download"></span>'+fm.escape(dlName));
 
- 									btn[fm.i18n('btnCancel')] = function() {
 
- 										dialog.elfinderdialog('destroy');
 
- 									};
 
- 									dialog = self.fmDialog(dllink, {
 
- 										title: fm.i18n('link'),
 
- 										buttons: btn,
 
- 										width: '200px',
 
- 										destroyOnClose: true,
 
- 										close: function() {
 
- 											(dfd.state() !== 'resolved') && dfd.resolve();
 
- 										}
 
- 									});
 
- 								} else {
 
- 									click(dllink.hide().appendTo('body').get(0));
 
- 									dllink.remove();
 
- 								}
 
- 							} else {
 
- 								form = $('<form action="'+fm.options.url+'" method="post" target="'+uniq+'" style="display:none"/>')
 
- 								.append('<input type="hidden" name="cmd" value="zipdl"/>')
 
- 								.append('<input type="hidden" name="download" value="1"/>');
 
- 								$.each([hashes[0], zipdl.file, dlName, zipdl.mime], function(key, val) {
 
- 									form.append('<input type="hidden" name="targets[]" value="'+fm.escape(val)+'"/>');
 
- 								});
 
- 								$.each(fm.customData, function(key, val) {
 
- 									form.append('<input type="hidden" name="'+key+'" value="'+fm.escape(val)+'"/>');
 
- 								});
 
- 								form.attr('target', uniq).appendTo('body');
 
- 								iframe = $('<iframe style="display:none" name="'+uniq+'">')
 
- 									.appendTo('body')
 
- 									.ready(function() {
 
- 										form.submit().remove();
 
- 										dfd.resolve();
 
- 										setTimeout(function() {
 
- 											iframe.remove();
 
- 										}, 20000); // give 20 sec file to be saved
 
- 									});
 
- 							}
 
- 						}
 
- 					}).fail(function(error) {
 
- 						error && fm.error(error);
 
- 						dfd.resolve();
 
- 					});
 
- 					return dfd.promise();
 
- 				};
 
- 			},
 
- 			// use MouseEvent to click element for Safari etc
 
- 			click = function(a) {
 
- 				var clickEv;
 
- 				if (typeof MouseEvent === 'function') {
 
- 					clickEv = new MouseEvent('click');
 
- 				} else {
 
- 					clickEv = document.createEvent('MouseEvents');
 
- 					clickEv.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
 
- 				}
 
- 				a.dispatchEvent(clickEv);
 
- 			},
 
- 			checkCookie = function(id) {
 
- 				var name = 'elfdl' + id,
 
- 					parts;
 
- 				parts = document.cookie.split(name + "=");
 
- 				if (parts.length === 2) {
 
- 					ntftm && clearTimeout(ntftm);
 
- 					document.cookie = name + '=; path=' + cpath + '; max-age=0';
 
- 					closeNotify();
 
- 				} else {
 
- 					setTimeout(function() { checkCookie(id); }, 200);
 
- 				}
 
- 			},
 
- 			closeNotify = function() {
 
- 				if (fm.ui.notify.children('.elfinder-notify-download').length) {
 
- 					fm.notify({
 
- 						type : 'download',
 
- 						cnt : -1
 
- 					});
 
- 				}
 
- 			},
 
- 			reqids = [],
 
- 			link, html5dl, fileCnt, clickEv, cid, ntftm, reqid;
 
- 			
 
- 		if (!files.length) {
 
- 			return dfrd.reject();
 
- 		}
 
- 		
 
- 		fileCnt = $.grep(files, function(f) { return f.mime === 'directory'? false : true; }).length;
 
- 		link = $('<a>').hide().appendTo('body');
 
- 		html5dl = (typeof link.get(0).download === 'string');
 
- 		
 
- 		if (zipOn && (fileCnt !== files.length || fileCnt >= (this.options.minFilesZipdl || 1))) {
 
- 			link.remove();
 
- 			linkdl = (!html5dl && fm.UA.Mobile);
 
- 			if (mixed) {
 
- 				targets = {};
 
- 				$.each(files, function(i, f) {
 
- 					var p = f.hash.split('_', 2);
 
- 					if (! targets[p[0]]) {
 
- 						targets[p[0]] = [ f.hash ];
 
- 					} else {
 
- 						targets[p[0]].push(f.hash);
 
- 					}
 
- 				});
 
- 				if (!linkdl && fm.UA.Mobile && Object.keys(targets).length > 1) {
 
- 					linkdl = true;
 
- 				}
 
- 			} else {
 
- 				targets = [ $.map(files, function(f) { return f.hash; }) ];
 
- 			}
 
- 			dfrd = fm.sequence($.map(targets, function(t) { return getTask(t); })).always(
 
- 				function() {
 
- 					fm.trigger('download', {files : files});
 
- 				}
 
- 			);
 
- 			return dfrd;
 
- 		} else {
 
- 			reqids = [];
 
- 			for (i = 0; i < files.length; i++) {
 
- 				url = fm.openUrl(files[i].hash, true);
 
- 				if (dlntf && url.substr(0, fm.options.url.length) === fm.options.url) {
 
- 					reqid = fm.getRequestId();
 
- 					reqids.push(reqid);
 
- 					url += '&cpath=' + cpath + '&reqid=' + reqid;
 
- 					ntftm = setTimeout(function() {
 
- 						fm.notify({
 
- 							type : 'download',
 
- 							cnt : 1,
 
- 							cancel : (fm.UA.IE || fm.UA.Edge)? void(0) : function() {
 
- 								if (reqids.length) {
 
- 									$.each(reqids, function() {
 
- 										fm.request({
 
- 											data: {
 
- 												cmd: 'abort',
 
- 												id: this
 
- 											},
 
- 											preventDefault: true
 
- 										});
 
- 									});
 
- 								}
 
- 								reqids = [];
 
- 							}
 
- 						});
 
- 					}, fm.notifyDelay);
 
- 					checkCookie(reqid);
 
- 				}
 
- 				if (html5dl && (!fm.UA.Safari || fm.isSameOrigin(url))) {
 
- 					click(link.attr('href', url)
 
- 						.attr('download', fm.escape(files[i].name))
 
- 						.get(0)
 
- 					);
 
- 				} else {
 
- 					if (fm.UA.Mobile) {
 
- 						setTimeout(function(){
 
- 							if (! window.open(url)) {
 
- 								fm.error('errPopup');
 
- 								ntftm && cleaerTimeout(ntftm);
 
- 								closeNotify();
 
- 							}
 
- 						}, 100);
 
- 					} else {
 
- 						iframes += '<iframe class="downloader" id="downloader-' + files[i].hash+'" style="display:none" src="'+url+'"/>';
 
- 					}
 
- 				}
 
- 			}
 
- 			link.remove();
 
- 			$(iframes)
 
- 				.appendTo('body')
 
- 				.ready(function() {
 
- 					setTimeout(function() {
 
- 						$(iframes).each(function() {
 
- 							$('#' + $(this).attr('id')).remove();
 
- 						});
 
- 					}, 20000 + (10000 * i)); // give 20 sec + 10 sec for each file to be saved
 
- 				});
 
- 			fm.trigger('download', {files : files});
 
- 			return dfrd.resolve();
 
- 		}
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/duplicate.js
 
-  */
 
- /**
 
-  * @class elFinder command "duplicate"
 
-  * Create file/folder copy with suffix "copy Number"
 
-  *
 
-  * @type  elFinder.command
 
-  * @author  Dmitry (dio) Levashov
 
-  */
 
- elFinder.prototype.commands.duplicate = function() {
 
- 		var fm = this.fm;
 
- 	
 
- 	this.getstate = function(select) {
 
- 		var sel = this.files(select),
 
- 			cnt = sel.length;
 
- 		return cnt && fm.cwd().write && $.grep(sel, function(f) { return f.read && f.phash === fm.cwd().hash && ! fm.isRoot(f)? true : false; }).length == cnt ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes) {
 
- 		var fm     = this.fm,
 
- 			files  = this.files(hashes),
 
- 			cnt    = files.length,
 
- 			dfrd   = $.Deferred()
 
- 				.fail(function(error) {
 
- 					error && fm.error(error);
 
- 				}), 
 
- 			args = [];
 
- 			
 
- 		if (! cnt) {
 
- 			return dfrd.reject();
 
- 		}
 
- 		
 
- 		$.each(files, function(i, file) {
 
- 			if (!file.read || !fm.file(file.phash).write) {
 
- 				return !dfrd.reject(['errCopy', file.name, 'errPerm']);
 
- 			}
 
- 		});
 
- 		
 
- 		if (dfrd.state() == 'rejected') {
 
- 			return dfrd;
 
- 		}
 
- 		
 
- 		return fm.request({
 
- 			data   : {cmd : 'duplicate', targets : this.hashes(hashes)},
 
- 			notify : {type : 'copy', cnt : cnt},
 
- 			navigate : {
 
- 				toast : {
 
- 					inbuffer : {msg: fm.i18n(['complete', fm.i18n('cmdduplicate')])}
 
- 				}
 
- 			}
 
- 		});
 
- 		
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/edit.js
 
-  */
 
- /**
 
-  * @class elFinder command "edit". 
 
-  * Edit text file in dialog window
 
-  *
 
-  * @author Dmitry (dio) Levashov, dio@std42.ru
 
-  **/
 
- elFinder.prototype.commands.edit = function() {
 
- 		var self  = this,
 
- 		fm    = this.fm,
 
- 		clsEditing = fm.res('class', 'editing'),
 
- 		mimesSingle = [],
 
- 		mimes = [],
 
- 		allowAll = false,
 
- 		rtrim = function(str){
 
- 			return str.replace(/\s+$/, '');
 
- 		},
 
- 		getEncSelect = function(heads) {
 
- 			var sel = $('<select class="ui-corner-all"/>'),
 
- 				hval;
 
- 			if (heads) {
 
- 				$.each(heads, function(i, head) {
 
- 					hval = fm.escape(head.value);
 
- 					sel.append('<option value="'+hval+'">'+(head.caption? fm.escape(head.caption) : hval)+'</option>');
 
- 				});
 
- 			}
 
- 			$.each(self.options.encodings, function(i, v) {
 
- 				sel.append('<option value="'+v+'">'+v+'</option>');
 
- 			});
 
- 			return sel;
 
- 		},
 
- 		getDlgWidth = function() {
 
- 			var m, width;
 
- 			if (typeof self.options.dialogWidth === 'string' && (m = self.options.dialogWidth.match(/(\d+)%/))) {
 
- 				width = parseInt(fm.getUI().width() * (m[1] / 100));
 
- 			} else {
 
- 				width = parseInt(self.options.dialogWidth || 650);
 
- 			}
 
- 			return Math.min(width, $(window).width());
 
- 		},
 
- 		/**
 
- 		 * Return files acceptable to edit
 
- 		 *
 
- 		 * @param  Array  files hashes
 
- 		 * @return Array
 
- 		 **/
 
- 		filter = function(files) {
 
- 			var cnt = files.length,
 
- 				mime, ext, skip;
 
- 			
 
- 			if (cnt > 1) {
 
- 				mime = files[0].mime;
 
- 				ext = files[0].name.replace(/^.*(\.[^.]+)$/, '$1');
 
- 			}
 
- 			return $.grep(files, function(file) {
 
- 				var res;
 
- 				if (skip || file.mime === 'directory') {
 
- 					return false;
 
- 				}
 
- 				res = file.read
 
- 					&& (allowAll || fm.mimeIsText(file.mime) || $.inArray(file.mime, cnt === 1? mimesSingle : mimes) !== -1) 
 
- 					&& (!self.onlyMimes.length || $.inArray(file.mime, self.onlyMimes) !== -1)
 
- 					&& (cnt === 1 || (file.mime === mime && file.name.substr(ext.length * -1) === ext))
 
- 					&& (fm.uploadMimeCheck(file.mime, file.phash)? true : false)
 
- 					&& setEditors(file, cnt)
 
- 					&& Object.keys(editors).length;
 
- 				if (!res) {
 
- 					skip = true;
 
- 				}
 
- 				return res;
 
- 			});
 
- 		},
 
- 		fileSync = function(hash) {
 
- 			var old = fm.file(hash),
 
- 				f;
 
- 			fm.request({
 
- 				cmd: 'info',
 
- 				targets: [hash],
 
- 				preventDefault: true
 
- 			}).done(function(data) {
 
- 				var changed;
 
- 				if (data && data.files && data.files.length) {
 
- 					f = data.files[0];
 
- 					if (old.ts != f.ts || old.size != f.size) {
 
- 						changed = { changed: [ f ] };
 
- 						fm.updateCache(changed);
 
- 						fm.change(changed);
 
- 					}
 
- 				}
 
- 			});
 
- 		},
 
- 		/**
 
- 		 * Open dialog with textarea to edit file
 
- 		 *
 
- 		 * @param  String  id       dialog id
 
- 		 * @param  Object  file     file object
 
- 		 * @param  String  content  file content
 
- 		 * @return $.Deferred
 
- 		 **/
 
- 		dialog = function(id, file, content, encoding, editor) {
 
- 			var dfrd = $.Deferred(),
 
- 				_loaded = false,
 
- 				loaded = function() {
 
- 					if (!_loaded) {
 
- 						fm.toast({
 
- 							mode: 'warning',
 
- 							msg: fm.i18n('nowLoading')
 
- 						});
 
- 						return false;
 
- 					}
 
- 					return true;
 
- 				},
 
- 				save = function() {
 
- 					var encord = selEncoding? selEncoding.val():void(0),
 
- 						saveDfd = $.Deferred().fail(function(err) {
 
- 							dialogNode.show().find('button.elfinder-btncnt-0,button.elfinder-btncnt-1').hide();
 
- 						}),
 
- 						conf, res;
 
- 					if (!loaded()) {
 
- 						return saveDfd.resolve();
 
- 					}
 
- 					if (ta.editor) {
 
- 						ta.editor.save(ta[0], ta.editor.instance);
 
- 						conf = ta.editor.confObj;
 
- 						if (conf.info && (conf.info.schemeContent || conf.info.arrayBufferContent)) {
 
- 							encord = 'scheme';
 
- 						}
 
- 					}
 
- 					res = getContent();
 
- 					setOld(res);
 
- 					if (res.promise) {
 
- 						res.done(function(data) {
 
- 							dfrd.notifyWith(ta, [encord, ta.data('hash'), old, saveDfd]);
 
- 						}).fail(function(err) {
 
- 							saveDfd.reject(err);
 
- 						});
 
- 					} else {
 
- 						dfrd.notifyWith(ta, [encord, ta.data('hash'), old, saveDfd]);
 
- 					}
 
- 					return saveDfd;
 
- 				},
 
- 				saveon = function() {
 
- 					if (!loaded()) { return; }
 
- 					save().fail(function(err) {
 
- 						err && fm.error(err);
 
- 					});
 
- 				},
 
- 				cancel = function() {
 
- 					ta.elfinderdialog('close');
 
- 				},
 
- 				savecl = function() {
 
- 					if (!loaded()) { return; }
 
- 					save().done(function() {
 
- 						_loaded = false;
 
- 						dialogNode.show();
 
- 						cancel();
 
- 					}).fail(function(err) {
 
- 						dialogNode.show();
 
- 						err && fm.error(err);
 
- 					});
 
- 					dialogNode.hide();
 
- 				},
 
- 				saveAs = function() {
 
- 					if (!loaded()) { return; }
 
- 					var prevOld = old,
 
- 						phash = fm.file(file.phash)? file.phash : fm.cwd().hash,
 
- 						fail = function(err) {
 
- 							dialogs.addClass(clsEditing).fadeIn(function() {
 
- 								err && fm.error(err);
 
- 							});
 
- 							old = prevOld;
 
- 							fm.disable();
 
- 						},
 
- 						make = function() {
 
- 							self.mime = saveAsFile.mime || file.mime;
 
- 							self.prefix = (saveAsFile.name || file.name).replace(/ \d+(\.[^.]+)?$/, '$1');
 
- 							self.requestCmd = 'mkfile';
 
- 							self.nextAction = {};
 
- 							self.data = {target : phash};
 
- 							$.proxy(fm.res('mixin', 'make'), self)()
 
- 								.done(function(data) {
 
- 									if (data.added && data.added.length) {
 
- 										ta.data('hash', data.added[0].hash);
 
- 										save().done(function() {
 
- 											_loaded = false;
 
- 											dialogNode.show();
 
- 											cancel();
 
- 											dialogs.fadeIn();
 
- 										}).fail(fail);
 
- 									} else {
 
- 										fail();
 
- 									}
 
- 								})
 
- 								.progress(function(err) {
 
- 									if (err && err === 'errUploadMime') {
 
- 										ta.trigger('saveAsFail');
 
- 									}
 
- 								})
 
- 								.fail(fail)
 
- 								.always(function() {
 
- 									delete self.mime;
 
- 									delete self.prefix;
 
- 									delete self.nextAction;
 
- 									delete self.data;
 
- 								});
 
- 							fm.trigger('unselectfiles', { files: [ file.hash ] });
 
- 						},
 
- 						reqOpen = null,
 
- 						dialogs = fm.getUI().children('.' + self.dialogClass + ':visible');
 
- 						if (dialogNode.is(':hidden')) {
 
- 							dialogs = dialogs.add(dialogNode);
 
- 						}
 
- 						dialogs.removeClass(clsEditing).fadeOut();
 
- 					
 
- 					fm.enable();
 
- 					
 
- 					if (fm.searchStatus.state < 2 && phash !== fm.cwd().hash) {
 
- 						reqOpen = fm.exec('open', [phash], {thash: phash});
 
- 					}
 
- 					
 
- 					$.when([reqOpen]).done(function() {
 
- 						reqOpen? fm.one('cwdrender', make) : make();
 
- 					}).fail(fail);
 
- 				},
 
- 				changed = function() {
 
- 					var dfd = $.Deferred(),
 
- 						res, tm;
 
- 					if (!_loaded) {
 
- 						return dfd.resolve(false);
 
- 					}
 
- 					ta.editor && ta.editor.save(ta[0], ta.editor.instance);
 
- 					res = getContent();
 
- 					if (res && res.promise) {
 
- 						tm = setTimeout(function() {
 
- 							fm.notify({
 
- 								type : 'chkcontent',
 
- 								cnt : 1,
 
- 								hideCnt: true
 
- 							});
 
- 						}, 100);
 
- 						res.always(function() {
 
- 							tm && clearTimeout(tm);
 
- 							fm.notify({ type : 'chkcontent', cnt: -1 });
 
- 						}).done(function(d) {
 
- 							dfd.resolve(old !== d);
 
- 						}).fail(function(err) {
 
- 							dfd.resolve(err || true);
 
- 						});
 
- 					} else {
 
- 						dfd.resolve(old !== res);
 
- 					}
 
- 					return dfd;
 
- 				},
 
- 				opts = {
 
- 					title   : fm.escape(file.name),
 
- 					width   : getDlgWidth(),
 
- 					buttons : {},
 
- 					cssClass  : clsEditing,
 
- 					maxWidth  : 'window',
 
- 					maxHeight : 'window',
 
- 					allowMinimize : true,
 
- 					allowMaximize : true,
 
- 					openMaximized : editorMaximized() || (editor && editor.info && editor.info.openMaximized),
 
- 					btnHoverFocus : false,
 
- 					closeOnEscape : false,
 
- 					propagationEvents : ['mousemove', 'mouseup', 'click'],
 
- 					minimize : function() {
 
- 						var conf;
 
- 						if (ta.editor && dialogNode.closest('.ui-dialog').is(':hidden')) {
 
- 							conf = ta.editor.confObj;
 
- 							if (conf.info && conf.info.syncInterval) {
 
- 								fileSync(file.hash);
 
- 							}
 
- 						}
 
- 					},
 
- 					close   : function() {
 
- 						var close = function() {
 
- 								var conf;
 
- 								dfrd.resolve();
 
- 								if (ta.editor) {
 
- 									ta.editor.close(ta[0], ta.editor.instance);
 
- 									conf = ta.editor.confObj;
 
- 									if (conf.info && conf.info.syncInterval) {
 
- 										fileSync(file.hash);
 
- 									}
 
- 								}
 
- 								ta.elfinderdialog('destroy');
 
- 							},
 
- 							onlySaveAs = (typeof saveAsFile.name !== 'undefined'),
 
- 							accept = onlySaveAs? {
 
- 								label    : 'btnSaveAs',
 
- 								callback : function() {
 
- 									requestAnimationFrame(saveAs);
 
- 								}
 
- 							} : {
 
- 								label    : 'btnSaveClose',
 
- 								callback : function() {
 
- 									save().done(function() {
 
- 										close();
 
- 									});
 
- 								}
 
- 							};
 
- 						changed().done(function(change) {
 
- 							var msgs = ['confirmNotSave'];
 
- 							if (change) {
 
- 								if (typeof change === 'string') {
 
- 									msgs.unshift(change);
 
- 								}
 
- 								fm.confirm({
 
- 									title  : self.title,
 
- 									text   : msgs,
 
- 									accept : accept,
 
- 									cancel : {
 
- 										label    : 'btnClose',
 
- 										callback : close
 
- 									},
 
- 									buttons : onlySaveAs? null : [{
 
- 										label    : 'btnSaveAs',
 
- 										callback : function() {
 
- 											requestAnimationFrame(saveAs);
 
- 										}
 
- 									}]
 
- 								});
 
- 							} else {
 
- 								close();
 
- 							}
 
- 						});
 
- 					},
 
- 					open    : function() {
 
- 						var loadRes, conf, interval;
 
- 						ta.initEditArea.call(ta, id, file, content, fm);
 
- 						if (ta.editor) {
 
- 							loadRes = ta.editor.load(ta[0]) || null;
 
- 							if (loadRes && loadRes.done) {
 
- 								loadRes.always(function() {
 
- 									_loaded = true;
 
- 								}).done(function(instance) {
 
- 									ta.editor.instance = instance;
 
- 									ta.editor.focus(ta[0], ta.editor.instance);
 
- 									setOld(getContent());
 
- 									requestAnimationFrame(function() {
 
- 										dialogNode.trigger('resize');
 
- 									});
 
- 								}).fail(function(error) {
 
- 									error && fm.error(error);
 
- 									ta.elfinderdialog('destroy');
 
- 									return;
 
- 								});
 
- 							} else {
 
- 								_loaded = true;
 
- 								if (loadRes && (typeof loadRes === 'string' || Array.isArray(loadRes))) {
 
- 									fm.error(loadRes);
 
- 									ta.elfinderdialog('destroy');
 
- 									return;
 
- 								}
 
- 								ta.editor.instance = loadRes;
 
- 								ta.editor.focus(ta[0], ta.editor.instance);
 
- 								setOld(getContent());
 
- 								requestAnimationFrame(function() {
 
- 									dialogNode.trigger('resize');
 
- 								});
 
- 							}
 
- 							conf = ta.editor.confObj;
 
- 							if (conf.info && conf.info.syncInterval) {
 
- 								if (interval = parseInt(conf.info.syncInterval)) {
 
- 									setTimeout(function() {
 
- 										autoSync(interval);
 
- 									}, interval);
 
- 								}
 
- 							}
 
- 						} else {
 
- 							_loaded = true;
 
- 							setOld(getContent());
 
- 						}
 
- 					},
 
- 					resize : function(e, data) {
 
- 						ta.editor && ta.editor.resize(ta[0], ta.editor.instance, e, data || {});
 
- 					}
 
- 				},
 
- 				getContent = function() {
 
- 					return ta.getContent.call(ta, ta[0]);
 
- 				},
 
- 				setOld = function(res) {
 
- 					if (res && res.promise) {
 
- 						res.done(function(d) {
 
- 							old = d;
 
- 						});
 
- 					} else {
 
- 						old = res;
 
- 					}
 
- 				},
 
- 				autoSync = function(interval) {
 
- 					if (dialogNode.is(':visible')) {
 
- 						fileSync(file.hash);
 
- 						setTimeout(function() {
 
- 							autoSync(interval);
 
- 						}, interval);
 
- 					}
 
- 				},
 
- 				saveAsFile = {},
 
- 				ta, old, dialogNode, selEncoding, extEditor, maxW, syncInterval;
 
- 				
 
- 			if (editor) {
 
- 				if (editor.html) {
 
- 					ta = $(editor.html);
 
- 				}
 
- 				extEditor = {
 
- 					init     : editor.init || null,
 
- 					load     : editor.load,
 
- 					getContent : editor.getContent || null,
 
- 					save     : editor.save,
 
- 					beforeclose : typeof editor.beforeclose == 'function' ? editor.beforeclose : void 0,
 
- 					close    : typeof editor.close == 'function' ? editor.close : function() {},
 
- 					focus    : typeof editor.focus == 'function' ? editor.focus : function() {},
 
- 					resize   : typeof editor.resize == 'function' ? editor.resize : function() {},
 
- 					instance : null,
 
- 					doSave   : saveon,
 
- 					doCancel : cancel,
 
- 					doClose  : savecl,
 
- 					file     : file,
 
- 					fm       : fm,
 
- 					confObj  : editor,
 
- 					trigger  : function(evName, data) {
 
- 						fm.trigger('editEditor' + evName, Object.assign({}, editor.info || {}, data));
 
- 					}
 
- 				};
 
- 			}
 
- 			
 
- 			if (!ta) {
 
- 				if (!fm.mimeIsText(file.mime)) {
 
- 					return dfrd.reject('errEditorNotFound');
 
- 				}
 
- 				(function() {
 
- 					var stateChange = function() {
 
- 							if (selEncoding) {
 
- 								changed().done(function(change) {
 
- 									if (change) {
 
- 										selEncoding.attr('title', fm.i18n('saveAsEncoding')).addClass('elfinder-edit-changed');
 
- 									} else {
 
- 										selEncoding.attr('title', fm.i18n('openAsEncoding')).removeClass('elfinder-edit-changed');
 
- 									}
 
- 								});
 
- 							}
 
- 						};
 
- 						
 
- 					ta = $('<textarea class="elfinder-file-edit" rows="20" id="'+id+'-ta"></textarea>')
 
- 						.on('input propertychange', stateChange);
 
- 					
 
- 					if (!ta.editor || !ta.editor.info || ta.editor.info.useTextAreaEvent) {
 
- 						ta.on('keydown', function(e) {
 
- 							var code = e.keyCode,
 
- 								value, start;
 
- 							
 
- 							e.stopPropagation();
 
- 							if (code == $.ui.keyCode.TAB) {
 
- 								e.preventDefault();
 
- 								// insert tab on tab press
 
- 								if (this.setSelectionRange) {
 
- 									value = this.value;
 
- 									start = this.selectionStart;
 
- 									this.value = value.substr(0, start) + "\t" + value.substr(this.selectionEnd);
 
- 									start += 1;
 
- 									this.setSelectionRange(start, start);
 
- 								}
 
- 							}
 
- 							
 
- 							if (e.ctrlKey || e.metaKey) {
 
- 								// close on ctrl+w/q
 
- 								if (code == 'Q'.charCodeAt(0) || code == 'W'.charCodeAt(0)) {
 
- 									e.preventDefault();
 
- 									cancel();
 
- 								}
 
- 								if (code == 'S'.charCodeAt(0)) {
 
- 									e.preventDefault();
 
- 									saveon();
 
- 								}
 
- 							}
 
- 							
 
- 						})
 
- 						.on('mouseenter', function(){this.focus();});
 
- 					}
 
- 					ta.initEditArea = function(id, file, content) {
 
- 						var heads = (encoding && encoding !== 'unknown')? [{value: encoding}] : [],
 
- 							wfake = $('<select/>').hide(),
 
- 							setSelW = function(init) {
 
- 								init && wfake.appendTo(selEncoding.parent());
 
- 								wfake.empty().append($('<option/>').text(selEncoding.val()));
 
- 								selEncoding.width(wfake.width());
 
- 							};
 
- 						// ta.hide() for performance tune. Need ta.show() in `load()` if use textarea node.
 
- 						ta.hide().val(content);
 
- 						if (content === '' || ! encoding || encoding !== 'UTF-8') {
 
- 							heads.push({value: 'UTF-8'});
 
- 						}
 
- 						selEncoding = getEncSelect(heads).on('touchstart', function(e) {
 
- 							// for touch punch event handler
 
- 							e.stopPropagation();
 
- 						}).on('change', function() {
 
- 							// reload to change encoding if not edited
 
- 							changed().done(function(change) {
 
- 								if (! change && getContent() !== '') {
 
- 									cancel();
 
- 									edit(file, selEncoding.val(), editor).fail(function(err) { err && fm.error(err); });
 
- 								}
 
- 							});
 
- 							setSelW();
 
- 						}).on('mouseover', stateChange);
 
- 						ta.parent().next().prepend($('<div class="ui-dialog-buttonset elfinder-edit-extras"/>').append(selEncoding));
 
- 						setSelW(true);
 
- 					};
 
- 				})();
 
- 			}
 
- 			
 
- 			ta.data('hash', file.hash);
 
- 			
 
- 			if (extEditor) {
 
- 				ta.editor = extEditor;
 
- 				
 
- 				if (typeof extEditor.beforeclose === 'function') {
 
- 					opts.beforeclose = function() {
 
- 						return extEditor.beforeclose(ta[0], extEditor.instance);
 
- 					};
 
- 				}
 
- 				
 
- 				if (typeof extEditor.init === 'function') {
 
- 					ta.initEditArea = extEditor.init;
 
- 				}
 
- 				
 
- 				if (typeof extEditor.getContent === 'function') {
 
- 					ta.getContent = extEditor.getContent;
 
- 				}
 
- 			}
 
- 			
 
- 			if (! ta.initEditArea) {
 
- 				ta.initEditArea = function() {};
 
- 			}
 
- 			
 
- 			if (! ta.getContent) {
 
- 				ta.getContent = function() {
 
- 					return rtrim(ta.val());
 
- 				};
 
- 			}
 
- 			
 
- 			if (!editor || !editor.info || !editor.info.preventGet) {
 
- 				opts.buttons[fm.i18n('btnSave')]      = saveon;
 
- 				opts.buttons[fm.i18n('btnSaveClose')] = savecl;
 
- 				opts.buttons[fm.i18n('btnSaveAs')]    = saveAs;
 
- 				opts.buttons[fm.i18n('btnCancel')]    = cancel;
 
- 			}
 
- 			
 
- 			if (editor && typeof editor.prepare === 'function') {
 
- 				editor.prepare(ta, opts, file);
 
- 			}
 
- 			
 
- 			dialogNode = self.fmDialog(ta, opts)
 
- 				.attr('id', id)
 
- 				.on('keydown keyup keypress', function(e) {
 
- 					e.stopPropagation();
 
- 				})
 
- 				.css({ overflow: 'hidden', minHeight: '7em' })
 
- 				.addClass('elfinder-edit-editor')
 
- 				.closest('.ui-dialog')
 
- 				.on('changeType', function(e, data) {
 
- 					if (data.extention && data.mime) {
 
- 						var ext = data.extention,
 
- 							mime = data.mime,
 
- 							btnSet = $(this).children('.ui-dialog-buttonpane').children('.ui-dialog-buttonset');
 
- 						btnSet.children('.elfinder-btncnt-0,.elfinder-btncnt-1').hide();
 
- 						saveAsFile.name = fm.splitFileExtention(file.name)[0] + '.' + data.extention;
 
- 						saveAsFile.mime = data.mime;
 
- 						if (!data.keepEditor) {
 
- 							btnSet.children('.elfinder-btncnt-2').trigger('click');
 
- 						}
 
- 					}
 
- 				});
 
- 			
 
- 			// care to viewport scale change with mobile devices
 
- 			maxW = (fm.options.dialogContained? elfNode : $(window)).width();
 
- 			(dialogNode.width() > maxW) && dialogNode.width(maxW);
 
- 			
 
- 			return dfrd.promise();
 
- 		},
 
- 		
 
- 		/**
 
- 		 * Get file content and
 
- 		 * open dialog with textarea to edit file content
 
- 		 *
 
- 		 * @param  String  file hash
 
- 		 * @return jQuery.Deferred
 
- 		 **/
 
- 		edit = function(file, convert, editor) {
 
- 			var hash   = file.hash,
 
- 				opts   = fm.options,
 
- 				dfrd   = $.Deferred(), 
 
- 				id     = 'edit-'+fm.namespace+'-'+file.hash,
 
- 				d      = fm.getUI().find('#'+id),
 
- 				conv   = !convert? 0 : convert,
 
- 				req, error, res;
 
- 			
 
- 			
 
- 			if (d.length) {
 
- 				d.elfinderdialog('toTop');
 
- 				return dfrd.resolve();
 
- 			}
 
- 			
 
- 			if (!file.read || (!file.write && (!editor.info || !editor.info.converter))) {
 
- 				error = ['errOpen', file.name, 'errPerm'];
 
- 				return dfrd.reject(error);
 
- 			}
 
- 			
 
- 			if (editor && editor.info) {
 
- 				if (typeof editor.info.edit === 'function') {
 
- 					res = editor.info.edit.call(fm, file, editor);
 
- 					if (res.promise) {
 
- 						res.done(function() {
 
- 							dfrd.resolve();
 
- 						}).fail(function(error) {
 
- 							dfrd.reject(error);
 
- 						});
 
- 					} else {
 
- 						res? dfrd.resolve() : dfrd.reject();
 
- 					}
 
- 					return dfrd;
 
- 				}
 
- 				if (editor.info.urlAsContent || editor.info.preventGet) {
 
- 					req = $.Deferred();
 
- 					if (! editor.info.preventGet) {
 
- 						fm.url(hash, { async: true, temporary: true }).done(function(url) {
 
- 							req.resolve({content: url});
 
- 						});
 
- 					} else {
 
- 						req.resolve({});
 
- 					}
 
- 				} else {
 
- 					req = fm.request({
 
- 						data           : {cmd : 'get', target : hash, conv : conv, _t : file.ts},
 
- 						options        : {type: 'get', cache : true},
 
- 						notify         : {type : 'file', cnt : 1},
 
- 						preventDefault : true
 
- 					});
 
- 				}
 
- 				req.done(function(data) {
 
- 					var selEncoding, reg, m, res;
 
- 					if (data.doconv) {
 
- 						fm.confirm({
 
- 							title  : self.title,
 
- 							text   : data.doconv === 'unknown'? 'confirmNonUTF8' : 'confirmConvUTF8',
 
- 							accept : {
 
- 								label    : 'btnConv',
 
- 								callback : function() {  
 
- 									dfrd = edit(file, selEncoding.val(), editor);
 
- 								}
 
- 							},
 
- 							cancel : {
 
- 								label    : 'btnCancel',
 
- 								callback : function() { dfrd.reject(); }
 
- 							},
 
- 							optionsCallback : function(options) {
 
- 								options.create = function() {
 
- 									var base = $('<div class="elfinder-dialog-confirm-encoding"/>'),
 
- 										head = {value: data.doconv},
 
- 										detected;
 
- 									
 
- 									if (data.doconv === 'unknown') {
 
- 										head.caption = '-';
 
- 									}
 
- 									selEncoding = getEncSelect([head]);
 
- 									$(this).next().find('.ui-dialog-buttonset')
 
- 										.prepend(base.append($('<label>'+fm.i18n('encoding')+' </label>').append(selEncoding)));
 
- 								};
 
- 							}
 
- 						});
 
- 					} else {
 
- 						if ((!editor || !editor.info || !editor.info.preventGet) && fm.mimeIsText(file.mime)) {
 
- 							reg = new RegExp('^(data:'+file.mime.replace(/([.+])/g, '\\$1')+';base64,)', 'i');
 
- 							if (!editor.info.dataScheme) {
 
- 								if (window.atob && (m = data.content.match(reg))) {
 
- 									data.content = atob(data.content.substr(m[1].length));
 
- 								}
 
- 							} else {
 
- 								if (window.btoa && !data.content.match(reg)) {
 
- 									data.content = 'data:'+file.mime+';base64,'+btoa(data.content);
 
- 								}
 
- 							}
 
- 						}
 
- 						dialog(id, file, data.content, data.encoding, editor)
 
- 							.done(function(data) {
 
- 								dfrd.resolve(data);
 
- 							})
 
- 							.progress(function(encoding, newHash, data, saveDfd) {
 
- 								var ta = this;
 
- 								if (newHash) {
 
- 									hash = newHash;
 
- 								}
 
- 								fm.request({
 
- 									options : {type : 'post'},
 
- 									data : {
 
- 										cmd     : 'put',
 
- 										target  : hash,
 
- 										encoding : encoding || data.encoding,
 
- 										content : data
 
- 									},
 
- 									notify : {type : 'save', cnt : 1},
 
- 									syncOnFail : true,
 
- 									preventFail : true,
 
- 									navigate : {
 
- 										target : 'changed',
 
- 										toast : {
 
- 											inbuffer : {msg: fm.i18n(['complete', fm.i18n('btnSave')])}
 
- 										}
 
- 									}
 
- 								})
 
- 								.fail(function(error) {
 
- 									dfrd.reject(error);
 
- 									saveDfd.reject();
 
- 								})
 
- 								.done(function(data) {
 
- 									requestAnimationFrame(function(){
 
- 										ta.trigger('focus');
 
- 										ta.editor && ta.editor.focus(ta[0], ta.editor.instance);
 
- 									});
 
- 									saveDfd.resolve();
 
- 								});
 
- 							})
 
- 							.fail(function(error) {
 
- 								dfrd.reject(error);
 
- 							});
 
- 					}
 
- 				})
 
- 				.fail(function(error) {
 
- 					var err = fm.parseError(error);
 
- 					err = Array.isArray(err)? err[0] : err;
 
- 					(err !== 'errConvUTF8') && fm.sync();
 
- 					dfrd.reject(error);
 
- 				});
 
- 			}
 
- 			return dfrd.promise();
 
- 		},
 
- 		
 
- 		/**
 
- 		 * Current editors of selected files
 
- 		 * 
 
- 		 * @type Object
 
- 		 */
 
- 		editors = {},
 
- 		
 
- 		/**
 
- 		 * Fallback editor (Simple text editor)
 
- 		 * 
 
- 		 * @type Object
 
- 		 */
 
- 		fallbackEditor = {
 
- 			// Simple Text (basic textarea editor)
 
- 			info : {
 
- 				id : 'textarea',
 
- 				name : 'TextArea',
 
- 				useTextAreaEvent : true
 
- 			},
 
- 			load : function(textarea) {
 
- 				// trigger event 'editEditorPrepare'
 
- 				this.trigger('Prepare', {
 
- 					node: textarea,
 
- 					editorObj: void(0),
 
- 					instance: void(0),
 
- 					opts: {}
 
- 				});
 
- 				textarea.setSelectionRange && textarea.setSelectionRange(0, 0);
 
- 				$(textarea).trigger('focus').show();
 
- 			},
 
- 			save : function(){}
 
- 		},
 
- 		/**
 
- 		 * Set current editors
 
- 		 * 
 
- 		 * @param  Object  file object
 
- 		 * @param  Number  cnt  count of selected items
 
- 		 * @return Void
 
- 		 */
 
- 		setEditors = function(file, cnt) {
 
- 			var mimeMatch = function(fileMime, editorMimes){
 
- 					if (!editorMimes) {
 
- 						return fm.mimeIsText(fileMime);
 
- 					} else {
 
- 						if (editorMimes[0] === '*' || $.inArray(fileMime, editorMimes) !== -1) {
 
- 							return true;
 
- 						}
 
- 						var i, l;
 
- 						l = editorMimes.length;
 
- 						for (i = 0; i < l; i++) {
 
- 							if (fileMime.indexOf(editorMimes[i]) === 0) {
 
- 								return true;
 
- 							}
 
- 						}
 
- 						return false;
 
- 					}
 
- 				},
 
- 				extMatch = function(fileName, editorExts){
 
- 					if (!editorExts || !editorExts.length) {
 
- 						return true;
 
- 					}
 
- 					var ext = fileName.replace(/^.+\.([^.]+)|(.+)$/, '$1$2').toLowerCase(),
 
- 					i, l;
 
- 					l = editorExts.length;
 
- 					for (i = 0; i < l; i++) {
 
- 						if (ext === editorExts[i].toLowerCase()) {
 
- 							return true;
 
- 						}
 
- 					}
 
- 					return false;
 
- 				},
 
- 				optEditors = self.options.editors || [],
 
- 				cwdWrite = fm.cwd().write;
 
- 			
 
- 			stored = fm.storage('storedEditors') || {};
 
- 			editors = {};
 
- 			if (!optEditors.length) {
 
- 				optEditors = [fallbackEditor];
 
- 			}
 
- 			$.each(optEditors, function(i, editor) {
 
- 				var name;
 
- 				if ((cnt === 1 || !editor.info.single)
 
- 						&& ((!editor.info || !editor.info.converter)? file.write : cwdWrite)
 
- 						&& (file.size > 0 || (!editor.info.converter && (editor.info.canMakeEmpty || (editor.info.canMakeEmpty !== false && fm.mimeIsText(file.mime)))))
 
- 						&& (!editor.info.maxSize || file.size <= editor.info.maxSize)
 
- 						&& mimeMatch(file.mime, editor.mimes || null)
 
- 						&& extMatch(file.name, editor.exts || null)
 
- 						&& typeof editor.load == 'function'
 
- 						&& typeof editor.save == 'function') {
 
- 					
 
- 					name = editor.info.name? editor.info.name : ('Editor ' + i);
 
- 					editor.id = editor.info.id? editor.info.id : ('editor' + i),
 
- 					editor.name = name;
 
- 					editor.i18n = fm.i18n(name);
 
- 					editors[editor.id] = editor;
 
- 				}
 
- 			});
 
- 			return Object.keys(editors).length? true : false;
 
- 		},
 
- 		store = function(mime, editor) {
 
- 			if (mime && editor) {
 
- 				if (!$.isPlainObject(stored)) {
 
- 					stored = {};
 
- 				}
 
- 				stored[mime] = editor.id;
 
- 				fm.storage('storedEditors', stored);
 
- 				fm.trigger('selectfiles', {files : fm.selected()});
 
- 			}
 
- 		},
 
- 		useStoredEditor = function() {
 
- 			var d = fm.storage('useStoredEditor');
 
- 			return d? (d > 0) : self.options.useStoredEditor;
 
- 		},
 
- 		editorMaximized = function() {
 
- 			var d = fm.storage('editorMaximized');
 
- 			return d? (d > 0) : self.options.editorMaximized;
 
- 		},
 
- 		getSubMenuRaw = function(files, callback) {
 
- 			var subMenuRaw = [];
 
- 			$.each(editors, function(id, ed) {
 
- 				subMenuRaw.push(
 
- 					{
 
- 						label    : fm.escape(ed.i18n),
 
- 						icon     : ed.info && ed.info.icon? ed.info.icon : 'edit',
 
- 						options  : { iconImg: ed.info && ed.info.iconImg? fm.baseUrl + ed.info.iconImg : void(0) },
 
- 						callback : function() {
 
- 							store(files[0].mime, ed);
 
- 							callback && callback.call(ed);
 
- 						}
 
- 					}		
 
- 				);
 
- 			});
 
- 			return subMenuRaw;
 
- 		},
 
- 		getStoreId = function(name) {
 
- 			// for compatibility to previous version
 
- 			return name.toLowerCase().replace(/ +/g, '');
 
- 		},
 
- 		getStoredEditor = function(mime) {
 
- 			var name = stored[mime];
 
- 			return name && Object.keys(editors).length? editors[getStoreId(name)] : void(0);
 
- 		},
 
- 		infoRequest = function() {
 
- 		},
 
- 		stored;
 
- 	
 
- 	
 
- 	this.shortcuts = [{
 
- 		pattern     : 'ctrl+e'
 
- 	}];
 
- 	
 
- 	this.init = function() {
 
- 		var self = this,
 
- 			fm   = this.fm,
 
- 			opts = this.options,
 
- 			cmdChecks = [],
 
- 			ccData, dfd;
 
- 		
 
- 		this.onlyMimes = this.options.mimes || [];
 
- 		
 
- 		fm.one('open', function() {
 
- 			// editors setup
 
- 			if (opts.editors && Array.isArray(opts.editors)) {
 
- 				fm.trigger('canMakeEmptyFile', {mimes: Object.keys(fm.storage('mkfileTextMimes') || {}).concat(opts.makeTextMimes || ['text/plain'])});
 
- 				$.each(opts.editors, function(i, editor) {
 
- 					if (editor.info && editor.info.cmdCheck) {
 
- 						cmdChecks.push(editor.info.cmdCheck);
 
- 					}
 
- 				});
 
- 				if (cmdChecks.length) {
 
- 					if (fm.api >= 2.1030) {
 
- 						dfd = fm.request({
 
- 							data : {
 
- 								cmd: 'editor',
 
- 								name: cmdChecks,
 
- 								method: 'enabled'
 
- 							},
 
- 							preventDefault : true
 
- 						}).done(function(d) {
 
- 							ccData = d;
 
- 						}).fail(function() {
 
- 							ccData = {};
 
- 						});
 
- 					} else {
 
- 						ccData = {};
 
- 						dfd = $.Deferred().resolve();
 
- 					}
 
- 				} else {
 
- 					dfd = $.Deferred().resolve();
 
- 				}
 
- 				
 
- 				dfd.always(function() {
 
- 					if (ccData) {
 
- 						opts.editors = $.grep(opts.editors, function(e) {
 
- 							if (e.info && e.info.cmdCheck) {
 
- 								return ccData[e.info.cmdCheck]? true : false;
 
- 							} else {
 
- 								return true;
 
- 							}
 
- 						});
 
- 					}
 
- 					$.each(opts.editors, function(i, editor) {
 
- 						if (editor.setup && typeof editor.setup === 'function') {
 
- 							editor.setup.call(editor, opts, fm);
 
- 						}
 
- 						if (!editor.disabled) {
 
- 							if (editor.mimes && Array.isArray(editor.mimes)) {
 
- 								mimesSingle = mimesSingle.concat(editor.mimes);
 
- 								if (!editor.info || !editor.info.single) {
 
- 									mimes = mimes.concat(editor.mimes);
 
- 								}
 
- 							}
 
- 							if (!allowAll && editor.mimes && editor.mimes[0] === '*') {
 
- 								allowAll = true;
 
- 							}
 
- 							if (!editor.info) {
 
- 								editor.info = {};
 
- 							}
 
- 							if (editor.info.integrate) {
 
- 								fm.trigger('helpIntegration', Object.assign({cmd: 'edit'}, editor.info.integrate));
 
- 							}
 
- 							if (editor.info.canMakeEmpty) {
 
- 								fm.trigger('canMakeEmptyFile', {mimes: editor.mimes});
 
- 							}
 
- 						}
 
- 					});
 
- 					
 
- 					mimesSingle = ($.uniqueSort || $.unique)(mimesSingle);
 
- 					mimes = ($.uniqueSort || $.unique)(mimes);
 
- 					
 
- 					opts.editors = $.grep(opts.editors, function(e) {
 
- 						return e.disabled? false : true;
 
- 					});
 
- 				});
 
- 			}
 
- 		})
 
- 		.bind('select', function() {
 
- 			editors = null;
 
- 		})
 
- 		.bind('contextmenucreate', function(e) {
 
- 			var file, editor,
 
- 				single = function(editor) {
 
- 					var title = self.title;
 
- 					fm.one('contextmenucreatedone', function() {
 
- 						self.title = title;
 
- 					});
 
- 					self.title = fm.escape(editor.i18n);
 
- 					if (editor.info && editor.info.iconImg) {
 
- 						self.contextmenuOpts = {
 
- 							iconImg: fm.baseUrl + editor.info.iconImg
 
- 						};
 
- 					}
 
- 					delete self.variants;
 
- 				};
 
- 			
 
- 			self.contextmenuOpts = void(0);
 
- 			if (e.data.type === 'files' && self.enabled()) {
 
- 				file = fm.file(e.data.targets[0]);
 
- 				if (setEditors(file, e.data.targets.length)) {
 
- 					if (Object.keys(editors).length > 1) {
 
- 						if (!useStoredEditor() || !(editor = getStoredEditor(file.mime))) {
 
- 							delete self.extra;
 
- 							self.variants = [];
 
- 							$.each(editors, function(id, editor) {
 
- 								self.variants.push([{ editor: editor }, editor.i18n, editor.info && editor.info.iconImg? fm.baseUrl + editor.info.iconImg : 'edit']);
 
- 							});
 
- 						} else {
 
- 							single(editor);
 
- 							self.extra = {
 
- 								icon: 'menu',
 
- 								node: $('<span/>')
 
- 									.attr({title: fm.i18n('select')})
 
- 									.on('click touchstart', function(e){
 
- 										if (e.type === 'touchstart' && e.originalEvent.touches.length > 1) {
 
- 											return;
 
- 										}
 
- 										var node = $(this);
 
- 										e.stopPropagation();
 
- 										e.preventDefault();
 
- 										fm.trigger('contextmenu', {
 
- 											raw: getSubMenuRaw(fm.selectedFiles(), function() {
 
- 												var hashes = fm.selected();
 
- 												fm.exec('edit', hashes, {editor: this});
 
- 												fm.trigger('selectfiles', {files : hashes});
 
- 											}),
 
- 											x: node.offset().left,
 
- 											y: node.offset().top
 
- 										});
 
- 									})
 
- 							};
 
- 						}
 
- 					} else {
 
- 						single(editors[Object.keys(editors)[0]]);
 
- 						delete self.extra;
 
- 					}
 
- 				}
 
- 			}
 
- 		})
 
- 		.bind('canMakeEmptyFile', function(e) {
 
- 			if (e.data && e.data.resetTexts) {
 
- 				var defs = fm.arrayFlip(self.options.makeTextMimes || ['text/plain']),
 
- 					hides = fm.storage('mkfileHides') || {};
 
- 				$.each((fm.storage('mkfileTextMimes') || {}), function(mime, type) {
 
- 					if (!defs[mime]) {
 
- 						delete fm.mimesCanMakeEmpty[mime];
 
- 						delete hides[mime];
 
- 					}
 
- 				});
 
- 				fm.storage('mkfileTextMimes', null);
 
- 				if (Object.keys(hides).length) {
 
- 					fm.storage('mkfileHides', hides);
 
- 				} else {
 
- 					fm.storage('mkfileHides', null);
 
- 				}
 
- 			}
 
- 		});
 
- 	};
 
- 	
 
- 	this.getstate = function(select) {
 
- 		var sel = this.files(select),
 
- 			cnt = sel.length;
 
- 		return cnt && filter(sel).length == cnt ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(select, opts) {
 
- 		var fm    = this.fm, 
 
- 			files = filter(this.files(select)),
 
- 			hashes = $.map(files, function(f) { return f.hash; }),
 
- 			list  = [],
 
- 			editor = opts && opts.editor? opts.editor : null,
 
- 			node = $(opts && opts._currentNode? opts._currentNode : $('#'+ fm.cwdHash2Id(hashes[0]))),
 
- 			getEditor = function() {
 
- 				var dfd = $.Deferred(),
 
- 					storedId;
 
- 				
 
- 				if (!editor && Object.keys(editors).length > 1) {
 
- 					if (useStoredEditor() && (editor = getStoredEditor(files[0].mime))) {
 
- 						return dfd.resolve(editor);
 
- 					}
 
- 					fm.trigger('contextmenu', {
 
- 						raw: getSubMenuRaw(files, function() {
 
- 							dfd.resolve(this);
 
- 						}),
 
- 						x: node.offset().left,
 
- 						y: node.offset().top + 22,
 
- 						opened: function() {
 
- 							fm.one('closecontextmenu',function() {
 
- 								requestAnimationFrame(function() {
 
- 									if (dfd.state() === 'pending') {
 
- 										dfd.reject();
 
- 									}
 
- 								});
 
- 							});
 
- 						}
 
- 					});
 
- 					
 
- 					fm.trigger('selectfiles', {files : hashes});
 
- 					
 
- 					return dfd;
 
- 				} else {
 
- 					Object.keys(editors).length > 1 && editor && store(files[0].mime, editor);
 
- 					return dfd.resolve(editor? editor : (Object.keys(editors).length? editors[Object.keys(editors)[0]] : null));
 
- 				}
 
- 			},
 
- 			dfrd = $.Deferred(),
 
- 			file;
 
- 		if (editors === null) {
 
- 			setEditors(files[0], hashes.length);
 
- 		}
 
- 		
 
- 		if (!node.length) {
 
- 			node = fm.getUI('cwd');
 
- 		}
 
- 		
 
- 		getEditor().done(function(editor) {
 
- 			while ((file = files.shift())) {
 
- 				list.push(edit(file, void(0), editor).fail(function(error) {
 
- 					error && fm.error(error);
 
- 				}));
 
- 			}
 
- 			
 
- 			if (list.length) { 
 
- 				$.when.apply(null, list).done(function() {
 
- 					dfrd.resolve();
 
- 				}).fail(function() {
 
- 					dfrd.reject();
 
- 				});
 
- 			} else {
 
- 				dfrd.reject();
 
- 			}
 
- 		}).fail(function() {
 
- 			dfrd.reject();
 
- 		});
 
- 		
 
- 		return dfrd;
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/empty.js
 
-  */
 
- /**
 
-  * @class elFinder command "empty".
 
-  * Empty the folder
 
-  *
 
-  * @type  elFinder.command
 
-  * @author  Naoki Sawada
 
-  */
 
- elFinder.prototype.commands.empty = function() {
 
- 		var self, fm,
 
- 		selFiles = function(select) {
 
- 			var sel = self.files(select);
 
- 			if (!sel.length) {
 
- 				sel = [ fm.cwd() ];
 
- 			}
 
- 			return sel;
 
- 		};
 
- 	
 
- 	this.linkedCmds = ['rm'];
 
- 	
 
- 	this.init = function() {
 
- 		// lazy assign to make possible to become superclass
 
- 		self = this;
 
- 		fm = this.fm;
 
- 	};
 
- 	this.getstate = function(select) {
 
- 		var sel = selFiles(select),
 
- 			cnt;
 
- 		
 
- 		cnt = sel.length;
 
- 		return $.grep(sel, function(f) { return f.read && f.write && f.mime === 'directory' ? true : false; }).length == cnt ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes) {
 
- 		var dirs = selFiles(hashes),
 
- 			cnt  = dirs.length,
 
- 			dfrd = $.Deferred()
 
- 				.done(function() {
 
- 					var data = {changed: {}};
 
- 					fm.toast({msg: fm.i18n(['"'+success.join('", ')+'"', 'complete', fm.i18n('cmdempty')])});
 
- 					$.each(dirs, function(i, dir) {
 
- 						data.changed[dir.hash] = dir;
 
- 					});
 
- 					fm.change(data);
 
- 				})
 
- 				.always(function() {
 
- 					var cwd = fm.cwd().hash;
 
- 					fm.trigger('selectfiles', {files: $.map(dirs, function(d) { return cwd === d.phash? d.hash : null; })});
 
- 				}),
 
- 			success = [],
 
- 			done = function(res) {
 
- 				if (typeof res === 'number') {
 
- 					success.push(dirs[res].name);
 
- 					delete dirs[res].dirs;
 
- 				} else {
 
- 					res && fm.error(res);
 
- 				}
 
- 				(--cnt < 1) && dfrd[success.length? 'resolve' : 'reject']();
 
- 			};
 
- 		$.each(dirs, function(i, dir) {
 
- 			var tm;
 
- 			if (!(dir.write && dir.mime === 'directory')) {
 
- 				done(['errEmpty', dir.name, 'errPerm']);
 
- 				return null;
 
- 			}
 
- 			if (!fm.isCommandEnabled('rm', dir.hash)) {
 
- 				done(['errCmdNoSupport', '"rm"']);
 
- 				return null;
 
- 			}
 
- 			tm = setTimeout(function() {
 
- 				fm.notify({type : 'search', cnt : 1, hideCnt : cnt > 1? false : true});
 
- 			}, fm.notifyDelay);
 
- 			fm.request({
 
- 				data : {cmd  : 'open', target : dir.hash},
 
- 				preventDefault : true,
 
- 				asNotOpen : true
 
- 			}).done(function(data) {
 
- 				var targets = [];
 
- 				tm && clearTimeout(tm);
 
- 				if (fm.ui.notify.children('.elfinder-notify-search').length) {
 
- 					fm.notify({type : 'search', cnt : -1, hideCnt : cnt > 1? false : true});
 
- 				}
 
- 				if (data && data.files && data.files.length) {
 
- 					if (data.files.length > fm.maxTargets) {
 
- 						done(['errEmpty', dir.name, 'errMaxTargets', fm.maxTargets]);
 
- 					} else {
 
- 						fm.updateCache(data);
 
- 						$.each(data.files, function(i, f) {
 
- 							if (!f.write || f.locked) {
 
- 								done(['errEmpty', dir.name, 'errRm', f.name, 'errPerm']);
 
- 								targets = [];
 
- 								return false;
 
- 							}
 
- 							targets.push(f.hash);
 
- 						});
 
- 						if (targets.length) {
 
- 							fm.exec('rm', targets, { _userAction : true, addTexts : [ fm.i18n('folderToEmpty', dir.name) ] })
 
- 							.fail(function(error) {
 
- 								fm.trigger('unselectfiles', {files: fm.selected()});
 
- 								done(fm.parseError(error) || '');
 
- 							})
 
- 							.done(function() { done(i); });
 
- 						}
 
- 					}
 
- 				} else {
 
- 					fm.toast({ mode: 'warning', msg: fm.i18n('filderIsEmpty', dir.name)});
 
- 					done('');
 
- 				}
 
- 			}).fail(function(error) {
 
- 				done(fm.parseError(error) || '');
 
- 			});
 
- 		});
 
- 		
 
- 		return dfrd;
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/extract.js
 
-  */
 
- /**
 
-  * @class  elFinder command "extract"
 
-  * Extract files from archive
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- elFinder.prototype.commands.extract = function() {
 
- 		var self    = this,
 
- 		fm      = self.fm,
 
- 		mimes   = [],
 
- 		filter  = function(files) {
 
- 			return $.grep(files, function(file) { 
 
- 				return file.read && $.inArray(file.mime, mimes) !== -1 ? true : false;
 
- 			});
 
- 		};
 
- 	
 
- 	this.variants = [];
 
- 	this.disableOnSearch = true;
 
- 	
 
- 	// Update mimes list on open/reload
 
- 	fm.bind('open reload', function() {
 
- 		mimes = fm.option('archivers')['extract'] || [];
 
- 		if (fm.api > 2) {
 
- 			self.variants = [[{makedir: true}, fm.i18n('cmdmkdir')], [{}, fm.i18n('btnCwd')]];
 
- 		} else {
 
- 			self.variants = [[{}, fm.i18n('btnCwd')]];
 
- 		}
 
- 		self.change();
 
- 	});
 
- 	
 
- 	this.getstate = function(select) {
 
- 		var sel = this.files(select),
 
- 			cnt = sel.length;
 
- 		
 
- 		return cnt && this.fm.cwd().write && filter(sel).length == cnt ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes, opts) {
 
- 		var files    = this.files(hashes),
 
- 			dfrd     = $.Deferred(),
 
- 			cnt      = files.length,
 
- 			makedir  = opts && opts.makedir ? 1 : 0,
 
- 			i, error,
 
- 			decision;
 
- 		var overwriteAll = false;
 
- 		var omitAll = false;
 
- 		var mkdirAll = 0;
 
- 		var names = $.map(fm.files(hashes), function(file) { return file.name; });
 
- 		var map = {};
 
- 		$.grep(fm.files(hashes), function(file) {
 
- 			map[file.name] = file;
 
- 			return false;
 
- 		});
 
- 		
 
- 		var decide = function(decision) {
 
- 			switch (decision) {
 
- 				case 'overwrite_all' :
 
- 					overwriteAll = true;
 
- 					break;
 
- 				case 'omit_all':
 
- 					omitAll = true;
 
- 					break;
 
- 			}
 
- 		};
 
- 		var unpack = function(file) {
 
- 			if (!(file.read && fm.file(file.phash).write)) {
 
- 				error = ['errExtract', file.name, 'errPerm'];
 
- 				fm.error(error);
 
- 				dfrd.reject(error);
 
- 			} else if ($.inArray(file.mime, mimes) === -1) {
 
- 				error = ['errExtract', file.name, 'errNoArchive'];
 
- 				fm.error(error);
 
- 				dfrd.reject(error);
 
- 			} else {
 
- 				fm.request({
 
- 					data:{cmd:'extract', target:file.hash, makedir:makedir},
 
- 					notify:{type:'extract', cnt:1},
 
- 					syncOnFail:true,
 
- 					navigate:{
 
- 						toast : makedir? {
 
- 							incwd    : {msg: fm.i18n(['complete', fm.i18n('cmdextract')]), action: {cmd: 'open', msg: 'cmdopen'}},
 
- 							inbuffer : {msg: fm.i18n(['complete', fm.i18n('cmdextract')]), action: {cmd: 'open', msg: 'cmdopen'}}
 
- 						} : {
 
- 							inbuffer : {msg: fm.i18n(['complete', fm.i18n('cmdextract')])}
 
- 						}
 
- 					}
 
- 				})
 
- 				.fail(function (error) {
 
- 					if (dfrd.state() != 'rejected') {
 
- 						dfrd.reject(error);
 
- 					}
 
- 				})
 
- 				.done(function () {
 
- 				});
 
- 			}
 
- 		};
 
- 		
 
- 		var confirm = function(files, index) {
 
- 			var file = files[index],
 
- 			name = fm.splitFileExtention(file.name)[0],
 
- 			existed = ($.inArray(name, names) >= 0),
 
- 			next = function(){
 
- 				if((index+1) < cnt) {
 
- 					confirm(files, index+1);
 
- 				} else {
 
- 					dfrd.resolve();
 
- 				}
 
- 			};
 
- 			if (!makedir && existed && map[name].mime != 'directory') {
 
- 				fm.confirm(
 
- 					{
 
- 						title : fm.i18n('ntfextract'),
 
- 						text  : ['errExists', name, 'confirmRepl'],
 
- 						accept:{
 
- 							label : 'btnYes',
 
- 							callback:function (all) {
 
- 								decision = all ? 'overwrite_all' : 'overwrite';
 
- 								decide(decision);
 
- 								if(!overwriteAll && !omitAll) {
 
- 									if('overwrite' == decision) {
 
- 										unpack(file);
 
- 									}
 
- 									if((index+1) < cnt) {
 
- 										confirm(files, index+1);
 
- 									} else {
 
- 										dfrd.resolve();
 
- 									}
 
- 								} else if(overwriteAll) {
 
- 									for (i = index; i < cnt; i++) {
 
- 										unpack(files[i]);
 
- 									}
 
- 									dfrd.resolve();
 
- 								}
 
- 							}
 
- 						},
 
- 						reject : {
 
- 							label : 'btnNo',
 
- 							callback:function (all) {
 
- 								decision = all ? 'omit_all' : 'omit';
 
- 								decide(decision);
 
- 								if(!overwriteAll && !omitAll && (index+1) < cnt) {
 
- 									confirm(files, index+1);
 
- 								} else if (omitAll) {
 
- 									dfrd.resolve();
 
- 								}
 
- 							}
 
- 						},
 
- 						cancel : {
 
- 							label : 'btnCancel',
 
- 							callback:function () {
 
- 								dfrd.resolve();
 
- 							}
 
- 						},
 
- 						all : ((index+1) < cnt)
 
- 					}
 
- 				);
 
- 			} else if (!makedir) {
 
- 				if (mkdirAll == 0) {
 
- 					fm.confirm({
 
- 						title : fm.i18n('cmdextract'),
 
- 						text  : [fm.i18n('cmdextract')+' "'+file.name+'"', 'confirmRepl'],
 
- 						accept:{
 
- 							label : 'btnYes',
 
- 							callback:function (all) {
 
- 								all && (mkdirAll = 1);
 
- 								unpack(file);
 
- 								next();
 
- 							}
 
- 						},
 
- 						reject : {
 
- 							label : 'btnNo',
 
- 							callback:function (all) {
 
- 								all && (mkdirAll = -1);
 
- 								next();
 
- 							}
 
- 						},
 
- 						cancel : {
 
- 							label : 'btnCancel',
 
- 							callback:function () {
 
- 								dfrd.resolve();
 
- 							}
 
- 						},
 
- 						all : ((index+1) < cnt)
 
- 					});
 
- 				} else {
 
- 					(mkdirAll > 0) && unpack(file);
 
- 					next();
 
- 				}
 
- 			} else {
 
- 				unpack(file);
 
- 				next();
 
- 			}
 
- 		};
 
- 		
 
- 		if (!(this.enabled() && cnt && mimes.length)) {
 
- 			return dfrd.reject();
 
- 		}
 
- 		
 
- 		if(cnt > 0) {
 
- 			confirm(files, 0);
 
- 		}
 
- 		return dfrd;
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/forward.js
 
-  */
 
- /**
 
-  * @class  elFinder command "forward"
 
-  * Open next visited folder
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- (elFinder.prototype.commands.forward = function() {
 
- 		this.alwaysEnabled = true;
 
- 	this.updateOnSelect = true;
 
- 	this.shortcuts = [{
 
- 		pattern     : 'ctrl+right'
 
- 	}];
 
- 	
 
- 	this.getstate = function() {
 
- 		return this.fm.history.canForward() ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function() {
 
- 		return this.fm.history.forward();
 
- 	};
 
- 	
 
- }).prototype = { forceLoad : true }; // this is required command
 
- /*
 
-  * File: /js/commands/fullscreen.js
 
-  */
 
- /**
 
-  * @class  elFinder command "fullscreen"
 
-  * elFinder node to full scrren mode
 
-  *
 
-  * @author Naoki Sawada
 
-  **/
 
- elFinder.prototype.commands.fullscreen = function() {
 
- 		var self   = this,
 
- 		fm     = this.fm,
 
- 		update = function(e, data) {
 
- 			e.preventDefault();
 
- 			e.stopPropagation();
 
- 			if (data && data.fullscreen) {
 
- 				self.update(void(0), (data.fullscreen === 'on'));
 
- 			}
 
- 		};
 
- 	this.alwaysEnabled  = true;
 
- 	this.updateOnSelect = false;
 
- 	this.syncTitleOnChange = true;
 
- 	this.value = false;
 
- 	this.options = {
 
- 		ui : 'fullscreenbutton'
 
- 	};
 
- 	this.getstate = function() {
 
- 		return 0;
 
- 	};
 
- 	
 
- 	this.exec = function() {
 
- 		var node = fm.getUI().get(0),
 
- 			full = (node === fm.toggleFullscreen(node));
 
- 		self.title = fm.i18n(full ? 'reinstate' : 'cmdfullscreen');
 
- 		self.update(void(0), full);
 
- 		return $.Deferred().resolve();
 
- 	};
 
- 	
 
- 	fm.bind('init', function() {
 
- 		fm.getUI().off('resize.' + fm.namespace, update).on('resize.' + fm.namespace, update);
 
- 	});
 
- };
 
- /*
 
-  * File: /js/commands/getfile.js
 
-  */
 
- /**
 
-  * @class elFinder command "getfile". 
 
-  * Return selected files info into outer callback.
 
-  * For use elFinder with wysiwyg editors etc.
 
-  *
 
-  * @author Dmitry (dio) Levashov, dio@std42.ru
 
-  **/
 
- (elFinder.prototype.commands.getfile = function() {
 
- 		var self   = this,
 
- 		fm     = this.fm,
 
- 		filter = function(files) {
 
- 			var o = self.options;
 
- 			files = $.grep(files, function(file) {
 
- 				return (file.mime != 'directory' || o.folders) && file.read ? true : false;
 
- 			});
 
- 			return o.multiple || files.length == 1 ? files : [];
 
- 		};
 
- 	
 
- 	this.alwaysEnabled = true;
 
- 	this.callback      = fm.options.getFileCallback;
 
- 	this._disabled     = typeof(this.callback) == 'function';
 
- 	
 
- 	this.getstate = function(select) {
 
- 		var sel = this.files(select),
 
- 			cnt = sel.length;
 
- 			
 
- 		return this.callback && cnt && filter(sel).length == cnt ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes) {
 
- 		var fm    = this.fm,
 
- 			opts  = this.options,
 
- 			files = this.files(hashes),
 
- 			cnt   = files.length,
 
- 			url   = fm.option('url'),
 
- 			tmb   = fm.option('tmbUrl'),
 
- 			dfrd  = $.Deferred()
 
- 				.done(function(data) {
 
- 					var res,
 
- 						done = function() {
 
- 							if (opts.oncomplete == 'close') {
 
- 								fm.hide();
 
- 							} else if (opts.oncomplete == 'destroy') {
 
- 								fm.destroy();
 
- 							}
 
- 						},
 
- 						fail = function(error) {
 
- 							if (opts.onerror == 'close') {
 
- 								fm.hide();
 
- 							} else if (opts.onerror == 'destroy') {
 
- 								fm.destroy();
 
- 							} else {
 
- 								error && fm.error(error);
 
- 							}
 
- 						};
 
- 					
 
- 					fm.trigger('getfile', {files : data});
 
- 					
 
- 					try {
 
- 						res = self.callback(data, fm);
 
- 					} catch(e) {
 
- 						fail(['Error in `getFileCallback`.', e.message]);
 
- 						return;
 
- 					}
 
- 					
 
- 					if (typeof res === 'object' && typeof res.done === 'function') {
 
- 						res.done(done).fail(fail);
 
- 					} else {
 
- 						done();
 
- 					}
 
- 				}),
 
- 			result = function(file) {
 
- 				return opts.onlyURL
 
- 					? opts.multiple ? $.map(files, function(f) { return f.url; }) : files[0].url
 
- 					: opts.multiple ? files : files[0];
 
- 			},
 
- 			req = [], 
 
- 			i, file, dim;
 
- 		for (i = 0; i < cnt; i++) {
 
- 			file = files[i];
 
- 			if (file.mime == 'directory' && !opts.folders) {
 
- 				return dfrd.reject();
 
- 			}
 
- 			file.baseUrl = url;
 
- 			if (file.url == '1') {
 
- 				req.push(fm.request({
 
- 					data : {cmd : 'url', target : file.hash},
 
- 					notify : {type : 'url', cnt : 1, hideCnt : true},
 
- 					preventDefault : true
 
- 				})
 
- 				.done(function(data) {
 
- 					if (data.url) {
 
- 						var rfile = fm.file(this.hash);
 
- 						rfile.url = this.url = data.url;
 
- 					}
 
- 				}.bind(file)));
 
- 			} else {
 
- 				file.url = fm.url(file.hash);
 
- 			}
 
- 			if (! opts.onlyURL) {
 
- 				if (opts.getPath) {
 
- 					file.path = fm.path(file.hash);
 
- 					if (file.path === '' && file.phash) {
 
- 						// get parents
 
- 						(function() {
 
- 							var dfd  = $.Deferred();
 
- 							req.push(dfd);
 
- 							fm.path(file.hash, false, {})
 
- 								.done(function(path) {
 
- 									file.path = path;
 
- 								})
 
- 								.fail(function() {
 
- 									file.path = '';
 
- 								})
 
- 								.always(function() {
 
- 									dfd.resolve();
 
- 								});
 
- 						})();
 
- 					}
 
- 				}
 
- 				if (file.tmb && file.tmb != 1) {
 
- 					file.tmb = tmb + file.tmb;
 
- 				}
 
- 				if (!file.width && !file.height) {
 
- 					if (file.dim) {
 
- 						dim = file.dim.split('x');
 
- 						file.width = dim[0];
 
- 						file.height = dim[1];
 
- 					} else if (opts.getImgSize && file.mime.indexOf('image') !== -1) {
 
- 						req.push(fm.request({
 
- 							data : {cmd : 'dim', target : file.hash},
 
- 							notify : {type : 'dim', cnt : 1, hideCnt : true},
 
- 							preventDefault : true
 
- 						})
 
- 						.done(function(data) {
 
- 							if (data.dim) {
 
- 								var dim = data.dim.split('x');
 
- 								var rfile = fm.file(this.hash);
 
- 								rfile.width = this.width = dim[0];
 
- 								rfile.height = this.height = dim[1];
 
- 							}
 
- 						}.bind(file)));
 
- 					}
 
- 				}
 
- 			}
 
- 		}
 
- 		
 
- 		if (req.length) {
 
- 			$.when.apply(null, req).always(function() {
 
- 				dfrd.resolve(result(files));
 
- 			});
 
- 			return dfrd;
 
- 		}
 
- 		
 
- 		return dfrd.resolve(result(files));
 
- 	};
 
- }).prototype = { forceLoad : true }; // this is required command
 
- /*
 
-  * File: /js/commands/help.js
 
-  */
 
- /**
 
-  * @class  elFinder command "help"
 
-  * "About" dialog
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- (elFinder.prototype.commands.help = function() {
 
- 		var fm   = this.fm,
 
- 		self = this,
 
- 		linktpl = '<div class="elfinder-help-link"> <a href="{url}">{link}</a></div>',
 
- 		linktpltgt = '<div class="elfinder-help-link"> <a href="{url}" target="_blank">{link}</a></div>',
 
- 		atpl    = '<div class="elfinder-help-team"><div>{author}</div>{work}</div>',
 
- 		url     = /\{url\}/,
 
- 		link    = /\{link\}/,
 
- 		author  = /\{author\}/,
 
- 		work    = /\{work\}/,
 
- 		r       = 'replace',
 
- 		prim    = 'ui-priority-primary',
 
- 		sec     = 'ui-priority-secondary',
 
- 		lic     = 'elfinder-help-license',
 
- 		tab     = '<li class="' + fm.res('class', 'tabstab') + ' elfinder-help-tab-{id}"><a href="#'+fm.namespace+'-help-{id}" class="ui-tabs-anchor">{title}</a></li>',
 
- 		html    = ['<div class="ui-tabs ui-widget ui-widget-content ui-corner-all elfinder-help">', 
 
- 				'<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-top">'],
 
- 		stpl    = '<div class="elfinder-help-shortcut"><div class="elfinder-help-shortcut-pattern">{pattern}</div> {descrip}</div>',
 
- 		sep     = '<div class="elfinder-help-separator"/>',
 
- 		selfUrl = $('base').length? document.location.href.replace(/#.*$/, '') : '',
 
- 		clTabActive = fm.res('class', 'tabsactive'),
 
- 		
 
- 		getTheme = function() {
 
- 			var src;
 
- 			if (fm.theme && fm.theme.author) {
 
- 				src = atpl[r]('elfinder-help-team', 'elfinder-help-team elfinder-help-term-theme')[r](author, fm.i18n(fm.theme.author) + (fm.theme.email? ' <'+fm.theme.email+'>' : ''))[r](work, fm.i18n('theme') + ' ('+fm.i18n(fm.theme.name)+')');
 
- 			} else {
 
- 				src = '<div class="elfinder-help-team elfinder-help-term-theme" style="display:none"></div>';
 
- 			}
 
- 			return src;
 
- 		},
 
- 		about = function() {
 
- 			html.push('<div id="'+fm.namespace+'-help-about" class="ui-tabs-panel ui-widget-content ui-corner-bottom"><div class="elfinder-help-logo"/>');
 
- 			html.push('<h3>elFinder</h3>');
 
- 			html.push('<div class="'+prim+'">'+fm.i18n('webfm')+'</div>');
 
- 			html.push('<div class="'+sec+'">'+fm.i18n('ver')+': '+fm.version+'</div>');
 
- 			html.push('<div class="'+sec+'">'+fm.i18n('protocolver')+': <span class="apiver"></span></div>');
 
- 			html.push('<div class="'+sec+'">jQuery/jQuery UI: '+$().jquery+'/'+$.ui.version+'</div>');
 
- 			html.push(sep);
 
- 			
 
- 			html.push(linktpltgt[r](url, 'https://studio-42.github.io/elFinder/')[r](link, fm.i18n('homepage')));
 
- 			html.push(linktpltgt[r](url, 'https://github.com/Studio-42/elFinder/wiki')[r](link, fm.i18n('docs')));
 
- 			html.push(linktpltgt[r](url, 'https://github.com/Studio-42/elFinder')[r](link, fm.i18n('github')));
 
- 			//html.push(linktpltgt[r](url, 'http://twitter.com/elrte_elfinder')[r](link, fm.i18n('twitter')));
 
- 			
 
- 			html.push(sep);
 
- 			
 
- 			html.push('<div class="'+prim+'">'+fm.i18n('team')+'</div>');
 
- 			
 
- 			html.push(atpl[r](author, 'Dmitry "dio" Levashov <dio@std42.ru>')[r](work, fm.i18n('chiefdev')));
 
- 			html.push(atpl[r](author, 'Naoki Sawada <hypweb+elfinder@gmail.com>')[r](work, fm.i18n('developer')));
 
- 			html.push(atpl[r](author, 'Troex Nevelin <troex@fury.scancode.ru>')[r](work, fm.i18n('maintainer')));
 
- 			html.push(atpl[r](author, 'Alexey Sukhotin <strogg@yandex.ru>')[r](work, fm.i18n('contributor')));
 
- 			
 
- 			if (fm.i18[fm.lang].translator) {
 
- 				$.each(fm.i18[fm.lang].translator.split(', '), function() {
 
- 					html.push(atpl[r](author, $.trim(this))[r](work, fm.i18n('translator')+' ('+fm.i18[fm.lang].language+')'));
 
- 				});	
 
- 			}
 
- 			
 
- 			html.push(getTheme());
 
- 			html.push(sep);
 
- 			html.push('<div class="'+lic+'">'+fm.i18n('icons')+': Pixelmixer, <a href="http://p.yusukekamiyamane.com" target="_blank">Fugue</a>, <a href="https://icons8.com" target="_blank">Icons8</a></div>');
 
- 			
 
- 			html.push(sep);
 
- 			html.push('<div class="'+lic+'">Licence: 3-clauses BSD Licence</div>');
 
- 			html.push('<div class="'+lic+'">Copyright © 2009-2018, Studio 42</div>');
 
- 			html.push('<div class="'+lic+'">„ …'+fm.i18n('dontforget')+' ”</div>');
 
- 			html.push('</div>');
 
- 		},
 
- 		shortcuts = function() {
 
- 			var sh = fm.shortcuts();
 
- 			// shortcuts tab
 
- 			html.push('<div id="'+fm.namespace+'-help-shortcuts" class="ui-tabs-panel ui-widget-content ui-corner-bottom">');
 
- 			
 
- 			if (sh.length) {
 
- 				html.push('<div class="ui-widget-content elfinder-help-shortcuts">');
 
- 				$.each(sh, function(i, s) {
 
- 					html.push(stpl.replace(/\{pattern\}/, s[0]).replace(/\{descrip\}/, s[1]));
 
- 				});
 
- 			
 
- 				html.push('</div>');
 
- 			} else {
 
- 				html.push('<div class="elfinder-help-disabled">'+fm.i18n('shortcutsof')+'</div>');
 
- 			}
 
- 			
 
- 			
 
- 			html.push('</div>');
 
- 			
 
- 		},
 
- 		help = function() {
 
- 			// help tab
 
- 			html.push('<div id="'+fm.namespace+'-help-help" class="ui-tabs-panel ui-widget-content ui-corner-bottom">');
 
- 			html.push('<a href="https://github.com/Studio-42/elFinder/wiki" target="_blank" class="elfinder-dont-panic"><span>DON\'T PANIC</span></a>');
 
- 			html.push('</div>');
 
- 			// end help
 
- 		},
 
- 		useInteg = false,
 
- 		integrations = function() {
 
- 			useInteg = true;
 
- 			html.push('<div id="'+fm.namespace+'-help-integrations" class="ui-tabs-panel ui-widget-content ui-corner-bottom"/>');
 
- 		},
 
- 		useDebug = false,
 
- 		debug = function() {
 
- 			useDebug = true;
 
- 			// debug tab
 
- 			html.push('<div id="'+fm.namespace+'-help-debug" class="ui-tabs-panel ui-widget-content ui-corner-bottom">');
 
- 			html.push('<div class="ui-widget-content elfinder-help-debug"><ul></ul></div>');
 
- 			html.push('</div>');
 
- 			// end debug
 
- 		},
 
- 		debugRender = function() {
 
- 			var render = function(elm, obj) {
 
- 				$.each(obj, function(k, v) {
 
- 					elm.append($('<dt/>').text(k));
 
- 					if (typeof v === 'undefined') {
 
- 						elm.append($('<dd/>').append($('<span/>').text('undfined')));
 
- 					} else if (typeof v === 'object' && !v) {
 
- 						elm.append($('<dd/>').append($('<span/>').text('null')));
 
- 					} else if (typeof v === 'object' && ($.isPlainObject(v) || v.length)) {
 
- 						elm.append( $('<dd/>').append(render($('<dl/>'), v)));
 
- 					} else {
 
- 						elm.append($('<dd/>').append($('<span/>').text((v && typeof v === 'object')? '[]' : (v? v : '""'))));
 
- 					}
 
- 				});
 
- 				return elm;
 
- 			},
 
- 			cnt = debugUL.children('li').length,
 
- 			targetL, target, tabId,
 
- 			info, lastUL, lastDIV;
 
- 			
 
- 			if (self.debug.options || self.debug.debug) {
 
- 				if (cnt >= 5) {
 
- 					lastUL = debugUL.children('li:last');
 
- 					lastDIV = debugDIV.children('div:last');
 
- 					if (lastDIV.is(':hidden')) {
 
- 						lastUL.remove();
 
- 						lastDIV.remove();
 
- 					} else {
 
- 						lastUL.prev().remove();
 
- 						lastDIV.prev().remove();
 
- 					}
 
- 				}
 
- 				
 
- 				tabId = fm.namespace + '-help-debug-' + (+new Date());
 
- 				targetL = $('<li/>').html('<a href="'+selfUrl+'#'+tabId+'">'+self.debug.debug.cmd+'</a>').prependTo(debugUL);
 
- 				target = $('<div id="'+tabId+'"/>').data('debug', self.debug);
 
- 				
 
- 				targetL.on('click.debugrender', function() {
 
- 					var debug = target.data('debug');
 
- 					target.removeData('debug');
 
- 					if (debug) {
 
- 						target.hide();
 
- 						if (debug.debug) {
 
- 							info = $('<fieldset>').append($('<legend/>').text('debug'), render($('<dl/>'), debug.debug));
 
- 							target.append(info);
 
- 						}
 
- 						if (debug.options) {
 
- 							info = $('<fieldset>').append($('<legend/>').text('options'), render($('<dl/>'), debug.options));
 
- 							target.append(info);
 
- 						}
 
- 						target.show();
 
- 					}
 
- 					targetL.off('click.debugrender');
 
- 				});
 
- 				
 
- 				debugUL.after(target);
 
- 				
 
- 				opened && debugDIV.tabs('refresh');
 
- 			}
 
- 		},
 
- 		content = '',
 
- 		opened, tabInteg, integDIV, tabDebug, debugDIV, debugUL;
 
- 	
 
- 	this.alwaysEnabled  = true;
 
- 	this.updateOnSelect = false;
 
- 	this.state = -1;
 
- 	
 
- 	this.shortcuts = [{
 
- 		pattern     : 'f1',
 
- 		description : this.title
 
- 	}];
 
- 	
 
- 	fm.bind('load', function() {
 
- 		var parts = self.options.view || ['about', 'shortcuts', 'help', 'integrations', 'debug'],
 
- 			i, helpSource, tabBase, tabNav, tabs, delta;
 
- 		
 
- 		// remove 'preference' tab, it moved to command 'preference'
 
- 		if ((i = $.inArray('preference', parts)) !== -1) {
 
- 			parts.splice(i, 1);
 
- 		}
 
- 		
 
- 		// debug tab require jQueryUI Tabs Widget
 
- 		if (! $.fn.tabs) {
 
- 			if ((i = $.inArray(parts, 'debug')) !== -1) {
 
- 				parts.splice(i, 1);
 
- 			}
 
- 		}
 
- 		
 
- 		$.each(parts, function(i, title) {
 
- 			html.push(tab[r](/\{id\}/g, title)[r](/\{title\}/, fm.i18n(title)));
 
- 		});
 
- 		
 
- 		html.push('</ul>');
 
- 		$.inArray('about', parts) !== -1 && about();
 
- 		$.inArray('shortcuts', parts) !== -1 && shortcuts();
 
- 		if ($.inArray('help', parts) !== -1) {
 
- 			helpSource = fm.i18nBaseUrl + 'help/%s.html.js';
 
- 			help();
 
- 		}
 
- 		$.inArray('integrations', parts) !== -1 && integrations();
 
- 		$.inArray('debug', parts) !== -1 && debug();
 
- 		
 
- 		html.push('</div>');
 
- 		content = $(html.join(''));
 
- 		
 
- 		content.find('.ui-tabs-nav li')
 
- 			.on('mouseenter mouseleave', function(e) {
 
- 				$(this).toggleClass('ui-state-hover', e.type === 'mouseenter');
 
- 			})
 
- 			.on('focus blur', 'a', function(e) {
 
- 				$(e.delegateTarget).toggleClass('ui-state-focus', e.type === 'focusin');
 
- 			})
 
- 			.children()
 
- 			.on('click', function(e) {
 
- 				var link = $(this);
 
- 				
 
- 				e.preventDefault();
 
- 				e.stopPropagation();
 
- 				
 
- 				link.parent().addClass(clTabActive).siblings().removeClass(clTabActive);
 
- 				content.children('.ui-tabs-panel').hide().filter(link.attr('href')).show();
 
- 			})
 
- 			.filter(':first').trigger('click');
 
- 		
 
- 		if (useInteg) {
 
- 			tabInteg = content.find('.elfinder-help-tab-integrations').hide();
 
- 			integDIV = content.find('#'+fm.namespace+'-help-integrations').hide().append($('<div class="elfinder-help-integrations-desc"/>').html(fm.i18n('integrationWith')));
 
- 			fm.bind('helpIntegration', function(e) {
 
- 				var ul = integDIV.children('ul:first'),
 
- 					data, elm, cmdUL, cmdCls;
 
- 				if (e.data) {
 
- 					if ($.isPlainObject(e.data)) {
 
- 						data = Object.assign({
 
- 							link: '',
 
- 							title: '',
 
- 							banner: ''
 
- 						}, e.data);
 
- 						if (data.title || data.link) {
 
- 							if (!data.title) {
 
- 								data.title = data.link;
 
- 							}
 
- 							if (data.link) {
 
- 								elm = $('<a/>').attr('href', data.link).attr('target', '_blank').text(data.title);
 
- 							} else {
 
- 								elm = $('<span/>').text(data.title);
 
- 							}
 
- 							if (data.banner) {
 
- 								elm = $('<span/>').append($('<img/>').attr(data.banner), elm);
 
- 							}
 
- 						}
 
- 					} else {
 
- 						elm = $(e.data);
 
- 						elm.filter('a').each(function() {
 
- 							var tgt = $(this);
 
- 							if (!tgt.attr('target')) {
 
- 								tgt.attr('target', '_blank');;
 
- 							}
 
- 						});
 
- 					}
 
- 					if (elm) {
 
- 						tabInteg.show();
 
- 						if (!ul.length) {
 
- 							ul = $('<ul class="elfinder-help-integrations"/>').appendTo(integDIV);
 
- 						}
 
- 						if (data && data.cmd) {
 
- 							cmdCls = 'elfinder-help-integration-' + data.cmd;
 
- 							cmdUL = ul.find('ul.' + cmdCls);
 
- 							if (!cmdUL.length) {
 
- 								cmdUL = $('<ul class="'+cmdCls+'"/>');
 
- 								ul.append($('<li/>').append($('<span/>').html(fm.i18n('cmd'+data.cmd))).append(cmdUL));
 
- 							}
 
- 							elm = cmdUL.append($('<li/>').append(elm));
 
- 						} else {
 
- 							ul.append($('<li/>').append(elm));
 
- 						}
 
- 					}
 
- 				}
 
- 			}).bind('themechange', function() {
 
- 				content.find('div.elfinder-help-term-theme').replaceWith(getTheme());
 
- 			});
 
- 		}
 
- 		// debug
 
- 		if (useDebug) {
 
- 			tabDebug = content.find('.elfinder-help-tab-debug').hide();
 
- 			debugDIV = content.find('#'+fm.namespace+'-help-debug').children('div:first');
 
- 			debugUL = debugDIV.children('ul:first').on('click', function(e) {
 
- 				e.preventDefault();
 
- 				e.stopPropagation();
 
- 			});
 
- 			self.debug = {};
 
- 	
 
- 			fm.bind('backenddebug', function(e) {
 
- 				// CAUTION: DO NOT TOUCH `e.data`
 
- 				if (useDebug && e.data && e.data.debug) {
 
- 					self.debug = { options : e.data.options, debug : Object.assign({ cmd : fm.currentReqCmd }, e.data.debug) };
 
- 					if (self.dialog) {
 
- 						debugRender();
 
- 					}
 
- 				}
 
- 			});
 
- 		}
 
- 		content.find('#'+fm.namespace+'-help-about').find('.apiver').text(fm.api);
 
- 		self.dialog = self.fmDialog(content, {
 
- 				title : self.title,
 
- 				width : 530,
 
- 				maxWidth: 'window',
 
- 				maxHeight: 'window',
 
- 				autoOpen : false,
 
- 				destroyOnClose : false,
 
- 				close : function() {
 
- 					if (useDebug) {
 
- 						tabDebug.hide();
 
- 						debugDIV.tabs('destroy');
 
- 					}
 
- 					opened = false;
 
- 				}
 
- 			})
 
- 			.on('click', function(e) {
 
- 				e.stopPropagation();
 
- 			})
 
- 			.css({
 
- 				overflow: 'hidden'
 
- 			});
 
- 		
 
- 		tabBase = self.dialog.children('.ui-tabs');
 
- 		tabNav = tabBase.children('.ui-tabs-nav:first');
 
- 		tabs = tabBase.children('.ui-tabs-panel');
 
- 		delta = self.dialog.outerHeight(true) - self.dialog.height();
 
- 		self.dialog.closest('.ui-dialog').on('resize', function() {
 
- 			tabs.height(self.dialog.height() - delta - tabNav.outerHeight(true) - 20);
 
- 		});
 
- 		
 
- 		if (helpSource) {
 
- 			self.dialog.one('initContents', function() {
 
- 				$.ajax({
 
- 					url: self.options.helpSource? self.options.helpSource : helpSource.replace('%s', fm.lang),
 
- 					dataType: 'html'
 
- 				}).done(function(source) {
 
- 					$('#'+fm.namespace+'-help-help').html(source);
 
- 				}).fail(function() {
 
- 					$.ajax({
 
- 						url: helpSource.replace('%s', 'en'),
 
- 						dataType: 'html'
 
- 					}).done(function(source) {
 
- 						$('#'+fm.namespace+'-help-help').html(source);
 
- 					});
 
- 				});
 
- 			});
 
- 		}
 
- 		
 
- 		self.state = 0;
 
- 		fm.trigger('helpBuilded', self.dialog);
 
- 	}).one('open', function() {
 
- 		var debug = false;
 
- 		fm.one('backenddebug', function() {
 
- 			debug =true;
 
- 		}).one('opendone', function() {
 
- 			requestAnimationFrame(function() {
 
- 				if (! debug && useDebug) {
 
- 					useDebug = false;
 
- 					tabDebug.hide();
 
- 					debugDIV.hide();
 
- 					debugUL.hide();
 
- 				}
 
- 			});
 
- 		});
 
- 	});
 
- 	
 
- 	this.getstate = function() {
 
- 		return 0;
 
- 	};
 
- 	
 
- 	this.exec = function(sel, opts) {
 
- 		var tab = opts? opts.tab : void(0),
 
- 			debugShow = function() {
 
- 				if (useDebug) {
 
- 					debugDIV.tabs();
 
- 					debugUL.find('a:first').trigger('click');
 
- 					tabDebug.show();
 
- 					opened = true;
 
- 				}
 
- 			};
 
- 		debugShow();
 
- 		this.dialog.trigger('initContents').elfinderdialog('open').find((tab? '.elfinder-help-tab-'+tab : '.ui-tabs-nav li') + ' a:first').trigger('click');
 
- 		return $.Deferred().resolve();
 
- 	};
 
- }).prototype = { forceLoad : true }; // this is required command
 
- /*
 
-  * File: /js/commands/hidden.js
 
-  */
 
- /**
 
-  * @class  elFinder command "hidden"
 
-  * Always hidden command for uiCmdMap
 
-  *
 
-  * @author Naoki Sawada
 
-  **/
 
- elFinder.prototype.commands.hidden = function() {
 
- 		this.hidden = true;
 
- 	this.updateOnSelect = false;
 
- 	this.getstate = function() {
 
- 		return -1;
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/hide.js
 
-  */
 
- /**
 
-  * @class elFinder command "hide".
 
-  * folders/files to hide as personal setting.
 
-  *
 
-  * @type  elFinder.command
 
-  * @author  Naoki Sawada
 
-  */
 
- elFinder.prototype.commands.hide = function() {
 
- 	
 
- 	var self = this,
 
- 		nameCache = {},
 
- 		hideData, hideCnt, cMenuType, sOrigin;
 
- 	this.syncTitleOnChange = true;
 
- 	this.shortcuts = [{
 
- 		pattern : 'ctrl+shift+dot',
 
- 		description : this.fm.i18n('toggleHidden')
 
- 	}];
 
- 	this.init = function() {
 
- 		var fm = this.fm;
 
- 		
 
- 		hideData = fm.storage('hide') || {items: {}};
 
- 		hideCnt = Object.keys(hideData.items).length;
 
- 		this.title = fm.i18n(hideData.show? 'hideHidden' : 'showHidden');
 
- 		self.update(void(0), self.title);
 
- 	};
 
- 	this.fm.bind('select contextmenucreate closecontextmenu', function(e, fm) {
 
- 		var sel = (e.data? (e.data.selected || e.data.targets) : null) || fm.selected();
 
- 		if (e.type === 'select' && e.data) {
 
- 			sOrigin = e.data.origin;
 
- 		} else if (e.type === 'contextmenucreate') {
 
- 			cMenuType = e.data.type;
 
- 		}
 
- 		if (!sel.length || (((e.type !== 'contextmenucreate' && sOrigin !== 'navbar') || cMenuType === 'cwd') && sel[0] === fm.cwd().hash)) {
 
- 			self.title = fm.i18n(hideData.show? 'hideHidden' : 'showHidden');
 
- 		} else {
 
- 			self.title = fm.i18n('cmdhide');
 
- 		}
 
- 		if (e.type !== 'closecontextmenu') {
 
- 			self.update(cMenuType === 'cwd'? (hideCnt? 0 : -1) : void(0), self.title);
 
- 		} else {
 
- 			cMenuType = '';
 
- 			requestAnimationFrame(function() {
 
- 				self.update(void(0), self.title);
 
- 			});
 
- 		}
 
- 	});
 
- 	this.getstate = function(sel) {
 
- 		return (cMenuType !== 'cwd' && (sel || this.fm.selected()).length) || hideCnt? 0 : -1;
 
- 	};
 
- 	this.exec = function(hashes, opts) {
 
- 		var fm = this.fm,
 
- 			dfrd = $.Deferred()
 
- 				.done(function() {
 
- 					fm.trigger('hide', {items: items, opts: opts});
 
- 				})
 
- 				.fail(function(error) {
 
- 					fm.error(error);
 
- 				}),
 
- 			o = opts || {},
 
- 			items = o.targets? o.targets : (hashes || fm.selected()),
 
- 			added = [],
 
- 			removed = [],
 
- 			notifyto, files, res;
 
- 		hideData = fm.storage('hide') || {};
 
- 		if (!$.isPlainObject(hideData)) {
 
- 			hideData = {};
 
- 		}
 
- 		if (!$.isPlainObject(hideData.items)) {
 
- 			hideData.items = {};
 
- 		}
 
- 		if (opts._currentType === 'shortcut' || !items.length || (opts._currentType !== 'navbar' && sOrigin !=='navbar' && items[0] === fm.cwd().hash)) {
 
- 			if (hideData.show) {
 
- 				o.hide = true;
 
- 			} else if (Object.keys(hideData.items).length) {
 
- 				o.show = true;
 
- 			}
 
- 		}
 
- 		if (o.reset) {
 
- 			o.show = true;
 
- 			hideCnt = 0;
 
- 		}
 
- 		if (o.show || o.hide) {
 
- 			if (o.show) {
 
- 				hideData.show = true;
 
- 			} else {
 
- 				delete hideData.show;
 
- 			}
 
- 			if (o.show) {
 
- 				fm.storage('hide', o.reset? null : hideData);
 
- 				self.title = fm.i18n('hideHidden');
 
- 				self.update(o.reset? -1 : void(0), self.title);
 
- 				$.each(hideData.items, function(h) {
 
- 					var f = fm.file(h, true);
 
- 					if (f && (fm.searchStatus.state || !f.phash || fm.file(f.phash))) {
 
- 						added.push(f);
 
- 					}
 
- 				});
 
- 				if (added.length) {
 
- 					fm.updateCache({added: added});
 
- 					fm.add({added: added});
 
- 				}
 
- 				if (o.reset) {
 
- 					hideData = {items: {}};
 
- 				}
 
- 				return dfrd.resolve();
 
- 			}
 
- 			items = Object.keys(hideData.items);
 
- 		}
 
- 		if (items.length) {
 
- 			$.each(items, function(i, h) {
 
- 				var f;
 
- 				if (!hideData.items[h]) {
 
- 					f = fm.file(h);
 
- 					if (f) {
 
- 						nameCache[h] = f.i18 || f.name;
 
- 					}
 
- 					hideData.items[h] = nameCache[h]? nameCache[h] : h;
 
- 				}
 
- 			});
 
- 			hideCnt = Object.keys(hideData.items).length;
 
- 			files = this.files(items);
 
- 			fm.storage('hide', hideData);
 
- 			fm.remove({removed: items});
 
- 			if (hideData.show) {
 
- 				this.exec(void(0), {hide: true});
 
- 			}
 
- 			if (!o.hide) {
 
- 				res = {};
 
- 				res.undo = {
 
- 					cmd : 'hide',
 
- 					callback : function() {
 
- 						var nData = fm.storage('hide');
 
- 						if (nData) {
 
- 							$.each(items, function(i, h) {
 
- 								delete nData.items[h];
 
- 							});
 
- 							hideCnt = Object.keys(nData.items).length;
 
- 							fm.storage('hide', nData);
 
- 							fm.trigger('hide', {items: items, opts: {}});
 
- 							self.update(hideCnt? 0 : -1);
 
- 						}
 
- 						fm.updateCache({added: files});
 
- 						fm.add({added: files});
 
- 					}
 
- 				};
 
- 				res.redo = {
 
- 					cmd : 'hide',
 
- 					callback : function() {
 
- 						return fm.exec('hide', void(0), {targets: items});
 
- 					}
 
- 				};
 
- 			}
 
- 		}
 
- 		return dfrd.state() == 'rejected' ? dfrd : dfrd.resolve(res);
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/home.js
 
-  */
 
- (elFinder.prototype.commands.home = function() {
 
- 		this.title = 'Home';
 
- 	this.alwaysEnabled  = true;
 
- 	this.updateOnSelect = false;
 
- 	this.shortcuts = [{
 
- 		pattern     : 'ctrl+home ctrl+shift+up',
 
- 		description : 'Home'
 
- 	}];
 
- 	
 
- 	this.getstate = function() {
 
- 		var root = this.fm.root(),
 
- 			cwd  = this.fm.cwd().hash;
 
- 			
 
- 		return root && cwd && root != cwd ? 0: -1;
 
- 	};
 
- 	
 
- 	this.exec = function() {
 
- 		return this.fm.exec('open', this.fm.root());
 
- 	};
 
- 	
 
- }).prototype = { forceLoad : true }; // this is required command
 
- /*
 
-  * File: /js/commands/info.js
 
-  */
 
- /**
 
-  * @class elFinder command "info". 
 
-  * Display dialog with file properties.
 
-  *
 
-  * @author Dmitry (dio) Levashov, dio@std42.ru
 
-  **/
 
- (elFinder.prototype.commands.info = function() {
 
- 		var m   = 'msg',
 
- 		fm  = this.fm,
 
- 		spclass = 'elfinder-spinner',
 
- 		btnclass = 'elfinder-info-button',
 
- 		msg = {
 
- 			calc     : fm.i18n('calc'),
 
- 			size     : fm.i18n('size'),
 
- 			unknown  : fm.i18n('unknown'),
 
- 			path     : fm.i18n('path'),
 
- 			aliasfor : fm.i18n('aliasfor'),
 
- 			modify   : fm.i18n('modify'),
 
- 			perms    : fm.i18n('perms'),
 
- 			locked   : fm.i18n('locked'),
 
- 			dim      : fm.i18n('dim'),
 
- 			kind     : fm.i18n('kind'),
 
- 			files    : fm.i18n('files'),
 
- 			folders  : fm.i18n('folders'),
 
- 			roots    : fm.i18n('volumeRoots'),
 
- 			items    : fm.i18n('items'),
 
- 			yes      : fm.i18n('yes'),
 
- 			no       : fm.i18n('no'),
 
- 			link     : fm.i18n('link'),
 
- 			owner    : fm.i18n('owner'),
 
- 			group    : fm.i18n('group'),
 
- 			perm     : fm.i18n('perm'),
 
- 			getlink  : fm.i18n('getLink')
 
- 		},
 
- 		applyZWSP = function(str, remove) {
 
- 			if (remove) {
 
- 				return str.replace(/\u200B/g, '');
 
- 			} else {
 
- 				return str.replace(/(\/|\\)/g, "$1\u200B");
 
- 			}
 
- 		};
 
- 	
 
- 	this.items = ['size', 'aliasfor', 'path', 'link', 'dim', 'modify', 'perms', 'locked', 'owner', 'group', 'perm'];
 
- 	if (this.options.custom && Object.keys(this.options.custom).length) {
 
- 		$.each(this.options.custom, function(name, details) {
 
- 			details.label && this.items.push(details.label);
 
- 		});
 
- 	}
 
- 	this.tpl = {
 
- 		main       : '<div class="ui-helper-clearfix elfinder-info-title {dirclass}"><span class="elfinder-cwd-icon {class} ui-corner-all"{style}/>{title}</div><table class="elfinder-info-tb">{content}</table>',
 
- 		itemTitle  : '<strong>{name}</strong><span class="elfinder-info-kind">{kind}</span>',
 
- 		groupTitle : '<strong>{items}: {num}</strong>',
 
- 		row        : '<tr><td class="elfinder-info-label">{label} : </td><td class="{class}">{value}</td></tr>',
 
- 		spinner    : '<span>{text}</span> <span class="'+spclass+' '+spclass+'-{name}"/>'
 
- 	};
 
- 	
 
- 	this.alwaysEnabled = true;
 
- 	this.updateOnSelect = false;
 
- 	this.shortcuts = [{
 
- 		pattern     : 'ctrl+i'
 
- 	}];
 
- 	
 
- 	this.init = function() {
 
- 		$.each(msg, function(k, v) {
 
- 			msg[k] = fm.i18n(v);
 
- 		});
 
- 	};
 
- 	
 
- 	this.getstate = function() {
 
- 		return 0;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes) {
 
- 		var files   = this.files(hashes);
 
- 		if (! files.length) {
 
- 			files   = this.files([ this.fm.cwd().hash ]);
 
- 		}
 
- 		var self    = this,
 
- 			fm      = this.fm,
 
- 			o       = this.options,
 
- 			tpl     = this.tpl,
 
- 			row     = tpl.row,
 
- 			cnt     = files.length,
 
- 			content = [],
 
- 			view    = tpl.main,
 
- 			l       = '{label}',
 
- 			v       = '{value}',
 
- 			reqs    = [],
 
- 			reqDfrd = null,
 
- 			opts    = {
 
- 				title : fm.i18n('selectionInfo'),
 
- 				width : 'auto',
 
- 				close : function() {
 
- 					$(this).elfinderdialog('destroy');
 
- 					if (reqDfrd && reqDfrd.state() === 'pending') {
 
- 						reqDfrd.reject();
 
- 					}
 
- 					$.grep(reqs, function(r) {
 
- 						r && r.state() === 'pending' && r.reject();
 
- 					});
 
- 				}
 
- 			},
 
- 			count = [],
 
- 			replSpinner = function(msg, name, className) {
 
- 				dialog.find('.'+spclass+'-'+name).parent().html(msg).addClass(className || '');
 
- 			},
 
- 			id = fm.namespace+'-info-'+$.map(files, function(f) { return f.hash; }).join('-'),
 
- 			dialog = fm.getUI().find('#'+id),
 
- 			customActions = [],
 
- 			style = '',
 
- 			hashClass = 'elfinder-font-mono elfinder-info-hash',
 
- 			size, tmb, file, title, dcnt, rdcnt, path, getHashAlgorisms, hideItems;
 
- 			
 
- 		if (!cnt) {
 
- 			return $.Deferred().reject();
 
- 		}
 
- 			
 
- 		if (dialog.length) {
 
- 			dialog.elfinderdialog('toTop');
 
- 			return $.Deferred().resolve();
 
- 		}
 
- 		
 
- 		hideItems = fm.storage('infohides') || fm.arrayFlip(o.hideItems, true);
 
- 		if (cnt === 1) {
 
- 			file = files[0];
 
- 			
 
- 			if (file.icon) {
 
- 				style = ' '+fm.getIconStyle(file);
 
- 			}
 
- 			
 
- 			view  = view.replace('{dirclass}', file.csscls? fm.escape(file.csscls) : '').replace('{class}', fm.mime2class(file.mime)).replace('{style}', style);
 
- 			title = tpl.itemTitle.replace('{name}', fm.escape(file.i18 || file.name)).replace('{kind}', '<span title="'+fm.escape(file.mime)+'">'+fm.mime2kind(file)+'</span>');
 
- 			tmb = fm.tmb(file);
 
- 			
 
- 			if (!file.read) {
 
- 				size = msg.unknown;
 
- 			} else if (file.mime != 'directory' || file.alias) {
 
- 				size = fm.formatSize(file.size);
 
- 			} else {
 
- 				size = tpl.spinner.replace('{text}', msg.calc).replace('{name}', 'size');
 
- 				count.push(file.hash);
 
- 			}
 
- 			
 
- 			!hideItems.size && content.push(row.replace(l, msg.size).replace(v, size));
 
- 			!hideItems.aleasfor && file.alias && content.push(row.replace(l, msg.aliasfor).replace(v, file.alias));
 
- 			if (!hideItems.path) {
 
- 				if (path = fm.path(file.hash, true)) {
 
- 					content.push(row.replace(l, msg.path).replace(v, applyZWSP(fm.escape(path))).replace('{class}', 'elfinder-info-path'));
 
- 				} else {
 
- 					content.push(row.replace(l, msg.path).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{name}', 'path')).replace('{class}', 'elfinder-info-path'));
 
- 					reqs.push(fm.path(file.hash, true, {notify: null})
 
- 					.fail(function() {
 
- 						replSpinner(msg.unknown, 'path');
 
- 					})
 
- 					.done(function(path) {
 
- 						replSpinner(applyZWSP(path), 'path');
 
- 					}));
 
- 				}
 
- 			}
 
- 			if (!hideItems.link && file.read) {
 
- 				var href,
 
- 				name_esc = fm.escape(file.name);
 
- 				if (file.url == '1') {
 
- 					content.push(row.replace(l, msg.link).replace(v, '<button class="'+btnclass+' '+spclass+'-url">'+msg.getlink+'</button>'));
 
- 				} else {
 
- 					if (file.url) {
 
- 						href = file.url;
 
- 					} else if (file.mime === 'directory') {
 
- 						if (o.nullUrlDirLinkSelf && file.url === null) {
 
- 							var loc = window.location;
 
- 							href = loc.pathname + loc.search + '#elf_' + file.hash;
 
- 						} else if (file.url !== '' && fm.option('url', (!fm.isRoot(file) && file.phash) || file.hash)) {
 
- 							href = fm.url(file.hash);
 
- 						}
 
- 					} else {
 
- 						href = fm.url(file.hash);
 
- 					}
 
- 					href && content.push(row.replace(l, msg.link).replace(v,  '<a href="'+href+'" target="_blank">'+name_esc+'</a>'));
 
- 				}
 
- 			}
 
- 			
 
- 			if (!hideItems.dim) {
 
- 				if (file.dim) { // old api
 
- 					content.push(row.replace(l, msg.dim).replace(v, file.dim));
 
- 				} else if (file.mime.indexOf('image') !== -1) {
 
- 					if (file.width && file.height) {
 
- 						content.push(row.replace(l, msg.dim).replace(v, file.width+'x'+file.height));
 
- 					} else {
 
- 						content.push(row.replace(l, msg.dim).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{name}', 'dim')));
 
- 						reqs.push(fm.request({
 
- 							data : {cmd : 'dim', target : file.hash},
 
- 							preventDefault : true
 
- 						})
 
- 						.fail(function() {
 
- 							replSpinner(msg.unknown, 'dim');
 
- 						})
 
- 						.done(function(data) {
 
- 							replSpinner(data.dim || msg.unknown, 'dim');
 
- 							if (data.dim) {
 
- 								var dim = data.dim.split('x');
 
- 								var rfile = fm.file(file.hash);
 
- 								rfile.width = dim[0];
 
- 								rfile.height = dim[1];
 
- 							}
 
- 						}));
 
- 					}
 
- 				}
 
- 			}
 
- 			
 
- 			!hideItems.modify && content.push(row.replace(l, msg.modify).replace(v, fm.formatDate(file)));
 
- 			!hideItems.perms && content.push(row.replace(l, msg.perms).replace(v, fm.formatPermissions(file)));
 
- 			!hideItems.locked && content.push(row.replace(l, msg.locked).replace(v, file.locked ? msg.yes : msg.no));
 
- 			!hideItems.owner && file.owner && content.push(row.replace(l, msg.owner).replace(v, file.owner));
 
- 			!hideItems.group && file.group && content.push(row.replace(l, msg.group).replace(v, file.group));
 
- 			!hideItems.perm && file.perm && content.push(row.replace(l, msg.perm).replace(v, fm.formatFileMode(file.perm)));
 
- 			
 
- 			// Get MD5 hash
 
- 			if (window.ArrayBuffer && (fm.options.cdns.sparkmd5 || fm.options.cdns.jssha) && file.mime !== 'directory' && file.size > 0 && (!o.showHashMaxsize || file.size <= o.showHashMaxsize)) {
 
- 				getHashAlgorisms = [];
 
- 				$.each(fm.storage('hashchekcer') || o.showHashAlgorisms, function(i, n) {
 
- 					if (!file[n]) {
 
- 					content.push(row.replace(l, fm.i18n(n)).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{name}', n)));
 
- 						getHashAlgorisms.push(n);
 
- 					} else {
 
- 						content.push(row.replace(l, fm.i18n(n)).replace(v, file[n]).replace('{class}', hashClass));
 
- 					}
 
- 				});
 
- 				reqs.push(
 
- 					fm.getContentsHashes(file.hash, getHashAlgorisms).progress(function(hashes) {
 
- 						$.each(getHashAlgorisms, function(i, n) {
 
- 							if (hashes[n]) {
 
- 								replSpinner(hashes[n], n, hashClass);
 
- 							}
 
- 						});
 
- 					}).always(function() {
 
- 						$.each(getHashAlgorisms, function(i, n) {
 
- 							replSpinner(msg.unknown, n);
 
- 						});
 
- 					})
 
- 				);
 
- 			}
 
- 			
 
- 			// Add custom info fields
 
- 			if (o.custom) {
 
- 				$.each(o.custom, function(name, details) {
 
- 					if (
 
- 					  !hideItems[details.label]
 
- 					    &&
 
- 					  (!details.mimes || $.grep(details.mimes, function(m){return (file.mime === m || file.mime.indexOf(m+'/') === 0)? true : false;}).length)
 
- 					    &&
 
- 					  (!details.hashRegex || file.hash.match(details.hashRegex))
 
- 					) {
 
- 						// Add to the content
 
- 						content.push(row.replace(l, fm.i18n(details.label)).replace(v , details.tpl.replace('{id}', id)));
 
- 						// Register the action
 
- 						if (details.action && (typeof details.action == 'function')) {
 
- 							customActions.push(details.action);
 
- 						}
 
- 					}
 
- 				});
 
- 			}
 
- 		} else {
 
- 			view  = view.replace('{class}', 'elfinder-cwd-icon-group');
 
- 			title = tpl.groupTitle.replace('{items}', msg.items).replace('{num}', cnt);
 
- 			dcnt  = $.grep(files, function(f) { return f.mime == 'directory' ? true : false ; }).length;
 
- 			if (!dcnt) {
 
- 				size = 0;
 
- 				$.each(files, function(h, f) { 
 
- 					var s = parseInt(f.size);
 
- 					
 
- 					if (s >= 0 && size >= 0) {
 
- 						size += s;
 
- 					} else {
 
- 						size = 'unknown';
 
- 					}
 
- 				});
 
- 				content.push(row.replace(l, msg.kind).replace(v, msg.files));
 
- 				!hideItems.size && content.push(row.replace(l, msg.size).replace(v, fm.formatSize(size)));
 
- 			} else {
 
- 				rdcnt = $.grep(files, function(f) { return f.mime === 'directory' && (! f.phash || f.isroot)? true : false ; }).length;
 
- 				dcnt -= rdcnt;
 
- 				content.push(row.replace(l, msg.kind).replace(v, (rdcnt === cnt || dcnt === cnt)? msg[rdcnt? 'roots' : 'folders'] : $.map({roots: rdcnt, folders: dcnt, files: cnt - rdcnt - dcnt}, function(c, t) { return c? msg[t]+' '+c : null; }).join(', ')));
 
- 				!hideItems.size && content.push(row.replace(l, msg.size).replace(v, tpl.spinner.replace('{text}', msg.calc).replace('{name}', 'size')));
 
- 				count = $.map(files, function(f) { return f.hash; });
 
- 				
 
- 			}
 
- 		}
 
- 		
 
- 		view = view.replace('{title}', title).replace('{content}', content.join('').replace(/{class}/g, ''));
 
- 		
 
- 		dialog = self.fmDialog(view, opts);
 
- 		dialog.attr('id', id).one('mousedown', '.elfinder-info-path', function() {
 
- 			$(this).html(applyZWSP($(this).html(), true));
 
- 		});
 
- 		if (fm.UA.Mobile && $.fn.tooltip) {
 
- 			dialog.children('.ui-dialog-content .elfinder-info-title').tooltip({
 
- 				classes: {
 
- 					'ui-tooltip': 'elfinder-ui-tooltip ui-widget-shadow'
 
- 				},
 
- 				tooltipClass: 'elfinder-ui-tooltip ui-widget-shadow',
 
- 				track: true
 
- 			});
 
- 		}
 
- 		if (file && file.url == '1') {
 
- 			dialog.on('click', '.'+spclass+'-url', function(){
 
- 				$(this).parent().html(tpl.spinner.replace('{text}', fm.i18n('ntfurl')).replace('{name}', 'url'));
 
- 				fm.request({
 
- 					data : {cmd : 'url', target : file.hash},
 
- 					preventDefault : true
 
- 				})
 
- 				.fail(function() {
 
- 					replSpinner(name_esc, 'url');
 
- 				})
 
- 				.done(function(data) {
 
- 					if (data.url) {
 
- 						replSpinner('<a href="'+data.url+'" target="_blank">'+name_esc+'</a>' || name_esc, 'url');
 
- 						var rfile = fm.file(file.hash);
 
- 						rfile.url = data.url;
 
- 					} else {
 
- 						replSpinner(name_esc, 'url');
 
- 					}
 
- 				});
 
- 			});
 
- 		}
 
- 		// load thumbnail
 
- 		if (tmb) {
 
- 			$('<img/>')
 
- 				.on('load', function() { dialog.find('.elfinder-cwd-icon').addClass(tmb.className).css('background-image', "url('"+tmb.url+"')"); })
 
- 				.attr('src', tmb.url);
 
- 		}
 
- 		
 
- 		// send request to count total size
 
- 		if (count.length) {
 
- 			reqDfrd = fm.getSize(count).done(function(data) {
 
- 				replSpinner(data.formated, 'size');
 
- 			}).fail(function() {
 
- 				replSpinner(msg.unknown, 'size');
 
- 			});
 
- 		}
 
- 		
 
- 		// call custom actions
 
- 		if (customActions.length) {
 
- 			$.each(customActions, function(i, action) {
 
- 				try {
 
- 					action(file, fm, dialog);
 
- 				} catch(e) {
 
- 					fm.debug('error', e);
 
- 				}
 
- 			});
 
- 		}
 
- 		
 
- 		return $.Deferred().resolve();
 
- 	};
 
- 	
 
- }).prototype = { forceLoad : true }; // this is required command
 
- /*
 
-  * File: /js/commands/mkdir.js
 
-  */
 
- /**
 
-  * @class  elFinder command "mkdir"
 
-  * Create new folder
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- elFinder.prototype.commands.mkdir = function() {
 
- 		var fm   = this.fm,
 
- 		self = this,
 
- 		curOrg;
 
- 	
 
- 	this.value           = '';
 
- 	this.disableOnSearch = true;
 
- 	this.updateOnSelect  = false;
 
- 	this.syncTitleOnChange = true;
 
- 	this.mime            = 'directory';
 
- 	this.prefix          = 'untitled folder';
 
- 	this.exec            = function(select, cOpts) {
 
- 		var onCwd;
 
- 		if (select && select.length && cOpts && cOpts._currentType && cOpts._currentType === 'navbar') {
 
- 			this.origin = cOpts._currentType;
 
- 			this.data = {
 
- 				target: select[0]
 
- 			};
 
- 		} else {
 
- 			onCwd = fm.cwd().hash === select[0];
 
- 			this.origin = curOrg && !onCwd? curOrg : 'cwd';
 
- 			delete this.data;
 
- 		}
 
- 		if (! select && ! this.options.intoNewFolderToolbtn) {
 
- 			fm.getUI('cwd').trigger('unselectall');
 
- 		}
 
- 		//this.move = (!onCwd && curOrg !== 'navbar' && fm.selected().length)? true : false;
 
- 		this.move = this.value === fm.i18n('cmdmkdirin');
 
- 		return $.proxy(fm.res('mixin', 'make'), self)();
 
- 	};
 
- 	
 
- 	this.shortcuts = [{
 
- 		pattern     : 'ctrl+shift+n'
 
- 	}];
 
- 	this.init = function() {
 
- 		if (this.options.intoNewFolderToolbtn) {
 
- 			this.syncTitleOnChange = true;
 
- 		}
 
- 	};
 
- 	
 
- 	fm.bind('select contextmenucreate closecontextmenu', function(e) {
 
- 		var sel = (e.data? (e.data.selected || e.data.targets) : null) || fm.selected();
 
- 		
 
- 		self.className = 'mkdir';
 
- 		curOrg = e.data && sel.length? (e.data.origin || e.data.type || '') : '';
 
- 		if (!self.options.intoNewFolderToolbtn && curOrg === '') {
 
- 			curOrg = 'cwd';
 
- 		}
 
- 		if (sel.length && curOrg !== 'navbar' && curOrg !== 'cwd' && fm.cwd().hash !== sel[0]) {
 
- 			self.title = fm.i18n('cmdmkdirin');
 
- 			self.className += ' elfinder-button-icon-mkdirin';
 
- 		} else {
 
- 			self.title = fm.i18n('cmdmkdir');
 
- 		}
 
- 		if (e.type !== 'closecontextmenu') {
 
- 			self.update(void(0), self.title);
 
- 		} else {
 
- 			requestAnimationFrame(function() {
 
- 				self.update(void(0), self.title);
 
- 			});
 
- 		}
 
- 	});
 
- 	
 
- 	this.getstate = function(select) {
 
- 		var cwd = fm.cwd(),
 
- 			sel = (curOrg === 'navbar' || (select && select[0] !== cwd.hash))? this.files(select || fm.selected()) : [],
 
- 			cnt = sel.length;
 
- 		if (curOrg === 'navbar') {
 
- 			return cnt && sel[0].write && sel[0].read? 0 : -1;  
 
- 		} else {
 
- 			return cwd.write && (!cnt || $.grep(sel, function(f) { return f.read && ! f.locked? true : false; }).length == cnt)? 0 : -1;
 
- 		}
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/mkfile.js
 
-  */
 
- /**
 
-  * @class  elFinder command "mkfile"
 
-  * Create new empty file
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- elFinder.prototype.commands.mkfile = function() {
 
- 		var self = this;
 
- 	this.disableOnSearch = true;
 
- 	this.updateOnSelect  = false;
 
- 	this.mime            = 'text/plain';
 
- 	this.prefix          = 'untitled file.txt';
 
- 	this.variants        = [];
 
- 	this.getTypeName = function(mime, type) {
 
- 		var fm = self.fm,
 
- 			name;
 
- 		if (name = fm.messages['kind' + fm.kinds[mime]]) {
 
- 			name = fm.i18n(['extentiontype', type.toUpperCase(), name]);
 
- 		} else {
 
- 			name = fm.i18n(['extentionfile', type.toUpperCase()]);
 
- 		}
 
- 		return name;
 
- 	};
 
- 	this.fm.bind('open reload canMakeEmptyFile', function() {
 
- 		var fm = self.fm,
 
- 			hides = fm.storage('mkfileHides') || {};
 
- 		self.variants = [];
 
- 		if (fm.mimesCanMakeEmpty) {
 
- 			$.each(fm.mimesCanMakeEmpty, function(mime, type) {
 
- 				type && !hides[mime] && fm.uploadMimeCheck(mime) && self.variants.push([mime, self.getTypeName(mime, type)]);
 
- 			});
 
- 		}
 
- 		self.change();
 
- 	});
 
- 	this.getstate = function() {
 
- 		return this.fm.cwd().write ? 0 : -1;
 
- 	};
 
- 	this.exec = function(_dum, mime) {
 
- 		var fm = self.fm,
 
- 			type, err;
 
- 		if (type = fm.mimesCanMakeEmpty[mime]) {
 
- 			if (fm.uploadMimeCheck(mime)) {
 
- 				this.mime = mime;
 
- 				this.prefix = fm.i18n(['untitled file', type]);
 
- 				return $.proxy(fm.res('mixin', 'make'), self)();
 
- 			}
 
- 			err = ['errMkfile', self.getTypeName(mime, type)];
 
- 		}
 
- 		return $.Deferred().reject(err);
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/netmount.js
 
-  */
 
- /**
 
-  * @class  elFinder command "netmount"
 
-  * Mount network volume with user credentials.
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- elFinder.prototype.commands.netmount = function() {
 
- 		var self = this,
 
- 		hasMenus = false,
 
- 		content;
 
- 	this.alwaysEnabled  = true;
 
- 	this.updateOnSelect = false;
 
- 	this.drivers = [];
 
- 	
 
- 	this.handlers = {
 
- 		load : function() {
 
- 			var fm = self.fm;
 
- 			self.drivers = fm.netDrivers;
 
- 			if (self.drivers.length) {
 
- 				requestAnimationFrame(function() {
 
- 					$.each(self.drivers, function() {
 
- 						var d = self.options[this];
 
- 						if (d) {
 
- 							hasMenus = true;
 
- 							if (d.integrateInfo) {
 
- 								fm.trigger('helpIntegration', Object.assign({cmd: 'netmount'}, d.integrateInfo));
 
- 							}
 
- 						}
 
- 					});
 
- 				});
 
- 			}
 
- 		}
 
- 	};
 
- 	this.getstate = function() {
 
- 		return hasMenus ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function() {
 
- 		var fm = self.fm,
 
- 			dfrd = $.Deferred(),
 
- 			o = self.options,
 
- 			create = function() {
 
- 				var winFocus = function() {
 
- 						inputs.protocol.trigger('change', 'winfocus');
 
- 					},
 
- 					inputs = {
 
- 						protocol : $('<select/>')
 
- 						.on('change', function(e, data){
 
- 							var protocol = this.value;
 
- 							content.find('.elfinder-netmount-tr').hide();
 
- 							content.find('.elfinder-netmount-tr-'+protocol).show();
 
- 							dialogNode && dialogNode.children('.ui-dialog-buttonpane:first').find('button').show();
 
- 							if (typeof o[protocol].select == 'function') {
 
- 								o[protocol].select(fm, e, data);
 
- 							}
 
- 							requestAnimationFrame(function() {
 
- 								content.find('input:text.elfinder-tabstop:visible:first').trigger('focus');
 
- 							});
 
- 						})
 
- 						.addClass('ui-corner-all')
 
- 					},
 
- 					opts = {
 
- 						title          : fm.i18n('netMountDialogTitle'),
 
- 						resizable      : false,
 
- 						modal          : true,
 
- 						destroyOnClose : false,
 
- 						open           : function() {
 
- 							$(window).on('focus.'+fm.namespace, winFocus);
 
- 							inputs.protocol.trigger('change');
 
- 						},
 
- 						close          : function() { 
 
- 							dfrd.state() == 'pending' && dfrd.reject();
 
- 							$(window).off('focus.'+fm.namespace, winFocus);
 
- 						},
 
- 						buttons        : {}
 
- 					},
 
- 					doMount = function() {
 
- 						var protocol = inputs.protocol.val(),
 
- 							data = {cmd : 'netmount', protocol: protocol},
 
- 							cur = o[protocol];
 
- 						$.each(content.find('input.elfinder-netmount-inputs-'+protocol), function(name, input) {
 
- 							var val, elm;
 
- 							elm = $(input);
 
- 							if (elm.is(':radio,:checkbox')) {
 
- 								if (elm.is(':checked')) {
 
- 									val = $.trim(elm.val());
 
- 								}
 
- 							} else {
 
- 								val = $.trim(elm.val());
 
- 							}
 
- 							if (val) {
 
- 								data[input.name] = val;
 
- 							}
 
- 						});
 
- 	
 
- 						if (!data.host) {
 
- 							return fm.trigger('error', {error : 'errNetMountHostReq', opts : {modal: true}});
 
- 						}
 
- 	
 
- 						fm.request({data : data, notify : {type : 'netmount', cnt : 1, hideCnt : true}})
 
- 							.done(function(data) {
 
- 								var pdir;
 
- 								if (data.added && data.added.length) {
 
- 									if (data.added[0].phash) {
 
- 										if (pdir = fm.file(data.added[0].phash)) {
 
- 											if (! pdir.dirs) {
 
- 												pdir.dirs = 1;
 
- 												fm.change({ changed: [ pdir ] });
 
- 											}
 
- 										}
 
- 									}
 
- 									fm.one('netmountdone', function() {
 
- 										fm.exec('open', data.added[0].hash);
 
- 									});
 
- 								}
 
- 								dfrd.resolve();
 
- 							})
 
- 							.fail(function(error) {
 
- 								if (cur.fail && typeof cur.fail == 'function') {
 
- 									cur.fail(fm, fm.parseError(error));
 
- 								}
 
- 								dfrd.reject(error);
 
- 							});
 
- 	
 
- 						self.dialog.elfinderdialog('close');
 
- 					},
 
- 					form = $('<form autocomplete="off"/>').on('keydown', 'input', function(e) {
 
- 						var comp = true,
 
- 							next;
 
- 						if (e.keyCode === $.ui.keyCode.ENTER) {
 
- 							$.each(form.find('input:visible:not(.elfinder-input-optional)'), function() {
 
- 								if ($(this).val() === '') {
 
- 									comp = false;
 
- 									next = $(this);
 
- 									return false;
 
- 								}
 
- 							});
 
- 							if (comp) {
 
- 								doMount();
 
- 							} else {
 
- 								next.trigger('focus');
 
- 							}
 
- 						}
 
- 					}),
 
- 					hidden  = $('<div/>'),
 
- 					dialog;
 
- 				content = $('<table class="elfinder-info-tb elfinder-netmount-tb"/>')
 
- 					.append($('<tr/>').append($('<td>'+fm.i18n('protocol')+'</td>')).append($('<td/>').append(inputs.protocol)));
 
- 				$.each(self.drivers, function(i, protocol) {
 
- 					if (o[protocol]) {
 
- 						inputs.protocol.append('<option value="'+protocol+'">'+fm.i18n(o[protocol].name || protocol)+'</option>');
 
- 						$.each(o[protocol].inputs, function(name, input) {
 
- 							input.attr('name', name);
 
- 							if (input.attr('type') != 'hidden') {
 
- 								input.addClass('ui-corner-all elfinder-netmount-inputs-'+protocol);
 
- 								content.append($('<tr/>').addClass('elfinder-netmount-tr elfinder-netmount-tr-'+protocol).append($('<td>'+fm.i18n(name)+'</td>')).append($('<td/>').append(input)));
 
- 							} else {
 
- 								input.addClass('elfinder-netmount-inputs-'+protocol);
 
- 								hidden.append(input);
 
- 							}
 
- 						});
 
- 						o[protocol].protocol = inputs.protocol;
 
- 					}
 
- 				});
 
- 				
 
- 				content.append(hidden);
 
- 				
 
- 				content.find('.elfinder-netmount-tr').hide();
 
- 				opts.buttons[fm.i18n('btnMount')] = doMount;
 
- 				opts.buttons[fm.i18n('btnCancel')] = function() {
 
- 					self.dialog.elfinderdialog('close');
 
- 				};
 
- 				
 
- 				content.find('select,input').addClass('elfinder-tabstop');
 
- 				
 
- 				dialog = self.fmDialog(form.append(content), opts);
 
- 				dialogNode = dialog.closest('.ui-dialog');
 
- 				dialog.ready(function(){
 
- 					inputs.protocol.trigger('change');
 
- 					dialog.elfinderdialog('posInit');
 
- 				});
 
- 				return dialog;
 
- 			},
 
- 			dialogNode;
 
- 		
 
- 		if (!self.dialog) {
 
- 			self.dialog = create();
 
- 		} else {
 
- 			self.dialog.elfinderdialog('open');
 
- 		}
 
- 		return dfrd.promise();
 
- 	};
 
- 	self.fm.bind('netmount', function(e) {
 
- 		var d = e.data || null,
 
- 			o = self.options;
 
- 		if (d && d.protocol) {
 
- 			if (o[d.protocol] && typeof o[d.protocol].done == 'function') {
 
- 				o[d.protocol].done(self.fm, d);
 
- 				content.find('select,input').addClass('elfinder-tabstop');
 
- 				self.dialog.elfinderdialog('tabstopsInit');
 
- 			}
 
- 		}
 
- 	});
 
- };
 
- elFinder.prototype.commands.netunmount = function() {
 
- 	var self = this;
 
- 	this.alwaysEnabled  = true;
 
- 	this.updateOnSelect = false;
 
- 	this.drivers = [];
 
- 	
 
- 	this.handlers = {
 
- 		load : function() {
 
- 			this.drivers = this.fm.netDrivers;
 
- 		}
 
- 	};
 
- 	this.getstate = function(sel) {
 
- 		var fm = this.fm,
 
- 			file;
 
- 		return !!sel && this.drivers.length && !this._disabled && (file = fm.file(sel[0])) && file.netkey ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes) {
 
- 		var self   = this,
 
- 			fm     = this.fm,
 
- 			dfrd   = $.Deferred()
 
- 				.fail(function(error) {
 
- 					error && fm.error(error);
 
- 				}),
 
- 			drive  = fm.file(hashes[0]),
 
- 			childrenRoots = function(hash) {
 
- 				var roots = [],
 
- 					work;
 
- 				if (fm.leafRoots) {
 
- 					work = [];
 
- 					$.each(fm.leafRoots, function(phash, hashes) {
 
- 						var parents = fm.parents(phash),
 
- 							idx, deep;
 
- 						if ((idx = $.inArray(hash, parents)) !== -1) {
 
- 							idx = parents.length - idx;
 
- 							$.each(hashes, function(i, h) {
 
- 								work.push({i: idx, hash: h});
 
- 							});
 
- 						}
 
- 					});
 
- 					if (work.length) {
 
- 						work.sort(function(a, b) { return a.i < b.i; });
 
- 						$.each(work, function(i, o) {
 
- 							roots.push(o.hash);
 
- 						});
 
- 					}
 
- 				}
 
- 				return roots;
 
- 			};
 
- 		if (this._disabled) {
 
- 			return dfrd.reject();
 
- 		}
 
- 		if (dfrd.state() == 'pending') {
 
- 			fm.confirm({
 
- 				title  : self.title,
 
- 				text   : fm.i18n('confirmUnmount', drive.name),
 
- 				accept : {
 
- 					label    : 'btnUnmount',
 
- 					callback : function() {  
 
- 						var target =  drive.hash,
 
- 							roots = childrenRoots(target),
 
- 							requests = [],
 
- 							removed = [],
 
- 							doUmount = function() {
 
- 								$.when(requests).done(function() {
 
- 									fm.request({
 
- 										data   : {cmd  : 'netmount', protocol : 'netunmount', host: drive.netkey, user : target, pass : 'dum'}, 
 
- 										notify : {type : 'netunmount', cnt : 1, hideCnt : true},
 
- 										preventFail : true
 
- 									})
 
- 									.fail(function(error) {
 
- 										dfrd.reject(error);
 
- 									})
 
- 									.done(function(data) {
 
- 										drive.volumeid && delete fm.volumeExpires[drive.volumeid];
 
- 										dfrd.resolve();
 
- 									});
 
- 								}).fail(function(error) {
 
- 									if (removed.length) {
 
- 										fm.remove({ removed: removed });
 
- 									}
 
- 									dfrd.reject(error);
 
- 								});
 
- 							};
 
- 						
 
- 						if (roots.length) {
 
- 							fm.confirm({
 
- 								title : self.title,
 
- 								text  : (function() {
 
- 									var msgs = ['unmountChildren'];
 
- 									$.each(roots, function(i, hash) {
 
- 										msgs.push([fm.file(hash).name]);
 
- 									});
 
- 									return msgs;
 
- 								})(),
 
- 								accept : {
 
- 									label : 'btnUnmount',
 
- 									callback : function() {
 
- 										$.each(roots, function(i, hash) {
 
- 											var d = fm.file(hash);
 
- 											if (d.netkey) {
 
- 												requests.push(fm.request({
 
- 													data   : {cmd  : 'netmount', protocol : 'netunmount', host: d.netkey, user : d.hash, pass : 'dum'}, 
 
- 													notify : {type : 'netunmount', cnt : 1, hideCnt : true},
 
- 													preventDefault : true
 
- 												}).done(function(data) {
 
- 													if (data.removed) {
 
- 														d.volumeid && delete fm.volumeExpires[d.volumeid];
 
- 														removed = removed.concat(data.removed);
 
- 													}
 
- 												}));
 
- 											}
 
- 										});
 
- 										doUmount();
 
- 									}
 
- 								},
 
- 								cancel : {
 
- 									label : 'btnCancel',
 
- 									callback : function() {
 
- 										dfrd.reject();
 
- 									}
 
- 								}
 
- 							});
 
- 						} else {
 
- 							requests = null;
 
- 							doUmount();
 
- 						}
 
- 					}
 
- 				},
 
- 				cancel : {
 
- 					label    : 'btnCancel',
 
- 					callback : function() { dfrd.reject(); }
 
- 				}
 
- 			});
 
- 		}
 
- 			
 
- 		return dfrd;
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/open.js
 
-  */
 
- /**
 
-  * @class  elFinder command "open"
 
-  * Enter folder or open files in new windows
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/  
 
- (elFinder.prototype.commands.open = function() {
 
- 		var fm = this.fm;
 
- 	this.alwaysEnabled = true;
 
- 	this.noChangeDirOnRemovedCwd = true;
 
- 	
 
- 	this._handlers = {
 
- 		dblclick : function(e) { e.preventDefault(); fm.exec('open', e.data && e.data.file? [ e.data.file ]: void(0)); },
 
- 		'select enable disable reload' : function(e) { this.update(e.type == 'disable' ? -1 : void(0));  }
 
- 	};
 
- 	
 
- 	this.shortcuts = [{
 
- 		pattern     : 'ctrl+down numpad_enter'+(fm.OS != 'mac' && ' enter')
 
- 	}];
 
- 	this.getstate = function(select) {
 
- 		var sel = this.files(select),
 
- 			cnt = sel.length;
 
- 		
 
- 		return cnt == 1 
 
- 			? (sel[0].read? 0 : -1) 
 
- 			: (cnt && !fm.UA.Mobile) ? ($.grep(sel, function(file) { return file.mime == 'directory' || ! file.read ? false : true;}).length == cnt ? 0 : -1) : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes, cOpts) {
 
- 		var dfrd  = $.Deferred().fail(function(error) { error && fm.error(error); }),
 
- 			files = this.files(hashes),
 
- 			cnt   = files.length,
 
- 			thash = (typeof cOpts == 'object')? cOpts.thash : false,
 
- 			opts  = this.options,
 
- 			into  = opts.into || 'window',
 
- 			file, url, s, w, imgW, imgH, winW, winH, reg, link, html5dl, inline,
 
- 			selAct, cmd;
 
- 		if (!cnt && !thash) {
 
- 			{
 
- 				return dfrd.reject();
 
- 			}
 
- 		}
 
- 		// open folder
 
- 		if (thash || (cnt == 1 && (file = files[0]) && file.mime == 'directory')) {
 
- 			if (!thash && file && !file.read) {
 
- 				return dfrd.reject(['errOpen', file.name, 'errPerm']);
 
- 			} else {
 
- 				if (fm.keyState.ctrlKey && (fm.keyState.shiftKey || typeof fm.options.getFileCallback !== 'function')) {
 
- 					if (fm.getCommand('opennew')) {
 
- 						return fm.exec('opennew', [thash? thash : file.hash]);
 
- 					}
 
- 				}
 
- 				return fm.request({
 
- 					data   : {cmd  : 'open', target : thash || file.hash},
 
- 					notify : {type : 'open', cnt : 1, hideCnt : true},
 
- 					syncOnFail : true,
 
- 					lazy : false
 
- 				});
 
- 			}
 
- 		}
 
- 		
 
- 		files = $.grep(files, function(file) { return file.mime != 'directory' ? true : false; });
 
- 		
 
- 		// nothing to open or files and folders selected - do nothing
 
- 		if (cnt != files.length) {
 
- 			return dfrd.reject();
 
- 		}
 
- 		
 
- 		var doOpen = function() {
 
- 			var wnd, target, getOnly;
 
- 			
 
- 			try {
 
- 				reg = new RegExp(fm.option('dispInlineRegex'), 'i');
 
- 			} catch(e) {
 
- 				reg = false;
 
- 			}
 
- 	
 
- 			// open files
 
- 			link     = $('<a>').hide().appendTo($('body')),
 
- 			html5dl  = (typeof link.get(0).download === 'string');
 
- 			cnt = files.length;
 
- 			while (cnt--) {
 
- 				target = 'elf_open_window';
 
- 				file = files[cnt];
 
- 				
 
- 				if (!file.read) {
 
- 					return dfrd.reject(['errOpen', file.name, 'errPerm']);
 
- 				}
 
- 				
 
- 				inline = (reg && file.mime.match(reg));
 
- 				url = fm.openUrl(file.hash, !inline);
 
- 				if (fm.UA.Mobile || !inline) {
 
- 					if (html5dl) {
 
- 						if (!inline) {
 
- 							link.attr('download', file.name);
 
- 						} else {
 
- 							link.attr('target', '_blank');
 
- 						}
 
- 						link.attr('href', url).get(0).click();
 
- 					} else {
 
- 						wnd = window.open(url);
 
- 						if (!wnd) {
 
- 							return dfrd.reject('errPopup');
 
- 						}
 
- 					}
 
- 				} else {
 
- 					getOnly = (typeof opts.method === 'string' && opts.method.toLowerCase() === 'get');
 
- 					if (!getOnly
 
- 						&& url.indexOf(fm.options.url) === 0
 
- 						&& fm.customData
 
- 						&& Object.keys(fm.customData).length
 
- 						// Since playback by POST request can not be done in Chrome, media allows GET request
 
- 						&& !file.mime.match(/^(?:video|audio)/)
 
- 					) {
 
- 						// Send request as 'POST' method to hide custom data at location bar
 
- 						url = '';
 
- 					}
 
- 					if (into === 'window') {
 
- 						// set window size for image if set
 
- 						imgW = winW = Math.round(2 * screen.availWidth / 3);
 
- 						imgH = winH = Math.round(2 * screen.availHeight / 3);
 
- 						if (parseInt(file.width) && parseInt(file.height)) {
 
- 							imgW = parseInt(file.width);
 
- 							imgH = parseInt(file.height);
 
- 						} else if (file.dim) {
 
- 							s = file.dim.split('x');
 
- 							imgW = parseInt(s[0]);
 
- 							imgH = parseInt(s[1]);
 
- 						}
 
- 						if (winW >= imgW && winH >= imgH) {
 
- 							winW = imgW;
 
- 							winH = imgH;
 
- 						} else {
 
- 							if ((imgW - winW) > (imgH - winH)) {
 
- 								winH = Math.round(imgH * (winW / imgW));
 
- 							} else {
 
- 								winW = Math.round(imgW * (winH / imgH));
 
- 							}
 
- 						}
 
- 						w = 'width='+winW+',height='+winH;
 
- 						wnd = window.open(url, target, w + ',top=50,left=50,scrollbars=yes,resizable=yes,titlebar=no');
 
- 					} else {
 
- 						if (into === 'tabs') {
 
- 							target = file.hash;
 
- 						}
 
- 						wnd = window.open('about:blank', target);
 
- 					}
 
- 					
 
- 					if (!wnd) {
 
- 						return dfrd.reject('errPopup');
 
- 					}
 
- 					
 
- 					if (url === '') {
 
- 						var form = document.createElement("form");
 
- 						form.action = fm.options.url;
 
- 						form.method = 'POST';
 
- 						form.target = target;
 
- 						form.style.display = 'none';
 
- 						var params = Object.assign({}, fm.customData, {
 
- 							cmd: 'file',
 
- 							target: file.hash,
 
- 							_t: file.ts || parseInt(+new Date()/1000)
 
- 						});
 
- 						$.each(params, function(key, val)
 
- 						{
 
- 							var input = document.createElement("input");
 
- 							input.name = key;
 
- 							input.value = val;
 
- 							form.appendChild(input);
 
- 						});
 
- 						
 
- 						document.body.appendChild(form);
 
- 						form.submit();
 
- 					} else if (into !== 'window') {
 
- 						wnd.location = url;
 
- 					}
 
- 					$(wnd).trigger('focus');
 
- 				}
 
- 			}
 
- 			link.remove();
 
- 			return dfrd.resolve(hashes);
 
- 		};
 
- 		
 
- 		if (cnt > 1) {
 
- 			fm.confirm({
 
- 				title: 'openMulti',
 
- 				text : ['openMultiConfirm', cnt + ''],
 
- 				accept : {
 
- 					label : 'cmdopen',
 
- 					callback : function() { doOpen(); }
 
- 				},
 
- 				cancel : {
 
- 					label : 'btnCancel',
 
- 					callback : function() { 
 
- 						dfrd.reject();
 
- 					}
 
- 				},
 
- 				buttons : (fm.getCommand('zipdl') && fm.isCommandEnabled('zipdl', fm.cwd().hash))? [
 
- 					{
 
- 						label : 'cmddownload',
 
- 						callback : function() {
 
- 							fm.exec('download', hashes);
 
- 							dfrd.reject();
 
- 						}
 
- 					}
 
- 				] : []
 
- 			});
 
- 		} else {
 
- 			selAct = fm.storage('selectAction') || opts.selectAction;
 
- 			if (selAct) {
 
- 				$.each(selAct.split('/'), function() {
 
- 					var cmdName = this.valueOf();
 
- 					if (cmdName !== 'open' && (cmd = fm.getCommand(cmdName)) && cmd.enabled()) {
 
- 						return false;
 
- 					}
 
- 					cmd = null;
 
- 				});
 
- 				if (cmd) {
 
- 					return fm.exec(cmd.name);
 
- 				}
 
- 			}
 
- 			doOpen();
 
- 		}
 
- 		
 
- 		return dfrd;
 
- 	};
 
- }).prototype = { forceLoad : true }; // this is required command
 
- /*
 
-  * File: /js/commands/opendir.js
 
-  */
 
- /**
 
-  * @class  elFinder command "opendir"
 
-  * Enter parent folder
 
-  *
 
-  * @author Naoki Sawada
 
-  **/  
 
- elFinder.prototype.commands.opendir = function() {
 
- 		this.alwaysEnabled = true;
 
- 	
 
- 	this.getstate = function() {
 
- 		var sel = this.fm.selected(),
 
- 			cnt = sel.length,
 
- 			wz;
 
- 		if (cnt !== 1) {
 
- 			return -1;
 
- 		}
 
- 		wz = this.fm.getUI('workzone');
 
- 		return wz.hasClass('elfinder-search-result')? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes) {
 
- 		var fm    = this.fm,
 
- 			dfrd  = $.Deferred(),
 
- 			files = this.files(hashes),
 
- 			cnt   = files.length,
 
- 			hash, pcheck = null;
 
- 		if (!cnt || !files[0].phash) {
 
- 			return dfrd.reject();
 
- 		}
 
- 		hash = files[0].phash;
 
- 		fm.trigger('searchend', { noupdate: true });
 
- 		fm.request({
 
- 			data   : {cmd  : 'open', target : hash},
 
- 			notify : {type : 'open', cnt : 1, hideCnt : true},
 
- 			syncOnFail : false
 
- 		});
 
- 		
 
- 		return dfrd;
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/opennew.js
 
-  */
 
- /**
 
-  * @class  elFinder command "opennew"
 
-  * Open folder in new window
 
-  *
 
-  * @author Naoki Sawada
 
-  **/  
 
- elFinder.prototype.commands.opennew = function() {
 
- 		var fm = this.fm;
 
- 	this.shortcuts = [{
 
- 		pattern  : (typeof(fm.options.getFileCallback) === 'function'? 'shift+' : '') + 'ctrl+enter'
 
- 	}];
 
- 	this.getstate = function(select) {
 
- 		var sel = this.files(select),
 
- 			cnt = sel.length;
 
- 		
 
- 		return cnt === 1 
 
- 			? (sel[0].mime === 'directory' && sel[0].read? 0 : -1) 
 
- 			: -1;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes) {
 
- 		var dfrd  = $.Deferred(),
 
- 			files = this.files(hashes),
 
- 			cnt   = files.length,
 
- 			opts  = this.options,
 
- 			file, loc, url, win;
 
- 		// open folder to new tab (window)
 
- 		if (cnt === 1 && (file = files[0]) && file.mime === 'directory') {
 
- 			loc = window.location;
 
- 			if (opts.url) {
 
- 				url = opts.url;
 
- 			} else {
 
- 				url = loc.pathname;
 
- 			}
 
- 			if (opts.useOriginQuery) {
 
- 				if (!url.match(/\?/)) {
 
- 					url += loc.search;
 
- 				} else if (loc.search) {
 
- 					url += '&' + loc.search.substr(1);
 
- 				}
 
- 			}
 
- 			url += '#elf_' + file.hash;
 
- 			win = window.open(url, '_blank');
 
- 			setTimeout(function() {
 
- 				win.focus();
 
- 			}, 1000);
 
- 			return dfrd.resolve();
 
- 		} else {
 
- 			return dfrd.reject();
 
- 		}
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/paste.js
 
-  */
 
- /**
 
-  * @class  elFinder command "paste"
 
-  * Paste filesfrom clipboard into directory.
 
-  * If files pasted in its parent directory - files duplicates will created
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- elFinder.prototype.commands.paste = function() {
 
- 		this.updateOnSelect  = false;
 
- 	
 
- 	this.handlers = {
 
- 		changeclipboard : function() { this.update(); }
 
- 	};
 
- 	this.shortcuts = [{
 
- 		pattern     : 'ctrl+v shift+insert'
 
- 	}];
 
- 	
 
- 	this.getstate = function(dst) {
 
- 		if (this._disabled) {
 
- 			return -1;
 
- 		}
 
- 		if (dst) {
 
- 			if (Array.isArray(dst)) {
 
- 				if (dst.length != 1) {
 
- 					return -1;
 
- 				}
 
- 				dst = this.fm.file(dst[0]);
 
- 			}
 
- 		} else {
 
- 			dst = this.fm.cwd();
 
- 		}
 
- 		return this.fm.clipboard().length && dst.mime == 'directory' && dst.write ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(select, cOpts) {
 
- 		var self   = this,
 
- 			fm     = self.fm,
 
- 			opts   = cOpts || {},
 
- 			dst    = select ? this.files(select)[0] : fm.cwd(),
 
- 			files  = fm.clipboard(),
 
- 			cnt    = files.length,
 
- 			cut    = cnt ? files[0].cut : false,
 
- 			cmd    = opts._cmd? opts._cmd : (cut? 'move' : 'copy'),
 
- 			error  = 'err' + cmd.charAt(0).toUpperCase() + cmd.substr(1),
 
- 			fpaste = [],
 
- 			fcopy  = [],
 
- 			dfrd   = $.Deferred()
 
- 				.fail(function(error) {
 
- 					error && fm.error(error);
 
- 				})
 
- 				.always(function() {
 
- 					fm.unlockfiles({files : $.map(files, function(f) { return f.hash; })});
 
- 				}),
 
- 			copy  = function(files) {
 
- 				return files.length && fm._commands.duplicate
 
- 					? fm.exec('duplicate', files)
 
- 					: $.Deferred().resolve();
 
- 			},
 
- 			paste = function(files) {
 
- 				var dfrd      = $.Deferred(),
 
- 					existed   = [],
 
- 					hashes  = {},
 
- 					intersect = function(files, names) {
 
- 						var ret = [], 
 
- 							i   = files.length;
 
- 						while (i--) {
 
- 							$.inArray(files[i].name, names) !== -1 && ret.unshift(i);
 
- 						}
 
- 						return ret;
 
- 					},
 
- 					confirm   = function(ndx) {
 
- 						var i    = existed[ndx],
 
- 							file = files[i],
 
- 							last = ndx == existed.length-1;
 
- 						if (!file) {
 
- 							return;
 
- 						}
 
- 						fm.confirm({
 
- 							title  : fm.i18n(cmd + 'Files'),
 
- 							text   : ['errExists', file.name, cmd === 'restore'? 'confirmRest' : 'confirmRepl'], 
 
- 							all    : !last,
 
- 							accept : {
 
- 								label    : 'btnYes',
 
- 								callback : function(all) {
 
- 									!last && !all
 
- 										? confirm(++ndx)
 
- 										: paste(files);
 
- 								}
 
- 							},
 
- 							reject : {
 
- 								label    : 'btnNo',
 
- 								callback : function(all) {
 
- 									var i;
 
- 									if (all) {
 
- 										i = existed.length;
 
- 										while (ndx < i--) {
 
- 											files[existed[i]].remove = true;
 
- 										}
 
- 									} else {
 
- 										files[existed[ndx]].remove = true;
 
- 									}
 
- 									!last && !all
 
- 										? confirm(++ndx)
 
- 										: paste(files);
 
- 								}
 
- 							},
 
- 							cancel : {
 
- 								label    : 'btnCancel',
 
- 								callback : function() {
 
- 									dfrd.resolve();
 
- 								}
 
- 							},
 
- 							buttons : [
 
- 								{
 
- 									label : 'btnBackup',
 
- 									callback : function(all) {
 
- 										var i;
 
- 										if (all) {
 
- 											i = existed.length;
 
- 											while (ndx < i--) {
 
- 												files[existed[i]].rename = true;
 
- 											}
 
- 										} else {
 
- 											files[existed[ndx]].rename = true;
 
- 										}
 
- 										!last && !all
 
- 											? confirm(++ndx)
 
- 											: paste(files);
 
- 									}
 
- 								}
 
- 							]
 
- 						});
 
- 					},
 
- 					valid     = function(names) {
 
- 						var exists = {}, existedArr;
 
- 						if (names) {
 
- 							if (Array.isArray(names)) {
 
- 								if (names.length) {
 
- 									if (typeof names[0] == 'string') {
 
- 										// elFinder <= 2.1.6 command `is` results
 
- 										existed = intersect(files, names);
 
- 									} else {
 
- 										$.each(names, function(i, v) {
 
- 											exists[v.name] = v.hash;
 
- 										});
 
- 										existed = intersect(files, $.map(exists, function(h, n) { return n; }));
 
- 										$.each(files, function(i, file) {
 
- 											if (exists[file.name]) {
 
- 												hashes[exists[file.name]] = file.name;
 
- 											}
 
- 										});
 
- 									}
 
- 								}
 
- 							} else {
 
- 								existedArr = [];
 
- 								existed = $.map(names, function(n) {
 
- 									if (typeof n === 'string') {
 
- 										return n;
 
- 									} else {
 
- 										// support to >=2.1.11 plugin Normalizer, Sanitizer
 
- 										existedArr = existedArr.concat(n);
 
- 										return false;
 
- 									}
 
- 								});
 
- 								if (existedArr.length) {
 
- 									existed = existed.concat(existedArr);
 
- 								}
 
- 								existed = intersect(files, existed);
 
- 								hashes = names;
 
- 							}
 
- 						}
 
- 						existed.length ? confirm(0) : paste(files);
 
- 					},
 
- 					paste     = function(selFiles) {
 
- 						var renames = [],
 
- 							files  = $.grep(selFiles, function(file) { 
 
- 								if (file.rename) {
 
- 									renames.push(file.name);
 
- 								}
 
- 								return !file.remove ? true : false;
 
- 							}),
 
- 							cnt    = files.length,
 
- 							groups = {},
 
- 							args   = [],
 
- 							targets, reqData;
 
- 						if (!cnt) {
 
- 							return dfrd.resolve();
 
- 						}
 
- 						targets = $.map(files, function(f) { return f.hash; });
 
- 						
 
- 						reqData = {cmd : 'paste', dst : dst.hash, targets : targets, cut : cut ? 1 : 0, renames : renames, hashes : hashes, suffix : fm.options.backupSuffix};
 
- 						if (fm.api < 2.1) {
 
- 							reqData.src = files[0].phash;
 
- 						}
 
- 						
 
- 						fm.request({
 
- 								data   : reqData,
 
- 								notify : {type : cmd, cnt : cnt},
 
- 								navigate : { 
 
- 									toast  : opts.noToast? {} : {
 
- 										inbuffer : {msg: fm.i18n(['complete', fm.i18n('cmd' + cmd)]), action: {
 
- 											cmd: 'open',
 
- 											msg: 'cmdopendir',
 
- 											data: [dst.hash],
 
- 											done: 'select',
 
- 											cwdNot: dst.hash
 
- 										}}
 
- 									}
 
- 								}
 
- 							})
 
- 							.done(function(data) {
 
- 								var dsts = {},
 
- 									added = data.added && data.added.length? data.added : null;
 
- 								if (cut && added) {
 
- 									// undo/redo
 
- 									$.each(files, function(i, f) {
 
- 										var phash = f.phash,
 
- 											srcHash = function(name) {
 
- 												var hash;
 
- 												$.each(added, function(i, f) {
 
- 													if (f.name === name) {
 
- 														hash = f.hash;
 
- 														return false;
 
- 													}
 
- 												});
 
- 												return hash;
 
- 											},
 
- 											shash = srcHash(f.name);
 
- 										if (shash) {
 
- 											if (dsts[phash]) {
 
- 												dsts[phash].push(shash);
 
- 											} else {
 
- 												dsts[phash] = [ shash ];
 
- 											}
 
- 										}
 
- 									});
 
- 									if (Object.keys(dsts).length) {
 
- 										data.undo = {
 
- 											cmd : 'move',
 
- 											callback : function() {
 
- 												var reqs = [];
 
- 												$.each(dsts, function(dst, targets) {
 
- 													reqs.push(fm.request({
 
- 														data : {cmd : 'paste', dst : dst, targets : targets, cut : 1},
 
- 														notify : {type : 'undo', cnt : targets.length}
 
- 													}));
 
- 												});
 
- 												return $.when.apply(null, reqs);
 
- 											}
 
- 										};
 
- 										data.redo = {
 
- 											cmd : 'move',
 
- 											callback : function() {
 
- 												return fm.request({
 
- 													data : reqData,
 
- 													notify : {type : 'redo', cnt : cnt}
 
- 												});
 
- 											}
 
- 										};
 
- 									}
 
- 								}
 
- 								dfrd.resolve(data);
 
- 							})
 
- 							.fail(function() {
 
- 								dfrd.reject();
 
- 							})
 
- 							.always(function() {
 
- 								fm.unlockfiles({files : files});
 
- 							});
 
- 					},
 
- 					internames;
 
- 				if (!fm.isCommandEnabled(self.name, dst.hash) || !files.length) {
 
- 					return dfrd.resolve();
 
- 				}
 
- 				
 
- 				if (fm.oldAPI) {
 
- 					paste(files);
 
- 				} else {
 
- 					
 
- 					if (!fm.option('copyOverwrite', dst.hash)) {
 
- 						paste(files);
 
- 					} else {
 
- 						internames = $.map(files, function(f) { return f.name; });
 
- 						dst.hash == fm.cwd().hash
 
- 							? valid($.map(fm.files(), function(file) { return file.phash == dst.hash ? {hash: file.hash, name: file.name} : null; }))
 
- 							: fm.request({
 
- 								data : {cmd : 'ls', target : dst.hash, intersect : internames},
 
- 								notify : {type : 'prepare', cnt : 1, hideCnt : true},
 
- 								preventFail : true
 
- 							})
 
- 							.always(function(data) {
 
- 								valid(data.list);
 
- 							});
 
- 					}
 
- 				}
 
- 				
 
- 				return dfrd;
 
- 			},
 
- 			parents, fparents;
 
- 		if (!cnt || !dst || dst.mime != 'directory') {
 
- 			return dfrd.reject();
 
- 		}
 
- 			
 
- 		if (!dst.write)	{
 
- 			return dfrd.reject([error, files[0].name, 'errPerm']);
 
- 		}
 
- 		
 
- 		parents = fm.parents(dst.hash);
 
- 		
 
- 		$.each(files, function(i, file) {
 
- 			if (!file.read) {
 
- 				return !dfrd.reject([error, file.name, 'errPerm']);
 
- 			}
 
- 			
 
- 			if (cut && file.locked) {
 
- 				return !dfrd.reject(['errLocked', file.name]);
 
- 			}
 
- 			
 
- 			if ($.inArray(file.hash, parents) !== -1) {
 
- 				return !dfrd.reject(['errCopyInItself', file.name]);
 
- 			}
 
- 			
 
- 			if (file.mime && file.mime !== 'directory' && ! fm.uploadMimeCheck(file.mime, dst.hash)) {
 
- 				return !dfrd.reject([error, file.name, 'errUploadMime']);
 
- 			}
 
- 			
 
- 			fparents = fm.parents(file.hash);
 
- 			fparents.pop();
 
- 			if ($.inArray(dst.hash, fparents) !== -1) {
 
- 				
 
- 				if ($.grep(fparents, function(h) { var d = fm.file(h); return d.phash == dst.hash && d.name == file.name ? true : false; }).length) {
 
- 					return !dfrd.reject(['errReplByChild', file.name]);
 
- 				}
 
- 			}
 
- 			
 
- 			if (file.phash == dst.hash) {
 
- 				fcopy.push(file.hash);
 
- 			} else {
 
- 				fpaste.push({
 
- 					hash  : file.hash,
 
- 					phash : file.phash,
 
- 					name  : file.name
 
- 				});
 
- 			}
 
- 		});
 
- 		if (dfrd.state() == 'rejected') {
 
- 			return dfrd;
 
- 		}
 
- 		$.when(
 
- 			copy(fcopy),
 
- 			paste(fpaste)
 
- 		)
 
- 		.done(function(cr, pr) {
 
- 			dfrd.resolve(pr && pr.undo? pr : void(0));
 
- 		})
 
- 		.fail(function() {
 
- 			dfrd.reject();
 
- 		})
 
- 		.always(function() {
 
- 			cut && fm.clipboard([]);
 
- 		});
 
- 		
 
- 		return dfrd;
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/places.js
 
-  */
 
- /**
 
-  * @class  elFinder command "places"
 
-  * Regist to Places
 
-  *
 
-  * @author Naoki Sawada
 
-  **/
 
- elFinder.prototype.commands.places = function() {
 
- 		var self   = this,
 
- 	fm     = this.fm,
 
- 	filter = function(hashes) {
 
- 		return $.grep(self.files(hashes), function(f) { return f.mime == 'directory' ? true : false; });
 
- 	},
 
- 	places = null;
 
- 	
 
- 	this.getstate = function(select) {
 
- 		var sel = this.hashes(select),
 
- 		cnt = sel.length;
 
- 		
 
- 		return  places && cnt && cnt == filter(sel).length ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes) {
 
- 		var files = this.files(hashes);
 
- 		places.trigger('regist', [ files ]);
 
- 		return $.Deferred().resolve();
 
- 	};
 
- 	
 
- 	fm.one('load', function(){
 
- 		places = fm.ui.places;
 
- 	});
 
- };
 
- /*
 
-  * File: /js/commands/preference.js
 
-  */
 
- /**
 
-  * @class  elFinder command "preference"
 
-  * "Preference" dialog
 
-  *
 
-  * @author Naoki Sawada
 
-  **/
 
- elFinder.prototype.commands.preference = function() {
 
- 	var self    = this,
 
- 		fm      = this.fm,
 
- 		r       = 'replace',
 
- 		tab     = '<li class="' + fm.res('class', 'tabstab') + ' elfinder-preference-tab-{id}"><a href="#'+fm.namespace+'-preference-{id}" id="'+fm.namespace+'-preference-tab-{id}" class="ui-tabs-anchor {class}">{title}</a></li>',
 
- 		base    = $('<div class="ui-tabs ui-widget ui-widget-content ui-corner-all elfinder-preference">'), 
 
- 		ul      = $('<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-top">'),
 
- 		tabs    = $('<div class="elfinder-preference-tabs ui-tabs-panel ui-widget-content ui-corner-bottom"/>'),
 
- 		sep     = '<div class="elfinder-preference-separator"/>',
 
- 		selfUrl = $('base').length? document.location.href.replace(/#.*$/, '') : '',
 
- 		selectTab = function(tab) {
 
- 			$('#'+fm.namespace+'-preference-tab-'+tab).trigger('mouseover').trigger('click');
 
- 			openTab = tab;
 
- 		},
 
- 		clTabActive = fm.res('class', 'tabsactive'),
 
- 		build   = function() {
 
- 			var cats = self.options.categories || {
 
- 					'language' : ['language'],
 
- 					'theme' : ['theme'],
 
- 					'toolbar' : ['toolbarPref'],
 
- 					'workspace' : ['iconSize','columnPref', 'selectAction', 'makefileTypes', 'useStoredEditor', 'editorMaximized', 'showHidden'],
 
- 					'dialog' : ['autoFocusDialog'],
 
- 					'selectionInfo' : ['infoItems', 'hashChecker'],
 
- 					'reset' : ['clearBrowserData'],
 
- 					'all' : true
 
- 				},
 
- 				forms = self.options.prefs || ['language', 'theme', 'toolbarPref', 'iconSize', 'columnPref', 'selectAction', 'makefileTypes', 'useStoredEditor', 'editorMaximized', 'showHidden', 'infoItems', 'hashChecker', 'autoFocusDialog', 'clearBrowserData'];
 
- 			
 
- 			forms = fm.arrayFlip(forms, true);
 
- 			
 
- 			if (fm.options.getFileCallback) {
 
- 				delete forms.selectAction;
 
- 			}
 
- 			
 
- 			forms.language && (forms.language = (function() {
 
- 				var langSel = $('<select/>').on('change', function() {
 
- 						var lang = $(this).val();
 
- 						fm.storage('lang', lang);
 
- 						$('#'+fm.id).elfinder('reload');
 
- 					}),
 
- 					optTags = [],
 
- 					langs = self.options.langs || {
 
- 						ar: 'اللغة العربية',
 
- 						bg: 'Български',
 
- 						ca: 'Català',
 
- 						cs: 'Čeština',
 
- 						da: 'Dansk',
 
- 						de: 'Deutsch',
 
- 						el: 'Ελληνικά',
 
- 						en: 'English',
 
- 						es: 'Español',
 
- 						fa: 'فارسی',
 
- 						fo: 'Føroyskt',
 
- 						fr: 'Français',
 
- 						he: 'עברית',
 
- 						hr: 'Hrvatski',
 
- 						hu: 'Magyar',
 
- 						id: 'Bahasa Indonesia',
 
- 						it: 'Italiano',
 
- 						ja: '日本語',
 
- 						ko: '한국어',
 
- 						nl: 'Nederlands',
 
- 						no: 'Norsk',
 
- 						pl: 'Polski',
 
- 						pt_BR: 'Português',
 
- 						ro: 'Română',
 
- 						ru: 'Pусский',
 
- 						si: 'සිංහල',
 
- 						sk: 'Slovenčina',
 
- 						sl: 'Slovenščina',
 
- 						sr: 'Srpski',
 
- 						sv: 'Svenska',
 
- 						tr: 'Türkçe',
 
- 						ug_CN: 'ئۇيغۇرچە',
 
- 						uk: 'Український',
 
- 						vi: 'Tiếng Việt',
 
- 						zh_CN: '简体中文',
 
- 						zh_TW: '正體中文'
 
- 					};
 
- 				$.each(langs, function(lang, name) {
 
- 					optTags.push('<option value="'+lang+'">'+name+'</option>');
 
- 				});
 
- 				return langSel.append(optTags.join('')).val(fm.lang);
 
- 			})());
 
- 			
 
- 			forms.theme && (forms.theme = (function() {
 
- 				if (!fm.options.themes || !Object.keys(fm.options.themes).length) {
 
- 					return null;
 
- 				}
 
- 				var themeSel = $('<select/>').on('change', function() {
 
- 						var theme = $(this).val();
 
- 						fm.changeTheme(theme).storage('theme', theme);
 
- 					}),
 
- 					optTags = [],
 
- 					tpl = {
 
- 						image: '<img class="elfinder-preference-theme elfinder-preference-theme-image" src="$2" />',
 
- 						link: '<a href="$1" target="_blank" title="$3">$2</a>',
 
- 						data: '<dt>$1</dt><dd><span class="elfinder-preference-theme elfinder-preference-theme-$0">$2</span></dd>'
 
- 					},
 
- 					items = ['image', 'description', 'author', 'email', 'license'],
 
- 					render = function(key, data) {
 
- 					},
 
- 					defBtn = $('<button class="ui-button ui-corner-all ui-widget elfinder-preference-theme-default"/>').text(fm.i18n('default')).on('click', function(e) {
 
- 						themeSel.val('default').trigger('change');
 
- 					}),
 
- 					list = $('<div class="elfinder-reference-hide-taball"/>').on('click', 'button', function() {
 
- 							var val = $(this).data('themeid')
 
- 							themeSel.val(val).trigger('change');
 
- 					});
 
- 				themeSel.append('<option value="default">'+fm.i18n('default')+'</option>');
 
- 				$.each(fm.options.themes, function(id, val) {
 
- 					var opt = $('<option class="elfinder-theme-option-'+id+'" value="'+id+'">'+fm.i18n(id)+'</option>'),
 
- 						dsc = $('<fieldset class="ui-widget ui-widget-content ui-corner-all elfinder-theme-list-'+id+'"><legend>'+fm.i18n(id)+'</legend><div><span class="elfinder-spinner"/></div></fieldset>'),
 
- 						tm;
 
- 					themeSel.append(opt);
 
- 					list.append(dsc);
 
- 					tm = setTimeout(function() {
 
- 						dsc.find('span.elfinder-spinner').replaceWith(fm.i18n(['errRead', id]));
 
- 					}, 10000);
 
- 					fm.getTheme(id).always(function() {
 
- 						tm && clearTimeout(tm);
 
- 					}).done(function(data) {
 
- 						var link, val = $(), dl = $('<dl/>');
 
- 						link = data.link? tpl.link.replace(/\$1/g, data.link).replace(/\$3/g, fm.i18n('website')) : '$2';
 
- 						if (data.name) {
 
- 							opt.html(fm.i18n(data.name));
 
- 						}
 
- 						dsc.children('legend').html(link.replace(/\$2/g, fm.i18n(data.name) || id));
 
- 						$.each(items, function(i, key) {
 
- 							var t = tpl[key] || tpl.data,
 
- 								elm;
 
- 							if (data[key]) {
 
- 								elm = t.replace(/\$0/g, fm.escape(key)).replace(/\$1/g, fm.i18n(key)).replace(/\$2/g, fm.i18n(data[key]));
 
- 								if (key === 'image' && data.link) {
 
- 									elm = $(elm).on('click', function() {
 
- 										themeSel.val(id).trigger('change');
 
- 									}).attr('title', fm.i18n('select'));
 
- 								}
 
- 								dl.append(elm);
 
- 							}
 
- 						});
 
- 						val = val.add(dl);
 
- 						val = val.add($('<div class="elfinder-preference-theme-btn"/>').append($('<button class="ui-button ui-corner-all ui-widget"/>').data('themeid', id).html(fm.i18n('select'))));
 
- 						dsc.find('span.elfinder-spinner').replaceWith(val);
 
- 					}).fail(function() {
 
- 						dsc.find('span.elfinder-spinner').replaceWith(fm.i18n(['errRead', id]));
 
- 					});
 
- 				});
 
- 				return $('<div/>').append(themeSel.val(fm.theme && fm.theme.id? fm.theme.id : 'default'), defBtn, list);
 
- 			})());
 
- 			forms.toolbarPref && (forms.toolbarPref = (function() {
 
- 				var pnls = $.map(fm.options.uiOptions.toolbar, function(v) {
 
- 						return $.isArray(v)? v : null;
 
- 					}),
 
- 					tags = [],
 
- 					hides = fm.storage('toolbarhides') || {};
 
- 				$.each(pnls, function() {
 
- 					var cmd = this,
 
- 						name = fm.i18n('cmd'+cmd);
 
- 					if (name === 'cmd'+cmd) {
 
- 						name = fm.i18n(cmd);
 
- 					}
 
- 					tags.push('<span class="elfinder-preference-toolbar-item"><label><input type="checkbox" value="'+cmd+'" '+(hides[cmd]? '' : 'checked')+'/>'+name+'</label></span>');
 
- 				});
 
- 				return $(tags.join(' ')).on('change', 'input', function() {
 
- 					var v = $(this).val(),
 
- 						o = $(this).is(':checked');
 
- 					if (!o && !hides[v]) {
 
- 						hides[v] = true;
 
- 					} else if (o && hides[v]) {
 
- 						delete hides[v];
 
- 					}
 
- 					fm.storage('toolbarhides', hides);
 
- 					fm.trigger('toolbarpref');
 
- 				});
 
- 			})());
 
- 			
 
- 			forms.iconSize && (forms.iconSize = (function() {
 
- 				var max = fm.options.uiOptions.cwd.iconsView.sizeMax || 3,
 
- 					size = fm.storage('iconsize') || 0,
 
- 					sld = $('<div class="touch-punch"/>').slider({
 
- 						classes: {
 
- 							'ui-slider-handle': 'elfinder-tabstop',
 
- 						},
 
- 						value: size,
 
- 						max: max,
 
- 						slide: function(e, ui) {
 
- 							fm.getUI('cwd').trigger('iconpref', {size: ui.value});
 
- 						},
 
- 						change: function(e, ui) {
 
- 							fm.storage('iconsize', ui.value);
 
- 						}
 
- 					});
 
- 				fm.getUI('cwd').on('iconpref', function(e, data) {
 
- 					sld.slider('option', 'value', data.size);
 
- 				});
 
- 				return sld;
 
- 			})());
 
- 			forms.columnPref && (forms.columnPref = (function() {
 
- 				var cols = fm.options.uiOptions.cwd.listView.columns,
 
- 					tags = [],
 
- 					hides = fm.storage('columnhides') || {};
 
- 				$.each(cols, function() {
 
- 					var key = this,
 
- 						name = fm.getColumnName(key);
 
- 					tags.push('<span class="elfinder-preference-column-item"><label><input type="checkbox" value="'+key+'" '+(hides[key]? '' : 'checked')+'/>'+name+'</label></span>');
 
- 				});
 
- 				return $(tags.join(' ')).on('change', 'input', function() {
 
- 					var v = $(this).val(),
 
- 						o = $(this).is(':checked');
 
- 					if (!o && !hides[v]) {
 
- 						hides[v] = true;
 
- 					} else if (o && hides[v]) {
 
- 						delete hides[v];
 
- 					}
 
- 					fm.storage('columnhides', hides);
 
- 					fm.trigger('columnpref', { repaint: true });
 
- 				});
 
- 			})());
 
- 			
 
- 			forms.selectAction && (forms.selectAction = (function() {
 
- 				var actSel = $('<select/>').on('change', function() {
 
- 						var act = $(this).val();
 
- 						fm.storage('selectAction', act === 'default'? null : act);
 
- 					}),
 
- 					optTags = [],
 
- 					acts = self.options.selectActions,
 
- 					defAct = fm.getCommand('open').options.selectAction || 'open';
 
- 				
 
- 				if ($.inArray(defAct, acts) === -1) {
 
- 					acts.unshift(defAct);
 
- 				}
 
- 				$.each(acts, function(i, act) {
 
- 					var names = $.map(act.split('/'), function(cmd) {
 
- 						var name = fm.i18n('cmd'+cmd);
 
- 						if (name === 'cmd'+cmd) {
 
- 							name = fm.i18n(cmd);
 
- 						}
 
- 						return name;
 
- 					});
 
- 					optTags.push('<option value="'+act+'">'+names.join('/')+'</option>');
 
- 				});
 
- 				return actSel.append(optTags.join('')).val(fm.storage('selectAction') || defAct);
 
- 			})());
 
- 			
 
- 			forms.makefileTypes && (forms.makefileTypes = (function() {
 
- 				var hides = fm.storage('mkfileHides') || {},
 
- 					getTag = function() {
 
- 						var tags = [];
 
- 						// re-assign hides
 
- 						hides = fm.storage('mkfileHides') || {};
 
- 						$.each(fm.mimesCanMakeEmpty, function(mime, type) {
 
- 							var name = fm.getCommand('mkfile').getTypeName(mime, type);
 
- 							tags.push('<span class="elfinder-preference-column-item" title="'+fm.escape(name)+'"><label><input type="checkbox" value="'+mime+'" '+(hides[mime]? '' : 'checked')+'/>'+type+'</label></span>');
 
- 						});
 
- 						return tags.join(' ');
 
- 					},
 
- 					elm = $('<div/>').on('change', 'input', function() {
 
- 						var v = $(this).val(),
 
- 							o = $(this).is(':checked');
 
- 						if (!o && !hides[v]) {
 
- 							hides[v] = true;
 
- 						} else if (o && hides[v]) {
 
- 							delete hides[v];
 
- 						}
 
- 						fm.storage('mkfileHides', hides);
 
- 						fm.trigger('canMakeEmptyFile');
 
- 					}).append(getTag()),
 
- 					add = $('<div/>').append(
 
- 						$('<input type="text" placeholder="'+fm.i18n('typeOfTextfile')+'"/>').on('keydown', function(e) {
 
- 							(e.keyCode === $.ui.keyCode.ENTER) && $(this).next().trigger('click');
 
- 						}),
 
- 						$('<button class="ui-button"/>').html(fm.i18n('add')).on('click', function() {
 
- 							var input = $(this).prev(),
 
- 								val = input.val(),
 
- 								uiToast = fm.getUI('toast'),
 
- 								err = function() {
 
- 									uiToast.appendTo(input.closest('.ui-dialog'));
 
- 									fm.toast({
 
- 										msg: fm.i18n('errUsupportType'),
 
- 										mode: 'warning',
 
- 										onHidden: function() {
 
- 											uiToast.children().length === 1 && uiToast.appendTo(fm.getUI());
 
- 										}
 
- 									});
 
- 									input.trigger('focus');
 
- 									return false;
 
- 								},
 
- 								tmpMimes;
 
- 							if (!val.match(/\//)) {
 
- 								val = fm.arrayFlip(fm.mimeTypes)[val];
 
- 								if (!val) {
 
- 									return err();
 
- 								}
 
- 								input.val(val);
 
- 							}
 
- 							if (!fm.mimeIsText(val) || !fm.mimeTypes[val]) {
 
- 								return err();
 
- 							}
 
- 							fm.trigger('canMakeEmptyFile', {mimes: [val], unshift: true});
 
- 							tmpMimes = {};
 
- 							tmpMimes[val] = fm.mimeTypes[val];
 
- 							fm.storage('mkfileTextMimes', Object.assign(tmpMimes, fm.storage('mkfileTextMimes') || {}));
 
- 							input.val('');
 
- 							uiToast.appendTo(input.closest('.ui-dialog'));
 
- 							fm.toast({
 
- 								msg: fm.i18n(['complete', val + ' (' + tmpMimes[val] + ')']),
 
- 								onHidden: function() {
 
- 									uiToast.children().length === 1 && uiToast.appendTo(fm.getUI());
 
- 								}
 
- 							});
 
- 						}),
 
- 						$('<button class="ui-button"/>').html(fm.i18n('reset')).on('click', function() {
 
- 							fm.one('canMakeEmptyFile', {done: function() {
 
- 								elm.empty().append(getTag());
 
- 							}});
 
- 							fm.trigger('canMakeEmptyFile', {resetTexts: true});
 
- 						})
 
- 					),
 
- 					tm;
 
- 				fm.bind('canMakeEmptyFile', {done: function(e) {
 
- 					if (e.data && e.data.mimes && e.data.mimes.length) {
 
- 						elm.empty().append(getTag());
 
- 					}
 
- 				}});
 
- 				return $('<div/>').append(elm, add);
 
- 			})());
 
- 			forms.useStoredEditor && (forms.useStoredEditor = $('<input type="checkbox"/>').prop('checked', (function() {
 
- 				var s = fm.storage('useStoredEditor');
 
- 				return s? (s > 0) : fm.options.commandsOptions.edit.useStoredEditor;
 
- 			})()).on('change', function(e) {
 
- 				fm.storage('useStoredEditor', $(this).is(':checked')? 1 : -1);
 
- 			}));
 
- 			forms.editorMaximized && (forms.editorMaximized = $('<input type="checkbox"/>').prop('checked', (function() {
 
- 				var s = fm.storage('editorMaximized');
 
- 				return s? (s > 0) : fm.options.commandsOptions.edit.editorMaximized;
 
- 			})()).on('change', function(e) {
 
- 				fm.storage('editorMaximized', $(this).is(':checked')? 1 : -1);
 
- 			}));
 
- 			if (forms.showHidden) {
 
- 				(function() {
 
- 					var setTitle = function() {
 
- 							var s = fm.storage('hide'),
 
- 								t = [],
 
- 								v;
 
- 							if (s && s.items) {
 
- 								$.each(s.items, function(h, n) {
 
- 									t.push(fm.escape(n));
 
- 								});
 
- 							}
 
- 							elms.prop('disabled', !t.length)[t.length? 'removeClass' : 'addClass']('ui-state-disabled');
 
- 							v = t.length? t.join('\n') : '';
 
- 							forms.showHidden.attr('title',v);
 
- 							useTooltip && forms.showHidden.tooltip('option', 'content', v.replace(/\n/g, '<br>')).tooltip('close');
 
- 						},
 
- 						chk = $('<input type="checkbox"/>').prop('checked', (function() {
 
- 							var s = fm.storage('hide');
 
- 							return s && s.show;
 
- 						})()).on('change', function(e) {
 
- 							var o = {};
 
- 							o[$(this).is(':checked')? 'show' : 'hide'] = true;
 
- 							fm.exec('hide', void(0), o);
 
- 						}),
 
- 						btn = $('<button class="ui-button ui-corner-all ui-widget"/>').append(fm.i18n('reset')).on('click', function() {
 
- 							fm.exec('hide', void(0), {reset: true});
 
- 							$(this).parent().find('input:first').prop('checked', false);
 
- 							setTitle();
 
- 						}),
 
- 						elms = $().add(chk).add(btn),
 
- 						useTooltip;
 
- 					
 
- 					forms.showHidden = $('<div/>').append(chk, btn);
 
- 					fm.bind('hide', function(e) {
 
- 						var d = e.data;
 
- 						if (!d.opts || (!d.opts.show && !d.opts.hide)) {
 
- 							setTitle();
 
- 						}
 
- 					});
 
- 					if (fm.UA.Mobile && $.fn.tooltip) {
 
- 						useTooltip = true;
 
- 						forms.showHidden.tooltip({
 
- 							classes: {
 
- 								'ui-tooltip': 'elfinder-ui-tooltip ui-widget-shadow'
 
- 							},
 
- 							tooltipClass: 'elfinder-ui-tooltip ui-widget-shadow',
 
- 							track: true
 
- 						}).css('user-select', 'none');
 
- 						btn.css('user-select', 'none');
 
- 					}
 
- 					setTitle();
 
- 				})();
 
- 			}
 
- 			
 
- 			forms.infoItems && (forms.infoItems = (function() {
 
- 				var items = fm.getCommand('info').items,
 
- 					tags = [],
 
- 					hides = fm.storage('infohides') || fm.arrayFlip(fm.options.commandsOptions.info.hideItems, true);
 
- 				$.each(items, function() {
 
- 					var key = this,
 
- 						name = fm.i18n(key);
 
- 					tags.push('<span class="elfinder-preference-info-item"><label><input type="checkbox" value="'+key+'" '+(hides[key]? '' : 'checked')+'/>'+name+'</label></span>');
 
- 				});
 
- 				return $(tags.join(' ')).on('change', 'input', function() {
 
- 					var v = $(this).val(),
 
- 						o = $(this).is(':checked');
 
- 					if (!o && !hides[v]) {
 
- 						hides[v] = true;
 
- 					} else if (o && hides[v]) {
 
- 						delete hides[v];
 
- 					}
 
- 					fm.storage('infohides', hides);
 
- 					fm.trigger('infopref', { repaint: true });
 
- 				});
 
- 			})());
 
- 			
 
- 			forms.hashChecker && fm.hashCheckers.length && (forms.hashChecker = (function() {
 
- 				var tags = [],
 
- 					enabled = fm.arrayFlip(fm.storage('hashchekcer') || fm.options.commandsOptions.info.showHashAlgorisms, true);
 
- 				$.each(fm.hashCheckers, function() {
 
- 					var cmd = this,
 
- 						name = fm.i18n(cmd);
 
- 					tags.push('<span class="elfinder-preference-hashchecker-item"><label><input type="checkbox" value="'+cmd+'" '+(enabled[cmd]? 'checked' : '')+'/>'+name+'</label></span>');
 
- 				});
 
- 				return $(tags.join(' ')).on('change', 'input', function() {
 
- 					var v = $(this).val(),
 
- 						o = $(this).is(':checked');
 
- 					if (o) {
 
- 						enabled[v] = true;
 
- 					} else if (enabled[v]) {
 
- 						delete enabled[v];
 
- 					}
 
- 					fm.storage('hashchekcer', $.grep(fm.hashCheckers, function(v) {
 
- 						return enabled[v];
 
- 					}));
 
- 				});
 
- 			})());
 
- 			forms.autoFocusDialog && (forms.autoFocusDialog = $('<input type="checkbox"/>').prop('checked', (function() {
 
- 				var s = fm.storage('autoFocusDialog');
 
- 				return s? (s > 0) : fm.options.uiOptions.dialog.focusOnMouseOver;
 
- 			})()).on('change', function(e) {
 
- 				fm.storage('autoFocusDialog', $(this).is(':checked')? 1 : -1);
 
- 			}));
 
- 			
 
- 			forms.clearBrowserData && (forms.clearBrowserData = $('<button/>').text(fm.i18n('reset')).button().on('click', function(e) {
 
- 				e.preventDefault();
 
- 				fm.storage();
 
- 				$('#'+fm.id).elfinder('reload');
 
- 			}));
 
- 			
 
- 			$.each(cats, function(id, prefs) {
 
- 				var dls, found;
 
- 				if (prefs === true) {
 
- 					found = 1;
 
- 				} else if (prefs) {
 
- 					dls = $();
 
- 					$.each(prefs, function(i, n) {
 
- 						var f, title, chks = '', cbox;
 
- 						if (f = forms[n]) {
 
- 							found = 2;
 
- 							title = fm.i18n(n);
 
- 							cbox = $(f).filter('input[type="checkbox"]');
 
- 							if (!cbox.length) {
 
- 								cbox = $(f).find('input[type="checkbox"]');
 
- 							}
 
- 							if (cbox.length === 1) {
 
- 								if (!cbox.attr('id')) {
 
- 									cbox.attr('id', 'elfinder-preference-'+n+'-checkbox');
 
- 								}
 
- 								title = '<label for="'+cbox.attr('id')+'">'+title+'</label>';
 
- 							} else if (cbox.length > 1) {
 
- 								chks = ' elfinder-preference-checkboxes';
 
- 							}
 
- 							dls = dls.add($('<dt class="elfinder-preference-'+n+chks+'">'+title+'</dt>')).add($('<dd class="elfinder-preference-'+n+chks+'"/>').append(f));
 
- 						}
 
- 					});
 
- 				}
 
- 				if (found) {
 
- 					ul.append(tab[r](/\{id\}/g, id)[r](/\{title\}/, fm.i18n(id))[r](/\{class\}/, openTab === id? 'elfinder-focus' : ''));
 
- 					if (found === 2) {
 
- 						tabs.append(
 
- 							$('<div id="'+fm.namespace+'-preference-'+id+'" class="elfinder-preference-content"/>')
 
- 							.hide()
 
- 							.append($('<dl/>').append(dls))
 
- 						);
 
- 					}
 
- 				}
 
- 			});
 
- 			ul.on('click', 'a', function(e) {
 
- 				var t = $(e.target),
 
- 					h = t.attr('href');
 
- 				e.preventDefault();
 
- 				e.stopPropagation();
 
- 				ul.children().removeClass(clTabActive);
 
- 				t.removeClass('ui-state-hover').parent().addClass(clTabActive);
 
- 				if (h.match(/all$/)) {
 
- 					tabs.addClass('elfinder-preference-taball').children().show();
 
- 				} else {
 
- 					tabs.removeClass('elfinder-preference-taball').children().hide();
 
- 					$(h).show();
 
- 				}
 
- 			}).on('focus blur', 'a', function(e) {
 
- 				$(this).parent().toggleClass('ui-state-focus', e.type === 'focusin');
 
- 			}).on('mouseenter mouseleave', 'li', function(e) {
 
- 				$(this).toggleClass('ui-state-hover', e.type === 'mouseenter');
 
- 			});
 
- 			tabs.find('a,input,select,button').addClass('elfinder-tabstop');
 
- 			base.append(ul, tabs);
 
- 			dialog = self.fmDialog(base, {
 
- 				title : self.title,
 
- 				width : self.options.width || 600,
 
- 				height: self.options.height || 400,
 
- 				maxWidth: 'window',
 
- 				maxHeight: 'window',
 
- 				autoOpen : false,
 
- 				destroyOnClose : false,
 
- 				allowMinimize : false,
 
- 				open : function() {
 
- 					openTab && selectTab(openTab);
 
- 					openTab = null;
 
- 				},
 
- 				resize : function() {
 
- 					tabs.height(dialog.height() - ul.outerHeight(true) - (tabs.outerHeight(true) - tabs.height()) - 5);
 
- 				}
 
- 			})
 
- 			.on('click', function(e) {
 
- 				e.stopPropagation();
 
- 			})
 
- 			.css({
 
- 				overflow: 'hidden'
 
- 			});
 
- 			dialog.closest('.ui-dialog')
 
- 			.css({
 
- 				overflow: 'hidden'
 
- 			})
 
- 			.addClass('elfinder-bg-translucent');
 
- 			
 
- 			openTab = 'all';
 
- 		},
 
- 		dialog, openTab;
 
- 	this.shortcuts = [{
 
- 		pattern     : 'ctrl+comma',
 
- 		description : this.title
 
- 	}];
 
- 	this.alwaysEnabled  = true;
 
- 	
 
- 	this.getstate = function() {
 
- 		return 0;
 
- 	};
 
- 	
 
- 	this.exec = function(sel, cOpts) {
 
- 		!dialog && build();
 
- 		if (cOpts) {
 
- 			if (cOpts.tab) {
 
- 				selectTab(cOpts.tab);
 
- 			} else if (cOpts._currentType === 'cwd') {
 
- 				selectTab('workspace');
 
- 			}
 
- 		}
 
- 		dialog.elfinderdialog('open');
 
- 		return $.Deferred().resolve();
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/quicklook.js
 
-  */
 
- /**
 
-  * @class  elFinder command "quicklook"
 
-  * Fast preview for some files types
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- (elFinder.prototype.commands.quicklook = function() {
 
- 		var self       = this,
 
- 		fm         = self.fm,
 
- 		/**
 
- 		 * window closed state
 
- 		 *
 
- 		 * @type Number
 
- 		 **/
 
- 		closed     = 0,
 
- 		/**
 
- 		 * window animated state
 
- 		 *
 
- 		 * @type Number
 
- 		 **/
 
- 		animated   = 1,
 
- 		/**
 
- 		 * window opened state
 
- 		 *
 
- 		 * @type Number
 
- 		 **/
 
- 		opened     = 2,
 
- 		/**
 
- 		 * window docked state
 
- 		 *
 
- 		 * @type Number
 
- 		 **/
 
- 		docked     = 3,
 
- 		/**
 
- 		 * window docked and hidden state
 
- 		 *
 
- 		 * @type Number
 
- 		 **/
 
- 		dockedhidden = 4,
 
- 		/**
 
- 		 * window state
 
- 		 *
 
- 		 * @type Number
 
- 		 **/
 
- 		state      = closed,
 
- 		/**
 
- 		 * Event name of update
 
- 		 * for fix conflicts with Prototype.JS
 
- 		 * 
 
- 		 * `@see https://github.com/Studio-42/elFinder/pull/2346
 
- 		 * @type String
 
- 		 **/
 
- 		evUpdate = Element.update? 'quicklookupdate' : 'update',
 
- 		/**
 
- 		 * navbar icon class
 
- 		 *
 
- 		 * @type String
 
- 		 **/
 
- 		navicon    = 'elfinder-quicklook-navbar-icon',
 
- 		/**
 
- 		 * navbar "fullscreen" icon class
 
- 		 *
 
- 		 * @type String
 
- 		 **/
 
- 		fullscreen = 'elfinder-quicklook-fullscreen',
 
- 		/**
 
- 		 * info wrapper class
 
- 		 * 
 
- 		 * @type String
 
- 		 */
 
- 		infocls    = 'elfinder-quicklook-info-wrapper',
 
- 		/**
 
- 		 * Triger keydown/keypress event with left/right arrow key code
 
- 		 *
 
- 		 * @param  Number  left/right arrow key code
 
- 		 * @return void
 
- 		 **/
 
- 		navtrigger = function(code) {
 
- 			$(document).trigger($.Event('keydown', { keyCode: code, ctrlKey : false, shiftKey : false, altKey : false, metaKey : false }));
 
- 		},
 
- 		/**
 
- 		 * Return css for closed window
 
- 		 *
 
- 		 * @param  jQuery  file node in cwd
 
- 		 * @return void
 
- 		 **/
 
- 		closedCss = function(node) {
 
- 			var elf = fm.getUI().offset(),
 
- 				base = (function() {
 
- 					var target = node.find('.elfinder-cwd-file-wrapper');
 
- 					return target.length? target : node;
 
- 				})(),
 
- 				baseOffset = base.offset() || { top: 0, left: 0 };
 
- 			return {
 
- 				opacity : 0,
 
- 				width   : base.width(),
 
- 				height  : base.height() - 30,
 
- 				top     : baseOffset.top - elf.top,
 
- 				left    : baseOffset.left  - elf.left
 
- 			};
 
- 		},
 
- 		/**
 
- 		 * Return css for opened window
 
- 		 *
 
- 		 * @return void
 
- 		 **/
 
- 		openedCss = function() {
 
- 			var contain = self.options.contain,
 
- 				win = contain? fm.getUI() : $(window),
 
- 				elf = fm.getUI().offset(),
 
- 				w = Math.min(width, win.width()-10),
 
- 				h = Math.min(height, win.height()-80);
 
- 			return {
 
- 				opacity : 1,
 
- 				width  : w,
 
- 				height : h,
 
- 				top    : parseInt((win.height() - h - 60) / 2 + (contain? 0 : win.scrollTop() - elf.top)),
 
- 				left   : parseInt((win.width() - w) / 2 + (contain? 0 : win.scrollLeft() - elf.left))
 
- 			};
 
- 		},
 
- 		
 
- 		mediaNode = {},
 
- 		support = function(codec, name) {
 
- 			var node  = name || codec.substr(0, codec.indexOf('/')),
 
- 				media = mediaNode[node]? mediaNode[node] : (mediaNode[node] = document.createElement(node)),
 
- 				value = false;
 
- 			
 
- 			try {
 
- 				value = media.canPlayType && media.canPlayType(codec);
 
- 			} catch(e) {}
 
- 			
 
- 			return (value && value !== '' && value != 'no')? true : false;
 
- 		},
 
- 		
 
- 		platformWin = (window.navigator.platform.indexOf('Win') != -1),
 
- 		
 
- 		/**
 
- 		 * Opened window width (from config)
 
- 		 *
 
- 		 * @type Number
 
- 		 **/
 
- 		width, 
 
- 		/**
 
- 		 * Opened window height (from config)
 
- 		 *
 
- 		 * @type Number
 
- 		 **/
 
- 		height, 
 
- 		/**
 
- 		 * Previous style before docked
 
- 		 *
 
- 		 * @type String
 
- 		 **/
 
- 		prevStyle,
 
- 		/**
 
- 		 * elFinder node
 
- 		 *
 
- 		 * @type jQuery
 
- 		 **/
 
- 		parent, 
 
- 		/**
 
- 		 * elFinder current directory node
 
- 		 *
 
- 		 * @type jQuery
 
- 		 **/
 
- 		cwd, 
 
- 		/**
 
- 		 * Current directory hash
 
- 		 *
 
- 		 * @type String
 
- 		 **/
 
- 		cwdHash,
 
- 		dockEnabled = false,
 
- 		navdrag = false,
 
- 		navmove = false,
 
- 		navtm   = null,
 
- 		leftKey = $.ui.keyCode.LEFT,
 
- 		rightKey = $.ui.keyCode.RIGHT,
 
- 		coverEv = 'mousemove touchstart ' + ('onwheel' in document? 'wheel' : 'onmousewheel' in document? 'mousewheel' : 'DOMMouseScroll'),
 
- 		title   = $('<span class="elfinder-dialog-title elfinder-quicklook-title"/>'),
 
- 		icon    = $('<div/>'),
 
- 		info    = $('<div class="elfinder-quicklook-info"/>'),//.hide(),
 
- 		cover   = $('<div class="ui-front elfinder-quicklook-cover"/>'),
 
- 		fsicon  = $('<div class="'+navicon+' '+navicon+'-fullscreen"/>')
 
- 			.on('click touchstart', function(e) {
 
- 				if (navmove) {
 
- 					return;
 
- 				}
 
- 				
 
- 				var win     = self.window,
 
- 					full    = win.hasClass(fullscreen),
 
- 					$window = $(window),
 
- 					resize  = function() { self.preview.trigger('changesize'); };
 
- 					
 
- 				e.stopPropagation();
 
- 				e.preventDefault();
 
- 				
 
- 				if (full) {
 
- 					navStyle = '';
 
- 					navShow();
 
- 					win.toggleClass(fullscreen)
 
- 					.css(win.data('position'));
 
- 					$window.trigger(self.resize).off(self.resize, resize);
 
- 					navbar.off('mouseenter mouseleave');
 
- 					cover.off(coverEv);
 
- 				} else {
 
- 					win.toggleClass(fullscreen)
 
- 					.data('position', {
 
- 						left   : win.css('left'), 
 
- 						top    : win.css('top'), 
 
- 						width  : win.width(), 
 
- 						height : win.height(),
 
- 						display: 'block'
 
- 					})
 
- 					.removeAttr('style');
 
- 					$(window).on(self.resize, resize)
 
- 					.trigger(self.resize);
 
- 					cover.on(coverEv, function(e) {
 
- 						if (! navdrag) {
 
- 							if (e.type === 'mousemove' || e.type === 'touchstart') {
 
- 								navShow();
 
- 								navtm = setTimeout(function() {
 
- 									if (fm.UA.Mobile || navbar.parent().find('.elfinder-quicklook-navbar:hover').length < 1) {
 
- 										navbar.fadeOut('slow', function() {
 
- 											cover.show();
 
- 										});
 
- 									}
 
- 								}, 3000);
 
- 							}
 
- 							if (cover.is(':visible')) {
 
- 								coverHide();
 
- 								cover.data('tm', setTimeout(function() {
 
- 									cover.show();
 
- 								}, 3000));
 
- 							}
 
- 						}
 
- 					}).show().trigger('mousemove');
 
- 					
 
- 					navbar.on('mouseenter mouseleave', function(e) {
 
- 						if (! navdrag) {
 
- 							if (e.type === 'mouseenter') {
 
- 								navShow();
 
- 							} else {
 
- 								cover.trigger('mousemove');
 
- 							}
 
- 						}
 
- 					});
 
- 				}
 
- 				if (fm.zIndex) {
 
- 					win.css('z-index', fm.zIndex + 1);
 
- 				}
 
- 				if (fm.UA.Mobile) {
 
- 					navbar.attr('style', navStyle);
 
- 				} else {
 
- 					navbar.attr('style', navStyle).draggable(full ? 'destroy' : {
 
- 						start: function() {
 
- 							navdrag = true;
 
- 							navmove = true;
 
- 							cover.show();
 
- 							navShow();
 
- 						},
 
- 						stop: function() {
 
- 							navdrag = false;
 
- 							navStyle = self.navbar.attr('style');
 
- 							requestAnimationFrame(function() {
 
- 								navmove = false;
 
- 							});
 
- 						}
 
- 					});
 
- 				}
 
- 				$(this).toggleClass(navicon+'-fullscreen-off');
 
- 				var collection = win;
 
- 				if (parent.is('.ui-resizable')) {
 
- 					collection = collection.add(parent);
 
- 				}
 
- 				collection.resizable(full ? 'enable' : 'disable').removeClass('ui-state-disabled');
 
- 				win.trigger('viewchange');
 
- 			}
 
- 		),
 
- 		
 
- 		updateOnSel = function() {
 
- 			self.update(void(0), (function() {
 
- 				var fm = self.fm,
 
- 					files = fm.selectedFiles(),
 
- 					cnt = files.length,
 
- 					inDock = self.docked(),
 
- 					getInfo = function() {
 
- 						var ts = 0;
 
- 						$.each(files, function(i, f) {
 
- 							var t = parseInt(f.ts);
 
- 							if (ts >= 0) {
 
- 								if (t > ts) {
 
- 									ts = t;
 
- 								}
 
- 							} else {
 
- 								ts = 'unknown';
 
- 							}
 
- 						});
 
- 						return {
 
- 							hash : files[0].hash  + '/' + (+new Date()),
 
- 							name : fm.i18n('items') + ': ' + cnt,
 
- 							mime : 'group',
 
- 							size : spinner,
 
- 							ts   : ts,
 
- 							files : $.map(files, function(f) { return f.hash; }),
 
- 							getSize : true
 
- 						};
 
- 					};
 
- 				if (! cnt) {
 
- 					cnt = 1;
 
- 					files = [fm.cwd()];
 
- 				}
 
- 				return (cnt === 1)? files[0] : getInfo();
 
- 			})());
 
- 		},
 
- 		
 
- 		navShow = function() {
 
- 			if (self.window.hasClass(fullscreen)) {
 
- 				navtm && clearTimeout(navtm);
 
- 				navtm = null;
 
- 				// if use `show()` it make infinite loop with old jQuery (jQuery/jQuery UI: 1.8.0/1.9.0)
 
- 				// see #1478 https://github.com/Studio-42/elFinder/issues/1478
 
- 				navbar.stop(true, true).css('display', 'block');
 
- 				coverHide();
 
- 			}
 
- 		},
 
- 		
 
- 		coverHide = function() {
 
- 			cover.data('tm') && clearTimeout(cover.data('tm'));
 
- 			cover.removeData('tm');
 
- 			cover.hide();
 
- 		},
 
- 			
 
- 		prev = $('<div class="'+navicon+' '+navicon+'-prev"/>').on('click touchstart', function(e) { ! navmove && navtrigger(leftKey); return false; }),
 
- 		next = $('<div class="'+navicon+' '+navicon+'-next"/>').on('click touchstart', function(e) { ! navmove && navtrigger(rightKey); return false; }),
 
- 		navbar  = $('<div class="elfinder-quicklook-navbar"/>')
 
- 			.append(prev)
 
- 			.append(fsicon)
 
- 			.append(next)
 
- 			.append('<div class="elfinder-quicklook-navbar-separator"/>')
 
- 			.append($('<div class="'+navicon+' '+navicon+'-close"/>').on('click touchstart', function(e) { ! navmove && self.window.trigger('close'); return false; }))
 
- 		,
 
- 		titleClose = $('<span class="ui-front ui-icon elfinder-icon-close ui-icon-closethick"/>').on('mousedown', function(e) {
 
- 			e.stopPropagation();
 
- 			self.window.trigger('close');
 
- 		}),
 
- 		titleDock = $('<span class="ui-front ui-icon elfinder-icon-minimize ui-icon-minusthick"/>').on('mousedown', function(e) {
 
- 			e.stopPropagation();
 
- 			if (! self.docked()) {
 
- 				self.window.trigger('navdockin');
 
- 			} else {
 
- 				self.window.trigger('navdockout');
 
- 			}
 
- 		}),
 
- 		spinner = '<span class="elfinder-spinner-text">' + fm.i18n('calc') + '</span>' + '<span class="elfinder-spinner"/>',
 
- 		navStyle = '',
 
- 		init = true,
 
- 		dockHeight,	getSize, tm4cwd, dockedNode, selectTm;
 
- 	this.cover = cover;
 
- 	this.evUpdate = evUpdate;
 
- 	(this.navbar = navbar)._show = navShow;
 
- 	this.resize = 'resize.'+fm.namespace;
 
- 	this.info = $('<div/>').addClass(infocls)
 
- 		.append(icon)
 
- 		.append(info);
 
- 	this.autoPlay = function() {
 
- 		if (self.opened()) {
 
- 			return !! self.options[self.docked()? 'dockAutoplay' : 'autoplay'];
 
- 		}
 
- 		return false;
 
- 	};
 
- 	this.preview = $('<div class="elfinder-quicklook-preview ui-helper-clearfix"/>')
 
- 		// clean info/icon
 
- 		.on('change', function() {
 
- 			navShow();
 
- 			navbar.attr('style', navStyle);
 
- 			self.docked() && navbar.hide();
 
- 			self.preview.attr('style', '').removeClass('elfinder-overflow-auto');
 
- 			self.info.attr('style', '').hide();
 
- 			self.cover.removeClass('elfinder-quicklook-coverbg');
 
- 			icon.removeAttr('class').attr('style', '');
 
- 			info.html('');
 
- 		})
 
- 		// update info/icon
 
- 		.on(evUpdate, function(e) {
 
- 			var preview = self.preview,
 
- 				file    = e.file,
 
- 				tpl     = '<div class="elfinder-quicklook-info-data">{value}</div>',
 
- 				update  = function() {
 
- 					var win = self.window.css('overflow', 'hidden');
 
- 					name = fm.escape(file.i18 || file.name);
 
- 					!file.read && e.stopImmediatePropagation();
 
- 					self.window.data('hash', file.hash);
 
- 					self.preview.off('changesize').trigger('change').children().remove();
 
- 					title.html(name);
 
- 					
 
- 					prev.css('visibility', '');
 
- 					next.css('visibility', '');
 
- 					if (file.hash === fm.cwdId2Hash(cwd.find('[id]:not(.elfinder-cwd-parent):first').attr('id'))) {
 
- 						prev.css('visibility', 'hidden');
 
- 					}
 
- 					if (file.hash === fm.cwdId2Hash(cwd.find('[id]:last').attr('id'))) {
 
- 						next.css('visibility', 'hidden');
 
- 					}
 
- 					
 
- 					if (file.mime === 'directory') {
 
- 						getSizeHashes = [ file.hash ];
 
- 					} else if (file.mime === 'group' && file.getSize) {
 
- 						getSizeHashes = file.files;
 
- 					}
 
- 					
 
- 					info.html(
 
- 						tpl.replace(/\{value\}/, name)
 
- 						+ tpl.replace(/\{value\}/, fm.mime2kind(file))
 
- 						+ tpl.replace(/\{value\}/, getSizeHashes.length ? spinner : fm.formatSize(file.size))
 
- 						+ tpl.replace(/\{value\}/, fm.i18n('modify')+': '+ fm.formatDate(file))
 
- 					);
 
- 					
 
- 					if (getSizeHashes.length) {
 
- 						getSize = fm.getSize(getSizeHashes).done(function(data) {
 
- 							info.find('span.elfinder-spinner').parent().html(data.formated);
 
- 						}).fail(function() {
 
- 							info.find('span.elfinder-spinner').parent().html(fm.i18n('unknown'));
 
- 						}).always(function() {
 
- 							getSize = null;
 
- 						});
 
- 						getSize._hash = file.hash;
 
- 					}
 
- 					
 
- 					icon.addClass('elfinder-cwd-icon ui-corner-all '+fm.mime2class(file.mime));
 
- 					
 
- 					if (file.icon) {
 
- 						icon.css(fm.getIconStyle(file, true));
 
- 					}
 
- 					
 
- 					self.info.attr('class', infocls);
 
- 					if (file.csscls) {
 
- 						self.info.addClass(file.csscls);
 
- 					}
 
- 	
 
- 					if (file.read && (tmb = fm.tmb(file))) {
 
- 						$('<img/>')
 
- 							.hide()
 
- 							.appendTo(self.preview)
 
- 							.on('load', function() {
 
- 								icon.addClass(tmb.className).css('background-image', "url('"+tmb.url+"')");
 
- 								$(this).remove();
 
- 							})
 
- 							.attr('src', tmb.url);
 
- 					}
 
- 					self.info.delay(100).fadeIn(10);
 
- 					if (self.window.hasClass(fullscreen)) {
 
- 						cover.trigger('mousemove');
 
- 					}
 
- 					win.css('overflow', '');
 
- 				},
 
- 				tmb, name, getSizeHashes = [];
 
- 			if (file && ! Object.keys(file).length) {
 
- 				file = fm.cwd();
 
- 			}
 
- 			if (file && getSize && getSize.state() === 'pending' && getSize._hash !== file.hash) {
 
- 				getSize.reject();
 
- 			}
 
- 			if (file && (e.forceUpdate || self.window.data('hash') !== file.hash)) {
 
- 				update();
 
- 			} else { 
 
- 				e.stopImmediatePropagation();
 
- 			}
 
- 		});
 
- 	this.window = $('<div class="ui-front ui-helper-reset ui-widget elfinder-quicklook touch-punch" style="position:absolute"/>')
 
- 		.hide()
 
- 		.addClass(fm.UA.Touch? 'elfinder-touch' : '')
 
- 		.on('click', function(e) {
 
- 			var win = this;
 
- 			e.stopPropagation();
 
- 			if (state === opened) {
 
- 				requestAnimationFrame(function() {
 
- 					state === opened && fm.toFront(win);
 
- 				});
 
- 			}
 
- 		})
 
- 		.append(
 
- 			$('<div class="ui-dialog-titlebar ui-widget-header ui-corner-top ui-helper-clearfix elfinder-quicklook-titlebar"/>')
 
- 			.append(
 
- 				$('<span class="ui-widget-header ui-dialog-titlebar-close ui-corner-all elfinder-titlebar-button elfinder-quicklook-titlebar-icon'+(platformWin? ' elfinder-titlebar-button-right' : '')+'"/>').append(
 
- 					titleClose, titleDock
 
- 				),
 
- 				title
 
- 			),
 
- 			this.preview,
 
- 			self.info.hide(),
 
- 			cover.hide(),
 
- 			navbar
 
- 		)
 
- 		.draggable({handle : 'div.elfinder-quicklook-titlebar'})
 
- 		.on('open', function(e, clcss) {
 
- 			var win  = self.window, 
 
- 				file = self.value,
 
- 				node = fm.getUI('cwd'),
 
- 				open = function(status) {
 
- 					state = status;
 
- 					self.update(1, self.value);
 
- 					self.change();
 
- 					win.trigger('resize.' + fm.namespace);
 
- 				};
 
- 			if (!init && state === closed) {
 
- 				if (file && file.hash !== cwdHash) {
 
- 					node = $('#'+fm.cwdHash2Id(file.hash.split('/', 2)[0]));
 
- 				}
 
- 				navStyle = '';
 
- 				navbar.attr('style', '');
 
- 				state = animated;
 
- 				node.trigger('scrolltoview');
 
- 				coverHide();
 
- 				win.css(clcss || closedCss(node))
 
- 					.show()
 
- 					.animate(openedCss(), 550, function() {
 
- 						open(opened);
 
- 						navShow();
 
- 					});
 
- 				fm.toFront(win);
 
- 			} else if (state === dockedhidden) {
 
- 				fm.getUI('navdock').data('addNode')(dockedNode);
 
- 				open(docked);
 
- 				self.preview.trigger('changesize');
 
- 				fm.storage('previewDocked', '1');
 
- 				if (fm.getUI('navdock').width() === 0) {
 
- 					win.trigger('navdockout');
 
- 				}
 
- 			}
 
- 		})
 
- 		.on('close', function(e, dfd) {
 
- 			var win     = self.window,
 
- 				preview = self.preview.trigger('change'),
 
- 				file    = self.value,
 
- 				hash    = (win.data('hash') || '').split('/', 2)[0],
 
- 				close   = function(status, winhide) {
 
- 					state = status;
 
- 					winhide && fm.toHide(win);
 
- 					preview.children().remove();
 
- 					self.update(0, self.value);
 
- 					win.data('hash', '');
 
- 					dfd && dfd.resolve();
 
- 				},
 
- 				node;
 
- 				
 
- 			if (self.opened()) {
 
- 				getSize && getSize.state() === 'pending' && getSize.reject();
 
- 				if (! self.docked()) {
 
- 					state = animated;
 
- 					win.hasClass(fullscreen) && fsicon.click();
 
- 					(hash && (node = cwd.find('#'+hash)).length)
 
- 						? win.animate(closedCss(node), 500, function() { close(closed, true); })
 
- 						: close(closed, true);
 
- 				} else {
 
- 					dockedNode = fm.getUI('navdock').data('removeNode')(self.window.attr('id'), 'detach');
 
- 					close(dockedhidden);
 
- 					fm.storage('previewDocked', '2');
 
- 				}
 
- 			}
 
- 		})
 
- 		.on('navdockin', function(e, data) {
 
- 			var w      = self.window,
 
- 				box    = fm.getUI('navdock'),
 
- 				height = dockHeight || box.width(),
 
- 				opts   = data || {};
 
- 			
 
- 			if (init) {
 
- 				opts.init = true;
 
- 			}
 
- 			state = docked;
 
- 			prevStyle = w.attr('style');
 
- 			w.toggleClass('ui-front').removeClass('ui-widget').draggable('disable').resizable('disable').removeAttr('style').css({
 
- 				width: '100%',
 
- 				height: height,
 
- 				boxSizing: 'border-box',
 
- 				paddingBottom: 0,
 
- 				zIndex: 'unset'
 
- 			});
 
- 			navbar.hide();
 
- 			titleDock.toggleClass('ui-icon-plusthick ui-icon-minusthick elfinder-icon-full elfinder-icon-minimize');
 
- 			
 
- 			fm.toHide(w, true);
 
- 			box.data('addNode')(w, opts);
 
- 			
 
- 			self.preview.trigger('changesize');
 
- 			
 
- 			fm.storage('previewDocked', '1');
 
- 		})
 
- 		.on('navdockout', function(e) {
 
- 			var w   = self.window,
 
- 				box = fm.getUI('navdock'),
 
- 				dfd = $.Deferred(),
 
- 				clcss = closedCss(self.preview);
 
- 			
 
- 			dockHeight = w.outerHeight();
 
- 			box.data('removeNode')(w.attr('id'), fm.getUI());
 
- 			w.toggleClass('ui-front').addClass('ui-widget').draggable('enable').resizable('enable').attr('style', prevStyle);
 
- 			titleDock.toggleClass('ui-icon-plusthick ui-icon-minusthick elfinder-icon-full elfinder-icon-minimize');
 
- 			
 
- 			state = closed;
 
- 			w.trigger('open', clcss);
 
- 			
 
- 			fm.storage('previewDocked', '0');
 
- 		})
 
- 		.on('resize.' + fm.namespace, function() {
 
- 			self.preview.trigger('changesize'); 
 
- 		});
 
- 	/**
 
- 	 * This command cannot be disable by backend
 
- 	 *
 
- 	 * @type Boolean
 
- 	 **/
 
- 	this.alwaysEnabled = true;
 
- 	
 
- 	/**
 
- 	 * Selected file
 
- 	 *
 
- 	 * @type Object
 
- 	 **/
 
- 	this.value = null;
 
- 	
 
- 	this.handlers = {
 
- 		// save selected file
 
- 		select : function(e, d) {
 
- 			selectTm && cancelAnimationFrame(selectTm);
 
- 			if (! e.data || ! e.data.selected || ! e.data.selected.length) {
 
- 				selectTm = requestAnimationFrame(function() {
 
- 					self.opened() && updateOnSel();
 
- 				});
 
- 			} else {
 
- 				self.opened() && updateOnSel();
 
- 			}
 
- 		},
 
- 		error  : function() { self.window.is(':visible') && self.window.trigger('close'); },
 
- 		'searchshow searchhide' : function() { this.opened() && this.window.trigger('close'); },
 
- 		navbarshow : function() {
 
- 			requestAnimationFrame(function() {
 
- 				self.docked() && self.preview.trigger('changesize');
 
- 			});
 
- 		},
 
- 		destroy : function() { self.window.remove(); }
 
- 	};
 
- 	
 
- 	this.shortcuts = [{
 
- 		pattern     : 'space'
 
- 	}];
 
- 	
 
- 	this.support = {
 
- 		audio : {
 
- 			ogg : support('audio/ogg;'),
 
- 			webm: support('audio/webm;'),
 
- 			mp3 : support('audio/mpeg;'),
 
- 			wav : support('audio/wav;'),
 
- 			m4a : support('audio/mp4;') || support('audio/x-m4a;') || support('audio/aac;'),
 
- 			flac: support('audio/flac;'),
 
- 			amr : support('audio/amr;')
 
- 		},
 
- 		video : {
 
- 			ogg  : support('video/ogg;'),
 
- 			webm : support('video/webm;'),
 
- 			mp4  : support('video/mp4;'),
 
- 			mkv  : support('video/x-matroska;') || support('video/webm;'),
 
- 			'3gp': support('video/3gpp;') || support('video/mp4;'), // try as mp4
 
- 			m3u8 : support('application/x-mpegURL', 'video') || support('application/vnd.apple.mpegURL', 'video'),
 
- 			mpd  : support('application/dash+xml', 'video')
 
- 		}
 
- 	};
 
- 	// for GC
 
- 	mediaNode = {};
 
- 	
 
- 	/**
 
- 	 * Return true if quickLoock window is hiddenReturn true if quickLoock window is visible and not animated
 
- 	 *
 
- 	 * @return Boolean
 
- 	 **/
 
- 	this.closed = function() {
 
- 		return (state == closed || state == dockedhidden);
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return true if quickLoock window is visible and not animated
 
- 	 *
 
- 	 * @return Boolean
 
- 	 **/
 
- 	this.opened = function() {
 
- 		return state == opened || state == docked;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Return true if quickLoock window is in NavDock
 
- 	 *
 
- 	 * @return Boolean
 
- 	 **/
 
- 	this.docked = function() {
 
- 		return state == docked;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Adds an integration into help dialog.
 
- 	 *
 
- 	 * @param Object opts  options
 
- 	 */
 
- 	this.addIntegration = function(opts) {
 
- 		requestAnimationFrame(function() {
 
- 			fm.trigger('helpIntegration', Object.assign({cmd: 'quicklook'}, opts));
 
- 		});
 
- 	};
 
- 	/**
 
- 	 * Init command.
 
- 	 * Add default plugins and init other plugins
 
- 	 *
 
- 	 * @return Object
 
- 	 **/
 
- 	this.init = function() {
 
- 		var o       = this.options, 
 
- 			win     = this.window,
 
- 			preview = this.preview,
 
- 			i, p, cwdDispInlineRegex;
 
- 		
 
- 		width  = o.width  > 0 ? parseInt(o.width)  : 450;	
 
- 		height = o.height > 0 ? parseInt(o.height) : 300;
 
- 		if (o.dockHeight !== 'auto') {
 
- 			dockHeight = parseInt(o.dockHeight);
 
- 			if (! dockHeight) {
 
- 				dockHeight = void(0);
 
- 			}
 
- 		}
 
- 		fm.one('load', function() {
 
- 			
 
- 			dockEnabled = fm.getUI('navdock').data('dockEnabled');
 
- 			
 
- 			! dockEnabled && titleDock.hide();
 
- 			
 
- 			parent = fm.getUI();
 
- 			cwd    = fm.getUI('cwd');
 
- 			if (fm.zIndex) {
 
- 				win.css('z-index', fm.zIndex + 1);
 
- 			}
 
- 			
 
- 			win.appendTo(parent);
 
- 			
 
- 			// close window on escape
 
- 			$(document).on('keydown.'+fm.namespace, function(e) {
 
- 				e.keyCode == $.ui.keyCode.ESCAPE && self.opened() && ! self.docked() && win.hasClass('elfinder-frontmost') && win.trigger('close');
 
- 			});
 
- 			
 
- 			win.resizable({ 
 
- 				handles   : 'se', 
 
- 				minWidth  : 350, 
 
- 				minHeight : 120, 
 
- 				resize    : function() { 
 
- 					// use another event to avoid recursion in fullscreen mode
 
- 					// may be there is clever solution, but i cant find it :(
 
- 					preview.trigger('changesize'); 
 
- 				}
 
- 			});
 
- 			
 
- 			self.change(function() {
 
- 				if (self.opened()) {
 
- 					if (self.value) {
 
- 						if (self.value.tmb && self.value.tmb == 1) {
 
- 							// try re-get file object
 
- 							self.value = Object.assign({}, fm.file(self.value.hash));
 
- 						}
 
- 						preview.trigger($.Event(evUpdate, {file : self.value}));
 
- 					}
 
- 				}
 
- 			});
 
- 			
 
- 			preview.on(evUpdate, function(e) {
 
- 				var file, hash, serach;
 
- 				
 
- 				if (file = e.file) {
 
- 					hash = file.hash;
 
- 					serach = (fm.searchStatus.mixed && fm.searchStatus.state > 1);
 
- 				
 
- 					if (file.mime !== 'directory') {
 
- 						if (parseInt(file.size) || file.mime.match(o.mimeRegexNotEmptyCheck)) {
 
- 							// set current dispInlineRegex
 
- 							self.dispInlineRegex = cwdDispInlineRegex;
 
- 							if (serach || fm.optionsByHashes[hash]) {
 
- 								try {
 
- 									self.dispInlineRegex = new RegExp(fm.option('dispInlineRegex', hash), 'i');
 
- 								} catch(e) {
 
- 									try {
 
- 										self.dispInlineRegex = new RegExp(!fm.isRoot(file)? fm.option('dispInlineRegex', file.phash) : fm.options.dispInlineRegex, 'i');
 
- 									} catch(e) {
 
- 										self.dispInlineRegex = /^$/;
 
- 									}
 
- 								}
 
- 							}
 
- 						} else {
 
- 							//  do not preview of file that size = 0
 
- 							e.stopImmediatePropagation();
 
- 						}
 
- 					} else {
 
- 						self.dispInlineRegex = /^$/;
 
- 					}
 
- 					
 
- 					self.info.show();
 
- 				} else {
 
- 					e.stopImmediatePropagation();
 
- 				}
 
- 			});
 
- 			$.each(fm.commands.quicklook.plugins || [], function(i, plugin) {
 
- 				if (typeof(plugin) == 'function') {
 
- 					new plugin(self);
 
- 				}
 
- 			});
 
- 		}).one('open', function() {
 
- 			var dock = Number(fm.storage('previewDocked') || o.docked),
 
- 				win;
 
- 			if (dockEnabled && dock >= 1) {
 
- 				win = self.window;
 
- 				self.exec();
 
- 				win.trigger('navdockin', { init : true });
 
- 				if (dock === 2) {
 
- 					win.trigger('close');
 
- 				} else {
 
- 					self.update(void(0), fm.cwd());
 
- 					self.change();
 
- 				}
 
- 			}
 
- 			init = false;
 
- 		}).bind('open', function() {
 
- 			cwdHash = fm.cwd().hash;
 
- 			self.value = fm.cwd();
 
- 			// set current volume dispInlineRegex
 
- 			try {
 
- 				cwdDispInlineRegex = new RegExp(fm.option('dispInlineRegex'), 'i');
 
- 			} catch(e) {
 
- 				cwdDispInlineRegex = /^$/;
 
- 			}
 
- 		}).bind('change', function(e) {
 
- 			if (e.data && e.data.changed && self.opened()) {
 
- 				$.each(e.data.changed, function() {
 
- 					if (self.window.data('hash') === this.hash) {
 
- 						self.window.data('hash', null);
 
- 						self.preview.trigger(evUpdate);
 
- 						return false;
 
- 					}
 
- 				});
 
- 			}
 
- 		}).bind('navdockresizestart navdockresizestop', function(e) {
 
- 			cover[e.type === 'navdockresizestart'? 'show' : 'hide']();
 
- 		});
 
- 	};
 
- 	
 
- 	this.getstate = function() {
 
- 		return self.opened()? 1 : 0;
 
- 	};
 
- 	
 
- 	this.exec = function() {
 
- 		self.closed() && updateOnSel();
 
- 		self.enabled() && self.window.trigger(self.opened() ? 'close' : 'open');
 
- 		return $.Deferred().resolve();
 
- 	};
 
- 	this.hideinfo = function() {
 
- 		this.info.stop(true, true).hide();
 
- 	};
 
- }).prototype = { forceLoad : true }; // this is required command
 
- /*
 
-  * File: /js/commands/quicklook.plugins.js
 
-  */
 
- elFinder.prototype.commands.quicklook.plugins = [
 
- 	
 
- 	/**
 
- 	 * Images preview plugin
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 **/
 
- 	function(ql) {
 
- 				var mimes   = ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/x-ms-bmp'],
 
- 			preview = ql.preview,
 
- 			WebP, flipMime;
 
- 		
 
- 		// webp support
 
- 		WebP = new Image();
 
- 		WebP.onload = WebP.onerror = function() {
 
- 			if (WebP.height == 2) {
 
- 				mimes.push('image/webp');
 
- 			}
 
- 		};
 
- 		WebP.src='data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
 
- 		
 
- 		// what kind of images we can display
 
- 		$.each(navigator.mimeTypes, function(i, o) {
 
- 			var mime = o.type;
 
- 			
 
- 			if (mime.indexOf('image/') === 0 && $.inArray(mime, mimes)) {
 
- 				mimes.push(mime);
 
- 			} 
 
- 		});
 
- 			
 
- 		preview.on(ql.evUpdate, function(e) {
 
- 			var fm   = ql.fm,
 
- 				file = e.file,
 
- 				showed = false,
 
- 				dimreq = null,
 
- 				setdim  = function(dim) {
 
- 					var rfile = fm.file(file.hash);
 
- 					rfile.width = dim[0];
 
- 					rfile.height = dim[1];
 
- 				},
 
- 				show = function() {
 
- 					var elm, varelm, memSize, width, height, prop;
 
- 					
 
- 					dimreq && dimreq.state && dimreq.state() === 'pending' && dimreq.reject();
 
- 					if (showed) {
 
- 						return;
 
- 					}
 
- 					showed = true;
 
- 					
 
- 					elm = img.get(0);
 
- 					memSize = file.width && file.height? {w: file.width, h: file.height} : (elm.naturalWidth? null : {w: img.width(), h: img.height()});
 
- 				
 
- 					memSize && img.removeAttr('width').removeAttr('height');
 
- 					
 
- 					width  = file.width || elm.naturalWidth || elm.width || img.width();
 
- 					height = file.height || elm.naturalHeight || elm.height || img.height();
 
- 					if (!file.width || !file.height) {
 
- 						setdim([width, height]);
 
- 					}
 
- 					
 
- 					memSize && img.width(memSize.w).height(memSize.h);
 
- 					prop = (width/height).toFixed(2);
 
- 					preview.on('changesize', function() {
 
- 						var pw = parseInt(preview.width()),
 
- 							ph = parseInt(preview.height()),
 
- 							w, h;
 
- 					
 
- 						if (prop < (pw/ph).toFixed(2)) {
 
- 							h = ph;
 
- 							w = Math.floor(h * prop);
 
- 						} else {
 
- 							w = pw;
 
- 							h = Math.floor(w/prop);
 
- 						}
 
- 						img.width(w).height(h).css('margin-top', h < ph ? Math.floor((ph - h)/2) : 0);
 
- 					
 
- 					})
 
- 					.trigger('changesize');
 
- 					
 
- 					//show image
 
- 					img.fadeIn(100);
 
- 				},
 
- 				hideInfo = function() {
 
- 					loading.remove();
 
- 					// hide info/icon
 
- 					ql.hideinfo();
 
- 				},
 
- 				url, img, loading, m;
 
- 			if (!flipMime) {
 
- 				flipMime = fm.arrayFlip(mimes);
 
- 			}
 
- 			if (flipMime[file.mime] && ql.dispInlineRegex.test(file.mime)) {
 
- 				// this is our file - stop event propagation
 
- 				e.stopImmediatePropagation();
 
- 				loading = $('<div class="elfinder-quicklook-info-data"><span class="elfinder-spinner-text">'+fm.i18n('nowLoading')+'</span><span class="elfinder-spinner"/></div>').appendTo(ql.info.find('.elfinder-quicklook-info'));
 
- 				url = fm.openUrl(file.hash);
 
- 				
 
- 				img = $('<img/>')
 
- 					.hide()
 
- 					.appendTo(preview)
 
- 					.on('load', function() {
 
- 						hideInfo();
 
- 						show();
 
- 					})
 
- 					.on('error', function() {
 
- 						loading.remove();
 
- 					})
 
- 					.attr('src', url);
 
- 				
 
- 				if (file.width && file.height) {
 
- 					show();
 
- 				} else if (file.size > (ql.options.getDimThreshold || 0)) {
 
- 					dimreq = fm.request({
 
- 						data : {cmd : 'dim', target : file.hash},
 
- 						preventDefault : true
 
- 					})
 
- 					.done(function(data) {
 
- 						if (data.dim) {
 
- 							var dim = data.dim.split('x');
 
- 							file.width = dim[0];
 
- 							file.height = dim[1];
 
- 							setdim(dim);
 
- 							show();
 
- 						}
 
- 					});
 
- 				}
 
- 			}
 
- 			
 
- 		});
 
- 	},
 
- 	
 
- 	/**
 
- 	 * PSD(Adobe Photoshop data) preview plugin
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 **/
 
- 	function(ql) {
 
- 				var fm      = ql.fm,
 
- 			mimes   = fm.arrayFlip(['image/vnd.adobe.photoshop', 'image/x-photoshop']),
 
- 			preview = ql.preview,
 
- 			load    = function(url, img, loading) {
 
- 				try {
 
- 					fm.replaceXhrSend();
 
- 					PSD.fromURL(url).then(function(psd) {
 
- 						var prop;
 
- 						img.attr('src', psd.image.toBase64());
 
- 						requestAnimationFrame(function() {
 
- 							prop = (img.width()/img.height()).toFixed(2);
 
- 							preview.on('changesize', function() {
 
- 								var pw = parseInt(preview.width()),
 
- 									ph = parseInt(preview.height()),
 
- 									w, h;
 
- 							
 
- 								if (prop < (pw/ph).toFixed(2)) {
 
- 									h = ph;
 
- 									w = Math.floor(h * prop);
 
- 								} else {
 
- 									w = pw;
 
- 									h = Math.floor(w/prop);
 
- 								}
 
- 								img.width(w).height(h).css('margin-top', h < ph ? Math.floor((ph - h)/2) : 0);
 
- 							}).trigger('changesize');
 
- 							
 
- 							loading.remove();
 
- 							// hide info/icon
 
- 							ql.hideinfo();
 
- 							//show image
 
- 							img.fadeIn(100);
 
- 						});
 
- 					}, function() {
 
- 						loading.remove();
 
- 						img.remove();
 
- 					});
 
- 					fm.restoreXhrSend();
 
- 				} catch(e) {
 
- 					fm.restoreXhrSend();
 
- 					loading.remove();
 
- 					img.remove();
 
- 				}
 
- 			},
 
- 			PSD;
 
- 		
 
- 		preview.on(ql.evUpdate, function(e) {
 
- 			var file = e.file,
 
- 				url, img, loading, m,
 
- 				_define, _require;
 
- 			if (mimes[file.mime] && fm.options.cdns.psd && ! fm.UA.ltIE10 && ql.dispInlineRegex.test(file.mime)) {
 
- 				// this is our file - stop event propagation
 
- 				e.stopImmediatePropagation();
 
- 				loading = $('<div class="elfinder-quicklook-info-data"><span class="elfinder-spinner-text">'+fm.i18n('nowLoading')+'</span><span class="elfinder-spinner"/></div>').appendTo(ql.info.find('.elfinder-quicklook-info'));
 
- 				url = fm.openUrl(file.hash);
 
- 				if (!fm.isSameOrigin(url)) {
 
- 					url = fm.openUrl(file.hash, true);
 
- 				}
 
- 				img = $('<img/>').hide().appendTo(preview);
 
- 				
 
- 				if (PSD) {
 
- 					load(url, img, loading);
 
- 				} else {
 
- 					_define = window.define;
 
- 					_require = window.require;
 
- 					window.require = null;
 
- 					window.define = null;
 
- 					fm.loadScript(
 
- 						[ fm.options.cdns.psd ],
 
- 						function() {
 
- 							PSD = require('psd');
 
- 							_define? (window.define = _define) : (delete window.define);
 
- 							_require? (window.require = _require) : (delete window.require);
 
- 							load(url, img, loading);
 
- 						}
 
- 					);
 
- 				}
 
- 			}
 
- 		});
 
- 	},
 
- 	
 
- 	/**
 
- 	 * HTML preview plugin
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 **/
 
- 	function(ql) {
 
- 				var fm      = ql.fm,
 
- 			mimes   = fm.arrayFlip(['text/html', 'application/xhtml+xml']),
 
- 			preview = ql.preview;
 
- 			
 
- 		preview.on(ql.evUpdate, function(e) {
 
- 			var file = e.file, jqxhr, loading;
 
- 			
 
- 			if (mimes[file.mime] && ql.dispInlineRegex.test(file.mime) && (!ql.options.getSizeMax || file.size <= ql.options.getSizeMax)) {
 
- 				e.stopImmediatePropagation();
 
- 				loading = $('<div class="elfinder-quicklook-info-data"><span class="elfinder-spinner-text">'+fm.i18n('nowLoading')+'</span><span class="elfinder-spinner"/></div>').appendTo(ql.info.find('.elfinder-quicklook-info'));
 
- 				// stop loading on change file if not loaded yet
 
- 				preview.one('change', function() {
 
- 					jqxhr.state() == 'pending' && jqxhr.reject();
 
- 				}).addClass('elfinder-overflow-auto');
 
- 				
 
- 				jqxhr = fm.request({
 
- 					data           : {cmd : 'get', target : file.hash, conv : 1, _t : file.ts},
 
- 					options        : {type: 'get', cache : true},
 
- 					preventDefault : true
 
- 				})
 
- 				.done(function(data) {
 
- 					ql.hideinfo();
 
- 					var doc = $('<iframe class="elfinder-quicklook-preview-html"/>').appendTo(preview)[0].contentWindow.document;
 
- 					doc.open();
 
- 					doc.write(data.content);
 
- 					doc.close();
 
- 				})
 
- 				.always(function() {
 
- 					loading.remove();
 
- 				});
 
- 			}
 
- 		});
 
- 	},
 
- 	
 
- 	/**
 
- 	 * MarkDown preview plugin
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 **/
 
- 	function(ql) {
 
- 				var fm      = ql.fm,
 
- 			mimes   = fm.arrayFlip(['text/x-markdown']),
 
- 			preview = ql.preview,
 
- 			marked  = null,
 
- 			show = function(data, loading) {
 
- 				ql.hideinfo();
 
- 				var doc = $('<iframe class="elfinder-quicklook-preview-html"/>').appendTo(preview)[0].contentWindow.document;
 
- 				doc.open();
 
- 				doc.write(marked(data.content));
 
- 				doc.close();
 
- 				loading.remove();
 
- 			},
 
- 			error = function(loading) {
 
- 				marked = false;
 
- 				loading.remove();
 
- 			};
 
- 			
 
- 		preview.on(ql.evUpdate, function(e) {
 
- 			var file = e.file, jqxhr, loading;
 
- 			
 
- 			if (mimes[file.mime] && fm.options.cdns.marked && marked !== false && ql.dispInlineRegex.test(file.mime) && (!ql.options.getSizeMax || file.size <= ql.options.getSizeMax)) {
 
- 				e.stopImmediatePropagation();
 
- 				loading = $('<div class="elfinder-quicklook-info-data"><span class="elfinder-spinner-text">'+fm.i18n('nowLoading')+'</span><span class="elfinder-spinner"/></div>').appendTo(ql.info.find('.elfinder-quicklook-info'));
 
- 				// stop loading on change file if not loaded yet
 
- 				preview.one('change', function() {
 
- 					jqxhr.state() == 'pending' && jqxhr.reject();
 
- 				}).addClass('elfinder-overflow-auto');
 
- 				
 
- 				jqxhr = fm.request({
 
- 					data           : {cmd : 'get', target : file.hash, conv : 1, _t : file.ts},
 
- 					options        : {type: 'get', cache : true},
 
- 					preventDefault : true
 
- 				})
 
- 				.done(function(data) {
 
- 					if (marked || window.marked) {
 
- 						if (!marked) {
 
- 							marked = window.marked;
 
- 						}
 
- 						show(data, loading);
 
- 					} else {
 
- 						fm.loadScript([fm.options.cdns.marked],
 
- 							function(res) { 
 
- 								marked = res || window.marked || false;
 
- 								delete window.marked;
 
- 								if (marked) {
 
- 									show(data, loading);
 
- 								} else {
 
- 									error(loading);
 
- 								}
 
- 							},
 
- 							{
 
- 								tryRequire: true,
 
- 								error: function() {
 
- 									error(loading);
 
- 								}
 
- 							}
 
- 						);
 
- 					}
 
- 				})
 
- 				.fail(function() {
 
- 					error(loading);
 
- 				});
 
- 			}
 
- 		});
 
- 	},
 
- 	/**
 
- 	 * PDF/ODT/ODS/ODP preview with ViewerJS
 
- 	 * 
 
- 	 * @param elFinder.commands.quicklook
 
- 	 */
 
- 	 function(ql) {
 
- 		if (ql.options.viewerjs) {
 
- 			var fm      = ql.fm,
 
- 				preview = ql.preview,
 
- 				opts    = ql.options.viewerjs,
 
- 				mimes   = opts.url? fm.arrayFlip(opts.mimes || []) : [];
 
- 			if (opts.url) {
 
- 				preview.on('update', function(e) {
 
- 					var win  = ql.window,
 
- 						file = e.file, node, loading;
 
- 					if (mimes[file.mime]) {
 
- 						var url = fm.openUrl(file.hash);
 
- 						if (url && fm.isSameOrigin(url)) {
 
- 							e.stopImmediatePropagation();
 
- 							loading = $('<div class="elfinder-quicklook-info-data"><span class="elfinder-spinner-text">'+fm.i18n('nowLoading')+'</span><span class="elfinder-spinner"/></div>').appendTo(ql.info.find('.elfinder-quicklook-info'));
 
- 							node = $('<iframe class="elfinder-quicklook-preview-iframe"/>')
 
- 								.css('background-color', 'transparent')
 
- 								.on('load', function() {
 
- 									ql.hideinfo();
 
- 									loading.remove();
 
- 									node.css('background-color', '#fff');
 
- 								})
 
- 								.on('error', function() {
 
- 									loading.remove();
 
- 									node.remove();
 
- 								})
 
- 								.appendTo(preview)
 
- 								.attr('src', opts.url + '#' + url);
 
- 							preview.one('change', function() {
 
- 								loading.remove();
 
- 								node.off('load').remove();
 
- 							});
 
- 						}
 
- 					}
 
- 				});
 
- 			}
 
- 		}
 
- 	},
 
- 	/**
 
- 	 * PDF preview plugin
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 **/
 
- 	function(ql) {
 
- 				var fm      = ql.fm,
 
- 			mime    = 'application/pdf',
 
- 			preview = ql.preview,
 
- 			active  = false,
 
- 			urlhash = '',
 
- 			firefox, toolbar;
 
- 			
 
- 		if ((fm.UA.Safari && fm.OS === 'mac' && !fm.UA.iOS) || fm.UA.IE || fm.UA.Firefox) {
 
- 			active = true;
 
- 		} else {
 
- 			$.each(navigator.plugins, function(i, plugins) {
 
- 				$.each(plugins, function(i, plugin) {
 
- 					if (plugin.type === mime) {
 
- 						return !(active = true);
 
- 					}
 
- 				});
 
- 			});
 
- 		}
 
- 		if (active) {
 
- 			if (typeof ql.options.pdfToolbar !== 'undefined' && !ql.options.pdfToolbar) {
 
- 				urlhash = '#toolbar=0';
 
- 			}
 
- 			preview.on(ql.evUpdate, function(e) {
 
- 				var file = e.file;
 
- 				
 
- 				if (active && file.mime === mime && ql.dispInlineRegex.test(file.mime)) {
 
- 					e.stopImmediatePropagation();
 
- 					ql.hideinfo();
 
- 					ql.cover.addClass('elfinder-quicklook-coverbg');
 
- 					$('<object class="elfinder-quicklook-preview-pdf" data="'+fm.openUrl(file.hash)+urlhash+'" type="application/pdf" />')
 
- 						.on('error', function(e) {
 
- 							active = false;
 
- 							ql.update(void(0), fm.cwd());
 
- 							ql.update(void(0), file);
 
- 						})
 
- 						.appendTo(preview);
 
- 				}
 
- 				
 
- 			});
 
- 		}
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Flash preview plugin
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 **/
 
- 	function(ql) {
 
- 				var fm      = ql.fm,
 
- 			mime    = 'application/x-shockwave-flash',
 
- 			preview = ql.preview,
 
- 			active  = false;
 
- 		$.each(navigator.plugins, function(i, plugins) {
 
- 			$.each(plugins, function(i, plugin) {
 
- 				if (plugin.type === mime) {
 
- 					return !(active = true);
 
- 				}
 
- 			});
 
- 		});
 
- 		
 
- 		active && preview.on(ql.evUpdate, function(e) {
 
- 			var file = e.file,
 
- 				node;
 
- 				
 
- 			if (file.mime === mime && ql.dispInlineRegex.test(file.mime)) {
 
- 				e.stopImmediatePropagation();
 
- 				ql.hideinfo();
 
- 				node = $('<embed class="elfinder-quicklook-preview-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" src="'+fm.openUrl(file.hash)+'" quality="high" type="application/x-shockwave-flash" wmode="transparent" />')
 
- 					.appendTo(preview);
 
- 			}
 
- 		});
 
- 	},
 
- 	
 
- 	/**
 
- 	 * HTML5 audio preview plugin
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 **/
 
- 	function(ql) {
 
- 				var fm       = ql.fm,
 
- 			preview  = ql.preview,
 
- 			mimes    = {
 
- 				'audio/mpeg'    : 'mp3',
 
- 				'audio/mpeg3'   : 'mp3',
 
- 				'audio/mp3'     : 'mp3',
 
- 				'audio/x-mpeg3' : 'mp3',
 
- 				'audio/x-mp3'   : 'mp3',
 
- 				'audio/x-wav'   : 'wav',
 
- 				'audio/wav'     : 'wav',
 
- 				'audio/x-m4a'   : 'm4a',
 
- 				'audio/aac'     : 'm4a',
 
- 				'audio/mp4'     : 'm4a',
 
- 				'audio/x-mp4'   : 'm4a',
 
- 				'audio/ogg'     : 'ogg',
 
- 				'audio/webm'    : 'webm',
 
- 				'audio/flac'    : 'flac',
 
- 				'audio/x-flac'  : 'flac',
 
- 				'audio/amr'     : 'amr'
 
- 			},
 
- 			node, curHash,
 
- 			win  = ql.window,
 
- 			navi = ql.navbar,
 
- 			AMR, autoplay,
 
- 			controlsList = typeof ql.options.mediaControlsList === 'string' && ql.options.mediaControlsList? ' controlsList="' + fm.escape(ql.options.mediaControlsList) + '"' : '',
 
- 			setNavi = function() {
 
- 				navi.css('bottom', win.hasClass('elfinder-quicklook-fullscreen')? '50px' : '');
 
- 			},
 
- 			getNode = function(src, hash) {
 
- 				return $('<audio class="elfinder-quicklook-preview-audio ui-front" controls' + controlsList + ' preload="auto" autobuffer><source src="'+src+'" /></audio>')
 
- 					.on('change', function(e) {
 
- 						// Firefox fire change event on seek or volume change
 
- 						e.stopPropagation();
 
- 					})
 
- 					.on('error', function(e) {
 
- 						node && node.data('hash') === hash && reset();
 
- 					})
 
- 					.data('hash', hash)
 
- 					.appendTo(preview);
 
- 			},
 
- 			amrToWavUrl = function(hash) {
 
- 				var dfd = $.Deferred(),
 
- 					loader = $.Deferred().done(function() {
 
- 						fm.getContents(hash).done(function(data) {
 
- 							try {
 
- 								var buffer = AMR.toWAV(new Uint8Array(data));
 
- 								if (buffer) {
 
- 									dfd.resolve(URL.createObjectURL(new Blob([buffer], { type: 'audio/x-wav' })));
 
- 								} else {
 
- 									dfd.reject();
 
- 								}
 
- 							} catch(e) {
 
- 								dfd.reject();
 
- 							}
 
- 						}).fail(function() {
 
- 							dfd.reject();
 
- 						});
 
- 					}).fail(function() {
 
- 						AMR = false;
 
- 						dfd.reject();
 
- 					}),
 
- 					_AMR;
 
- 				if (window.TextEncoder && window.URL && URL.createObjectURL && typeof AMR === 'undefined') {
 
- 					// previous window.AMR
 
- 					_AMR = window.AMR;
 
- 					delete window.AMR;
 
- 					fm.loadScript(
 
- 						[ fm.options.cdns.amr ],
 
- 						function() { 
 
- 							AMR = window.AMR? window.AMR : false;
 
- 							// restore previous window.AMR
 
- 							window.AMR = _AMR;
 
- 							loader[AMR? 'resolve':'reject']();
 
- 						},
 
- 						{
 
- 							error: function() {
 
- 								loader.reject();
 
- 							}
 
- 						}
 
- 					);
 
- 				} else {
 
- 					loader[AMR? 'resolve':'reject']();
 
- 				}
 
- 				return dfd;
 
- 			},
 
- 			play = function(player) {
 
- 				var hash = node.data('hash'),
 
- 					playPromise;
 
- 				autoplay && (playPromise = player.play());
 
- 				// uses "playPromise['catch']" instead "playPromise.catch" to support Old IE
 
- 				if (playPromise && playPromise['catch']) {
 
- 					playPromise['catch'](function(e) {
 
- 						if (!player.paused) {
 
- 							node && node.data('hash') === hash && reset();
 
- 						}
 
- 					});
 
- 				}
 
- 			},
 
- 			reset = function() {
 
- 				if (node && node.parent().length) {
 
- 					var elm = node[0],
 
- 						url = node.children('source').attr('src');
 
- 					win.off('viewchange.audio');
 
- 					try {
 
- 						elm.pause();
 
- 						node.empty();
 
- 						if (url.match(/^blob:/)) {
 
- 							URL.revokeObjectURL(url);
 
- 						}
 
- 						elm.src = '';
 
- 						elm.load();
 
- 					} catch(e) {}
 
- 					node.remove();
 
- 					node = null;
 
- 				}
 
- 			};
 
- 		preview.on(ql.evUpdate, function(e) {
 
- 			var file = e.file,
 
- 				type = mimes[file.mime],
 
- 				html5, srcUrl;
 
- 			if (mimes[file.mime] && ql.dispInlineRegex.test(file.mime) && ((html5 = ql.support.audio[type]) || (type === 'amr'))) {
 
- 				autoplay = ql.autoPlay();
 
- 				curHash = file.hash;
 
- 				srcUrl = html5? fm.openUrl(curHash) : '';
 
- 				if (!html5) {
 
- 					if (fm.options.cdns.amr && type === 'amr' && AMR !== false) {
 
- 						e.stopImmediatePropagation();
 
- 						node = getNode(srcUrl, curHash);
 
- 						amrToWavUrl(file.hash).done(function(url) {
 
- 							if (curHash === file.hash) {
 
- 								var elm = node[0];
 
- 								try {
 
- 									node.children('source').attr('src', url);
 
- 									elm.pause();
 
- 									elm.load();
 
- 									play(elm);
 
- 									win.on('viewchange.audio', setNavi);
 
- 									setNavi();
 
- 								} catch(e) {
 
- 									URL.revokeObjectURL(url);
 
- 									node.remove();
 
- 								}
 
- 							} else {
 
- 								URL.revokeObjectURL(url);
 
- 							}
 
- 						}).fail(function() {
 
- 							node.remove();
 
- 						});
 
- 					}
 
- 				} else {
 
- 					e.stopImmediatePropagation();
 
- 					node = getNode(srcUrl, curHash);
 
- 					play(node[0]);
 
- 					win.on('viewchange.audio', setNavi);
 
- 					setNavi();
 
- 				}
 
- 			}
 
- 		}).on('change', reset);
 
- 	},
 
- 	
 
- 	/**
 
- 	 * HTML5 video preview plugin
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 **/
 
- 	function(ql) {
 
- 				var fm       = ql.fm,
 
- 			preview  = ql.preview,
 
- 			mimes    = {
 
- 				'video/mp4'       : 'mp4',
 
- 				'video/x-m4v'     : 'mp4',
 
- 				'video/quicktime' : 'mp4',
 
- 				'video/ogg'       : 'ogg',
 
- 				'application/ogg' : 'ogg',
 
- 				'video/webm'      : 'webm',
 
- 				'video/x-matroska': 'mkv',
 
- 				'video/3gpp'      : '3gp',
 
- 				'application/vnd.apple.mpegurl' : 'm3u8',
 
- 				'application/x-mpegurl' : 'm3u8',
 
- 				'application/dash+xml'  : 'mpd',
 
- 				'video/x-flv'     : 'flv'
 
- 			},
 
- 			node,
 
- 			win  = ql.window,
 
- 			navi = ql.navbar,
 
- 			cHls, cDash, pDash, cFlv, autoplay, tm,
 
- 			controlsList = typeof ql.options.mediaControlsList === 'string' && ql.options.mediaControlsList? ' controlsList="' + fm.escape(ql.options.mediaControlsList) + '"' : '',
 
- 			setNavi = function() {
 
- 				if (fm.UA.iOS) {
 
- 					if (win.hasClass('elfinder-quicklook-fullscreen')) {
 
- 						preview.css('height', '-webkit-calc(100% - 50px)');
 
- 						navi._show();
 
- 					} else {
 
- 						preview.css('height', '');
 
- 					}
 
- 				} else {
 
- 					navi.css('bottom', win.hasClass('elfinder-quicklook-fullscreen')? '50px' : '');
 
- 				}
 
- 			},
 
- 			render = function(file, opts) {
 
- 				var errTm = function(e) {
 
- 						if (err > 1) {
 
- 							tm && clearTimeout(tm);
 
- 							tm = setTimeout(function() {
 
- 								!canPlay && reset(true);
 
- 							}, 800);
 
- 						}
 
- 					},
 
- 					err = 0, 
 
- 					canPlay;
 
- 				//reset();
 
- 				pDash = null;
 
- 				opts = opts || {};
 
- 				ql.hideinfo();
 
- 				node = $('<video class="elfinder-quicklook-preview-video" controls' + controlsList + ' preload="auto" autobuffer playsinline>'
 
- 						+'</video>')
 
- 					.on('change', function(e) {
 
- 						// Firefox fire change event on seek or volume change
 
- 						e.stopPropagation();
 
- 					})
 
- 					.on('timeupdate progress', errTm)
 
- 					.on('canplay', function() {
 
- 						canPlay = true;
 
- 					})
 
- 					.data('hash', file.hash);
 
- 				// can not handling error event with jQuery `on` event handler
 
- 				node[0].addEventListener('error', function(e) {
 
- 					if (opts.src && fm.convAbsUrl(opts.src) === fm.convAbsUrl(e.target.src)) {
 
- 						++err;
 
- 						errTm();
 
- 					}
 
- 				}, true);
 
- 				if (opts.src) {
 
- 					node.append('<source src="'+opts.src+'" type="'+file.mime+'"/><source src="'+opts.src+'"/>');
 
- 				}
 
- 				
 
- 				node.appendTo(preview);
 
- 				win.on('viewchange.video', setNavi);
 
- 				setNavi();
 
- 			},
 
- 			loadHls = function(file) {
 
- 				var hls;
 
- 				render(file);
 
- 				hls = new cHls();
 
- 				hls.loadSource(fm.openUrl(file.hash));
 
- 				hls.attachMedia(node[0]);
 
- 				if (autoplay) {
 
- 					hls.on(cHls.Events.MANIFEST_PARSED, function() {
 
- 						play(node[0]);
 
- 					});
 
- 				}
 
- 			},
 
- 			loadDash = function(file) {
 
- 				render(file);
 
- 				pDash = window.dashjs.MediaPlayer().create();
 
- 				pDash.getDebug().setLogToBrowserConsole(false);
 
- 				pDash.initialize(node[0], fm.openUrl(file.hash), autoplay);
 
- 				pDash.on('error', function(e) {
 
- 					reset(true);
 
- 				});
 
- 			},
 
- 			loadFlv = function(file) {
 
- 				if (!cFlv.isSupported()) {
 
- 					cFlv = false;
 
- 					return;
 
- 				}
 
- 				var player = cFlv.createPlayer({
 
- 					type: 'flv',
 
- 					url: fm.openUrl(file.hash)
 
- 				});
 
- 				render(file);
 
- 				player.on(cFlv.Events.ERROR, function() {
 
- 					player.destroy();
 
- 					reset(true);
 
- 				});
 
- 				player.attachMediaElement(node[0]);
 
- 				player.load();
 
- 				play(player);
 
- 			},
 
- 			play = function(player) {
 
- 				var hash = node.data('hash'),
 
- 					playPromise;
 
- 				autoplay && (playPromise = player.play());
 
- 				// uses "playPromise['catch']" instead "playPromise.catch" to support Old IE
 
- 				if (playPromise && playPromise['catch']) {
 
- 					playPromise['catch'](function(e) {
 
- 						if (!player.paused) {
 
- 							node && node.data('hash') === hash && reset(true);
 
- 						}
 
- 					});
 
- 				}
 
- 			},
 
- 			reset = function(showInfo) {
 
- 				tm && clearTimeout(tm);
 
- 				if (node && node.parent().length) {
 
- 					var elm = node[0];
 
- 					win.off('viewchange.video');
 
- 					pDash && pDash.reset();
 
- 					try {
 
- 						elm.pause();
 
- 						node.empty();
 
- 						elm.src = '';
 
- 						elm.load();
 
- 					} catch(e) {}
 
- 					node.remove();
 
- 					node = null;
 
- 				}
 
- 				showInfo && ql.info.show();
 
- 			};
 
- 		preview.on(ql.evUpdate, function(e) {
 
- 			var file = e.file,
 
- 				mime = file.mime.toLowerCase(),
 
- 				type = mimes[mime],
 
- 				stock, playPromise;
 
- 			
 
- 			if (mimes[mime] && ql.dispInlineRegex.test(file.mime) && (((type === 'm3u8' || (type === 'mpd' && !fm.UA.iOS) || type === 'flv') && !fm.UA.ltIE10) || ql.support.video[type])) {
 
- 				autoplay = ql.autoPlay();
 
- 				if (ql.support.video[type] && (type !== 'm3u8' || fm.UA.Safari)) {
 
- 					e.stopImmediatePropagation();
 
- 					render(file, { src: fm.openUrl(file.hash) });
 
- 					play(node[0]);
 
- 				} else {
 
- 					if (cHls !== false && fm.options.cdns.hls && type === 'm3u8') {
 
- 						e.stopImmediatePropagation();
 
- 						if (cHls) {
 
- 							loadHls(file);
 
- 						} else {
 
- 							stock = window.Hls;
 
- 							delete window.Hls;
 
- 							fm.loadScript(
 
- 								[ fm.options.cdns.hls ],
 
- 								function(res) { 
 
- 									cHls = res || window.Hls || false;
 
- 									window.Hls = stock;
 
- 									cHls && loadHls(file);
 
- 								},
 
- 								{
 
- 									tryRequire: true,
 
- 									error : function() {
 
- 										cHls = false;
 
- 									}
 
- 								}
 
- 							);
 
- 						}
 
- 					} else if (cDash !== false && fm.options.cdns.dash && type === 'mpd') {
 
- 						e.stopImmediatePropagation();
 
- 						if (cDash) {
 
- 							loadDash(file);
 
- 						} else {
 
- 							fm.loadScript(
 
- 								[ fm.options.cdns.dash ],
 
- 								function() {
 
- 									// dashjs require window.dashjs in global scope
 
- 									cDash = window.dashjs? true : false;
 
- 									cDash && loadDash(file);
 
- 								},
 
- 								{
 
- 									tryRequire: true,
 
- 									error : function() {
 
- 										cDash = false;
 
- 									}
 
- 								}
 
- 							);
 
- 						}
 
- 					} else if (cFlv !== false && fm.options.cdns.flv && type === 'flv') {
 
- 						e.stopImmediatePropagation();
 
- 						if (cFlv) {
 
- 							loadFlv(file);
 
- 						} else {
 
- 							stock = window.flvjs;
 
- 							delete window.flvjs;
 
- 							fm.loadScript(
 
- 								[ fm.options.cdns.flv ],
 
- 								function(res) { 
 
- 									cFlv = res || window.flvjs || false;
 
- 									window.flvjs = stock;
 
- 									cFlv && loadFlv(file);
 
- 								},
 
- 								{
 
- 									tryRequire: true,
 
- 									error : function() {
 
- 										cFlv = false;
 
- 									}
 
- 								}
 
- 							);
 
- 						}
 
- 					}
 
- 				}
 
- 			}
 
- 		}).on('change', reset);
 
- 	},
 
- 	
 
- 	/**
 
- 	 * Audio/video preview plugin using browser plugins
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 **/
 
- 	function(ql) {
 
- 				var preview = ql.preview,
 
- 			mimes   = [],
 
- 			node,
 
- 			win  = ql.window,
 
- 			navi = ql.navbar;
 
- 			
 
- 		$.each(navigator.plugins, function(i, plugins) {
 
- 			$.each(plugins, function(i, plugin) {
 
- 				(plugin.type.indexOf('audio/') === 0 || plugin.type.indexOf('video/') === 0) && mimes.push(plugin.type);
 
- 			});
 
- 		});
 
- 		mimes = ql.fm.arrayFlip(mimes);
 
- 		
 
- 		preview.on(ql.evUpdate, function(e) {
 
- 			var file  = e.file,
 
- 				mime  = file.mime,
 
- 				video,
 
- 				setNavi = function() {
 
- 					navi.css('bottom', win.hasClass('elfinder-quicklook-fullscreen')? '50px' : '');
 
- 				};
 
- 			
 
- 			if (mimes[file.mime] && ql.dispInlineRegex.test(file.mime)) {
 
- 				e.stopImmediatePropagation();
 
- 				(video = mime.indexOf('video/') === 0) && ql.hideinfo();
 
- 				node = $('<embed src="'+ql.fm.openUrl(file.hash)+'" type="'+mime+'" class="elfinder-quicklook-preview-'+(video ? 'video' : 'audio')+'"/>')
 
- 					.appendTo(preview);
 
- 				
 
- 				win.on('viewchange.embed', setNavi);
 
- 				setNavi();
 
- 			}
 
- 		}).on('change', function() {
 
- 			if (node && node.parent().length) {
 
- 				win.off('viewchange.embed');
 
- 				node.remove();
 
- 				node= null;
 
- 			}
 
- 		});
 
- 		
 
- 	},
 
- 	/**
 
- 	 * Archive(zip|gzip|tar) preview plugin using https://github.com/imaya/zlib.js
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 **/
 
- 	function(ql) {
 
- 				var fm      = ql.fm,
 
- 			mimes   = fm.arrayFlip(['application/zip', 'application/x-gzip', 'application/x-tar']),
 
- 			preview = ql.preview,
 
- 			unzipFiles = function() {
 
- 				/** @type {Array.<string>} */
 
- 				var filenameList = [];
 
- 				/** @type {number} */
 
- 				var i;
 
- 				/** @type {number} */
 
- 				var il;
 
- 				/** @type {Array.<Zlib.Unzip.FileHeader>} */
 
- 				var fileHeaderList;
 
- 				// need check this.Y when update cdns.zlibUnzip
 
- 				this.Y();
 
- 				fileHeaderList = this.i;
 
- 				for (i = 0, il = fileHeaderList.length; i < il; ++i) {
 
- 					// need check fileHeaderList[i].J when update cdns.zlibUnzip
 
- 					filenameList[i] = fileHeaderList[i].filename + (fileHeaderList[i].J? ' (' + fm.formatSize(fileHeaderList[i].J) + ')' : '');
 
- 				}
 
- 				return filenameList;
 
- 			},
 
- 			tarFiles = function(tar) {
 
- 				var filenames = [],
 
- 					tarlen = tar.length,
 
- 					offset = 0,
 
- 					toStr = function(arr) {
 
- 						return String.fromCharCode.apply(null, arr).replace(/\0+$/, '');
 
- 					},
 
- 					h, name, prefix, size, dbs;
 
- 				while (offset < tarlen && tar[offset] !== 0) {
 
- 					h = tar.subarray(offset, offset + 512);
 
- 					name = toStr(h.subarray(0, 100));
 
- 					if (prefix = toStr(h.subarray(345, 500))) {
 
- 						name = prefix + name;
 
- 					}
 
- 					size = parseInt(toStr(h.subarray(124, 136)), 8);
 
- 					dbs = Math.ceil(size / 512) * 512;
 
- 					if (name === '././@LongLink') {
 
- 						name = toStr(tar.subarray(offset + 512, offset + 512 + dbs));
 
- 					}
 
- 					(name !== 'pax_global_header') && filenames.push(name + (size? ' (' + fm.formatSize(size) + ')': ''));
 
- 					offset = offset + 512 + dbs;
 
- 				}
 
- 				return filenames;
 
- 			},
 
- 			Zlib;
 
- 		if (window.Uint8Array && window.DataView && fm.options.cdns.zlibUnzip && fm.options.cdns.zlibGunzip) {
 
- 			preview.on(ql.evUpdate, function(e) {
 
- 				var file  = e.file,
 
- 					isTar = (file.mime === 'application/x-tar');
 
- 				if (mimes[file.mime] && (
 
- 						isTar
 
- 						|| ((typeof Zlib === 'undefined' || Zlib) && (file.mime === 'application/zip' || file.mime === 'application/x-gzip'))
 
- 					)) {
 
- 					var jqxhr, loading, url,
 
- 						req = function() {
 
- 							url = fm.openUrl(file.hash);
 
- 							if (!fm.isSameOrigin(url)) {
 
- 								url = fm.openUrl(file.hash, true);
 
- 							}
 
- 							jqxhr = fm.request({
 
- 								data    : {cmd : 'get'},
 
- 								options : {
 
- 									url: url,
 
- 									type: 'get',
 
- 									cache : true,
 
- 									dataType : 'binary',
 
- 									responseType :'arraybuffer',
 
- 									processData: false
 
- 								}
 
- 							})
 
- 							.fail(function() {
 
- 								loading.remove();
 
- 							})
 
- 							.done(function(data) {
 
- 								var unzip, filenames;
 
- 								try {
 
- 									if (file.mime === 'application/zip') {
 
- 										unzip = new Zlib.Unzip(new Uint8Array(data));
 
- 										//filenames = unzip.getFilenames();
 
- 										filenames = unzipFiles.call(unzip);
 
- 									} else if (file.mime === 'application/x-gzip') {
 
- 										unzip = new Zlib.Gunzip(new Uint8Array(data));
 
- 										filenames = tarFiles(unzip.decompress());
 
- 									} else if (file.mime === 'application/x-tar') {
 
- 										filenames = tarFiles(new Uint8Array(data));
 
- 									}
 
- 									makeList(filenames);
 
- 								} catch (e) {
 
- 									loading.remove();
 
- 									fm.debug('error', e);
 
- 								}
 
- 							});
 
- 						},
 
- 						makeList = function(filenames) {
 
- 							var header, doc;
 
- 							if (filenames && filenames.length) {
 
- 								filenames = $.map(filenames, function(str) {
 
- 									return fm.decodeRawString(str);
 
- 								});
 
- 								filenames.sort();
 
- 								loading.remove();
 
- 								header = '<strong>'+fm.escape(file.mime)+'</strong> ('+fm.formatSize(file.size)+')'+'<hr/>';
 
- 								doc = $('<div class="elfinder-quicklook-preview-archive-wrapper">'+header+'<pre class="elfinder-quicklook-preview-text">'+fm.escape(filenames.join("\n"))+'</pre></div>')
 
- 									.on('touchstart', function(e) {
 
- 										if ($(this)['scroll' + (fm.direction === 'ltr'? 'Right' : 'Left')]() > 5) {
 
- 											e.originalEvent._preventSwipeX = true;
 
- 										}
 
- 									})
 
- 									.appendTo(preview);
 
- 								ql.hideinfo();
 
- 							}
 
- 						},
 
- 						_Zlib;
 
- 					// this is our file - stop event propagation
 
- 					e.stopImmediatePropagation();
 
- 					
 
- 					loading = $('<div class="elfinder-quicklook-info-data"><span class="elfinder-spinner-text">'+fm.i18n('nowLoading')+'</span><span class="elfinder-spinner"/></div>').appendTo(ql.info.find('.elfinder-quicklook-info'));
 
- 					
 
- 					// stop loading on change file if not loaded yet
 
- 					preview.one('change', function() {
 
- 						jqxhr.state() === 'pending' && jqxhr.reject();
 
- 						loading.remove();
 
- 					});
 
- 					
 
- 					if (Zlib) {
 
- 						req();
 
- 					} else {
 
- 						if (window.Zlib) {
 
- 							_Zlib = window.Zlib;
 
- 							delete window.Zlib;
 
- 						}
 
- 						fm.loadScript(
 
- 							[ fm.options.cdns.zlibUnzip, fm.options.cdns.zlibGunzip ],
 
- 							function() {
 
- 								if (window.Zlib && (Zlib = window.Zlib)) {
 
- 									if (_Zlib) {
 
- 										window.Zlib = _Zlib;
 
- 									} else {
 
- 										delete window.Zlib;
 
- 									}
 
- 									req();
 
- 								} else {
 
- 									error();
 
- 								}
 
- 							}
 
- 						);
 
- 					}
 
- 				}
 
- 			});
 
- 		}
 
- 	},
 
- 	/**
 
- 	 * RAR Archive preview plugin using https://github.com/43081j/rar.js
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 **/
 
- 	function(ql) {
 
- 				var fm      = ql.fm,
 
- 			mimes   = fm.arrayFlip(['application/x-rar']),
 
- 			preview = ql.preview,
 
- 			RAR;
 
- 		if (window.DataView) {
 
- 			preview.on(ql.evUpdate, function(e) {
 
- 				var file = e.file;
 
- 				if (mimes[file.mime] && fm.options.cdns.rar && RAR !== false) {
 
- 					var loading, url, archive, abort,
 
- 						getList = function(url) {
 
- 							if (abort) {
 
- 								loading.remove();
 
- 								return;
 
- 							}
 
- 							try {
 
- 								archive = RAR({
 
- 									file: url,
 
- 									type: 2,
 
- 									xhrHeaders: fm.customHeaders,
 
- 									xhrFields: fm.xhrFields
 
- 								}, function(err) {
 
- 									loading.remove();
 
- 									var filenames = [],
 
- 										header, doc;
 
- 									if (abort || err) {
 
- 										// An error occurred (not a rar, read error, etc)
 
- 										err && fm.debug('error', err);
 
- 										return;
 
- 									}
 
- 									$.each(archive.entries, function() {
 
- 										filenames.push(this.path + (this.size? ' (' + fm.formatSize(this.size) + ')' : ''));
 
- 									});
 
- 									if (filenames.length) {
 
- 										filenames = $.map(filenames, function(str) {
 
- 											return fm.decodeRawString(str);
 
- 										});
 
- 										filenames.sort();
 
- 										header = '<strong>'+fm.escape(file.mime)+'</strong> ('+fm.formatSize(file.size)+')'+'<hr/>';
 
- 										doc = $('<div class="elfinder-quicklook-preview-archive-wrapper">'+header+'<pre class="elfinder-quicklook-preview-text">'+fm.escape(filenames.join("\n"))+'</pre></div>')
 
- 											.on('touchstart', function(e) {
 
- 												if ($(this)['scroll' + (fm.direction === 'ltr'? 'Right' : 'Left')]() > 5) {
 
- 													e.originalEvent._preventSwipeX = true;
 
- 												}
 
- 											})
 
- 											.appendTo(preview);
 
- 										ql.hideinfo();
 
- 									}
 
- 								});
 
- 							} catch(e) {
 
- 								loading.remove();
 
- 							}
 
- 						},
 
- 						error = function() {
 
- 							RAR = false;
 
- 							loading.remove();
 
- 						},
 
- 						_RAR;
 
- 					// this is our file - stop event propagation
 
- 					e.stopImmediatePropagation();
 
- 					
 
- 					loading = $('<div class="elfinder-quicklook-info-data"><span class="elfinder-spinner-text">'+fm.i18n('nowLoading')+'</span><span class="elfinder-spinner"/></div>').appendTo(ql.info.find('.elfinder-quicklook-info'));
 
- 					
 
- 					// stop loading on change file if not loaded yet
 
- 					preview.one('change', function() {
 
- 						archive && (archive.abort = true);
 
- 						loading.remove();
 
- 						abort = true;
 
- 					});
 
- 					
 
- 					url = fm.openUrl(file.hash);
 
- 					if (!fm.isSameOrigin(url)) {
 
- 						url = fm.openUrl(file.hash, true);
 
- 					}
 
- 					if (RAR) {
 
- 						getList(url);
 
- 					} else {
 
- 						if (window.RarArchive) {
 
- 							_RAR = window.RarArchive;
 
- 							delete window.RarArchive;
 
- 						}
 
- 						fm.loadScript(
 
- 							[ fm.options.cdns.rar ],
 
- 							function() {
 
- 								if (fm.hasRequire) {
 
- 									require(['rar'], function(RarArchive) {
 
- 										RAR = RarArchive;
 
- 										getList(url);
 
- 									}, error);
 
- 								} else {
 
- 									if (RAR = window.RarArchive) {
 
- 										if (_RAR) {
 
- 											window.RarArchive = _RAR;
 
- 										} else {
 
- 											delete window.RarArchive;
 
- 										}
 
- 										getList(url);
 
- 									} else {
 
- 										error();
 
- 									}
 
- 								}
 
- 							},
 
- 							{
 
- 								tryRequire: true,
 
- 								error : error
 
- 							}
 
- 						);
 
- 					}
 
- 				}
 
- 			});
 
- 		}
 
- 	},
 
- 	/**
 
- 	 * CAD-Files and 3D-Models online viewer on sharecad.org
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 **/
 
- 	function(ql) {
 
- 				var fm      = ql.fm,
 
- 			mimes   = fm.arrayFlip(ql.options.sharecadMimes || []),
 
- 			preview = ql.preview,
 
- 			win     = ql.window,
 
- 			node;
 
- 			
 
- 		if (ql.options.sharecadMimes.length) {
 
- 			ql.addIntegration({
 
- 				title: 'ShareCAD.org CAD and 3D-Models viewer',
 
- 				link: 'https://sharecad.org/DWGOnlinePlugin'
 
- 			});
 
- 		}
 
- 		preview.on(ql.evUpdate, function(e) {
 
- 			var file = e.file;
 
- 			if (mimes[file.mime.toLowerCase()]) {
 
- 				var win     = ql.window,
 
- 					loading, url;
 
- 				
 
- 				e.stopImmediatePropagation();
 
- 				if (file.url == '1') {
 
- 					preview.hide();
 
- 					$('<div class="elfinder-quicklook-info-data"><button class="elfinder-info-button">'+fm.i18n('getLink')+'</button></div>').appendTo(ql.info.find('.elfinder-quicklook-info'))
 
- 					.on('click', function() {
 
- 						var self = $(this);
 
- 						self.html('<span class="elfinder-spinner">');
 
- 						fm.request({
 
- 							data : {cmd : 'url', target : file.hash},
 
- 							preventDefault : true
 
- 						})
 
- 						.always(function() {
 
- 							self.html('');
 
- 						})
 
- 						.done(function(data) {
 
- 							var rfile = fm.file(file.hash);
 
- 							file.url = rfile.url = data.url || '';
 
- 							if (file.url) {
 
- 								preview.trigger({
 
- 									type: ql.evUpdate,
 
- 									file: file,
 
- 									forceUpdate: true
 
- 								});
 
- 							}
 
- 						});
 
- 					});
 
- 				}
 
- 				if (file.url !== '' && file.url != '1') {
 
- 					preview.one('change', function() {
 
- 						loading.remove();
 
- 						node.off('load').remove();
 
- 						node = null;
 
- 					}).addClass('elfinder-overflow-auto');
 
- 					
 
- 					loading = $('<div class="elfinder-quicklook-info-data"><span class="elfinder-spinner-text">'+fm.i18n('nowLoading')+'</span><span class="elfinder-spinner"/></div>').appendTo(ql.info.find('.elfinder-quicklook-info'));
 
- 					
 
- 					url = fm.convAbsUrl(fm.url(file.hash));
 
- 					node = $('<iframe class="elfinder-quicklook-preview-iframe" scrolling="no"/>')
 
- 						.css('background-color', 'transparent')
 
- 						.appendTo(preview)
 
- 						.on('load', function() {
 
- 							ql.hideinfo();
 
- 							loading.remove();
 
- 							ql.preview.after(ql.info);
 
- 							$(this).css('background-color', '#fff').show();
 
- 						})
 
- 						.on('error', function() {
 
- 							loading.remove();
 
- 							ql.preview.after(ql.info);
 
- 						})
 
- 						.attr('src', '//sharecad.org/cadframe/load?url=' + encodeURIComponent(url));
 
- 					
 
- 					ql.info.after(ql.preview);
 
- 				}
 
- 			}
 
- 			
 
- 		});
 
- 	},
 
- 	/**
 
- 	 * KML preview with GoogleMaps API
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 */
 
- 	function(ql) {
 
- 				var fm      = ql.fm,
 
- 			mimes   = {
 
- 				'application/vnd.google-earth.kml+xml' : true,
 
- 				'application/vnd.google-earth.kmz' : true
 
- 			},
 
- 			preview = ql.preview,
 
- 			gMaps, loadMap, wGmfail, fail, mapScr;
 
- 		if (ql.options.googleMapsApiKey) {
 
- 			ql.addIntegration({
 
- 				title: 'Google Maps',
 
- 				link: 'https://www.google.com/intl/' + fm.lang.replace('_', '-') + '/help/terms_maps.html'
 
- 			});
 
- 			gMaps = (window.google && google.maps);
 
- 			// start load maps
 
- 			loadMap = function(file, node) {
 
- 				var mapsOpts = ql.options.googleMapsOpts.maps;
 
- 				ql.hideinfo();
 
- 				try {
 
- 					new gMaps.KmlLayer(fm.convAbsUrl(fm.url(file.hash)), Object.assign({
 
- 						map: new gMaps.Map(node.get(0), mapsOpts)
 
- 					}, ql.options.googleMapsOpts.kml));
 
- 				} catch(e) {
 
- 					fail();
 
- 				}
 
- 			};
 
- 			// keep stored error handler if exists
 
- 			wGmfail = window.gm_authFailure;
 
- 			// on error function
 
- 			fail = function() {
 
- 				mapScr = null;
 
- 			};
 
- 			// API script url
 
- 			mapScr = 'https://maps.googleapis.com/maps/api/js?key=' + ql.options.googleMapsApiKey;
 
- 			// error handler
 
- 			window.gm_authFailure = function() {
 
- 				fail();
 
- 				wGmfail && wGmfail();
 
- 			};
 
- 			preview.on(ql.evUpdate, function(e) {
 
- 				var file = e.file;
 
- 				if (mapScr && mimes[file.mime.toLowerCase()]) {
 
- 					var win     = ql.window,
 
- 						loading, url, node;
 
- 				
 
- 					e.stopImmediatePropagation();
 
- 					if (file.url == '1') {
 
- 						preview.hide();
 
- 						$('<div class="elfinder-quicklook-info-data"><button class="elfinder-info-button">'+fm.i18n('getLink')+'</button></div>').appendTo(ql.info.find('.elfinder-quicklook-info'))
 
- 						.on('click', function() {
 
- 							var self = $(this);
 
- 							self.html('<span class="elfinder-spinner">');
 
- 							fm.request({
 
- 								data : {cmd : 'url', target : file.hash},
 
- 								preventDefault : true
 
- 							})
 
- 							.always(function() {
 
- 								self.html('');
 
- 							})
 
- 							.done(function(data) {
 
- 								var rfile = fm.file(file.hash);
 
- 								file.url = rfile.url = data.url || '';
 
- 								if (file.url) {
 
- 									preview.trigger({
 
- 										type: ql.evUpdate,
 
- 										file: file,
 
- 										forceUpdate: true
 
- 									});
 
- 								}
 
- 							});
 
- 						});
 
- 					}
 
- 					if (file.url !== '' && file.url != '1') {
 
- 						node = $('<div style="width:100%;height:100%;"/>').appendTo(preview);
 
- 						preview.one('change', function() {
 
- 							node.remove();
 
- 							node = null;
 
- 						});
 
- 						if (!gMaps) {
 
- 							fm.loadScript([mapScr], function() {
 
- 								gMaps = window.google && google.maps;
 
- 								gMaps && loadMap(file, node);
 
- 							});
 
- 						} else {
 
- 							loadMap(file, node);
 
- 						}
 
- 					}
 
- 				}
 
- 			});
 
- 		}
 
- 	},
 
- 	/**
 
- 	 * Any supported files preview plugin using (Google docs | MS Office) online viewer
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 **/
 
- 	function(ql) {
 
- 				var fm      = ql.fm,
 
- 			mimes   = Object.assign(fm.arrayFlip(ql.options.googleDocsMimes || [], 'g'), fm.arrayFlip(ql.options.officeOnlineMimes || [], 'm')),
 
- 			preview = ql.preview,
 
- 			win     = ql.window,
 
- 			navi    = ql.navbar,
 
- 			urls    = {
 
- 				g: 'docs.google.com/gview?embedded=true&url=',
 
- 				m: 'view.officeapps.live.com/op/embed.aspx?wdStartOn=0&src='
 
- 			},
 
- 			navBottom = {
 
- 				g: '56px',
 
- 				m: '24px'
 
- 			},
 
- 			mLimits = {
 
- 				xls  : 5242880, // 5MB
 
- 				xlsb : 5242880,
 
- 				xlsx : 5242880,
 
- 				xlsm : 5242880,
 
- 				other: 10485760 // 10MB
 
- 			},
 
- 			node, enable;
 
- 		
 
- 		if (ql.options.googleDocsMimes.length) {
 
- 			enable = true;
 
- 			ql.addIntegration({
 
- 				title: 'Google Docs Viewer',
 
- 				link: 'https://docs.google.com/'
 
- 			});
 
- 		}
 
- 		if (ql.options.officeOnlineMimes.length) {
 
- 			enable = true;
 
- 			ql.addIntegration({
 
- 				title: 'MS Online Doc Viewer',
 
- 				link: 'https://products.office.com/office-online/view-office-documents-online'
 
- 			});
 
- 		}
 
- 		if (enable) {
 
- 			preview.on(ql.evUpdate, function(e) {
 
- 				var file = e.file,
 
- 					type;
 
- 				// 25MB is maximum filesize of Google Docs prevew
 
- 				if (file.size <= 26214400 && (type = mimes[file.mime])) {
 
- 					var win     = ql.window,
 
- 						setNavi = function() {
 
- 							navi.css('bottom', win.hasClass('elfinder-quicklook-fullscreen')? navBottom[type] : '');
 
- 						},
 
- 						ext     = fm.mimeTypes[file.mime],
 
- 						loading, url;
 
- 					
 
- 					if (type === 'm') {
 
- 						if ((mLimits[ext] && file.size > mLimits[ext]) || file.size > mLimits.other) {
 
- 							type = 'g';
 
- 						}
 
- 					}
 
- 					if (file.url == '1') {
 
- 						preview.hide();
 
- 						$('<div class="elfinder-quicklook-info-data"><button class="elfinder-info-button">'+fm.i18n('getLink')+'</button></div>').appendTo(ql.info.find('.elfinder-quicklook-info'))
 
- 						.on('click', function() {
 
- 							var self = $(this);
 
- 							self.html('<span class="elfinder-spinner">');
 
- 							fm.request({
 
- 								data : {cmd : 'url', target : file.hash},
 
- 								preventDefault : true
 
- 							})
 
- 							.always(function() {
 
- 								self.html('');
 
- 							})
 
- 							.done(function(data) {
 
- 								var rfile = fm.file(file.hash);
 
- 								file.url = rfile.url = data.url || '';
 
- 								if (file.url) {
 
- 									preview.trigger({
 
- 										type: ql.evUpdate,
 
- 										file: file,
 
- 										forceUpdate: true
 
- 									});
 
- 								}
 
- 							});
 
- 						});
 
- 					}
 
- 					if (file.url !== '' && file.url != '1') {
 
- 						e.stopImmediatePropagation();
 
- 						preview.one('change', function() {
 
- 							win.off('viewchange.googledocs');
 
- 							loading.remove();
 
- 							node.off('load').remove();
 
- 							node = null;
 
- 						}).addClass('elfinder-overflow-auto');
 
- 						
 
- 						loading = $('<div class="elfinder-quicklook-info-data"><span class="elfinder-spinner-text">'+fm.i18n('nowLoading')+'</span><span class="elfinder-spinner"/></div>').appendTo(ql.info.find('.elfinder-quicklook-info'));
 
- 						
 
- 						url = fm.convAbsUrl(fm.url(file.hash));
 
- 						if (file.ts) {
 
- 							url += (url.match(/\?/)? '&' : '?') + '_t=' + file.ts;
 
- 						}
 
- 						node = $('<iframe class="elfinder-quicklook-preview-iframe"/>')
 
- 							.css('background-color', 'transparent')
 
- 							.appendTo(preview)
 
- 							.on('load', function() {
 
- 								ql.hideinfo();
 
- 								loading.remove();
 
- 								ql.preview.after(ql.info);
 
- 								$(this).css('background-color', '#fff').show();
 
- 							})
 
- 							.on('error', function() {
 
- 								loading.remove();
 
- 								ql.preview.after(ql.info);
 
- 							})
 
- 							.attr('src', 'https://' + urls[type] + encodeURIComponent(url));
 
- 						
 
- 						win.on('viewchange.googledocs', setNavi);
 
- 						setNavi();
 
- 						ql.info.after(ql.preview);
 
- 					}
 
- 				}
 
- 				
 
- 			});
 
- 		}
 
- 	},
 
- 	/**
 
- 	 * Texts preview plugin
 
- 	 *
 
- 	 * @param elFinder.commands.quicklook
 
- 	 **/
 
- 	function(ql) {
 
- 				var fm      = ql.fm,
 
- 			preview = ql.preview,
 
- 			textMaxlen = parseInt(ql.options.textMaxlen) || 2000,
 
- 			prettify = function() {
 
- 				if (fm.options.cdns.prettify) {
 
- 					fm.loadScript([fm.options.cdns.prettify + (fm.options.cdns.prettify.match(/\?/)? '&' : '?') + 'autorun=false']);
 
- 					prettify = function() { return true; };
 
- 				} else {
 
- 					prettify = function() { return false; };
 
- 				}
 
- 			},
 
- 			PRcheck = function(node, cnt) {
 
- 				if (prettify()) {
 
- 					if (typeof window.PR === 'undefined' && cnt--) {
 
- 						setTimeout(function() { PRcheck(node, cnt); }, 100);
 
- 					} else {
 
- 						if (typeof window.PR === 'object') {
 
- 							node.css('cursor', 'wait');
 
- 							requestAnimationFrame(function() {
 
- 								PR.prettyPrint && PR.prettyPrint(null, node.get(0));
 
- 								node.css('cursor', '');
 
- 							});
 
- 						} else {
 
- 							prettify = function() { return false; };
 
- 						}
 
- 					}
 
- 				}
 
- 			};
 
- 		
 
- 		preview.on(ql.evUpdate, function(e) {
 
- 			var file = e.file,
 
- 				mime = file.mime,
 
- 				jqxhr, loading;
 
- 			
 
- 			if (fm.mimeIsText(file.mime) && (!ql.options.getSizeMax || file.size <= ql.options.getSizeMax)) {
 
- 				e.stopImmediatePropagation();
 
- 				
 
- 				(typeof window.PR === 'undefined') && prettify();
 
- 				
 
- 				loading = $('<div class="elfinder-quicklook-info-data"><span class="elfinder-spinner-text">'+fm.i18n('nowLoading')+'</span><span class="elfinder-spinner"/></div>').appendTo(ql.info.find('.elfinder-quicklook-info'));
 
- 				// stop loading on change file if not loadin yet
 
- 				preview.one('change', function() {
 
- 					jqxhr.state() == 'pending' && jqxhr.reject();
 
- 				});
 
- 				
 
- 				jqxhr = fm.request({
 
- 					data           : {cmd : 'get', target : file.hash, conv : 1, _t : file.ts},
 
- 					options        : {type: 'get', cache : true},
 
- 					preventDefault : true
 
- 				})
 
- 				.done(function(data) {
 
- 					var reg = new RegExp('^(data:'+file.mime.replace(/([.+])/g, '\\$1')+';base64,)', 'i'),
 
- 						text = data.content,
 
- 						part, more, node, m;
 
- 					ql.hideinfo();
 
- 					if (window.atob && (m = text.match(reg))) {
 
- 						text = atob(text.substr(m[1].length));
 
- 					}
 
- 					
 
- 					more = text.length - textMaxlen;
 
- 					if (more > 100) {
 
- 						part = text.substr(0, textMaxlen) + '...';
 
- 					} else {
 
- 						more = 0;
 
- 					}
 
- 					
 
- 					node = $('<div class="elfinder-quicklook-preview-text-wrapper"><pre class="elfinder-quicklook-preview-text prettyprint"></pre></div>');
 
- 					
 
- 					if (more) {
 
- 						node.append($('<div class="elfinder-quicklook-preview-charsleft"><hr/><span>' + fm.i18n('charsLeft', fm.toLocaleString(more)) + '</span></div>')
 
- 							.on('click', function() {
 
- 								var top = node.scrollTop();
 
- 								$(this).remove();
 
- 								node.children('pre').removeClass('prettyprinted').text(text).scrollTop(top);
 
- 								PRcheck(node, 100);
 
- 							})
 
- 						);
 
- 					}
 
- 					node.children('pre').text(part || text);
 
- 					
 
- 					node.on('touchstart', function(e) {
 
- 						if ($(this)['scroll' + (fm.direction === 'ltr'? 'Right' : 'Left')]() > 5) {
 
- 							e.originalEvent._preventSwipeX = true;
 
- 						}
 
- 					}).appendTo(preview);
 
- 					
 
- 					PRcheck(node, 100);
 
- 				})
 
- 				.always(function() {
 
- 					loading.remove();
 
- 				});
 
- 			}
 
- 		});
 
- 	}
 
- ];
 
- /*
 
-  * File: /js/commands/reload.js
 
-  */
 
- /**
 
-  * @class  elFinder command "reload"
 
-  * Sync files and folders
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- (elFinder.prototype.commands.reload = function() {
 
- 	"use strict";
 
- 	var self   = this,
 
- 		search = false;
 
- 	
 
- 	this.alwaysEnabled = true;
 
- 	this.updateOnSelect = true;
 
- 	
 
- 	this.shortcuts = [{
 
- 		pattern     : 'ctrl+shift+r f5'
 
- 	}];
 
- 	
 
- 	this.getstate = function() {
 
- 		return 0;
 
- 	};
 
- 	
 
- 	this.init = function() {
 
- 		this.fm.bind('search searchend', function() {
 
- 			search = this.type == 'search';
 
- 		});
 
- 	};
 
- 	
 
- 	this.fm.bind('contextmenu', function(){
 
- 		var fm = self.fm;
 
- 		if (fm.options.sync >= 1000) {
 
- 			self.extra = {
 
- 				icon: 'accept',
 
- 				node: $('<span/>')
 
- 					.attr({title: fm.i18n('autoSync')})
 
- 					.on('click touchstart', function(e){
 
- 						if (e.type === 'touchstart' && e.originalEvent.touches.length > 1) {
 
- 							return;
 
- 						}
 
- 						e.stopPropagation();
 
- 						e.preventDefault();
 
- 						$(this).parent()
 
- 							.toggleClass('ui-state-disabled', fm.options.syncStart)
 
- 							.parent().removeClass('ui-state-hover');
 
- 						fm.options.syncStart = !fm.options.syncStart;
 
- 						fm.autoSync(fm.options.syncStart? null : 'stop');
 
- 					}).on('ready', function(){
 
- 						$(this).parent().toggleClass('ui-state-disabled', !fm.options.syncStart).css('pointer-events', 'auto');
 
- 					})
 
- 			};
 
- 		}
 
- 	});
 
- 	
 
- 	this.exec = function() {
 
- 		var fm = this.fm;
 
- 		if (!search) {
 
- 			var dfrd    = fm.sync(),
 
- 				timeout = setTimeout(function() {
 
- 					fm.notify({type : 'reload', cnt : 1, hideCnt : true});
 
- 					dfrd.always(function() { fm.notify({type : 'reload', cnt  : -1}); });
 
- 				}, fm.notifyDelay);
 
- 				
 
- 			return dfrd.always(function() { 
 
- 				clearTimeout(timeout); 
 
- 				fm.trigger('reload');
 
- 			});
 
- 		} else {
 
- 			$('div.elfinder-toolbar > div.'+fm.res('class', 'searchbtn') + ' > span.ui-icon-search').click();
 
- 		}
 
- 	};
 
- }).prototype = { forceLoad : true }; // this is required command
 
- /*
 
-  * File: /js/commands/rename.js
 
-  */
 
- /**
 
-  * @class elFinder command "rename". 
 
-  * Rename selected file.
 
-  *
 
-  * @author Dmitry (dio) Levashov, dio@std42.ru
 
-  * @author Naoki Sawada
 
-  **/
 
- elFinder.prototype.commands.rename = function() {
 
- 	"use strict";
 
- 	// set alwaysEnabled to allow root rename on client size
 
- 	this.alwaysEnabled = true;
 
- 	this.syncTitleOnChange = true;
 
- 	var self = this,
 
- 		fm = self.fm,
 
- 		request = function(dfrd, targtes, file, name) {
 
- 			var sel = targtes? [file.hash].concat(targtes) : [file.hash],
 
- 				cnt = sel.length,
 
- 				data = {}, rootNames;
 
- 			
 
- 			fm.lockfiles({files : sel});
 
- 			
 
- 			if (fm.isRoot(file)) {
 
- 				if (!(rootNames = fm.storage('rootNames'))) {
 
- 					rootNames = {};
 
- 				}
 
- 				if (name === '') {
 
- 					if (rootNames[file.hash]) {
 
- 						file.name = file._name;
 
- 						file.i18 = file._i18;
 
- 						delete rootNames[file.hash];
 
- 						delete file._name;
 
- 						delete file._i18;
 
- 					} else {
 
- 						dfrd && dfrd.reject();
 
- 						fm.unlockfiles({files : sel}).trigger('selectfiles', {files : sel});
 
- 						return;
 
- 					}
 
- 				} else {
 
- 					if (typeof file._name === 'undefined') {
 
- 						file._name = file.name;
 
- 						file._i18 = file.i18;
 
- 					}
 
- 					file.name = rootNames[file.hash] = name;
 
- 					delete file.i18;
 
- 				}
 
- 				fm.storage('rootNames', rootNames);
 
- 				data = { changed: [file] };
 
- 				fm.updateCache(data);
 
- 				fm.change(data);
 
- 				dfrd && dfrd.resolve(data);
 
- 				fm.unlockfiles({files : sel}).trigger('selectfiles', {files : sel});
 
- 				return;
 
- 			}
 
- 			data = {
 
- 				cmd : 'rename',
 
- 				name : name,
 
- 				target : file.hash
 
- 			};
 
- 			if (cnt > 1) {
 
- 				data['targets'] = targtes;
 
- 				if (name.match(/\*/)) {
 
- 					data['q'] = name;
 
- 				}
 
- 			}
 
- 			
 
- 			fm.request({
 
- 					data   : data,
 
- 					notify : {type : 'rename', cnt : cnt},
 
- 					navigate : {}
 
- 				})
 
- 				.fail(function(error) {
 
- 					var err = fm.parseError(error);
 
- 					dfrd && dfrd.reject();
 
- 					if (! err || ! Array.isArray(err) || err[0] !== 'errRename') {
 
- 						fm.sync();
 
- 					}
 
- 				})
 
- 				.done(function(data) {
 
- 					var cwdHash;
 
- 					if (data.added && data.added.length && cnt === 1) {
 
- 						data.undo = {
 
- 							cmd : 'rename',
 
- 							callback : function() {
 
- 								return fm.request({
 
- 									data   : {cmd : 'rename', target : data.added[0].hash, name : file.name},
 
- 									notify : {type : 'undo', cnt : 1}
 
- 								});
 
- 							}
 
- 						};
 
- 						data.redo = {
 
- 							cmd : 'rename',
 
- 							callback : function() {
 
- 								return fm.request({
 
- 									data   : {cmd : 'rename', target : file.hash, name : name},
 
- 									notify : {type : 'rename', cnt : 1}
 
- 								});
 
- 							}
 
- 						};
 
- 					}
 
- 					dfrd && dfrd.resolve(data);
 
- 					if (!(cwdHash = fm.cwd().hash) || cwdHash === file.hash) {
 
- 						fm.exec('open', $.map(data.added, function(f) {
 
- 							return (f.mime === 'directory')? f.hash : null;
 
- 						})[0]);
 
- 					}
 
- 				})
 
- 				.always(function() {
 
- 					fm.unlockfiles({files : sel}).trigger('selectfiles', {files : sel});
 
- 				}
 
- 			);
 
- 		},
 
- 		getHint = function(name, target) {
 
- 			var sel = target || fm.selected(),
 
- 				splits = fm.splitFileExtention(name),
 
- 				f1 = fm.file(sel[0]),
 
- 				f2 = fm.file(sel[1]),
 
- 				ext, hint, add;
 
- 			
 
- 			ext = splits[1]? ('.' + splits[1]) : '';
 
- 			if (splits[1] && splits[0] === '*') {
 
- 				// change extention
 
- 				hint =  '"' + fm.splitFileExtention(f1.name)[0] + ext + '", ';
 
- 				hint += '"' + fm.splitFileExtention(f2.name)[0] + ext + '"';
 
- 			} else if (splits[0].length > 1) {
 
- 				if (splits[0].substr(-1) === '*') {
 
- 					// add prefix
 
- 					add = splits[0].substr(0, splits[0].length - 1);
 
- 					hint =  '"' + add + f1.name+'", ';
 
- 					hint += '"' + add + f2.name+'"';
 
- 				} else if (splits[0].substr(0, 1) === '*') {
 
- 					// add suffix
 
- 					add = splits[0].substr(1);
 
- 					hint =  '"'+fm.splitFileExtention(f1.name)[0] + add + ext + '", ';
 
- 					hint += '"'+fm.splitFileExtention(f2.name)[0] + add + ext + '"';
 
- 				}
 
- 			}
 
- 			if (!hint) {
 
- 				hint = '"'+splits[0] + '1' + ext + '", "' + splits[0] + '2' + ext + '"';
 
- 			}
 
- 			if (sel.length > 2) {
 
- 				hint += ' ...';
 
- 			}
 
- 			return hint;
 
- 		},
 
- 		batchRename = function() {
 
- 			var sel = fm.selected(),
 
- 				tplr = '<input name="type" type="radio" class="elfinder-tabstop">',
 
- 				mkChk = function(node, label) {
 
- 					return $('<label class="elfinder-rename-batch-checks">' + fm.i18n(label) + '</label>').prepend(node);
 
- 				},
 
- 				name = $('<input type="text" class="ui-corner-all elfinder-tabstop">'),
 
- 				num  = $(tplr),
 
- 				prefix  = $(tplr),
 
- 				suffix  = $(tplr),
 
- 				extention  = $(tplr),
 
- 				checks = $('<div/>').append(
 
- 					mkChk(num, 'plusNumber'),
 
- 					mkChk(prefix, 'asPrefix'),
 
- 					mkChk(suffix, 'asSuffix'),
 
- 					mkChk(extention, 'changeExtention')
 
- 				),
 
- 				preview = $('<div class="elfinder-rename-batch-preview"/>'),
 
- 				node = $('<div class="elfinder-rename-batch"/>').append(
 
- 						$('<div class="elfinder-rename-batch-name"/>').append(name),
 
- 						$('<div class="elfinder-rename-batch-type"/>').append(checks),
 
- 						preview
 
- 					),
 
- 				opts = {
 
- 					title : fm.i18n('batchRename'),
 
- 					modal : true,
 
- 					destroyOnClose : true,
 
- 					width: Math.min(380, fm.getUI().width() - 20),
 
- 					buttons : {},
 
- 					open : function() {
 
- 						name.on('input', mkPrev).trigger('focus');
 
- 					}
 
- 				},
 
- 				getName = function() {
 
- 					var vName = name.val(),
 
- 						ext = fm.splitFileExtention(fm.file(sel[0]).name)[1];
 
- 					if (vName !== '' || num.is(':checked')) {
 
- 						if (prefix.is(':checked')) {
 
- 							vName += '*';
 
- 						} else if (suffix.is(':checked')) {
 
- 							vName = '*' + vName + '.' + ext;
 
- 						} else if (extention.is(':checked')) {
 
- 							vName = '*.' + vName;
 
- 						} else if (ext) {
 
- 							vName += '.' + ext;
 
- 						}
 
- 					}
 
- 					return vName;
 
- 				},
 
- 				mkPrev = function() {
 
- 					var vName = getName();
 
- 					if (vName !== '') {
 
- 						preview.html(fm.i18n(['renameMultiple', sel.length, getHint(vName)]));
 
- 					} else {
 
- 						preview.empty();
 
- 					}
 
- 				},
 
- 				radios = checks.find('input:radio').on('change', mkPrev),
 
- 				dialog;
 
- 			
 
- 			opts.buttons[fm.i18n('btnApply')] = function() {
 
- 				var vName = getName(),
 
- 					file, targets;
 
- 				if (vName !== '') {
 
- 					dialog.elfinderdialog('close');
 
- 					targets = sel;
 
- 					file = fm.file(targets.shift());
 
- 					request(void(0), targets, file, vName);
 
- 				}
 
- 			};
 
- 			opts.buttons[fm.i18n('btnCancel')] = function() {
 
- 				dialog.elfinderdialog('close');
 
- 			};
 
- 			if ($.fn.checkboxradio) {
 
- 				radios.checkboxradio({
 
- 					create: function(e, ui) {
 
- 						if (this === num.get(0)) {
 
- 							num.prop('checked', true).change();
 
- 						}
 
- 					}
 
- 				});
 
- 			} else {
 
- 				checks.buttonset({
 
- 					create: function(e, ui) {
 
- 						num.prop('checked', true).change();
 
- 					}
 
- 				});
 
- 			}
 
- 			dialog = self.fmDialog(node, opts);
 
- 		};
 
- 	
 
- 	this.noChangeDirOnRemovedCwd = true;
 
- 	
 
- 	this.shortcuts = [{
 
- 		pattern : 'f2' + (fm.OS == 'mac' ? ' enter' : '')
 
- 	}, {
 
- 		pattern : 'shift+f2',
 
- 		description : 'batchRename',
 
- 		callback : function() {
 
- 			fm.selected().length > 1 && batchRename();
 
- 		}
 
- 	}];
 
- 	
 
- 	this.getstate = function(select) {
 
- 		var sel = this.files(select),
 
- 			cnt = sel.length,
 
- 			phash, ext, mime, brk, state, isRoot;
 
- 		
 
- 		if (!cnt) {
 
- 			return -1;
 
- 		}
 
- 		
 
- 		if (cnt > 1 && sel[0].phash) {
 
- 			phash = sel[0].phash;
 
- 			ext = fm.splitFileExtention(sel[0].name)[1].toLowerCase();
 
- 			mime = sel[0].mime;
 
- 		}
 
- 		if (cnt === 1) {
 
- 			isRoot = fm.isRoot(sel[0]);
 
- 		}
 
- 		state = (cnt === 1 && (isRoot || !sel[0].locked) || (fm.api > 2.1030 && cnt === $.grep(sel, function(f) {
 
- 			if (!brk && !f.locked && f.phash === phash && !fm.isRoot(f) && (mime === f.mime || ext === fm.splitFileExtention(f.name)[1].toLowerCase())) {
 
- 				return true;
 
- 			} else {
 
- 				brk && (brk = true);
 
- 				return false;
 
- 			}
 
- 		}).length)) ? 0 : -1;
 
- 		
 
- 		// because alwaysEnabled = true, it need check disabled on connector 
 
- 		if (!isRoot && state === 0 && fm.option('disabledFlip', sel[0].hash)['rename']) {
 
- 			state = -1;
 
- 		}
 
- 		if (state !== -1 && cnt > 1) {
 
- 			self.extra = {
 
- 				icon: 'preference',
 
- 				node: $('<span/>')
 
- 					.attr({title: fm.i18n('batchRename')})
 
- 					.on('click touchstart', function(e){
 
- 						if (e.type === 'touchstart' && e.originalEvent.touches.length > 1) {
 
- 							return;
 
- 						}
 
- 						e.stopPropagation();
 
- 						e.preventDefault();
 
- 						fm.getUI().trigger('click'); // to close the context menu immediately
 
- 						batchRename();
 
- 					})
 
- 			};
 
- 		} else {
 
- 			delete self.extra;
 
- 		}
 
- 			
 
- 		return state;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes, cOpts) {
 
- 		var cwd      = fm.getUI('cwd'),
 
- 			sel      = hashes || (fm.selected().length? fm.selected() : false) || [fm.cwd().hash],
 
- 			cnt      = sel.length,
 
- 			file     = fm.file(sel.shift()),
 
- 			filename = '.elfinder-cwd-filename',
 
- 			opts     = cOpts || {},
 
- 			incwd    = (fm.cwd().hash == file.hash),
 
- 			type     = (opts._currentType === 'navbar' || opts._currentType === 'files')? opts._currentType : (incwd? 'navbar' : 'files'),
 
- 			navbar   = (type !== 'files'),
 
- 			target   = $('#'+fm[navbar? 'navHash2Id' : 'cwdHash2Id'](file.hash)),
 
- 			tarea    = (!navbar && fm.storage('view') != 'list'),
 
- 			split    = function(name) {
 
- 				var ext = fm.splitFileExtention(name)[1];
 
- 				return [name.substr(0, name.length - ext.length - 1), ext];
 
- 			},
 
- 			unselect = function() {
 
- 				requestAnimationFrame(function() {
 
- 					input && input.trigger('blur');
 
- 				});
 
- 			},
 
- 			rest     = function(){
 
- 				if (!overlay.is(':hidden')) {
 
- 					overlay.elfinderoverlay('hide').off('click close', cancel);
 
- 				}
 
- 				pnode.removeClass('ui-front')
 
- 					.css('position', '')
 
- 					.off('unselect.'+fm.namespace, unselect);
 
- 				if (tarea) {
 
- 					node && node.css('max-height', '');
 
- 				} else if (!navbar) {
 
- 					pnode.css('width', '')
 
- 						.parent('td').css('overflow', '');
 
- 				}
 
- 			}, colwidth,
 
- 			dfrd     = $.Deferred()
 
- 				.fail(function(error) {
 
- 					var parent = input.parent(),
 
- 						name   = fm.escape(file.i18 || file.name);
 
- 					input.off();
 
- 					if (tarea) {
 
- 						name = name.replace(/([_.])/g, '​$1');
 
- 					}
 
- 					requestAnimationFrame(function() {
 
- 						if (navbar) {
 
- 							input.replaceWith(name);
 
- 						} else {
 
- 							if (parent.length) {
 
- 								input.remove();
 
- 								parent.html(name);
 
- 							} else {
 
- 								target.find(filename).html(name);
 
- 							}
 
- 						}
 
- 					});
 
- 					error && fm.error(error);
 
- 				})
 
- 				.always(function() {
 
- 					rest();
 
- 					fm.unbind('resize', resize);
 
- 					fm.enable();
 
- 				}),
 
- 			blur = function(e) {
 
- 				var name   = $.trim(input.val()),
 
- 				splits = fm.splitFileExtention(name),
 
- 				valid  = true,
 
- 				req = function() {
 
- 					input.off();
 
- 					rest();
 
- 					if (navbar) {
 
- 						input.replaceWith(fm.escape(name));
 
- 					} else {
 
- 						node.html(fm.escape(name));
 
- 					}
 
- 					request(dfrd, sel, file, name);
 
- 				};
 
- 				if (!overlay.is(':hidden')) {
 
- 					pnode.css('z-index', '');
 
- 				}
 
- 				if (name === '') {
 
- 					if (!fm.isRoot(file)) {
 
- 						return cancel();
 
- 					}
 
- 					if (navbar) {
 
- 						input.replaceWith(fm.escape(file.name));
 
- 					} else {
 
- 						node.html(fm.escape(file.name));
 
- 					}
 
- 				}
 
- 				if (!inError && pnode.length) {
 
- 					
 
- 					input.off('blur');
 
- 					
 
- 					if (cnt === 1 && name === file.name) {
 
- 						return dfrd.reject();
 
- 					}
 
- 					if (fm.options.validName && fm.options.validName.test) {
 
- 						try {
 
- 							valid = fm.options.validName.test(name);
 
- 						} catch(e) {
 
- 							valid = false;
 
- 						}
 
- 					}
 
- 					if (name === '.' || name === '..' || !valid) {
 
- 						inError = true;
 
- 						fm.error(file.mime === 'directory'? 'errInvDirname' : 'errInvName', {modal: true, close: function(){setTimeout(select, 120);}});
 
- 						return false;
 
- 					}
 
- 					if (cnt === 1 && fm.fileByName(name, file.phash)) {
 
- 						inError = true;
 
- 						fm.error(['errExists', name], {modal: true, close: function(){setTimeout(select, 120);}});
 
- 						return false;
 
- 					}
 
- 					
 
- 					if (cnt === 1) {
 
- 						req();
 
- 					} else {
 
- 						fm.confirm({
 
- 							title : 'cmdrename',
 
- 							text  : ['renameMultiple', cnt, getHint(name, [file.hash].concat(sel))],
 
- 							accept : {
 
- 								label : 'btnYes',
 
- 								callback : req
 
- 							},
 
- 							cancel : {
 
- 								label : 'btnCancel',
 
- 								callback : function() {
 
- 									setTimeout(function() {
 
- 										inError = true;
 
- 										select();
 
- 									}, 120);
 
- 								}
 
- 							}
 
- 						});
 
- 						setTimeout(function() {
 
- 							fm.trigger('unselectfiles', {files: fm.selected()})
 
- 								.trigger('selectfiles', {files : [file.hash].concat(sel)});
 
- 						}, 120);
 
- 					}
 
- 				}
 
- 			},
 
- 			input = $(tarea? '<textarea/>' : '<input type="text"/>')
 
- 				.on('keyup text', function(){
 
- 					if (tarea) {
 
- 						this.style.height = '1px';
 
- 						this.style.height = this.scrollHeight + 'px';
 
- 					} else if (colwidth) {
 
- 						this.style.width = colwidth + 'px';
 
- 						if (this.scrollWidth > colwidth) {
 
- 							this.style.width = this.scrollWidth + 10 + 'px';
 
- 						}
 
- 					}
 
- 				})
 
- 				.on('keydown', function(e) {
 
- 					e.stopImmediatePropagation();
 
- 					if (e.keyCode == $.ui.keyCode.ESCAPE) {
 
- 						dfrd.reject();
 
- 					} else if (e.keyCode == $.ui.keyCode.ENTER) {
 
- 						e.preventDefault();
 
- 						input.trigger('blur');
 
- 					}
 
- 				})
 
- 				.on('mousedown click dblclick', function(e) {
 
- 					e.stopPropagation();
 
- 					if (e.type === 'dblclick') {
 
- 						e.preventDefault();
 
- 					}
 
- 				})
 
- 				.on('blur', blur)
 
- 				.on('dragenter dragleave dragover drop', function(e) {
 
- 					// stop bubbling to prevent upload with native drop event
 
- 					e.stopPropagation();
 
- 				}),
 
- 			select = function() {
 
- 				var name = fm.splitFileExtention(input.val())[0];
 
- 				if (!inError && fm.UA.Mobile && !fm.UA.iOS) { // since iOS has a bug? (z-index not effect) so disable it
 
- 					overlay.on('click close', cancel).elfinderoverlay('show');
 
- 					pnode.css('z-index', overlay.css('z-index') + 1);
 
- 				}
 
- 				! fm.enabled() && fm.enable();
 
- 				if (inError) {
 
- 					inError = false;
 
- 					input.on('blur', blur);
 
- 				}
 
- 				input.trigger('focus').trigger('select');
 
- 				input[0].setSelectionRange && input[0].setSelectionRange(0, name.length);
 
- 			},
 
- 			node = navbar? target.contents().filter(function(){ return this.nodeType==3 && $(this).parent().attr('id') === fm.navHash2Id(file.hash); })
 
- 					: target.find(filename),
 
- 			pnode = node.parent(),
 
- 			overlay = fm.getUI('overlay'),
 
- 			cancel = function(e) { 
 
- 				if (!overlay.is(':hidden')) {
 
- 					pnode.css('z-index', '');
 
- 				}
 
- 				if (! inError) {
 
- 					dfrd.reject();
 
- 					if (e) {
 
- 						e.stopPropagation();
 
- 						e.preventDefault();
 
- 					}
 
- 				}
 
- 			},
 
- 			resize = function() {
 
- 				target.trigger('scrolltoview', {blink : false});
 
- 			},
 
- 			inError = false;
 
- 		
 
- 		pnode.addClass('ui-front')
 
- 			.css('position', 'relative')
 
- 			.on('unselect.'+fm.namespace, unselect);
 
- 		fm.bind('resize', resize);
 
- 		if (navbar) {
 
- 			node.replaceWith(input.val(file.name));
 
- 		} else {
 
- 			if (tarea) {
 
- 				node.css('max-height', 'none');
 
- 			} else if (!navbar) {
 
- 				colwidth = pnode.width();
 
- 				pnode.width(colwidth - 15)
 
- 					.parent('td').css('overflow', 'visible');
 
- 			}
 
- 			node.empty().append(input.val(file.name));
 
- 		}
 
- 		
 
- 		if (cnt > 1 && fm.api <= 2.1030) {
 
- 			return dfrd.reject();
 
- 		}
 
- 		
 
- 		if (!file || !node.length) {
 
- 			return dfrd.reject('errCmdParams', this.title);
 
- 		}
 
- 		
 
- 		if (file.locked && !fm.isRoot(file)) {
 
- 			return dfrd.reject(['errLocked', file.name]);
 
- 		}
 
- 		
 
- 		fm.one('select', function() {
 
- 			input.parent().length && file && $.inArray(file.hash, fm.selected()) === -1 && input.trigger('blur');
 
- 		});
 
- 		
 
- 		input.trigger('keyup');
 
- 		
 
- 		select();
 
- 		
 
- 		return dfrd;
 
- 	};
 
- 	fm.bind('select contextmenucreate closecontextmenu', function(e) {
 
- 		var sel = (e.data? (e.data.selected || e.data.targets) : null) || fm.selected(),
 
- 			file;
 
- 		if (sel && sel.length === 1 && (file = fm.file(sel[0])) && fm.isRoot(file)) {
 
- 			self.title = fm.i18n('kindAlias') + ' (' + fm.i18n('preference') + ')';
 
- 		} else {
 
- 			self.title = fm.i18n('cmdrename');
 
- 		}
 
- 		if (e.type !== 'closecontextmenu') {
 
- 			self.update(void(0), self.title);
 
- 		} else {
 
- 			requestAnimationFrame(function() {
 
- 				self.update(void(0), self.title);
 
- 			});
 
- 		}
 
- 	}).remove(function(e) {
 
- 		var rootNames;
 
- 		if (e.data && e.data.removed && (rootNames = fm.storage('rootNames'))) {
 
- 			$.each(e.data.removed, function(i, h) {
 
- 				if (rootNames[h]) {
 
- 					delete rootNames[h];
 
- 				}
 
- 			});
 
- 			fm.storage('rootNames', rootNames);
 
- 		}
 
- 	});
 
- };
 
- /*
 
-  * File: /js/commands/resize.js
 
-  */
 
- /**
 
-  * @class  elFinder command "resize"
 
-  * Open dialog to resize image
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  * @author Alexey Sukhotin
 
-  * @author Naoki Sawada
 
-  * @author Sergio Jovani
 
-  **/
 
- elFinder.prototype.commands.resize = function() {
 
- 	"use strict";
 
- 	var losslessRotate = 0,
 
- 		getBounceBox = function(w, h, theta) {
 
- 			var srcPts = [
 
- 					{x: w/2, y: h/2},
 
- 					{x: -w/2, y: h/2},
 
- 					{x: -w/2, y: -h/2},
 
- 					{x: w/2, y: -h/2}
 
- 				],
 
- 				dstPts = [],
 
- 				min = {x: Number.MAX_VALUE, y: Number.MAX_VALUE},
 
- 				max = {x: Number.MIN_VALUE, y: Number.MIN_VALUE};
 
- 			$.each(srcPts, function(i, srcPt){
 
- 				dstPts.push({
 
- 					x: srcPt.x * Math.cos(theta) - srcPt.y * Math.sin(theta),
 
- 					y: srcPt.x * Math.sin(theta) + srcPt.y * Math.cos(theta)
 
- 				});
 
- 			});
 
- 			$.each(dstPts, function(i, pt) {
 
- 				min.x = Math.min(min.x, pt.x);
 
- 				min.y = Math.min(min.y, pt.y);
 
- 				max.x = Math.max(max.x, pt.x);
 
- 				max.y = Math.max(max.y, pt.y);
 
- 			});
 
- 			return {
 
- 				width: max.x - min.x, height: max.y - min.y
 
- 			};
 
- 		};
 
- 	
 
- 	this.updateOnSelect = false;
 
- 	
 
- 	this.getstate = function() {
 
- 		var sel = this.fm.selectedFiles();
 
- 		return sel.length == 1 && sel[0].read && sel[0].write && sel[0].mime.indexOf('image/') !== -1 ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.resizeRequest = function(data, f, dfrd) {
 
- 		var fm   = this.fm,
 
- 			file = f || fm.file(data.target),
 
- 			tmb  = file? file.tmb : null,
 
- 			enabled = fm.isCommandEnabled('resize', data.target);
 
- 		
 
- 		if (enabled && (! file || (file && file.read && file.write && file.mime.indexOf('image/') !== -1 ))) {
 
- 			return fm.request({
 
- 				data : Object.assign(data, {
 
- 					cmd : 'resize'
 
- 				}),
 
- 				notify : {type : 'resize', cnt : 1}
 
- 			})
 
- 			.fail(function(error) {
 
- 				if (dfrd) {
 
- 					dfrd.reject(error);
 
- 				}
 
- 			})
 
- 			.done(function() {
 
- 				if (data.quality) {
 
- 					fm.storage('jpgQuality', data.quality === fm.option('jpgQuality')? null : data.quality);
 
- 				}
 
- 				dfrd && dfrd.resolve();
 
- 			});
 
- 		} else {
 
- 			var error;
 
- 			
 
- 			if (file) {
 
- 				if (file.mime.indexOf('image/') === -1) {
 
- 					error = ['errResize', file.name, 'errUsupportType'];
 
- 				} else {
 
- 					error = ['errResize', file.name, 'errPerm'];
 
- 				}
 
- 			} else {
 
- 				error = ['errResize', data.target, 'errPerm'];
 
- 			}
 
- 			
 
- 			if (dfrd) {
 
- 				dfrd.reject(error);
 
- 			} else {
 
- 				fm.error(error);
 
- 			}
 
- 			return $.Deferred().reject(error);
 
- 		}
 
- 	};
 
- 	
 
- 	this.exec = function(hashes) {
 
- 		var self  = this,
 
- 			fm    = this.fm,
 
- 			files = this.files(hashes),
 
- 			dfrd  = $.Deferred(),
 
- 			api2  = (fm.api > 1),
 
- 			options = this.options,
 
- 			dialogWidth = 650,
 
- 			fmnode = fm.getUI(),
 
- 			ctrgrup = $().controlgroup? 'controlgroup' : 'buttonset',
 
- 			grid8Def = typeof options.grid8px === 'undefined' || options.grid8px !== 'disable'? true : false,
 
- 			presetSize = Array.isArray(options.presetSize)? options.presetSize : [],
 
- 			clactive = 'elfinder-dialog-active',
 
- 			clsediting = fm.res('class', 'editing'),
 
- 			open = function(file, id) {
 
- 				var isJpeg   = (file.mime === 'image/jpeg'),
 
- 					dialog   = $('<div class="elfinder-resize-container"/>'),
 
- 					input    = '<input type="number" class="ui-corner-all"/>',
 
- 					row      = '<div class="elfinder-resize-row"/>',
 
- 					label    = '<div class="elfinder-resize-label"/>',
 
- 					changeTm = null,
 
- 					operate  = false,
 
- 					opStart  = function() { operate = true; },
 
- 					opStop   = function() {
 
- 						if (operate) {
 
- 							operate = false;
 
- 							control.trigger('change');
 
- 						}
 
- 					},
 
- 					control  = $('<div class="elfinder-resize-control"/>')
 
- 						.on('focus', 'input[type=text],input[type=number]', function() {
 
- 							$(this).trigger('select');
 
- 						})
 
- 						.on('change', function() {
 
- 							changeTm && cancelAnimationFrame(changeTm);
 
- 							changeTm = requestAnimationFrame(function() {
 
- 								var panel, quty, canvas, ctx, img, sx, sy, sw, sh, deg, theta, bb;
 
- 								if (sizeImg && ! operate && (canvas = sizeImg.data('canvas'))) {
 
- 									panel = control.children('div.elfinder-resize-control-panel:visible');
 
- 									quty = panel.find('input.elfinder-resize-quality');
 
- 									if (quty.is(':visible')) {
 
- 										ctx = sizeImg.data('ctx');
 
- 										img = sizeImg.get(0);
 
- 										if (panel.hasClass('elfinder-resize-uiresize')) {
 
- 											// resize
 
- 											sw = canvas.width = width.val();
 
- 											sh = canvas.height = height.val();
 
- 											ctx.drawImage(img, 0, 0, sw, sh);
 
- 										} else if (panel.hasClass('elfinder-resize-uicrop')) {
 
- 											// crop
 
- 											sx = pointX.val();
 
- 											sy = pointY.val();
 
- 											sw = offsetX.val();
 
- 											sh = offsetY.val();
 
- 											canvas.width = sw;
 
- 											canvas.height = sh;
 
- 											ctx.drawImage(img, sx, sy, sw, sh, 0, 0, sw, sh);
 
- 										} else {
 
- 											// rotate
 
- 											deg = degree.val();
 
- 											theta = (degree.val() * Math.PI) / 180;
 
- 											bb = getBounceBox(owidth, oheight, theta);
 
- 											sw = canvas.width = bb.width;
 
- 											sh = canvas.height = bb.height;
 
- 											ctx.save();
 
- 											if (deg % 90 !== 0) {
 
- 												ctx.fillStyle = bg.val() || '#FFF';
 
- 												ctx.fillRect(0, 0, sw, sh);
 
- 											}
 
- 											ctx.translate(sw / 2, sh / 2);
 
- 											ctx.rotate(theta);
 
- 											ctx.drawImage(img, -img.width/2, -img.height/2, owidth, oheight);
 
- 											ctx.restore();
 
- 										}
 
- 										canvas.toBlob(function(blob) {
 
- 											blob && quty.next('span').text(' (' + fm.formatSize(blob.size) + ')');
 
- 										}, 'image/jpeg', Math.max(Math.min(quty.val(), 100), 1) / 100);
 
- 									}
 
- 								}
 
- 							});
 
- 						})
 
- 						.on('mouseup', 'input', function(e) {
 
- 							$(e.target).trigger('change');
 
- 						}),
 
- 					preview  = $('<div class="elfinder-resize-preview"/>')
 
- 						.on('touchmove', function(e) {
 
- 							if ($(e.target).hasClass('touch-punch')) {
 
- 								e.stopPropagation();
 
- 								e.preventDefault();
 
- 							}
 
- 						}),
 
- 					spinner  = $('<div class="elfinder-resize-loading">'+fm.i18n('ntfloadimg')+'</div>'),
 
- 					rhandle  = $('<div class="elfinder-resize-handle touch-punch"/>'),
 
- 					rhandlec = $('<div class="elfinder-resize-handle touch-punch"/>'),
 
- 					uiresize = $('<div class="elfinder-resize-uiresize elfinder-resize-control-panel"/>'),
 
- 					uicrop   = $('<div class="elfinder-resize-uicrop elfinder-resize-control-panel"/>'),
 
- 					uirotate = $('<div class="elfinder-resize-rotate elfinder-resize-control-panel"/>'),
 
- 					uideg270 = $('<button/>').attr('title',fm.i18n('rotate-cw')).append($('<span class="elfinder-button-icon elfinder-button-icon-rotate-l"/>')),
 
- 					uideg90  = $('<button/>').attr('title',fm.i18n('rotate-ccw')).append($('<span class="elfinder-button-icon elfinder-button-icon-rotate-r"/>')),
 
- 					uiprop   = $('<span />'),
 
- 					reset    = $('<button class="elfinder-resize-reset">').text(fm.i18n('reset'))
 
- 						.on('click', function() {
 
- 							resetView();
 
- 						})
 
- 						.button({
 
- 							icons: {
 
- 								primary: 'ui-icon-arrowrefresh-1-n'
 
- 							},
 
- 							text: false
 
- 						}),
 
- 					uitype   = $('<div class="elfinder-resize-type"/>')
 
- 						.append('<input type="radio" name="type" id="'+id+'-resize" value="resize" checked="checked" /><label for="'+id+'-resize">'+fm.i18n('resize')+'</label>',
 
- 						'<input class="api2" type="radio" name="type" id="'+id+'-crop" value="crop" /><label class="api2" for="'+id+'-crop">'+fm.i18n('crop')+'</label>',
 
- 						'<input class="api2" type="radio" name="type" id="'+id+'-rotate" value="rotate" /><label class="api2" for="'+id+'-rotate">'+fm.i18n('rotate')+'</label>'),
 
- 					mode     = 'resize',
 
- 					type     = uitype[ctrgrup]()[ctrgrup]('disable').find('input')
 
- 						.on('change', function() {
 
- 							mode = $(this).val();
 
- 							
 
- 							resetView();
 
- 							resizable(true);
 
- 							croppable(true);
 
- 							rotateable(true);
 
- 							
 
- 							if (mode == 'resize') {
 
- 								uiresize.show();
 
- 								uirotate.hide();
 
- 								uicrop.hide();
 
- 								resizable();
 
- 								isJpeg && grid8px.insertAfter(uiresize.find('.elfinder-resize-grid8'));
 
- 							}
 
- 							else if (mode == 'crop') {
 
- 								uirotate.hide();
 
- 								uiresize.hide();
 
- 								uicrop.show();
 
- 								croppable();
 
- 								isJpeg && grid8px.insertAfter(uicrop.find('.elfinder-resize-grid8'));
 
- 							} else if (mode == 'rotate') {
 
- 								uiresize.hide();
 
- 								uicrop.hide();
 
- 								uirotate.show();
 
- 								rotateable();
 
- 							}
 
- 						}),
 
- 					width   = $(input)
 
- 						.on('change', function() {
 
- 							var w = round(parseInt(width.val())),
 
- 								h = round(cratio ? w/ratio : parseInt(height.val()));
 
- 							if (w > 0 && h > 0) {
 
- 								resize.updateView(w, h);
 
- 								width.val(w);
 
- 								height.val(h);
 
- 							}
 
- 						}).addClass('elfinder-focus'),
 
- 					height  = $(input)
 
- 						.on('change', function() {
 
- 							var h = round(parseInt(height.val())),
 
- 								w = round(cratio ? h*ratio : parseInt(width.val()));
 
- 							if (w > 0 && h > 0) {
 
- 								resize.updateView(w, h);
 
- 								width.val(w);
 
- 								height.val(h);
 
- 							}
 
- 						}),
 
- 					pointX  = $(input).on('change', function(){crop.updateView();}),
 
- 					pointY  = $(input).on('change', function(){crop.updateView();}),
 
- 					offsetX = $(input).on('change', function(){crop.updateView('w');}),
 
- 					offsetY = $(input).on('change', function(){crop.updateView('h');}),
 
- 					quality = isJpeg && api2?
 
- 						$(input).val(fm.storage('jpgQuality') > 0? fm.storage('jpgQuality') : fm.option('jpgQuality'))
 
- 							.addClass('elfinder-resize-quality')
 
- 							.attr('min', '1').attr('max', '100').attr('title', '1 - 100')
 
- 							.on('blur', function(){
 
- 								var q = Math.min(100, Math.max(1, parseInt(this.value)));
 
- 								control.find('input.elfinder-resize-quality').val(q);
 
- 							})
 
- 						: null,
 
- 					degree = $('<input type="number" class="ui-corner-all" maxlength="3" value="0" />')
 
- 						.on('change', function() {
 
- 							rotate.update();
 
- 						}),
 
- 					uidegslider = $('<div class="elfinder-resize-rotate-slider touch-punch"/>')
 
- 						.slider({
 
- 							min: 0,
 
- 							max: 360,
 
- 							value: degree.val(),
 
- 							animate: true,
 
- 							start: opStart,
 
- 							stop: opStop,
 
- 							change: function(event, ui) {
 
- 								if (ui.value != uidegslider.slider('value')) {
 
- 									rotate.update(ui.value);
 
- 								}
 
- 							},
 
- 							slide: function(event, ui) {
 
- 								rotate.update(ui.value, false);
 
- 							}
 
- 						}).find('.ui-slider-handle')
 
- 							.addClass('elfinder-tabstop')
 
- 							.off('keydown')
 
- 							.on('keydown', function(e) {
 
- 								if (e.keyCode == $.ui.keyCode.LEFT || e.keyCode == $.ui.keyCode.RIGHT) {
 
- 									e.stopPropagation();
 
- 									e.preventDefault();
 
- 									rotate.update(Number(degree.val()) + (e.keyCode == $.ui.keyCode.RIGHT? 1 : -1), false);
 
- 								}
 
- 							})
 
- 						.end(),
 
- 					pickimg,
 
- 					pickcanv,
 
- 					pickctx,
 
- 					pickc = {},
 
- 					pick = function(e) {
 
- 						var color, r, g, b, h, s, l;
 
- 						try {
 
- 							color = pickc[Math.round(e.offsetX)][Math.round(e.offsetY)];
 
- 						} catch(e) {}
 
- 						if (!color) return;
 
- 						r = color[0]; g = color[1]; b = color[2];
 
- 						h = color[3]; s = color[4]; l = color[5];
 
- 						setbg(r, g, b, (e.type === 'click'));
 
- 					},
 
- 					palpick = function(e) {
 
- 						setbg($(this).css('backgroundColor'), '', '', (e.type === 'click'));
 
- 					},
 
- 					setbg = function(r, g, b, off) {
 
- 						var s, m, cc;
 
- 						if (typeof r === 'string') {
 
- 							g = '';
 
- 							if (r && (s = $('<span>').css('backgroundColor', r).css('backgroundColor')) && (m = s.match(/rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/i))) {
 
- 								r = Number(m[1]);
 
- 								g = Number(m[2]);
 
- 								b = Number(m[3]);
 
- 							}
 
- 						}
 
- 						cc = (g === '')? r : '#' + getColorCode(r, g, b);
 
- 						bg.val(cc).css({ backgroundColor: cc, backgroundImage: 'none', color: (r+g+b < 384? '#fff' : '#000') });
 
- 						preview.css('backgroundColor', cc);
 
- 						if (off) {
 
- 							imgr.off('.picker').removeClass('elfinder-resize-picking');
 
- 							pallet.off('.picker').removeClass('elfinder-resize-picking');
 
- 						}
 
- 					},
 
- 					getColorCode = function(r, g, b) {
 
- 						return $.map([r,g,b], function(c){return ('0'+parseInt(c).toString(16)).slice(-2);}).join('');
 
- 					},
 
- 					picker = $('<button>').text(fm.i18n('colorPicker'))
 
- 					.on('click', function() { 
 
- 						imgr.on('mousemove.picker click.picker', pick).addClass('elfinder-resize-picking');
 
- 						pallet.on('mousemove.picker click.picker', 'span', palpick).addClass('elfinder-resize-picking');
 
- 					})
 
- 					.button({
 
- 						icons: {
 
- 							primary: 'ui-icon-pin-s'
 
- 						},
 
- 						text: false
 
- 					}),
 
- 					reseter = $('<button>').text(fm.i18n('reset'))
 
- 						.on('click', function() { 
 
- 							setbg('', '', '', true);
 
- 						})
 
- 						.button({
 
- 							icons: {
 
- 								primary: 'ui-icon-arrowrefresh-1-n'
 
- 							},
 
- 							text: false
 
- 						}),
 
- 					bg = $('<input class="ui-corner-all elfinder-resize-bg" type="text">')
 
- 						.on('focus', function() {
 
- 							$(this).attr('style', '');
 
- 						})
 
- 						.on('blur', function() {
 
- 							setbg($(this).val());
 
- 						}),
 
- 					pallet  = $('<div class="elfinder-resize-pallet">').on('click', 'span', function() {
 
- 						setbg($(this).css('backgroundColor'));
 
- 					}),
 
- 					ratio   = 1,
 
- 					prop    = 1,
 
- 					owidth  = 0,
 
- 					oheight = 0,
 
- 					cratio  = true,
 
- 					cratioc = false,
 
- 					pwidth  = 0,
 
- 					pheight = 0,
 
- 					rwidth  = 0,
 
- 					rheight = 0,
 
- 					rdegree = 0,
 
- 					grid8   = isJpeg? grid8Def : false,
 
- 					constr  = $('<button>').html(fm.i18n('aspectRatio'))
 
- 						.on('click', function() {
 
- 							cratio = ! cratio;
 
- 							constr.button('option', {
 
- 								icons : { primary: cratio? 'ui-icon-locked' : 'ui-icon-unlocked'}
 
- 							});
 
- 							resize.fixHeight();
 
- 							rhandle.resizable('option', 'aspectRatio', cratio).data('uiResizable')._aspectRatio = cratio;
 
- 						})
 
- 						.button({
 
- 							icons : {
 
- 								primary: cratio? 'ui-icon-locked' : 'ui-icon-unlocked'
 
- 							},
 
- 							text: false
 
- 						}),
 
- 					constrc = $('<button>').html(fm.i18n('aspectRatio'))
 
- 						.on('click', function() {
 
- 							cratioc = ! cratioc;
 
- 							constrc.button('option', {
 
- 								icons : { primary: cratioc? 'ui-icon-locked' : 'ui-icon-unlocked'}
 
- 							});
 
- 							rhandlec.resizable('option', 'aspectRatio', cratioc).data('uiResizable')._aspectRatio = cratioc;
 
- 						})
 
- 						.button({
 
- 							icons : {
 
- 								primary: cratioc? 'ui-icon-locked' : 'ui-icon-unlocked'
 
- 							},
 
- 							text: false
 
- 						}),
 
- 					grid8px = $('<button>').html(fm.i18n(grid8? 'enabled' : 'disabled')).toggleClass('ui-state-active', grid8)
 
- 						.on('click', function() {
 
- 							grid8 = ! grid8;
 
- 							grid8px.html(fm.i18n(grid8? 'enabled' : 'disabled')).toggleClass('ui-state-active', grid8);
 
- 							setStep8();
 
- 						})
 
- 						.button(),
 
- 					setStep8 = function() {
 
- 						var step = grid8? 8 : 1;
 
- 						$.each([width, height, offsetX, offsetY, pointX, pointY], function() {
 
- 							this.attr('step', step);
 
- 						});
 
- 						if (grid8) {
 
- 							width.val(round(width.val()));
 
- 							height.val(round(height.val()));
 
- 							offsetX.val(round(offsetX.val()));
 
- 							offsetY.val(round(offsetY.val()));
 
- 							pointX.val(round(pointX.val()));
 
- 							pointY.val(round(pointY.val()));
 
- 							if (uiresize.is(':visible')) {
 
- 								resize.updateView(width.val(), height.val());
 
- 							} else if (uicrop.is(':visible')) {
 
- 								crop.updateView();
 
- 							}
 
- 						}
 
- 					},
 
- 					setuprimg = function() {
 
- 						var r_scale,
 
- 							fail = function() {
 
- 								bg.parent().hide();
 
- 								pallet.hide();
 
- 							};
 
- 						r_scale = Math.min(pwidth, pheight) / Math.sqrt(Math.pow(owidth, 2) + Math.pow(oheight, 2));
 
- 						rwidth = Math.ceil(owidth * r_scale);
 
- 						rheight = Math.ceil(oheight * r_scale);
 
- 						imgr.width(rwidth)
 
- 							.height(rheight)
 
- 							.css('margin-top', (pheight-rheight)/2 + 'px')
 
- 							.css('margin-left', (pwidth-rwidth)/2 + 'px');
 
- 						if (imgr.is(':visible') && bg.is(':visible')) {
 
- 							if (file.mime !== 'image/png') {
 
- 								preview.css('backgroundColor', bg.val());
 
- 								pickimg = $('<img>');
 
- 								if (fm.isCORS) {
 
- 									pickimg.attr('crossorigin', 'use-credentials');
 
- 								}
 
- 								pickimg.on('load', function() {
 
- 									if (pickcanv && pickcanv.width !== rwidth) {
 
- 										setColorData();
 
- 									}
 
- 								})
 
- 								.on('error', fail)
 
- 								.attr('src', canvSrc);
 
- 							} else {
 
- 								fail();
 
- 							}
 
- 						}
 
- 					},
 
- 					setupimg = function() {
 
- 						resize.updateView(owidth, oheight);
 
- 						setuprimg();
 
- 						basec
 
- 							.width(img.width())
 
- 							.height(img.height());
 
- 						imgc
 
- 							.width(img.width())
 
- 							.height(img.height());
 
- 						crop.updateView();
 
- 						jpgCalc();
 
- 					},
 
- 					setColorData = function() {
 
- 						if (pickctx) {
 
- 							var n, w, h, r, g, b, a, s, l, hsl, hue,
 
- 								data, scale, tx1, tx2, ty1, ty2, rgb,
 
- 								domi = {},
 
- 								domic = [],
 
- 								domiv, palc,
 
- 								rgbToHsl = function (r, g, b) {
 
- 									var h, s, l,
 
- 										max = Math.max(Math.max(r, g), b),
 
- 										min = Math.min(Math.min(r, g), b);
 
- 		
 
- 									// Hue, 0 ~ 359
 
- 									if (max === min) {
 
- 										h = 0;
 
- 									} else if (r === max) {
 
- 										h = ((g - b) / (max - min) * 60 + 360) % 360;
 
- 									} else if (g === max) {
 
- 										h = (b - r) / (max - min) * 60 + 120;
 
- 									} else if (b === max) {
 
- 										h = (r - g) / (max - min) * 60 + 240;
 
- 									}
 
- 									// Saturation, 0 ~ 1
 
- 									s = (max - min) / max;
 
- 									// Lightness, 0 ~ 1
 
- 									l = (r *  0.3 + g * 0.59 + b * 0.11) / 255;
 
- 		
 
- 									return [h, s, l, 'hsl'];
 
- 								},
 
- 								rgbRound = function(c) {
 
- 									return Math.round(c / 8) * 8;
 
- 								};
 
- 							
 
- 							calc:
 
- 							try {
 
- 								w = pickcanv.width = imgr.width();
 
- 								h = pickcanv.height = imgr.height();
 
- 								scale = w / owidth;
 
- 								pickctx.scale(scale, scale);
 
- 								pickctx.drawImage(pickimg.get(0), 0, 0);
 
- 			
 
- 								data = pickctx.getImageData(0, 0, w, h).data;
 
- 			
 
- 								// Range to detect the dominant color
 
- 								tx1 = w * 0.1;
 
- 								tx2 = w * 0.9;
 
- 								ty1 = h * 0.1;
 
- 								ty2 = h * 0.9;
 
- 			
 
- 								for (var y = 0; y < h - 1; y++) {
 
- 									for (var x = 0; x < w - 1; x++) {
 
- 										n = x * 4 + y * w * 4;
 
- 										// RGB
 
- 										r = data[n]; g = data[n + 1]; b = data[n + 2]; a = data[n + 3];
 
- 										// check alpha ch
 
- 										if (a !== 255) {
 
- 											bg.parent().hide();
 
- 											pallet.hide();
 
- 											break calc;
 
- 										}
 
- 										// HSL
 
- 										hsl = rgbToHsl(r, g, b);
 
- 										hue = Math.round(hsl[0]); s = Math.round(hsl[1] * 100); l = Math.round(hsl[2] * 100);
 
- 										if (! pickc[x]) {
 
- 											pickc[x] = {};
 
- 										}
 
- 										// set pickc
 
- 										pickc[x][y] = [r, g, b, hue, s, l];
 
- 										// detect the dominant color
 
- 										if ((x < tx1 || x > tx2) && (y < ty1 || y > ty2)) {
 
- 											rgb = rgbRound(r) + ',' + rgbRound(g) + ',' + rgbRound(b);
 
- 											if (! domi[rgb]) {
 
- 												domi[rgb] = 1;
 
- 											} else {
 
- 												++domi[rgb];
 
- 											}
 
- 										}
 
- 									}
 
- 								}
 
- 								
 
- 								if (! pallet.children(':first').length) {
 
- 									palc = 1;
 
- 									$.each(domi, function(c, v) {
 
- 										domic.push({c: c, v: v});
 
- 									});
 
- 									$.each(domic.sort(function(a, b) {
 
- 										return (a.v > b.v)? -1 : 1;
 
- 									}), function() {
 
- 										if (this.v < 2 || palc > 10) {
 
- 											return false;
 
- 										}
 
- 										pallet.append($('<span style="width:20px;height:20px;display:inline-block;background-color:rgb('+this.c+');">'));
 
- 										++palc;
 
- 									});
 
- 								}
 
- 							} catch(e) {
 
- 								picker.hide();
 
- 								pallet.hide();
 
- 							}
 
- 						}
 
- 					},
 
- 					setupPicker = function() {
 
- 						try {
 
- 							pickcanv = document.createElement('canvas');
 
- 							pickctx = pickcanv.getContext('2d');
 
- 						} catch(e) {
 
- 							picker.hide();
 
- 							pallet.hide();
 
- 						}
 
- 					},
 
- 					setupPreset = function() {
 
- 						preset.on('click', 'span.elfinder-resize-preset', function() {
 
- 							var btn = $(this),
 
- 								w = btn.data('s')[0],
 
- 								h = btn.data('s')[1],
 
- 								r = owidth / oheight;
 
- 							btn.data('s', [h, w]).text(h + 'x' + w);
 
- 							if (owidth > w || oheight > h) {
 
- 								if (owidth <= w) {
 
- 									w = round(h * r);
 
- 								} else if (oheight <= h) {
 
- 									h = round(w / r);
 
- 								} else {
 
- 									if (owidth - w > oheight - h) {
 
- 										h = round(w / r);
 
- 									} else {
 
- 										w = round(h * r);
 
- 									}
 
- 								}
 
- 							} else {
 
- 								w = owidth;
 
- 								h = oheight;
 
- 							}
 
- 							width.val(w);
 
- 							height.val(h);
 
- 							resize.updateView(w, h);
 
- 							jpgCalc();
 
- 						});
 
- 						presetc.on('click', 'span.elfinder-resize-preset', function() {
 
- 							var btn = $(this),
 
- 								w = btn.data('s')[0],
 
- 								h = btn.data('s')[1],
 
- 								x = pointX.val(),
 
- 								y = pointY.val();
 
- 							
 
- 							btn.data('s', [h, w]).text(h + 'x' + w);
 
- 							if (owidth >= w && oheight >= h) {
 
- 								if (owidth - w - x < 0) {
 
- 									x = owidth - w;
 
- 								}
 
- 								if (oheight - h - y < 0) {
 
- 									y = oheight - h;
 
- 								}
 
- 								pointX.val(x);
 
- 								pointY.val(y);
 
- 								offsetX.val(w);
 
- 								offsetY.val(h);
 
- 								crop.updateView();
 
- 								jpgCalc();
 
- 							}
 
- 						});
 
- 						presetc.children('span.elfinder-resize-preset').each(function() {
 
- 							var btn = $(this),
 
- 								w = btn.data('s')[0],
 
- 								h = btn.data('s')[1];
 
- 							
 
- 							btn[(owidth >= w && oheight >= h)? 'show' : 'hide']();
 
- 						});
 
- 					},
 
- 					dimreq  = null,
 
- 					inited  = false,
 
- 					setdim  = function(dim) {
 
- 						var rfile = fm.file(file.hash);
 
- 						rfile.width = dim[0];
 
- 						rfile.height = dim[1];
 
- 					},
 
- 					init    = function() {
 
- 						var elm, memSize, r_scale, imgRatio;
 
- 						
 
- 						if (inited) {
 
- 							return;
 
- 						}
 
- 						inited = true;
 
- 						dimreq && dimreq.state && dimreq.state() === 'pending' && dimreq.reject();
 
- 						
 
- 						// check lossless rotete
 
- 						if (fm.api >= 2.1030) {
 
- 							if (losslessRotate === 0) {
 
- 								fm.request({
 
- 									data: {
 
- 										cmd    : 'resize',
 
- 										target : file.hash,
 
- 										degree : 0,
 
- 										mode   : 'rotate'
 
- 									},
 
- 									preventDefault : true
 
- 								}).done(function(data) {
 
- 									losslessRotate = data.losslessRotate? 1 : -1;
 
- 									if (losslessRotate === 1 && (degree.val() % 90 === 0)) {
 
- 										uirotate.children('div.elfinder-resize-quality').hide();
 
- 									}
 
- 								}).fail(function() {
 
- 									losslessRotate = -1;
 
- 								});
 
- 							}
 
- 						} else {
 
- 							losslessRotate = -1;
 
- 						}
 
- 						
 
- 						elm = img.get(0);
 
- 						memSize = file.width && file.height? {w: file.width, h: file.height} : (elm.naturalWidth? null : {w: img.width(), h: img.height()});
 
- 					
 
- 						memSize && img.removeAttr('width').removeAttr('height');
 
- 						
 
- 						owidth  = file.width || elm.naturalWidth || elm.width || img.width();
 
- 						oheight = file.height || elm.naturalHeight || elm.height || img.height();
 
- 						if (!file.width || !file.height) {
 
- 							setdim([owidth, oheight]);
 
- 						}
 
- 						
 
- 						memSize && img.width(memSize.w).height(memSize.h);
 
- 						
 
- 						dMinBtn.show();
 
- 	
 
- 						imgRatio = oheight / owidth;
 
- 						
 
- 						if (imgRatio < 1 && preview.height() > preview.width() * imgRatio) {
 
- 							preview.height(preview.width() * imgRatio);
 
- 						}
 
- 						
 
- 						if (preview.height() > img.height() + 20) {
 
- 							preview.height(img.height() + 20);
 
- 						}
 
- 						
 
- 						pheight = preview.height() - (rhandle.outerHeight() - rhandle.height());
 
- 						
 
- 						spinner.remove();
 
- 						
 
- 						ratio = owidth/oheight;
 
- 	
 
- 						rhandle.append(img.show()).show();
 
- 						width.val(owidth);
 
- 						height.val(oheight);
 
- 	
 
- 						setupPicker();
 
- 						setupPreset();
 
- 						setupimg();
 
- 						
 
- 						uitype[ctrgrup]('enable');
 
- 						control.find('input,select').prop('disabled', false)
 
- 							.filter(':text').on('keydown', function(e) {
 
- 								var cOpts;
 
- 								if (e.keyCode == $.ui.keyCode.ENTER) {
 
- 									e.stopPropagation();
 
- 									e.preventDefault();
 
- 									cOpts = {
 
- 										title  : $('input:checked', uitype).val(),
 
- 										text   : 'confirmReq',
 
- 										accept : {
 
- 											label    : 'btnApply',
 
- 											callback : function() {  
 
- 												save();
 
- 											}
 
- 										},
 
- 										cancel : {
 
- 											label    : 'btnCancel',
 
- 											callback : function(){
 
- 												$(this).trigger('focus');
 
- 											}
 
- 										}
 
- 									};
 
- 										
 
- 									if (useSaveAs) {
 
- 										cOpts['buttons'] = [{
 
- 											label    : 'btnSaveAs',
 
- 											callback : function() {
 
- 												requestAnimationFrame(saveAs);
 
- 											}
 
- 										}];
 
- 									}
 
- 									fm.confirm(cOpts);
 
- 									return;
 
- 								}
 
- 							})
 
- 							.on('keyup', function() {
 
- 								var $this = $(this);
 
- 								if (! $this.hasClass('elfinder-resize-bg')) {
 
- 									requestAnimationFrame(function() {
 
- 										$this.val($this.val().replace(/[^0-9]/g, ''));
 
- 									});
 
- 								}
 
- 							})
 
- 							.filter(':first');
 
- 						
 
- 						setStep8();
 
- 						!fm.UA.Mobile && width.trigger('focus');
 
- 						resizable();
 
- 					},
 
- 					img     = $('<img/>')
 
- 						.on('load', init)
 
- 						.on('error', function() {
 
- 							spinner.text('Unable to load image').css('background', 'transparent');
 
- 						}),
 
- 					basec = $('<div/>'),
 
- 					imgc = $('<img/>'),
 
- 					coverc = $('<div/>'),
 
- 					imgr = $('<img class="elfinder-resize-imgrotate" />'),
 
- 					round = function(v, max) {
 
- 						v = grid8? Math.round(v/8)*8 : Math.round(v);
 
- 						v = Math.max(0, v);
 
- 						if (max && v > max) {
 
- 							v = grid8? Math.floor(max/8)*8 : max;
 
- 						}
 
- 						return v;
 
- 					},
 
- 					resetView = function() {
 
- 						width.val(owidth);
 
- 						height.val(oheight);
 
- 						resize.updateView(owidth, oheight);
 
- 						pointX.val(0);
 
- 						pointY.val(0);
 
- 						offsetX.val(owidth);
 
- 						offsetY.val(oheight);
 
- 						crop.updateView();
 
- 						jpgCalc();
 
- 					},
 
- 					resize = {
 
- 						update : function() {
 
- 							width.val(round(img.width()/prop));
 
- 							height.val(round(img.height()/prop));
 
- 							jpgCalc();
 
- 						},
 
- 						
 
- 						updateView : function(w, h) {
 
- 							if (w > pwidth || h > pheight) {
 
- 								if (w / pwidth > h / pheight) {
 
- 									prop = pwidth / w;
 
- 									img.width(pwidth).height(round(h*prop));
 
- 								} else {
 
- 									prop = pheight / h;
 
- 									img.height(pheight).width(round(w*prop));
 
- 								}
 
- 							} else {
 
- 								img.width(round(w)).height(round(h));
 
- 							}
 
- 							
 
- 							prop = img.width()/w;
 
- 							uiprop.text('1 : '+(1/prop).toFixed(2));
 
- 							resize.updateHandle();
 
- 						},
 
- 						
 
- 						updateHandle : function() {
 
- 							rhandle.width(img.width()).height(img.height());
 
- 						},
 
- 						fixHeight : function() {
 
- 							var w, h;
 
- 							if (cratio) {
 
- 								w = width.val();
 
- 								h = round(w/ratio);
 
- 								resize.updateView(w, h);
 
- 								height.val(h);
 
- 							}
 
- 						}
 
- 					},
 
- 					crop = {
 
- 						update : function(change) {
 
- 							pointX.val(round(((rhandlec.data('x')||rhandlec.position().left))/prop, owidth));
 
- 							pointY.val(round(((rhandlec.data('y')||rhandlec.position().top))/prop, oheight));
 
- 							if (change !== 'xy') {
 
- 								offsetX.val(round((rhandlec.data('w')||rhandlec.width())/prop, owidth - pointX.val()));
 
- 								offsetY.val(round((rhandlec.data('h')||rhandlec.height())/prop, oheight - pointY.val()));
 
- 							}
 
- 							jpgCalc();
 
- 						},
 
- 						updateView : function(change) {
 
- 							var r, x, y, w, h;
 
- 							
 
- 							pointX.val(round(pointX.val(), owidth - (grid8? 8 : 1)));
 
- 							pointY.val(round(pointY.val(), oheight - (grid8? 8 : 1)));
 
- 							offsetX.val(round(offsetX.val(), owidth - pointX.val()));
 
- 							offsetY.val(round(offsetY.val(), oheight - pointY.val()));
 
- 							
 
- 							if (cratioc) {
 
- 								r = coverc.width() / coverc.height();
 
- 								if (change === 'w') {
 
- 									offsetY.val(round(parseInt(offsetX.val()) / r));
 
- 								} else if (change === 'h') {
 
- 									offsetX.val(round(parseInt(offsetY.val()) * r));
 
- 								}
 
- 							}
 
- 							x = Math.round(parseInt(pointX.val()) * prop);
 
- 							y = Math.round(parseInt(pointY.val()) * prop);
 
- 							if (change !== 'xy') {
 
- 								w = Math.round(parseInt(offsetX.val()) * prop);
 
- 								h = Math.round(parseInt(offsetY.val()) * prop);
 
- 							} else {
 
- 								w = rhandlec.data('w');
 
- 								h = rhandlec.data('h');
 
- 							}
 
- 							rhandlec.data({x: x, y: y, w: w, h: h})
 
- 								.width(w)
 
- 								.height(h)
 
- 								.css({left: x, top: y});
 
- 							coverc.width(w)
 
- 								.height(h);
 
- 						},
 
- 						resize_update : function(e, ui) {
 
- 							rhandlec.data({x: ui.position.left, y: ui.position.top, w: ui.size.width, h: ui.size.height});
 
- 							crop.update();
 
- 							crop.updateView();
 
- 						},
 
- 						drag_update : function(e, ui) {
 
- 							rhandlec.data({x: ui.position.left, y: ui.position.top});
 
- 							crop.update('xy');
 
- 						}
 
- 					},
 
- 					rotate = {
 
- 						mouseStartAngle : 0,
 
- 						imageStartAngle : 0,
 
- 						imageBeingRotated : false,
 
- 						
 
- 						setQuality : function() {
 
- 							uirotate.children('div.elfinder-resize-quality')[(losslessRotate > 0 && (degree.val() % 90) === 0)? 'hide' : 'show']();
 
- 						},
 
- 						
 
- 						update : function(value, animate) {
 
- 							if (typeof value == 'undefined') {
 
- 								rdegree = value = parseInt(degree.val());
 
- 							}
 
- 							if (typeof animate == 'undefined') {
 
- 								animate = true;
 
- 							}
 
- 							if (! animate || fm.UA.Opera || fm.UA.ltIE8) {
 
- 								imgr.rotate(value);
 
- 							} else {
 
- 								imgr.animate({rotate: value + 'deg'});
 
- 							}
 
- 							value = value % 360;
 
- 							if (value < 0) {
 
- 								value += 360;
 
- 							}
 
- 							degree.val(parseInt(value));
 
- 							uidegslider.slider('value', degree.val());
 
- 							
 
- 							rotate.setQuality();
 
- 						},
 
- 						
 
- 						execute : function ( e ) {
 
- 							
 
- 							if ( !rotate.imageBeingRotated ) return;
 
- 							
 
- 							var imageCentre = rotate.getCenter( imgr );
 
- 							var ev = e.originalEvent.touches? e.originalEvent.touches[0] : e;
 
- 							var mouseXFromCentre = ev.pageX - imageCentre[0];
 
- 							var mouseYFromCentre = ev.pageY - imageCentre[1];
 
- 							var mouseAngle = Math.atan2( mouseYFromCentre, mouseXFromCentre );
 
- 							
 
- 							var rotateAngle = mouseAngle - rotate.mouseStartAngle + rotate.imageStartAngle;
 
- 							rotateAngle = Math.round(parseFloat(rotateAngle) * 180 / Math.PI);
 
- 							
 
- 							if ( e.shiftKey ) {
 
- 								rotateAngle = Math.round((rotateAngle + 6)/15) * 15;
 
- 							}
 
- 							
 
- 							imgr.rotate(rotateAngle);
 
- 							
 
- 							rotateAngle = rotateAngle % 360;
 
- 							if (rotateAngle < 0) {
 
- 								rotateAngle += 360;
 
- 							}
 
- 							degree.val(rotateAngle);
 
- 							uidegslider.slider('value', degree.val());
 
- 							
 
- 							rotate.setQuality();
 
- 							
 
- 							return false;
 
- 						},
 
- 						
 
- 						start : function ( e ) {
 
- 							if (imgr.hasClass('elfinder-resize-picking')) {
 
- 								return;
 
- 							}
 
- 							
 
- 							opStart();
 
- 							rotate.imageBeingRotated = true;
 
- 							
 
- 							var imageCentre = rotate.getCenter( imgr );
 
- 							var ev = e.originalEvent.touches? e.originalEvent.touches[0] : e;
 
- 							var mouseStartXFromCentre = ev.pageX - imageCentre[0];
 
- 							var mouseStartYFromCentre = ev.pageY - imageCentre[1];
 
- 							rotate.mouseStartAngle = Math.atan2( mouseStartYFromCentre, mouseStartXFromCentre );
 
- 							
 
- 							rotate.imageStartAngle = parseFloat(imgr.rotate()) * Math.PI / 180.0;
 
- 							
 
- 							$(document).on('mousemove', rotate.execute);
 
- 							imgr.on('touchmove', rotate.execute);
 
- 							
 
- 							return false;
 
- 						},
 
- 							
 
- 						stop : function ( e ) {
 
- 							
 
- 							if ( !rotate.imageBeingRotated ) return;
 
- 							
 
- 							$(document).off('mousemove', rotate.execute);
 
- 							imgr.off('touchmove', rotate.execute);
 
- 							
 
- 							requestAnimationFrame(function() { rotate.imageBeingRotated = false; });
 
- 							opStop();
 
- 							
 
- 							return false;
 
- 						},
 
- 						
 
- 						getCenter : function ( image ) {
 
- 							
 
- 							var currentRotation = imgr.rotate();
 
- 							imgr.rotate(0);
 
- 							
 
- 							var imageOffset = imgr.offset();
 
- 							var imageCentreX = imageOffset.left + imgr.width() / 2;
 
- 							var imageCentreY = imageOffset.top + imgr.height() / 2;
 
- 							
 
- 							imgr.rotate(currentRotation);
 
- 							
 
- 							return Array( imageCentreX, imageCentreY );
 
- 						}
 
- 					},
 
- 					resizable = function(destroy) {
 
- 						if (destroy) {
 
- 							rhandle.filter(':ui-resizable').resizable('destroy');
 
- 							rhandle.hide();
 
- 						}
 
- 						else {
 
- 							rhandle.show();
 
- 							rhandle.resizable({
 
- 								alsoResize  : img,
 
- 								aspectRatio : cratio,
 
- 								resize      : resize.update,
 
- 								start       : opStart,
 
- 								stop        : function(e) {
 
- 									resize.fixHeight;
 
- 									resize.updateView(width.val(), height.val());
 
- 									opStop();
 
- 								}
 
- 							});
 
- 							dinit();
 
- 						}
 
- 					},
 
- 					croppable = function(destroy) {
 
- 						if (destroy) {
 
- 							rhandlec.filter(':ui-resizable').resizable('destroy')
 
- 								.filter(':ui-draggable').draggable('destroy');
 
- 							basec.hide();
 
- 						}
 
- 						else {
 
- 							basec.show();
 
- 							
 
- 							rhandlec
 
- 								.resizable({
 
- 									containment : basec,
 
- 									aspectRatio : cratioc,
 
- 									resize      : crop.resize_update,
 
- 									start       : opStart,
 
- 									stop        : opStop,
 
- 									handles     : 'all'
 
- 								})
 
- 								.draggable({
 
- 									handle      : coverc,
 
- 									containment : imgc,
 
- 									drag        : crop.drag_update,
 
- 									start       : opStart,
 
- 									stop        : function() {
 
- 										crop.updateView('xy');
 
- 										opStop();
 
- 									}
 
- 								});
 
- 							
 
- 							dinit();
 
- 							crop.update();
 
- 						}
 
- 					},
 
- 					rotateable = function(destroy) {
 
- 						if (destroy) {
 
- 							imgr.hide();
 
- 						}
 
- 						else {
 
- 							imgr.show();
 
- 							dinit();
 
- 						}
 
- 					},
 
- 					checkVals = function() {
 
- 						var w, h, x, y, d, q, b = '';
 
- 						
 
- 						if (mode == 'resize') {
 
- 							w = parseInt(width.val()) || 0;
 
- 							h = parseInt(height.val()) || 0;
 
- 						} else if (mode == 'crop') {
 
- 							w = parseInt(offsetX.val()) || 0;
 
- 							h = parseInt(offsetY.val()) || 0;
 
- 							x = parseInt(pointX.val()) || 0;
 
- 							y = parseInt(pointY.val()) || 0;
 
- 						} else if (mode == 'rotate') {
 
- 							w = owidth;
 
- 							h = oheight;
 
- 							d = parseInt(degree.val()) || 0;
 
- 							if (d < 0 || d > 360) {
 
- 								fm.error('Invalid rotate degree');
 
- 								return false;
 
- 							}
 
- 							if (d == 0 || d == 360) {
 
- 								fm.error('errResizeNoChange');
 
- 								return false;
 
- 							}
 
- 							b = bg.val();
 
- 						}
 
- 						q = quality? parseInt(quality.val()) : 0;
 
- 						
 
- 						if (mode != 'rotate') {
 
- 							if (w <= 0 || h <= 0) {
 
- 								fm.error('Invalid image size');
 
- 								return false;
 
- 							}
 
- 							if (w == owidth && h == oheight) {
 
- 								fm.error('errResizeNoChange');
 
- 								return false;
 
- 							}
 
- 						}
 
- 						
 
- 						return {w: w, h: h, x: x, y: y, d: d, q: q, b: b};
 
- 					},
 
- 					save = function() {
 
- 						var vals;
 
- 						
 
- 						if (vals = checkVals()) {
 
- 							dialog.elfinderdialog('close');
 
- 							self.resizeRequest({
 
- 								target : file.hash,
 
- 								width  : vals.w,
 
- 								height : vals.h,
 
- 								x      : vals.x,
 
- 								y      : vals.y,
 
- 								degree : vals.d,
 
- 								quality: vals.q,
 
- 								bg     : vals.b,
 
- 								mode   : mode
 
- 							}, file, dfrd);
 
- 						}
 
- 					},
 
- 					saveAs = function() {
 
- 						var fail = function() {
 
- 								dialogs.addClass(clsediting).fadeIn(function() {
 
- 									base.addClass(clactive);
 
- 								});
 
- 								fm.disable();
 
- 							},
 
- 							make = function() {
 
- 								self.mime = file.mime;
 
- 								self.prefix = file.name.replace(/ \d+(\.[^.]+)?$/, '$1');
 
- 								self.requestCmd = 'mkfile';
 
- 								self.nextAction = {};
 
- 								self.data = {target : file.phash};
 
- 								$.proxy(fm.res('mixin', 'make'), self)()
 
- 									.done(function(data) {
 
- 										var hash, dfd;
 
- 										if (data.added && data.added.length) {
 
- 											hash = data.added[0].hash;
 
- 											dfd = fm.api < 2.1032? fm.url(file.hash, { async: true, temporary: true }) : null;
 
- 											$.when(dfd).done(function(url) {
 
- 												fm.request({
 
- 													options : {type : 'post'},
 
- 													data : {
 
- 														cmd     : 'put',
 
- 														target  : hash,
 
- 														encoding: dfd? 'scheme' : 'hash', 
 
- 														content : dfd? fm.convAbsUrl(url) : file.hash
 
- 													},
 
- 													notify : {type : 'copy', cnt : 1},
 
- 													syncOnFail : true
 
- 												})
 
- 												.fail(fail)
 
- 												.done(function(data) {
 
- 													data = fm.normalize(data);
 
- 													fm.updateCache(data);
 
- 													file = fm.file(hash);
 
- 													data.changed && data.changed.length && fm.change(data);
 
- 													base.show().find('.elfinder-dialog-title').html(fm.escape(file.name));
 
- 													save();
 
- 													dialogs.fadeIn();
 
- 												});
 
- 											}).fail(fail);
 
- 										} else {
 
- 											fail();
 
- 										}
 
- 									})
 
- 									.fail(fail)
 
- 									.always(function() {
 
- 										delete self.mime;
 
- 										delete self.prefix;
 
- 										delete self.nextAction;
 
- 										delete self.data;
 
- 									});
 
- 								fm.trigger('unselectfiles', { files: [ file.hash ] });
 
- 							},
 
- 							reqOpen = null,
 
- 							dialogs;
 
- 						
 
- 						if (checkVals()) {
 
- 							dialogs = fmnode.children('.' + self.dialogClass + ':visible').removeClass(clsediting).fadeOut();
 
- 							base.removeClass(clactive);
 
- 							fm.enable();
 
- 							if (fm.searchStatus.state < 2 && file.phash !== fm.cwd().hash) {
 
- 								reqOpen = fm.exec('open', [file.phash], {thash: file.phash});
 
- 							}
 
- 							
 
- 							$.when([reqOpen]).done(function() {
 
- 								reqOpen? fm.one('cwdrender', make) : make();
 
- 							}).fail(fail);
 
- 						}
 
- 					},
 
- 					buttons = {},
 
- 					hline   = 'elfinder-resize-handle-hline',
 
- 					vline   = 'elfinder-resize-handle-vline',
 
- 					rpoint  = 'elfinder-resize-handle-point',
 
- 					src     = fm.openUrl(file.hash),
 
- 					canvSrc = fm.openUrl(file.hash, !fm.isSameOrigin(src)),
 
- 					sizeImg = quality? $('<img>').attr('crossorigin', fm.isCORS? 'use-credentials' : '').attr('src', canvSrc).on('load', function() {
 
- 						try {
 
- 							var canv = document.createElement('canvas');
 
- 							sizeImg.data('canvas', canv).data('ctx', canv.getContext('2d'));
 
- 							jpgCalc();
 
- 						} catch(e) {
 
- 							sizeImg.removeData('canvas').removeData('ctx');
 
- 						}
 
- 					}) : null,
 
- 					jpgCalc = function() {
 
- 						control.find('input.elfinder-resize-quality:visible').trigger('change');
 
- 					},
 
- 					dinit   = function(e) {
 
- 						if (base.hasClass('elfinder-dialog-minimized') || base.is(':hidden')) {
 
- 							return;
 
- 						}
 
- 						
 
- 						preset.hide();
 
- 						presetc.hide();
 
- 						
 
- 						var win   = fm.options.dialogContained? fmnode : $(window),
 
- 							winH  = win.height(),
 
- 							winW  = win.width(),
 
- 							presW = 'auto',
 
- 							presIn = true,
 
- 							dw, ctrW, prvW;
 
- 						
 
- 						base.width(Math.min(dialogWidth, winW - 30));
 
- 						preview.attr('style', '');
 
- 						if (owidth && oheight) {
 
- 							pwidth  = preview.width()  - (rhandle.outerWidth()  - rhandle.width());
 
- 							pheight = preview.height() - (rhandle.outerHeight() - rhandle.height());
 
- 							resize.updateView(owidth, oheight);
 
- 						}
 
- 						ctrW  = dialog.find('div.elfinder-resize-control').width();
 
- 						prvW  = preview.width();
 
- 						
 
- 						dw = dialog.width() - 20;
 
- 						if (prvW > dw) {
 
- 							preview.width(dw);
 
- 							presIn = false;
 
- 						} else if ((dw - prvW) < ctrW) {
 
- 							if (winW > winH) {
 
- 								preview.width(dw - ctrW - 20);
 
- 							} else {
 
- 								preview.css({ float: 'none', marginLeft: 'auto', marginRight: 'auto'});
 
- 								presIn = false;
 
- 							}
 
- 						}
 
- 						if (presIn) {
 
- 							presW = ctrW;
 
- 						}
 
- 						pwidth  = preview.width()  - (rhandle.outerWidth()  - rhandle.width());
 
- 						if (fmnode.hasClass('elfinder-fullscreen')) {
 
- 							if (base.height() > winH) {
 
- 								winH -= 2;
 
- 								preview.height(winH - base.height() + preview.height());
 
- 								base.css('top', 0 - fmnode.offset().top);
 
- 							}
 
- 						} else {
 
- 							winH -= 30;
 
- 							(preview.height() > winH) && preview.height(winH);
 
- 						}
 
- 						pheight = preview.height() - (rhandle.outerHeight() - rhandle.height());
 
- 						if (owidth && oheight) {
 
- 							setupimg();
 
- 						}
 
- 						if (img.height() && preview.height() > img.height() + 20) {
 
- 							preview.height(img.height() + 20);
 
- 							pheight = preview.height() - (rhandle.outerHeight() - rhandle.height());
 
- 							setuprimg();
 
- 						}
 
- 						
 
- 						preset.css('width', presW).show();
 
- 						presetc.css('width', presW).show();
 
- 						if (!presetc.children('span.elfinder-resize-preset:visible').length) {
 
- 							presetc.hide();
 
- 						}
 
- 					},
 
- 					preset = (function() {
 
- 						var sets = $('<fieldset class="elfinder-resize-preset-container">').append($('<legend>').html(fm.i18n('presets'))).hide(),
 
- 							hasC;
 
- 						$.each(presetSize, function(i, s) {
 
- 							if (s.length === 2) {
 
- 								hasC = true;
 
- 								sets.append($('<span class="elfinder-resize-preset"/>')
 
- 									.data('s', s)
 
- 									.text(s[0]+'x'+s[1])
 
- 									.button()
 
- 								);
 
- 							}
 
- 						});
 
- 						if (!hasC) {
 
- 							return $();
 
- 						} else {
 
- 							return sets;
 
- 						}
 
- 					})(),
 
- 					presetc = preset.clone(true),
 
- 					useSaveAs = fm.uploadMimeCheck(file.mime, file.phash),
 
- 					dMinBtn, base;
 
- 				
 
- 				uiresize.append(
 
- 					$(row).append($(label).text(fm.i18n('width')), width),
 
- 					$(row).append($(label).text(fm.i18n('height')), height, $('<div class="elfinder-resize-whctrls">').append(constr, reset)),
 
- 					(quality? $(row).append($(label).text(fm.i18n('quality')), quality, $('<span/>')) : $()),
 
- 					(isJpeg? $(row).append($(label).text(fm.i18n('8pxgrid')).addClass('elfinder-resize-grid8'), grid8px) : $()),
 
- 					$(row).append($(label).text(fm.i18n('scale')), uiprop),
 
- 					$(row).append(preset)
 
- 				);
 
- 				if (api2) {
 
- 					uicrop.append(
 
- 						$(row).append($(label).text('X'), pointX),
 
- 						$(row).append($(label).text('Y')).append(pointY),
 
- 						$(row).append($(label).text(fm.i18n('width')), offsetX),
 
- 						$(row).append($(label).text(fm.i18n('height')), offsetY, $('<div class="elfinder-resize-whctrls">').append(constrc, reset.clone(true))),
 
- 						(quality? $(row).append($(label).text(fm.i18n('quality')), quality.clone(true), $('<span/>')) : $()),
 
- 						(isJpeg? $(row).append($(label).text(fm.i18n('8pxgrid')).addClass('elfinder-resize-grid8')) : $()),
 
- 						$(row).append(presetc)
 
- 					);
 
- 					
 
- 					uirotate.append(
 
- 						$(row).addClass('elfinder-resize-degree').append(
 
- 							$(label).text(fm.i18n('rotate')),
 
- 							degree,
 
- 							$('<span/>').text(fm.i18n('degree')),
 
- 							$('<div/>').append(uideg270, uideg90)[ctrgrup]()
 
- 						),
 
- 						$(row).css('height', '20px').append(uidegslider),
 
- 						((quality)? $(row)[losslessRotate < 1? 'show' : 'hide']().addClass('elfinder-resize-quality').append(
 
- 							$(label).text(fm.i18n('quality')),
 
- 							quality.clone(true),
 
- 							$('<span/>')) : $()
 
- 						),
 
- 						$(row).append($(label).text(fm.i18n('bgcolor')), bg, picker, reseter),
 
- 						$(row).css('height', '20px').append(pallet)
 
- 					);
 
- 					uideg270.on('click', function() {
 
- 						rdegree = rdegree - 90;
 
- 						rotate.update(rdegree);
 
- 					});
 
- 					uideg90.on('click', function(){
 
- 						rdegree = rdegree + 90;
 
- 						rotate.update(rdegree);
 
- 					});
 
- 				}
 
- 				
 
- 				dialog.append(uitype).on('resize', function(e){
 
- 					e.stopPropagation();
 
- 				});
 
- 				if (api2) {
 
- 					control.append(/*$(row), */uiresize, uicrop.hide(), uirotate.hide());
 
- 				} else {
 
- 					control.append(/*$(row), */uiresize);
 
- 				}
 
- 				
 
- 				rhandle.append('<div class="'+hline+' '+hline+'-top"/>',
 
- 					'<div class="'+hline+' '+hline+'-bottom"/>',
 
- 					'<div class="'+vline+' '+vline+'-left"/>',
 
- 					'<div class="'+vline+' '+vline+'-right"/>',
 
- 					'<div class="'+rpoint+' '+rpoint+'-e"/>',
 
- 					'<div class="'+rpoint+' '+rpoint+'-se"/>',
 
- 					'<div class="'+rpoint+' '+rpoint+'-s"/>');
 
- 					
 
- 				preview.append(spinner).append(rhandle.hide()).append(img.hide());
 
- 				if (api2) {
 
- 					rhandlec.css('position', 'absolute')
 
- 						.append('<div class="'+hline+' '+hline+'-top"/>',
 
- 						'<div class="'+hline+' '+hline+'-bottom"/>',
 
- 						'<div class="'+vline+' '+vline+'-left"/>',
 
- 						'<div class="'+vline+' '+vline+'-right"/>',
 
- 						'<div class="'+rpoint+' '+rpoint+'-n"/>',
 
- 						'<div class="'+rpoint+' '+rpoint+'-e"/>',
 
- 						'<div class="'+rpoint+' '+rpoint+'-s"/>',
 
- 						'<div class="'+rpoint+' '+rpoint+'-w"/>',
 
- 						'<div class="'+rpoint+' '+rpoint+'-ne"/>',
 
- 						'<div class="'+rpoint+' '+rpoint+'-se"/>',
 
- 						'<div class="'+rpoint+' '+rpoint+'-sw"/>',
 
- 						'<div class="'+rpoint+' '+rpoint+'-nw"/>');
 
- 					preview.append(basec.css('position', 'absolute').hide().append(imgc, rhandlec.append(coverc)));
 
- 					
 
- 					preview.append(imgr.hide());
 
- 				}
 
- 				
 
- 				preview.css('overflow', 'hidden');
 
- 				
 
- 				dialog.append(preview, control);
 
- 				
 
- 				buttons[fm.i18n('btnApply')] = save;
 
- 				if (useSaveAs) {
 
- 					buttons[fm.i18n('btnSaveAs')] = function() { requestAnimationFrame(saveAs); };
 
- 				}
 
- 				buttons[fm.i18n('btnCancel')] = function() { dialog.elfinderdialog('close'); };
 
- 				
 
- 				dialog.find('input,button').addClass('elfinder-tabstop');
 
- 				
 
- 				base = self.fmDialog(dialog, {
 
- 					title          : fm.escape(file.name),
 
- 					width          : dialogWidth,
 
- 					resizable      : false,
 
- 					buttons        : buttons,
 
- 					open           : function() {
 
- 						var substituteImg = (fm.option('substituteImg', file.hash) && file.size > options.dimSubImgSize)? true : false,
 
- 							hasSize = (file.width && file.height)? true : false;
 
- 						dialog.parent().css('overflow', 'hidden');
 
- 						dMinBtn = base.find('.ui-dialog-titlebar .elfinder-titlebar-minimize').hide();
 
- 						fm.bind('resize', dinit);
 
- 						img.attr('src', src);
 
- 						imgc.attr('src', src);
 
- 						imgr.attr('src', src);
 
- 						if (api2) {
 
- 							imgr.on('mousedown touchstart', rotate.start)
 
- 								.on('touchend', rotate.stop);
 
- 							base.on('mouseup', rotate.stop);
 
- 						}
 
- 						if (hasSize && !substituteImg) {
 
- 							return init();
 
- 						}
 
- 						if (file.size > (options.getDimThreshold || 0)) {
 
- 							dimreq = fm.request({
 
- 								data : {cmd : 'dim', target : file.hash, substitute : (substituteImg? 400 : '')},
 
- 								preventDefault : true
 
- 							})
 
- 							.done(function(data) {
 
- 								if (data.dim) {
 
- 									var dim = data.dim.split('x');
 
- 									file.width = dim[0];
 
- 									file.height = dim[1];
 
- 									setdim(dim);
 
- 									if (data.url) {
 
- 										img.attr('src', data.url);
 
- 										imgc.attr('src', data.url);
 
- 										imgr.attr('src', data.url);
 
- 									}
 
- 									return init();
 
- 								}
 
- 							});
 
- 						} else if (hasSize) {
 
- 							return init();
 
- 						}
 
- 					},
 
- 					close          : function() {
 
- 						if (api2) {
 
- 							imgr.off('mousedown touchstart', rotate.start)
 
- 								.off('touchend', rotate.stop);
 
- 							$(document).off('mouseup', rotate.stop);
 
- 						}
 
- 						fm.unbind('resize', dinit);
 
- 						$(this).elfinderdialog('destroy');
 
- 					},
 
- 					resize         : function(e, data) {
 
- 						if (data && data.minimize === 'off') {
 
- 							dinit();
 
- 						}
 
- 					}
 
- 				}).attr('id', id).closest('.ui-dialog').addClass(clsediting);
 
- 				
 
- 				// for IE < 9 dialog mising at open second+ time.
 
- 				if (fm.UA.ltIE8) {
 
- 					$('.elfinder-dialog').css('filter', '');
 
- 				}
 
- 				
 
- 				coverc.css({ 'opacity': 0.2, 'background-color': '#fff', 'position': 'absolute'}),
 
- 				rhandlec.css('cursor', 'move');
 
- 				rhandlec.find('.elfinder-resize-handle-point').css({
 
- 					'background-color' : '#fff',
 
- 					'opacity': 0.5,
 
- 					'border-color':'#000'
 
- 				});
 
- 				if (! api2) {
 
- 					uitype.find('.api2').remove();
 
- 				}
 
- 				
 
- 				control.find('input,select').prop('disabled', true);
 
- 				control.find('input.elfinder-resize-quality')
 
- 					.next('span').addClass('elfinder-resize-jpgsize').attr('title', fm.i18n('roughFileSize'));
 
- 			},
 
- 			
 
- 			id, dialog
 
- 			;
 
- 			
 
- 		if (!files.length || files[0].mime.indexOf('image/') === -1) {
 
- 			return dfrd.reject();
 
- 		}
 
- 		
 
- 		id = 'resize-'+fm.namespace+'-'+files[0].hash;
 
- 		dialog = fmnode.find('#'+id);
 
- 		
 
- 		if (dialog.length) {
 
- 			dialog.elfinderdialog('toTop');
 
- 			return dfrd.resolve();
 
- 		}
 
- 		
 
- 		open(files[0], id);
 
- 			
 
- 		return dfrd;
 
- 	};
 
- };
 
- (function ($) {
 
- 	
 
- 	var findProperty = function (styleObject, styleArgs) {
 
- 		var i = 0 ;
 
- 		for( i in styleArgs) {
 
- 	        if (typeof styleObject[styleArgs[i]] != 'undefined') 
 
- 	        	return styleArgs[i];
 
- 		}
 
- 		styleObject[styleArgs[i]] = '';
 
- 	    return styleArgs[i];
 
- 	};
 
- 	
 
- 	$.cssHooks.rotate = {
 
- 		get: function(elem, computed, extra) {
 
- 			return $(elem).rotate();
 
- 		},
 
- 		set: function(elem, value) {
 
- 			$(elem).rotate(value);
 
- 			return value;
 
- 		}
 
- 	};
 
- 	$.cssHooks.transform = {
 
- 		get: function(elem, computed, extra) {
 
- 			var name = findProperty( elem.style , 
 
- 				['WebkitTransform', 'MozTransform', 'OTransform' , 'msTransform' , 'transform'] );
 
- 			return elem.style[name];
 
- 		},
 
- 		set: function(elem, value) {
 
- 			var name = findProperty( elem.style , 
 
- 				['WebkitTransform', 'MozTransform', 'OTransform' , 'msTransform' , 'transform'] );
 
- 			elem.style[name] = value;
 
- 			return value;
 
- 		}
 
- 	};
 
- 	
 
- 	$.fn.rotate = function(val) {
 
- 		var r;
 
- 		if (typeof val == 'undefined') {
 
- 			if (!!window.opera) {
 
- 				r = this.css('transform').match(/rotate\((.*?)\)/);
 
- 				return  ( r && r[1])?
 
- 					Math.round(parseFloat(r[1]) * 180 / Math.PI) : 0;
 
- 			} else {
 
- 				r = this.css('transform').match(/rotate\((.*?)\)/);
 
- 				return  ( r && r[1])? parseInt(r[1]) : 0;
 
- 			}
 
- 		}
 
- 		this.css('transform', 
 
- 			this.css('transform').replace(/none|rotate\(.*?\)/, '') + 'rotate(' + parseInt(val) + 'deg)');
 
- 		return this;
 
- 	};
 
- 	$.fx.step.rotate  = function(fx) {
 
- 		if ( fx.state == 0 ) {
 
- 			fx.start = $(fx.elem).rotate();
 
- 			fx.now = fx.start;
 
- 		}
 
- 		$(fx.elem).rotate(fx.now);
 
- 	};
 
- 	if (typeof window.addEventListener == "undefined" && typeof document.getElementsByClassName == "undefined") { // IE & IE<9
 
- 		var GetAbsoluteXY = function(element) {
 
- 			var pnode = element;
 
- 			var x = pnode.offsetLeft;
 
- 			var y = pnode.offsetTop;
 
- 			
 
- 			while ( pnode.offsetParent ) {
 
- 				pnode = pnode.offsetParent;
 
- 				if (pnode != document.body && pnode.currentStyle['position'] != 'static') {
 
- 					break;
 
- 				}
 
- 				if (pnode != document.body && pnode != document.documentElement) {
 
- 					x -= pnode.scrollLeft;
 
- 					y -= pnode.scrollTop;
 
- 				}
 
- 				x += pnode.offsetLeft;
 
- 				y += pnode.offsetTop;
 
- 			}
 
- 			
 
- 			return { x: x, y: y };
 
- 		};
 
- 		
 
- 		var StaticToAbsolute = function (element) {
 
- 			if ( element.currentStyle['position'] != 'static') {
 
- 				return ;
 
- 			}
 
- 			var xy = GetAbsoluteXY(element);
 
- 			element.style.position = 'absolute' ;
 
- 			element.style.left = xy.x + 'px';
 
- 			element.style.top = xy.y + 'px';
 
- 		};
 
- 		var IETransform = function(element,transform){
 
- 			var r;
 
- 			var m11 = 1;
 
- 			var m12 = 1;
 
- 			var m21 = 1;
 
- 			var m22 = 1;
 
- 			if (typeof element.style['msTransform'] != 'undefined'){
 
- 				return true;
 
- 			}
 
- 			StaticToAbsolute(element);
 
- 			r = transform.match(/rotate\((.*?)\)/);
 
- 			var rotate =  ( r && r[1])	?	parseInt(r[1])	:	0;
 
- 			rotate = rotate % 360;
 
- 			if (rotate < 0) rotate = 360 + rotate;
 
- 			var radian= rotate * Math.PI / 180;
 
- 			var cosX =Math.cos(radian);
 
- 			var sinY =Math.sin(radian);
 
- 			m11 *= cosX;
 
- 			m12 *= -sinY;
 
- 			m21 *= sinY;
 
- 			m22 *= cosX;
 
- 			element.style.filter =  (element.style.filter || '').replace(/progid:DXImageTransform\.Microsoft\.Matrix\([^)]*\)/, "" ) +
 
- 				("progid:DXImageTransform.Microsoft.Matrix(" + 
 
- 					 "M11=" + m11 + 
 
- 					",M12=" + m12 + 
 
- 					",M21=" + m21 + 
 
- 					",M22=" + m22 + 
 
- 					",FilterType='bilinear',sizingMethod='auto expand')") 
 
- 				;
 
- 	  		var ow = parseInt(element.style.width || element.width || 0 );
 
- 	  		var oh = parseInt(element.style.height || element.height || 0 );
 
- 			radian = rotate * Math.PI / 180;
 
- 			var absCosX =Math.abs(Math.cos(radian));
 
- 			var absSinY =Math.abs(Math.sin(radian));
 
- 			var dx = (ow - (ow * absCosX + oh * absSinY)) / 2;
 
- 			var dy = (oh - (ow * absSinY + oh * absCosX)) / 2;
 
- 			element.style.marginLeft = Math.floor(dx) + "px";
 
- 			element.style.marginTop  = Math.floor(dy) + "px";
 
- 			return(true);
 
- 		};
 
- 		
 
- 		var transform_set = $.cssHooks.transform.set;
 
- 		$.cssHooks.transform.set = function(elem, value) {
 
- 			transform_set.apply(this, [elem, value] );
 
- 			IETransform(elem,value);
 
- 			return value;
 
- 		};
 
- 	}
 
- })(jQuery);
 
- /*
 
-  * File: /js/commands/restore.js
 
-  */
 
- /**
 
-  * @class  elFinder command "restore"
 
-  * Restore items from the trash
 
-  *
 
-  * @author Naoki Sawada
 
-  **/
 
- (elFinder.prototype.commands.restore = function() {
 
- 	"use strict";
 
- 	var self = this,
 
- 		fm = this.fm,
 
- 		fakeCnt = 0,
 
- 		getFilesRecursively = function(files) {
 
- 			var dfd = $.Deferred(),
 
- 				dirs = [],
 
- 				results = [],
 
- 				reqs = [],
 
- 				phashes = [],
 
- 				getFile;
 
- 			
 
- 			dfd._xhrReject = function() {
 
- 				$.each(reqs, function() {
 
- 					this && this.reject && this.reject();
 
- 				});
 
- 				getFile && getFile._xhrReject();
 
- 			};
 
- 			
 
- 			$.each(files, function(i, f) {
 
- 				f.mime === 'directory'? dirs.push(f) : results.push(f);
 
- 			});
 
- 			
 
- 			if (dirs.length) {
 
- 				$.each(dirs, function(i, d) {
 
- 					reqs.push(fm.request({
 
- 						data : {cmd  : 'open', target : d.hash},
 
- 						preventDefault : true,
 
- 						asNotOpen : true
 
- 					}));
 
- 					phashes[i] = d.hash;
 
- 				});
 
- 				$.when.apply($, reqs).fail(function() {
 
- 					dfd.reject();
 
- 				}).done(function() {
 
- 					var items = [];
 
- 					$.each(arguments, function(i, r) {
 
- 						var files;
 
- 						if (r.files) {
 
- 							if (r.files.length) {
 
- 								items = items.concat(r.files);
 
- 							} else {
 
- 								items.push({
 
- 									hash: 'fakefile_' + (fakeCnt++),
 
- 									phash: phashes[i],
 
- 									mime: 'fakefile',
 
- 									name: 'fakefile',
 
- 									ts: 0
 
- 								});
 
- 							}
 
- 						}
 
- 					});
 
- 					fm.cache(items);
 
- 					getFile = getFilesRecursively(items).done(function(res) {
 
- 						results = results.concat(res);
 
- 						dfd.resolve(results);
 
- 					});
 
- 				});
 
- 			} else {
 
- 				dfd.resolve(results);
 
- 			}
 
- 			
 
- 			return dfd;
 
- 		},
 
- 		restore = function(dfrd, files, targets, ops) {
 
- 			var rHashes = {},
 
- 				others = [],
 
- 				found = false,
 
- 				dirs = [],
 
- 				opts = ops || {},
 
- 				id = +new Date(),
 
- 				tm, getFile;
 
- 			
 
- 			fm.lockfiles({files : targets});
 
- 			
 
- 			dirs = $.map(files, function(f) {
 
- 				return f.mime === 'directory'? f.hash : null;
 
- 			});
 
- 			
 
- 			dfrd.done(function() {
 
- 				dirs && fm.exec('rm', dirs, {forceRm : true, quiet : true});
 
- 			}).always(function() {
 
- 				fm.unlockfiles({files : targets});
 
- 			});
 
- 			
 
- 			tm = setTimeout(function() {
 
- 				fm.notify({type : 'search', id : id, cnt : 1, hideCnt : true, cancel : function() {
 
- 					getFile && getFile._xhrReject();
 
- 					dfrd.reject();
 
- 				}});
 
- 			}, fm.notifyDelay);
 
- 			fakeCnt = 0;
 
- 			getFile = getFilesRecursively(files).always(function() {
 
- 				tm && clearTimeout(tm);
 
- 				fm.notify({type : 'search', id: id, cnt : -1, hideCnt : true});
 
- 			}).fail(function() {
 
- 				dfrd.reject('errRestore', 'errFileNotFound');
 
- 			}).done(function(res) {
 
- 				var errFolderNotfound = ['errRestore', 'errFolderNotFound'],
 
- 					dirTop = '';
 
- 				
 
- 				if (res.length) {
 
- 					$.each(res, function(i, f) {
 
- 						var phash = f.phash,
 
- 							pfile,
 
- 							srcRoot, tPath;
 
- 						while(phash) {
 
- 							if (srcRoot = fm.trashes[phash]) {
 
- 								if (! rHashes[srcRoot]) {
 
- 									if (found) {
 
- 										// Keep items of other trash
 
- 										others.push(f.hash);
 
- 										return null; // continue $.each
 
- 									}
 
- 									rHashes[srcRoot] = {};
 
- 									found = true;
 
- 								}
 
- 		
 
- 								tPath = fm.path(f.hash).substr(fm.path(phash).length).replace(/\\/g, '/');
 
- 								tPath = tPath.replace(/\/[^\/]+?$/, '');
 
- 								if (tPath === '') {
 
- 									tPath = '/';
 
- 								}
 
- 								if (!rHashes[srcRoot][tPath]) {
 
- 									rHashes[srcRoot][tPath] = [];
 
- 								}
 
- 								if (f.mime === 'fakefile') {
 
- 									fm.updateCache({removed:[f.hash]});
 
- 								} else {
 
- 									rHashes[srcRoot][tPath].push(f.hash);
 
- 								}
 
- 								if (!dirTop || dirTop.length > tPath.length) {
 
- 									dirTop = tPath;
 
- 								}
 
- 								break;
 
- 							}
 
- 							
 
- 							// Go up one level for next check
 
- 							pfile = fm.file(phash);
 
- 							
 
- 							if (!pfile) {
 
- 								phash = false;
 
- 								// Detection method for search results
 
- 								$.each(fm.trashes, function(ph) {
 
- 									var file = fm.file(ph),
 
- 										filePath = fm.path(ph);
 
- 									if ((!file.volumeid || f.hash.indexOf(file.volumeid) === 0) && fm.path(f.hash).indexOf(filePath) === 0) {
 
- 										phash = ph;
 
- 										return false;
 
- 									}
 
- 								});
 
- 							} else {
 
- 								phash = pfile.phash;
 
- 							}
 
- 						}
 
- 					});
 
- 					if (found) {
 
- 						$.each(rHashes, function(src, dsts) {
 
- 							var dirs = Object.keys(dsts),
 
- 								cnt = dirs.length;
 
- 							fm.request({
 
- 								data   : {cmd  : 'mkdir', target : src, dirs : dirs}, 
 
- 								notify : {type : 'chkdir', cnt : cnt},
 
- 								preventFail : true
 
- 							}).fail(function(error) {
 
- 								dfrd.reject(error);
 
- 								fm.unlockfiles({files : targets});
 
- 							}).done(function(data) {
 
- 								var cmdPaste, hashes;
 
- 								
 
- 								if (hashes = data.hashes) {
 
- 									cmdPaste = fm.getCommand('paste');
 
- 									if (cmdPaste) {
 
- 										// wait until file cache made
 
- 										fm.one('mkdirdone', function() {
 
- 											var hasErr = false;
 
- 											$.each(dsts, function(dir, files) {
 
- 												if (hashes[dir]) {
 
- 													if (files.length) {
 
- 														if (fm.file(hashes[dir])) {
 
- 															fm.clipboard(files, true);
 
- 															fm.exec('paste', [ hashes[dir] ], {_cmd : 'restore', noToast : (opts.noToast || dir !== dirTop)})
 
- 															.done(function(data) {
 
- 																if (data && (data.error || data.warning)) {
 
- 																	hasErr = true;
 
- 																}
 
- 															})
 
- 															.fail(function() {
 
- 																hasErr = true;
 
- 															})
 
- 															.always(function() {
 
- 																if (--cnt < 1) {
 
- 																	dfrd[hasErr? 'reject' : 'resolve']();
 
- 																	if (others.length) {
 
- 																		// Restore items of other trash
 
- 																		fm.exec('restore', others);
 
- 																	}
 
- 																}
 
- 															});
 
- 														} else {
 
- 															dfrd.reject(errFolderNotfound);
 
- 														}
 
- 													} else {
 
- 														if (--cnt < 1) {
 
- 															dfrd.resolve();
 
- 															if (others.length) {
 
- 																// Restore items of other trash
 
- 																fm.exec('restore', others);
 
- 															}
 
- 														}
 
- 													}
 
- 												}
 
- 											});
 
- 										});
 
- 									} else {
 
- 										dfrd.reject(['errRestore', 'errCmdNoSupport', '(paste)']);
 
- 									}
 
- 								} else {
 
- 									dfrd.reject(errFolderNotfound);
 
- 								}
 
- 							});
 
- 						});
 
- 					} else {
 
- 						dfrd.reject(errFolderNotfound);
 
- 					}
 
- 				} else {
 
- 					dfrd.reject('errFileNotFound');
 
- 					dirs && fm.exec('rm', dirs, {forceRm : true, quiet : true});
 
- 				}
 
- 			});
 
- 		};
 
- 	
 
- 	// for to be able to overwrite
 
- 	this.restore = restore;
 
- 	this.linkedCmds = ['copy', 'paste', 'mkdir', 'rm'];
 
- 	this.updateOnSelect = false;
 
- 	
 
- 	this.init = function() {
 
- 		// re-assign for extended command
 
- 		self = this;
 
- 		fm = this.fm;
 
- 	};
 
- 	this.getstate = function(sel, e) {
 
- 		sel = sel || fm.selected();
 
- 		return sel.length && $.grep(sel, function(h) {var f = fm.file(h); return f && ! f.locked && ! fm.isRoot(f)? true : false; }).length == sel.length
 
- 			? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes, opts) {
 
- 		var dfrd   = $.Deferred()
 
- 				.fail(function(error) {
 
- 					error && fm.error(error);
 
- 				}),
 
- 			files  = self.files(hashes);
 
- 		if (! files.length) {
 
- 			return dfrd.reject();
 
- 		}
 
- 		
 
- 		$.each(files, function(i, file) {
 
- 			if (fm.isRoot(file)) {
 
- 				return !dfrd.reject(['errRestore', file.name]);
 
- 			}
 
- 			if (file.locked) {
 
- 				return !dfrd.reject(['errLocked', file.name]);
 
- 			}
 
- 		});
 
- 		if (dfrd.state() === 'pending') {
 
- 			this.restore(dfrd, files, hashes, opts);
 
- 		}
 
- 			
 
- 		return dfrd;
 
- 	};
 
- }).prototype = { forceLoad : true }; // this is required command
 
- /*
 
-  * File: /js/commands/rm.js
 
-  */
 
- /**
 
-  * @class  elFinder command "rm"
 
-  * Delete files
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  * @author Naoki Sawada
 
-  **/
 
- elFinder.prototype.commands.rm = function() {
 
- 	"use strict";
 
- 	var self = this,
 
- 		fm = this.fm,
 
- 		tpl = '<div class="ui-helper-clearfix elfinder-rm-title"><span class="elfinder-cwd-icon {class} ui-corner-all"/>{title}<div class="elfinder-rm-desc">{desc}</div></div>',
 
- 		confirm = function(dfrd, targets, files, tHash, addTexts) {
 
- 			var cnt = targets.length,
 
- 				cwd = fm.cwd().hash,
 
- 				descs = [],
 
- 				spinner = fm.i18n('calc') + '<span class="elfinder-spinner"/>',
 
- 				dialog, text, tmb, size, f, fname;
 
- 			
 
- 			if (cnt > 1) {
 
- 				size = 0;
 
- 				$.each(files, function(h, f) { 
 
- 					if (f.size && f.size != 'unknown' && f.mime !== 'directory') {
 
- 						var s = parseInt(f.size);
 
- 						if (s >= 0 && size >= 0) {
 
- 							size += s;
 
- 						}
 
- 					} else {
 
- 						size = 'unknown';
 
- 						return false;
 
- 					}
 
- 				});
 
- 				getSize = (size === 'unknown');
 
- 				descs.push(fm.i18n('size')+': '+(getSize? spinner : fm.formatSize(size)));
 
- 				text = [$(tpl.replace('{class}', 'elfinder-cwd-icon-group').replace('{title}', '<strong>' + fm.i18n('items')+ ': ' + cnt + '</strong>').replace('{desc}', descs.join('<br>')))];
 
- 			} else {
 
- 				f = files[0];
 
- 				tmb = fm.tmb(f);
 
- 				getSize = (f.mime === 'directory');
 
- 				descs.push(fm.i18n('size')+': '+(getSize? spinner : fm.formatSize(f.size)));
 
- 				descs.push(fm.i18n('modify')+': '+fm.formatDate(f));
 
- 				fname = fm.escape(f.i18 || f.name).replace(/([_.])/g, '​$1');
 
- 				text = [$(tpl.replace('{class}', fm.mime2class(f.mime)).replace('{title}', '<strong>' + fname + '</strong>').replace('{desc}', descs.join('<br>')))];
 
- 			}
 
- 			
 
- 			if (addTexts) {
 
- 				text = text.concat(addTexts);
 
- 			}
 
- 			
 
- 			text.push(tHash? 'confirmTrash' : 'confirmRm');
 
- 			
 
- 			dialog = fm.confirm({
 
- 				title  : self.title,
 
- 				text   : text,
 
- 				accept : {
 
- 					label    : 'btnRm',
 
- 					callback : function() {  
 
- 						if (tHash) {
 
- 							self.toTrash(dfrd, targets, tHash);
 
- 						} else {
 
- 							remove(dfrd, targets);
 
- 						}
 
- 					}
 
- 				},
 
- 				cancel : {
 
- 					label    : 'btnCancel',
 
- 					callback : function() {
 
- 						fm.unlockfiles({files : targets});
 
- 						if (targets.length === 1 && fm.file(targets[0]).phash !== cwd) {
 
- 							fm.select({selected : targets});
 
- 						} else {
 
- 							fm.selectfiles({files : targets});
 
- 						}
 
- 						dfrd.reject();
 
- 					}
 
- 				}
 
- 			});
 
- 			// load thumbnail
 
- 			if (tmb) {
 
- 				$('<img/>')
 
- 					.on('load', function() { dialog.find('.elfinder-cwd-icon').addClass(tmb.className).css('background-image', "url('"+tmb.url+"')"); })
 
- 					.attr('src', tmb.url);
 
- 			}
 
- 			
 
- 			if (getSize) {
 
- 				getSize = fm.getSize($.map(files, function(f) { return f.mime === 'directory'? f.hash : null; })).done(function(data) {
 
- 					dialog.find('span.elfinder-spinner').parent().html(fm.i18n('size')+': '+data.formated);
 
- 				}).fail(function() {
 
- 					dialog.find('span.elfinder-spinner').parent().html(fm.i18n('size')+': '+fm.i18n('unknown'));
 
- 				}).always(function() {
 
- 					getSize = false;
 
- 				});
 
- 			}
 
- 		},
 
- 		toTrash = function(dfrd, targets, tHash) {
 
- 			var dsts = {},
 
- 				itemCnt = targets.length,
 
- 				maxCnt = self.options.toTrashMaxItems,
 
- 				checkDirs = [],
 
- 				reqDfd = $.Deferred(),
 
- 				req, dirs, cnt;
 
- 			
 
- 			if (itemCnt > maxCnt) {
 
- 				self.confirm(dfrd, targets, self.files(targets), null, [fm.i18n('tooManyToTrash')]);
 
- 				return;
 
- 			}
 
- 			
 
- 			// Directory preparation preparation and directory enumeration
 
- 			$.each(targets, function(i, h) {
 
- 				var file = fm.file(h),
 
- 					path = fm.path(h).replace(/\\/g, '/'),
 
- 					m = path.match(/^[^\/]+?(\/(?:[^\/]+?\/)*)[^\/]+?$/);
 
- 				
 
- 				if (file) {
 
- 					if (m) {
 
- 						m[1] = m[1].replace(/(^\/.*?)\/?$/, '$1');
 
- 						if (! dsts[m[1]]) {
 
- 							dsts[m[1]] = [];
 
- 						}
 
- 						dsts[m[1]].push(h);
 
- 					}
 
- 					if (file.mime === 'directory') {
 
- 						checkDirs.push(h);
 
- 					}
 
- 				}
 
- 			});
 
- 			
 
- 			// Check directory information
 
- 			if (checkDirs.length) {
 
- 				req = fm.request({
 
- 					data : {cmd : 'size', targets : checkDirs},
 
- 					notify : {type: 'readdir', cnt: 1, hideCnt: true},
 
- 					preventDefault : true
 
- 				}).done(function(data) {
 
- 					var cnt = 0;
 
- 					data.fileCnt && (cnt += parseInt(data.fileCnt));
 
- 					data.dirCnt && (cnt += parseInt(data.dirCnt));
 
- 					reqDfd[cnt > maxCnt ? 'reject' : 'resolve']();
 
- 				}).fail(function() {
 
- 					reqDfd.reject();
 
- 				});
 
- 				setTimeout(function() {
 
- 					var xhr = (req && req.xhr)? req.xhr : null;
 
- 					if (xhr && xhr.state() == 'pending') {
 
- 						req.syncOnFail(false);
 
- 						req.reject();
 
- 						reqDfd.reject();
 
- 					}
 
- 				}, self.options.infoCheckWait * 1000);
 
- 			} else {
 
- 				reqDfd.resolve();
 
- 			}
 
- 			
 
- 			// Directory creation and paste command execution
 
- 			reqDfd.done(function() {
 
- 				dirs = Object.keys(dsts);
 
- 				cnt = dirs.length;
 
- 				if (cnt) {
 
- 					fm.request({
 
- 						data   : {cmd  : 'mkdir', target : tHash, dirs : dirs}, 
 
- 						notify : {type : 'chkdir', cnt : cnt},
 
- 						preventFail : true
 
- 					})
 
- 					.fail(function(error) {
 
- 						dfrd.reject(error);
 
- 						fm.unlockfiles({files : targets});
 
- 					})
 
- 					.done(function(data) {
 
- 						var margeRes = function(data, phash, reqData) {
 
- 								var undo, prevUndo, redo, prevRedo;
 
- 								$.each(data, function(k, v) {
 
- 									if (Array.isArray(v)) {
 
- 										if (res[k]) {
 
- 											res[k] = res[k].concat(v);
 
- 										} else {
 
- 											res[k] = v;
 
- 										}
 
- 									}
 
- 								});
 
- 								if (data.sync) {
 
- 									res.sync = 1;
 
- 								}
 
- 								if (data.added && data.added.length) {
 
- 									undo = function() {
 
- 										var targets = [],
 
- 											dirs    = $.map(data.added, function(f) { return f.mime === 'directory'? f.hash : null; });
 
- 										$.each(data.added, function(i, f) {
 
- 											if ($.inArray(f.phash, dirs) === -1) {
 
- 												targets.push(f.hash);
 
- 											}
 
- 										});
 
- 										return fm.exec('restore', targets, {noToast: true});
 
- 									};
 
- 									redo = function() {
 
- 										return fm.request({
 
- 											data   : reqData,
 
- 											notify : {type : 'redo', cnt : targets.length}
 
- 										});
 
- 									};
 
- 									if (res.undo) {
 
- 										prevUndo = res.undo;
 
- 										res.undo = function() {
 
- 											undo();
 
- 											prevUndo();
 
- 										};
 
- 									} else {
 
- 										res.undo = undo;
 
- 									}
 
- 									if (res.redo) {
 
- 										prevRedo = res.redo;
 
- 										res.redo = function() {
 
- 											redo();
 
- 											prevRedo();
 
- 										};
 
- 									} else {
 
- 										res.redo = redo;
 
- 									}
 
- 								}
 
- 							},
 
- 							err = ['errTrash'],
 
- 							res = {},
 
- 							hasNtf = function() {
 
- 								return fm.ui.notify.children('.elfinder-notify-trash').length;
 
- 							},
 
- 							hashes, tm, prg, prgSt;
 
- 						
 
- 						if (hashes = data.hashes) {
 
- 							prg = 1 / cnt * 100;
 
- 							prgSt = cnt === 1? 100 : 5;
 
- 							tm = setTimeout(function() {
 
- 								fm.notify({type : 'trash', cnt : 1, hideCnt : true, progress : prgSt});
 
- 							}, fm.notifyDelay);
 
- 							$.each(dsts, function(dir, files) {
 
- 								var phash = fm.file(files[0]).phash,
 
- 									reqData;
 
- 								if (hashes[dir]) {
 
- 									reqData = {cmd : 'paste', dst : hashes[dir], targets : files, cut : 1};
 
- 									fm.request({
 
- 										data : reqData,
 
- 										preventDefault : true
 
- 									})
 
- 									.fail(function(error) {
 
- 										if (error) {
 
- 											err = err.concat(error);
 
- 										}
 
- 									})
 
- 									.done(function(data) {
 
- 										data = fm.normalize(data);
 
- 										fm.updateCache(data);
 
- 										margeRes(data, phash, reqData);
 
- 										if (data.warning) {
 
- 											err = err.concat(data.warning);
 
- 											delete data.warning;
 
- 										}
 
- 										// fire some event to update cache/ui
 
- 										data.removed && data.removed.length && fm.remove(data);
 
- 										data.added   && data.added.length   && fm.add(data);
 
- 										data.changed && data.changed.length && fm.change(data);
 
- 										// fire event with command name
 
- 										fm.trigger('paste', data);
 
- 										// fire event with command name + 'done'
 
- 										fm.trigger('pastedone');
 
- 										// force update content
 
- 										data.sync && fm.sync();
 
- 									})
 
- 									.always(function() {
 
- 										var hashes = [], addTexts, end = 2;
 
- 										if (hasNtf()) {
 
- 											fm.notify({type : 'trash', cnt : 0, hideCnt : true, progress : prg});
 
- 										} else {
 
- 											prgSt+= prg;
 
- 										}
 
- 										if (--cnt < 1) {
 
- 											tm && clearTimeout(tm);
 
- 											hasNtf() && fm.notify({type : 'trash', cnt  : -1});
 
- 											fm.unlockfiles({files : targets});
 
- 											if (Object.keys(res).length) {
 
- 												if (err.length > 1) {
 
- 													if (res.removed || res.removed.length) {
 
- 														hashes = $.grep(targets, function(h) {
 
- 															return $.inArray(h, res.removed) === -1? true : false;
 
- 														});
 
- 													}
 
- 													if (hashes.length) {
 
- 														if (err.length > end) {
 
- 															end = (fm.messages[err[end-1]] || '').indexOf('$') === -1? end : end + 1;
 
- 														}
 
- 														dfrd.reject();
 
- 														fm.exec('rm', hashes, { addTexts: err.slice(0, end), forceRm: true });
 
- 													} else {
 
- 														fm.error(err);
 
- 													}
 
- 												}
 
- 												res._noSound = true;
 
- 												if (res.undo && res.redo) {
 
- 													res.undo = {
 
- 														cmd : 'trash',
 
- 														callback : res.undo,
 
- 													};
 
- 													res.redo = {
 
- 														cmd : 'trash',
 
- 														callback : res.redo
 
- 													};
 
- 												}
 
- 												dfrd.resolve(res);
 
- 											} else {
 
- 												dfrd.reject(err);
 
- 											}
 
- 										}
 
- 									});
 
- 								}
 
- 							});
 
- 						} else {
 
- 							dfrd.reject('errFolderNotFound');
 
- 							fm.unlockfiles({files : targets});
 
- 						}
 
- 					});
 
- 				} else {
 
- 					dfrd.reject(['error', 'The folder hierarchy to be deleting can not be determined.']);
 
- 					fm.unlockfiles({files : targets});
 
- 				}
 
- 			}).fail(function() {
 
- 				self.confirm(dfrd, targets, self.files(targets), null, [fm.i18n('tooManyToTrash')]);
 
- 			});
 
- 		},
 
- 		remove = function(dfrd, targets, quiet) {
 
- 			var notify = quiet? {} : {type : 'rm', cnt : targets.length};
 
- 			fm.request({
 
- 				data   : {cmd  : 'rm', targets : targets}, 
 
- 				notify : notify,
 
- 				preventFail : true
 
- 			})
 
- 			.fail(function(error) {
 
- 				dfrd.reject(error);
 
- 			})
 
- 			.done(function(data) {
 
- 				if (data.error || data.warning) {
 
- 					data.sync = true;
 
- 				}
 
- 				dfrd.resolve(data);
 
- 			})
 
- 			.always(function() {
 
- 				fm.unlockfiles({files : targets});
 
- 			});
 
- 		},
 
- 		getTHash = function(targets) {
 
- 			var thash = null,
 
- 				root1st;
 
- 			
 
- 			if (targets && targets.length) {
 
- 				if (targets.length > 1 && fm.searchStatus.state === 2) {
 
- 					root1st = fm.file(fm.root(targets[0])).volumeid;
 
- 					if (!$.grep(targets, function(h) { return h.indexOf(root1st) !== 0? true : false ; }).length) {
 
- 						thash = fm.option('trashHash', targets[0]);
 
- 					}
 
- 				} else {
 
- 					thash = fm.option('trashHash', targets[0]);
 
- 				}
 
- 			}
 
- 			return thash;
 
- 		},
 
- 		getSize = false;
 
- 	
 
- 	// for to be able to overwrite
 
- 	this.confirm = confirm;
 
- 	this.toTrash = toTrash;
 
- 	this.remove = remove;
 
- 	this.syncTitleOnChange = true;
 
- 	this.updateOnSelect = false;
 
- 	this.shortcuts = [{
 
- 		pattern     : 'delete ctrl+backspace shift+delete'
 
- 	}];
 
- 	this.value = 'rm';
 
- 	
 
- 	this.init = function() {
 
- 		// re-assign for extended command
 
- 		self = this;
 
- 		fm = this.fm;
 
- 		// bind function of change
 
- 		self.change(function() {
 
- 			var targets;
 
- 			delete self.extra;
 
- 			self.title = fm.i18n('cmd' + self.value);
 
- 			self.className = self.value;
 
- 			self.button && self.button.children('span.elfinder-button-icon')[self.value === 'trash'? 'addClass' : 'removeClass']('elfinder-button-icon-trash');
 
- 			if (self.value === 'trash') {
 
- 				self.extra = {
 
- 					icon: 'rm',
 
- 					node: $('<span/>')
 
- 						.attr({title: fm.i18n('cmdrm')})
 
- 						.on('ready', function(e, data) {
 
- 							targets = data.targets;
 
- 						})
 
- 						.on('click touchstart', function(e){
 
- 							if (e.type === 'touchstart' && e.originalEvent.touches.length > 1) {
 
- 								return;
 
- 							}
 
- 							e.stopPropagation();
 
- 							e.preventDefault();
 
- 							fm.getUI().trigger('click'); // to close the context menu immediately
 
- 							fm.exec('rm', targets, {_userAction: true, forceRm : true});
 
- 						})
 
- 				};
 
- 			}
 
- 		});
 
- 	};
 
- 	
 
- 	this.getstate = function(select) {
 
- 		var sel   = this.hashes(select);
 
- 		
 
- 		return sel.length && $.grep(sel, function(h) { var f = fm.file(h); return f && ! f.locked && ! fm.isRoot(f)? true : false; }).length == sel.length
 
- 			? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes, cOpts) {
 
- 		var opts   = cOpts || {},
 
- 			dfrd   = $.Deferred()
 
- 				.always(function() {
 
- 					if (getSize && getSize.state && getSize.state() === 'pending') {
 
- 						getSize.reject();
 
- 					}
 
- 				})
 
- 				.fail(function(error) {
 
- 					error && fm.error(error);
 
- 				}).done(function(data) {
 
- 					!opts.quiet && !data._noSound && data.removed && data.removed.length && fm.trigger('playsound', {soundFile : 'rm.wav'});
 
- 				}),
 
- 			files  = self.files(hashes),
 
- 			cnt    = files.length,
 
- 			tHash  = null,
 
- 			addTexts = opts.addTexts? opts.addTexts : null,
 
- 			forceRm = opts.forceRm,
 
- 			quiet = opts.quiet,
 
- 			targets;
 
- 		if (! cnt) {
 
- 			return dfrd.reject();
 
- 		}
 
- 		
 
- 		$.each(files, function(i, file) {
 
- 			if (fm.isRoot(file)) {
 
- 				return !dfrd.reject(['errRm', file.name, 'errPerm']);
 
- 			}
 
- 			if (file.locked) {
 
- 				return !dfrd.reject(['errLocked', file.name]);
 
- 			}
 
- 		});
 
- 		if (dfrd.state() === 'pending') {
 
- 			targets = self.hashes(hashes);
 
- 			cnt     = files.length;
 
- 			
 
- 			if (forceRm || (self.event && self.event.originalEvent && self.event.originalEvent.shiftKey)) {
 
- 				tHash = '';
 
- 				self.title = fm.i18n('cmdrm');
 
- 			}
 
- 			
 
- 			if (tHash === null) {
 
- 				tHash = getTHash(targets);
 
- 			}
 
- 			
 
- 			fm.lockfiles({files : targets});
 
- 			
 
- 			if (tHash && self.options.quickTrash) {
 
- 				self.toTrash(dfrd, targets, tHash);
 
- 			} else {
 
- 				if (quiet) {
 
- 					remove(dfrd, targets, quiet);
 
- 				} else {
 
- 					self.confirm(dfrd, targets, files, tHash, addTexts);
 
- 				}
 
- 			}
 
- 		}
 
- 			
 
- 		return dfrd;
 
- 	};
 
- 	fm.bind('select contextmenucreate closecontextmenu', function(e) {
 
- 		var targets = (e.data? (e.data.selected || e.data.targets) : null) || fm.selected();
 
- 		if (targets && targets.length) {
 
- 			self.update(void(0), (targets? getTHash(targets) : fm.option('trashHash'))? 'trash' : 'rm');
 
- 		}
 
- 	});
 
- };
 
- /*
 
-  * File: /js/commands/search.js
 
-  */
 
- /**
 
-  * @class  elFinder command "search"
 
-  * Find files
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- elFinder.prototype.commands.search = function() {
 
- 	"use strict";
 
- 	this.title          = 'Find files';
 
- 	this.options        = {ui : 'searchbutton'};
 
- 	this.alwaysEnabled  = true;
 
- 	this.updateOnSelect = false;
 
- 	
 
- 	/**
 
- 	 * Return command status.
 
- 	 * Search does not support old api.
 
- 	 *
 
- 	 * @return Number
 
- 	 **/
 
- 	this.getstate = function() {
 
- 		return 0;
 
- 	};
 
- 	
 
- 	/**
 
- 	 * Send search request to backend.
 
- 	 *
 
- 	 * @param  String  search string
 
- 	 * @return $.Deferred
 
- 	 **/
 
- 	this.exec = function(q, target, mime, type) {
 
- 		var fm = this.fm,
 
- 			reqDef = [],
 
- 			sType = type || '',
 
- 			onlyMimes = fm.options.onlyMimes,
 
- 			phash, targetVolids = [],
 
- 			setType = function(data) {
 
- 				if (sType && sType !== 'SearchName' && sType !== 'SearchMime') {
 
- 					data.type = sType;
 
- 				}
 
- 				return data;
 
- 			};
 
- 		
 
- 		if (typeof q == 'string' && q) {
 
- 			if (typeof target == 'object') {
 
- 				mime = target.mime || '';
 
- 				target = target.target || '';
 
- 			}
 
- 			target = target? target : '';
 
- 			if (mime) {
 
- 				mime = $.trim(mime).replace(',', ' ').split(' ');
 
- 				if (onlyMimes.length) {
 
- 					mime = $.map(mime, function(m){ 
 
- 						m = $.trim(m);
 
- 						return m && ($.inArray(m, onlyMimes) !== -1
 
- 									|| $.grep(onlyMimes, function(om) { return m.indexOf(om) === 0? true : false; }).length
 
- 									)? m : null;
 
- 					});
 
- 				}
 
- 			} else {
 
- 				mime = [].concat(onlyMimes);
 
- 			}
 
- 			fm.trigger('searchstart', setType({query : q, target : target, mimes : mime}));
 
- 			
 
- 			if (! onlyMimes.length || mime.length) {
 
- 				if (target === '' && fm.api >= 2.1) {
 
- 					$.each(fm.roots, function(id, hash) {
 
- 						reqDef.push(fm.request({
 
- 							data   : setType({cmd : 'search', q : q, target : hash, mimes : mime}),
 
- 							notify : {type : 'search', cnt : 1, hideCnt : (reqDef.length? false : true)},
 
- 							cancel : true,
 
- 							preventDone : true
 
- 						}));
 
- 					});
 
- 				} else {
 
- 					reqDef.push(fm.request({
 
- 						data   : setType({cmd : 'search', q : q, target : target, mimes : mime}),
 
- 						notify : {type : 'search', cnt : 1, hideCnt : true},
 
- 						cancel : true,
 
- 						preventDone : true
 
- 					}));
 
- 					if (target !== '' && fm.api >= 2.1 && Object.keys(fm.leafRoots).length) {
 
- 						$.each(fm.leafRoots, function(hash, roots) {
 
- 							phash = hash;
 
- 							while(phash) {
 
- 								if (target === phash) {
 
- 									$.each(roots, function() {
 
- 										var f = fm.file(this);
 
- 										f && f.volumeid && targetVolids.push(f.volumeid);
 
- 										reqDef.push(fm.request({
 
- 											data   : setType({cmd : 'search', q : q, target : this, mimes : mime}),
 
- 											notify : {type : 'search', cnt : 1, hideCnt : false},
 
- 											cancel : true,
 
- 											preventDone : true
 
- 										}));
 
- 									});
 
- 								}
 
- 								phash = (fm.file(phash) || {}).phash;
 
- 							}
 
- 						});
 
- 					}
 
- 				}
 
- 			} else {
 
- 				reqDef = [$.Deferred().resolve({files: []})];
 
- 			}
 
- 			
 
- 			fm.searchStatus.mixed = (reqDef.length > 1)? targetVolids : false;
 
- 			
 
- 			return $.when.apply($, reqDef).done(function(data) {
 
- 				var argLen = arguments.length,
 
- 					i;
 
- 				
 
- 				data.warning && fm.error(data.warning);
 
- 				
 
- 				if (argLen > 1) {
 
- 					data.files = (data.files || []);
 
- 					for(i = 1; i < argLen; i++) {
 
- 						arguments[i].warning && fm.error(arguments[i].warning);
 
- 						
 
- 						if (arguments[i].files) {
 
- 							data.files.push.apply(data.files, arguments[i].files);
 
- 						}
 
- 					}
 
- 				}
 
- 				
 
- 				// because "preventDone : true" so update files cache
 
- 				data.files && data.files.length && fm.cache(data.files);
 
- 				
 
- 				fm.lazy(function() {
 
- 					fm.trigger('search', data);
 
- 				}).then(function() {
 
- 					// fire event with command name + 'done'
 
- 					return fm.lazy(function() {
 
- 						fm.trigger('searchdone');
 
- 					});
 
- 				}).then(function() {
 
- 					// force update content
 
- 					data.sync && fm.sync();
 
- 				});
 
- 			});
 
- 		}
 
- 		fm.getUI('toolbar').find('.'+fm.res('class', 'searchbtn')+' :text').trigger('focus');
 
- 		return $.Deferred().reject();
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/selectall.js
 
-  */
 
- /**
 
-  * @class  elFinder command "selectall"
 
-  * Select ALL of cwd items
 
-  *
 
-  * @author Naoki Sawada
 
-  **/
 
- elFinder.prototype.commands.selectall = function() {
 
- 	"use strict";
 
- 	var self = this,
 
- 		state = 0;
 
- 	
 
- 	this.fm.bind('select', function(e) {
 
- 		state = (e.data && e.data.selectall)? -1 : 0;
 
- 	});
 
- 	
 
- 	this.state = 0;
 
- 	this.updateOnSelect = false;
 
- 	
 
- 	this.getstate = function() {
 
- 		return state;
 
- 	};
 
- 	
 
- 	this.exec = function() {
 
- 		$(document).trigger($.Event('keydown', { keyCode: 65, ctrlKey : true, shiftKey : false, altKey : false, metaKey : false }));
 
- 		return $.Deferred().resolve();
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/selectinvert.js
 
-  */
 
- /**
 
-  * @class  elFinder command "selectinvert"
 
-  * Invert Selection of cwd items
 
-  *
 
-  * @author Naoki Sawada
 
-  **/
 
- elFinder.prototype.commands.selectinvert = function() {
 
- 	"use strict";
 
- 	this.updateOnSelect = false;
 
- 	
 
- 	this.getstate = function() {
 
- 		return 0;
 
- 	};
 
- 	
 
- 	this.exec = function() {
 
- 		$(document).trigger($.Event('keydown', { keyCode: 73, ctrlKey : true, shiftKey : true, altKey : false, metaKey : false }));
 
- 		return $.Deferred().resolve();
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/selectnone.js
 
-  */
 
- /**
 
-  * @class  elFinder command "selectnone"
 
-  * Unselect ALL of cwd items
 
-  *
 
-  * @author Naoki Sawada
 
-  **/
 
- elFinder.prototype.commands.selectnone = function() {
 
- 	"use strict";
 
- 	var self = this,
 
- 		fm = this.fm,
 
- 		state = -1;
 
- 	
 
- 	fm.bind('select', function(e) {
 
- 		state = (e.data && e.data.unselectall)? -1 : 0;
 
- 	});
 
- 	
 
- 	this.state = -1;
 
- 	this.updateOnSelect = false;
 
- 	
 
- 	this.getstate = function() {
 
- 		return state;
 
- 	};
 
- 	
 
- 	this.exec = function() {
 
- 		fm.getUI('cwd').trigger('unselectall');
 
- 		return $.Deferred().resolve();
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/sort.js
 
-  */
 
- /**
 
-  * @class  elFinder command "sort"
 
-  * Change sort files rule
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- elFinder.prototype.commands.sort = function() {
 
- 	"use strict";
 
- 	var self  = this,
 
- 		fm    = self.fm,
 
- 		setVar = function() {
 
- 			self.variants = [];
 
- 			$.each(fm.sortRules, function(name, value) {
 
- 				if (fm.sorters[name]) {
 
- 					var arr = (name === fm.sortType)? (fm.sortOrder === 'asc'? 'n' : 's') : '';
 
- 					self.variants.push([name, (arr? '<span class="ui-icon ui-icon-arrowthick-1-'+arr+'"></span>' : '') + ' ' + fm.i18n('sort'+name)]);
 
- 				}
 
- 			});
 
- 			self.variants.push('|');
 
- 			self.variants.push([
 
- 				'stick',
 
- 				(fm.sortStickFolders? '<span class="ui-icon ui-icon-check"/>' : '') + ' ' + fm.i18n('sortFoldersFirst')
 
- 			]);
 
- 			if (fm.ui.tree) {
 
- 				self.variants.push('|');
 
- 				self.variants.push([
 
- 					'tree',
 
- 					(fm.sortAlsoTreeview? '<span class="ui-icon ui-icon-check"/>' : '') + ' ' + fm.i18n('sortAlsoTreeview')
 
- 				]);
 
- 			}
 
- 			updateContextmenu();
 
- 		},
 
- 		updateContextmenu = function() {
 
- 			var cm = fm.getUI('contextmenu'),
 
- 				icon, sub;
 
- 			if (cm.is(':visible')) {
 
- 				icon = cm.find('span.elfinder-button-icon-sort');
 
- 				sub = icon.siblings('div.elfinder-contextmenu-sub');
 
- 				sub.find('span.ui-icon').remove();
 
- 				sub.children('div.elfinder-contextsubmenu-item').each(function() {
 
- 					var tgt = $(this).children('span'),
 
- 						name = tgt.text().trim(),
 
- 						arr;
 
- 					if (name === (i18Name.stick || (i18Name.stick = fm.i18n('sortFoldersFirst')))) {
 
- 						if (fm.sortStickFolders) {
 
- 							tgt.prepend('<span class="ui-icon ui-icon-check"/>');
 
- 						}
 
- 					} else if (name === (i18Name.tree || (i18Name.tree = fm.i18n('sortAlsoTreeview')))) {
 
- 						if (fm.sortAlsoTreeview) {
 
- 							tgt.prepend('<span class="ui-icon ui-icon-check"/>');
 
- 						}
 
- 					} else if (name === (i18Name[fm.sortType] || (i18Name[fm.sortType] = fm.i18n('sort' + fm.sortType)))) {
 
- 						arr = fm.sortOrder === 'asc'? 'n' : 's';
 
- 						tgt.prepend('<span class="ui-icon ui-icon-arrowthick-1-'+arr+'"></span>');
 
- 					}
 
- 				});
 
- 			}
 
- 		},
 
- 		i18Name = {};
 
- 	
 
- 	/**
 
- 	 * Command options
 
- 	 *
 
- 	 * @type  Object
 
- 	 */
 
- 	this.options = {ui : 'sortbutton'};
 
- 	
 
- 	this.keepContextmenu = true;
 
- 	fm.bind('sortchange', setVar)
 
- 	.bind('sorterupdate', function() {
 
- 		setVar();
 
- 		fm.getUI('toolbar').find('.elfiner-button-sort .elfinder-button-menu .elfinder-button-menu-item').each(function() {
 
- 			var tgt = $(this),
 
- 				rel = tgt.attr('rel');
 
- 			tgt.toggle(! rel || fm.sorters[rel]);
 
- 		});
 
- 	})
 
- 	.bind('cwdrender', function() {
 
- 		var cols = $(fm.cwd).find('div.elfinder-cwd-wrapper-list table');
 
- 		if (cols.length) {
 
- 			$.each(fm.sortRules, function(name, value) {
 
- 				var td = cols.find('thead tr td.elfinder-cwd-view-th-'+name);
 
- 				if (td.length) {
 
- 					var current = ( name == fm.sortType),
 
- 					sort = {
 
- 						type  : name,
 
- 						order : current ? fm.sortOrder == 'asc' ? 'desc' : 'asc' : fm.sortOrder
 
- 					},arr;
 
- 					if (current) {
 
- 						td.addClass('ui-state-active');
 
- 						arr = fm.sortOrder == 'asc' ? 'n' : 's';
 
- 						$('<span class="ui-icon ui-icon-triangle-1-'+arr+'"/>').appendTo(td);
 
- 					}
 
- 					$(td).on('click', function(e){
 
- 						if (! $(this).data('dragging')) {
 
- 							e.stopPropagation();
 
- 							if (! fm.getUI('cwd').data('longtap')) {
 
- 								fm.exec('sort', [], sort);
 
- 							}
 
- 						}
 
- 					})
 
- 					.on('mouseenter mouseleave', function(e) {
 
- 						$(this).toggleClass('ui-state-hover', e.type === 'mouseenter');
 
- 					});
 
- 				}
 
- 				
 
- 			});
 
- 		}
 
- 	});
 
- 	
 
- 	this.getstate = function() {
 
- 		return 0;
 
- 	};
 
- 	
 
- 	this.exec = function(hashes, cOpt) {
 
- 		var fm = this.fm,
 
- 			sortopt = $.isPlainObject(cOpt)? cOpt : (function() {
 
- 				cOpt += '';
 
- 				var sOpts = {};
 
- 				if (cOpt === 'stick') {
 
- 					sOpts.stick = !fm.sortStickFolders;
 
- 				} else if (cOpt === 'tree') {
 
- 					sOpts.tree = !fm.sortAlsoTreeview;
 
- 				} else if (fm.sorters[cOpt]) {
 
- 					if (fm.sortType === cOpt) {
 
- 						sOpts.order = fm.sortOrder === 'asc'? 'desc' : 'asc';
 
- 					} else {
 
- 						sOpts.type = cOpt;
 
- 					}
 
- 				}
 
- 				return sOpts;
 
- 			})(),
 
- 			sort = Object.assign({
 
- 				type  : fm.sortType,
 
- 				order : fm.sortOrder,
 
- 				stick : fm.sortStickFolders,
 
- 				tree  : fm.sortAlsoTreeview
 
- 			}, sortopt);
 
- 		return fm.lazy(function() {
 
- 			fm.setSort(sort.type, sort.order, sort.stick, sort.tree);
 
- 			this.resolve();
 
- 		});
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/undo.js
 
-  */
 
- /**
 
-  * @class  elFinder command "undo"
 
-  * Undo previous commands
 
-  *
 
-  * @author Naoki Sawada
 
-  **/
 
- elFinder.prototype.commands.undo = function() {
 
- 	"use strict";
 
- 	var self = this,
 
- 		fm = this.fm,
 
- 		setTitle = function(undo) {
 
- 			if (undo) {
 
- 				self.title = fm.i18n('cmdundo') + ' ' + fm.i18n('cmd'+undo.cmd);
 
- 				self.state = 0;
 
- 			} else {
 
- 				self.title = fm.i18n('cmdundo');
 
- 				self.state = -1;
 
- 			}
 
- 			self.change();
 
- 		},
 
- 		cmds = [];
 
- 	
 
- 	this.alwaysEnabled  = true;
 
- 	this.updateOnSelect = false;
 
- 	this.shortcuts      = [{
 
- 		pattern     : 'ctrl+z'
 
- 	}];
 
- 	this.syncTitleOnChange = true;
 
- 	
 
- 	this.getstate = function() {
 
- 		return cmds.length? 0 : -1;
 
- 	};
 
- 	
 
- 	this.setUndo = function(undo, redo) {
 
- 		var _undo = {};
 
- 		if (undo) {
 
- 			if ($.isPlainObject(undo) && undo.cmd && undo.callback) {
 
- 				Object.assign(_undo, undo);
 
- 				if (redo) {
 
- 					delete redo.undo;
 
- 					_undo.redo = redo;
 
- 				} else {
 
- 					fm.getCommand('redo').setRedo(null);
 
- 				}
 
- 				cmds.push(_undo);
 
- 				setTitle(_undo);
 
- 			}
 
- 		}
 
- 	};
 
- 	
 
- 	this.exec = function() {
 
- 		var redo = fm.getCommand('redo'),
 
- 			dfd = $.Deferred(),
 
- 			undo, res, _redo = {};
 
- 		if (cmds.length) {
 
- 			undo = cmds.pop();
 
- 			if (undo.redo) {
 
- 				Object.assign(_redo, undo.redo);
 
- 				delete undo.redo;
 
- 			} else {
 
- 				_redo = null;
 
- 			} 
 
- 			dfd.done(function() {
 
- 				if (_redo) {
 
- 					redo.setRedo(_redo, undo);
 
- 				}
 
- 			});
 
- 			
 
- 			setTitle(cmds.length? cmds[cmds.length-1] : void(0));
 
- 			
 
- 			res = undo.callback();
 
- 			
 
- 			if (res && res.done) {
 
- 				res.done(function() {
 
- 					dfd.resolve();
 
- 				}).fail(function() {
 
- 					dfd.reject();
 
- 				});
 
- 			} else {
 
- 				dfd.resolve();
 
- 			}
 
- 			if (cmds.length) {
 
- 				this.update(0, cmds[cmds.length - 1].name);
 
- 			} else {
 
- 				this.update(-1, '');
 
- 			}
 
- 		} else {
 
- 			dfd.reject();
 
- 		}
 
- 		return dfd;
 
- 	};
 
- 	
 
- 	fm.bind('exec', function(e) {
 
- 		var data = e.data || {};
 
- 		if (data.opts && data.opts._userAction) {
 
- 			if (data.dfrd && data.dfrd.done) {
 
- 				data.dfrd.done(function(res) {
 
- 					if (res && res.undo && res.redo) {
 
- 						res.undo.redo = res.redo;
 
- 						self.setUndo(res.undo);
 
- 					}
 
- 				});
 
- 			}
 
- 		}
 
- 	});
 
- };
 
- /**
 
-  * @class  elFinder command "redo"
 
-  * Redo previous commands
 
-  *
 
-  * @author Naoki Sawada
 
-  **/
 
- elFinder.prototype.commands.redo = function() {
 
- 	"use strict";
 
- 	var self = this,
 
- 		fm   = this.fm,
 
- 		setTitle = function(redo) {
 
- 			if (redo && redo.callback) {
 
- 				self.title = fm.i18n('cmdredo') + ' ' + fm.i18n('cmd'+redo.cmd);
 
- 				self.state = 0;
 
- 			} else {
 
- 				self.title = fm.i18n('cmdredo');
 
- 				self.state = -1;
 
- 			}
 
- 			self.change();
 
- 		},
 
- 		cmds = [];
 
- 	
 
- 	this.alwaysEnabled  = true;
 
- 	this.updateOnSelect = false;
 
- 	this.shortcuts      = [{
 
- 		pattern     : 'shift+ctrl+z ctrl+y'
 
- 	}];
 
- 	this.syncTitleOnChange = true;
 
- 	
 
- 	this.getstate = function() {
 
- 		return cmds.length? 0 : -1;
 
- 	};
 
- 	
 
- 	this.setRedo = function(redo, undo) {
 
- 		if (redo === null) {
 
- 			cmds = [];
 
- 			setTitle();
 
- 		} else {
 
- 			if (redo && redo.cmd && redo.callback) {
 
- 				if (undo) {
 
- 					redo.undo = undo;
 
- 				}
 
- 				cmds.push(redo);
 
- 				setTitle(redo);
 
- 			}
 
- 		}
 
- 	};
 
- 	
 
- 	this.exec = function() {
 
- 		var undo = fm.getCommand('undo'),
 
- 			dfd = $.Deferred(),
 
- 			redo, res, _undo = {}, _redo = {};
 
- 		if (cmds.length) {
 
- 			redo = cmds.pop();
 
- 			if (redo.undo) {
 
- 				Object.assign(_undo, redo.undo);
 
- 				Object.assign(_redo, redo);
 
- 				delete _redo.undo;
 
- 				dfd.done(function() {
 
- 					undo.setUndo(_undo, _redo);
 
- 				});
 
- 			}
 
- 			
 
- 			setTitle(cmds.length? cmds[cmds.length-1] : void(0));
 
- 			
 
- 			res = redo.callback();
 
- 			
 
- 			if (res && res.done) {
 
- 				res.done(function() {
 
- 					dfd.resolve();
 
- 				}).fail(function() {
 
- 					dfd.reject();
 
- 				});
 
- 			} else {
 
- 				dfd.resolve();
 
- 			}
 
- 			return dfd;
 
- 		} else {
 
- 			return dfd.reject();
 
- 		}
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/up.js
 
-  */
 
- /**
 
-  * @class  elFinder command "up"
 
-  * Go into parent directory
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- (elFinder.prototype.commands.up = function() {
 
- 	"use strict";
 
- 	this.alwaysEnabled = true;
 
- 	this.updateOnSelect = false;
 
- 	
 
- 	this.shortcuts = [{
 
- 		pattern     : 'ctrl+up'
 
- 	}];
 
- 	
 
- 	this.getstate = function() {
 
- 		return this.fm.cwd().phash ? 0 : -1;
 
- 	};
 
- 	
 
- 	this.exec = function() {
 
- 		var fm = this.fm,
 
- 			cwdhash = fm.cwd().hash;
 
- 		return this.fm.cwd().phash ? this.fm.exec('open', this.fm.cwd().phash).done(function() {
 
- 			fm.one('opendone', function() {
 
- 				fm.selectfiles({files : [cwdhash]});
 
- 			});
 
- 		}) : $.Deferred().reject();
 
- 	};
 
- }).prototype = { forceLoad : true }; // this is required command
 
- /*
 
-  * File: /js/commands/upload.js
 
-  */
 
- /**
 
-  * @class elFinder command "upload"
 
-  * Upload files using iframe or XMLHttpRequest & FormData.
 
-  * Dialog allow to send files using drag and drop
 
-  *
 
-  * @type  elFinder.command
 
-  * @author  Dmitry (dio) Levashov
 
-  */
 
- elFinder.prototype.commands.upload = function() {
 
- 	"use strict";
 
- 	var hover = this.fm.res('class', 'hover');
 
- 	
 
- 	this.disableOnSearch = true;
 
- 	this.updateOnSelect  = false;
 
- 	
 
- 	// Shortcut opens dialog
 
- 	this.shortcuts = [{
 
- 		pattern     : 'ctrl+u'
 
- 	}];
 
- 	
 
- 	/**
 
- 	 * Return command state
 
- 	 *
 
- 	 * @return Number
 
- 	 **/
 
- 	this.getstate = function(select) {
 
- 		var fm = this.fm, f,
 
- 		sel = (select || [fm.cwd().hash]);
 
- 		if (!this._disabled && sel.length == 1) {
 
- 			f = fm.file(sel[0]);
 
- 		}
 
- 		return (f && f.mime == 'directory' && f.write)? 0 : -1;
 
- 	};
 
- 	
 
- 	
 
- 	this.exec = function(data) {
 
- 		var fm = this.fm,
 
- 			cwdHash = fm.cwd().hash,
 
- 			getTargets = function() {
 
- 				var tgts = data && (data instanceof Array)? data : null,
 
- 					sel;
 
- 				if (! data || data instanceof Array) {
 
- 					if (! tgts && (sel = fm.selected()).length === 1 && fm.file(sel[0]).mime === 'directory') {
 
- 						tgts = sel;
 
- 					} else if (!tgts || tgts.length !== 1 || fm.file(tgts[0]).mime !== 'directory') {
 
- 						tgts = [ cwdHash ];
 
- 					}
 
- 				}
 
- 				return tgts;
 
- 			},
 
- 			targets = getTargets(),
 
- 			check = targets? targets[0] : (data && data.target? data.target : null),
 
- 			targetDir = check? fm.file(check) : fm.cwd(),
 
- 			fmUpload = function(data) {
 
- 				fm.upload(data)
 
- 					.fail(function(error) {
 
- 						dfrd.reject(error);
 
- 					})
 
- 					.done(function(data) {
 
- 						var cwd = fm.getUI('cwd'),
 
- 							node;
 
- 						dfrd.resolve(data);
 
- 						if (data && data.added && data.added[0] && ! fm.ui.notify.children('.elfinder-notify-upload').length) {
 
- 							var newItem = fm.findCwdNodes(data.added);
 
- 							if (newItem.length) {
 
- 								newItem.trigger('scrolltoview');
 
- 							} else {
 
- 								if (targetDir.hash !== cwdHash) {
 
- 									node = $('<div/>').append(
 
- 										$('<button type="button" class="ui-button ui-widget ui-state-default ui-corner-all elfinder-tabstop"><span class="ui-button-text">'+fm.i18n('cmdopendir')+'</span></button>')
 
- 										.on('mouseenter mouseleave', function(e) { 
 
- 											$(this).toggleClass('ui-state-hover', e.type == 'mouseenter');
 
- 										}).on('click', function() {
 
- 											fm.exec('open', check).done(function() {
 
- 												fm.one('opendone', function() {
 
- 													fm.trigger('selectfiles', {files : $.map(data.added, function(f) {return f.hash;})});
 
- 												});
 
- 											});
 
- 										})
 
- 									);
 
- 								} else {
 
- 									fm.trigger('selectfiles', {files : $.map(data.added, function(f) {return f.hash;})});
 
- 								}
 
- 								fm.toast({msg: fm.i18n(['complete', fm.i18n('cmdupload')]), extNode: node});
 
- 							}
 
- 						}
 
- 					})
 
- 					.progress(function() {
 
- 						dfrd.notifyWith(this, Array.from(arguments));
 
- 					});
 
- 			},
 
- 			upload = function(data) {
 
- 				dialog.elfinderdialog('close');
 
- 				if (targets) {
 
- 					data.target = targets[0];
 
- 				}
 
- 				fmUpload(data);
 
- 			},
 
- 			getSelector = function() {
 
- 				var hash = targetDir.hash,
 
- 					dirs = $.map(fm.files(hash), function(f) {
 
- 						return (f.mime === 'directory' && f.write)? f : null; 
 
- 					});
 
- 				
 
- 				if (! dirs.length) {
 
- 					return $();
 
- 				}
 
- 				
 
- 				return $('<div class="elfinder-upload-dirselect elfinder-tabstop" title="' + fm.i18n('folders') + '"/>')
 
- 				.on('click', function(e) {
 
- 					e.stopPropagation();
 
- 					e.preventDefault();
 
- 					dirs = fm.sortFiles(dirs);
 
- 					var $this  = $(this),
 
- 						cwd    = fm.cwd(),
 
- 						base   = dialog.closest('div.ui-dialog'),
 
- 						getRaw = function(f, icon) {
 
- 							return {
 
- 								label    : fm.escape(f.i18 || f.name),
 
- 								icon     : icon,
 
- 								remain   : false,
 
- 								callback : function() {
 
- 									var title = base.children('.ui-dialog-titlebar:first').find('span.elfinder-upload-target');
 
- 									targets = [ f.hash ];
 
- 									title.html(' - ' + fm.escape(f.i18 || f.name));
 
- 									$this.trigger('focus');
 
- 								},
 
- 								options  : {
 
- 									className : (targets && targets.length && f.hash === targets[0])? 'ui-state-active' : '',
 
- 									iconClass : f.csscls || '',
 
- 									iconImg   : f.icon   || ''
 
- 								}
 
- 							};
 
- 						},
 
- 						raw = [ getRaw(targetDir, 'opendir'), '|' ];
 
- 					$.each(dirs, function(i, f) {
 
- 						raw.push(getRaw(f, 'dir'));
 
- 					});
 
- 					$this.trigger('blur');
 
- 					fm.trigger('contextmenu', {
 
- 						raw: raw,
 
- 						x: e.pageX || $(this).offset().left,
 
- 						y: e.pageY || $(this).offset().top,
 
- 						prevNode: base,
 
- 						fitHeight: true
 
- 					});
 
- 				}).append('<span class="elfinder-button-icon elfinder-button-icon-dir" />');
 
- 			},
 
- 			inputButton = function(type, caption) {
 
- 				var button,
 
- 					input = $('<input type="file" ' + type + '/>')
 
- 					.on('click', function() {
 
- 						// for IE's bug
 
- 						if (fm.UA.IE) {
 
- 							setTimeout(function() {
 
- 								form.css('display', 'none').css('position', 'relative');
 
- 								requestAnimationFrame(function() {
 
- 									form.css('display', '').css('position', '');
 
- 								});
 
- 							}, 100);
 
- 						}
 
- 					})
 
- 					.on('change', function() {
 
- 						upload({input : input.get(0), type : 'files'});
 
- 					})
 
- 					.on('dragover', function(e) {
 
- 						e.originalEvent.dataTransfer.dropEffect = 'copy';
 
- 					}),
 
- 					form = $('<form/>').append(input);
 
- 				return $('<div class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only elfinder-tabstop elfinder-focus"><span class="ui-button-text">'+fm.i18n(caption)+'</span></div>')
 
- 					.append(form)
 
- 					.on('click', function(e) {
 
- 						if (e.target === this) {
 
- 							e.stopPropagation();
 
- 							e.preventDefault();
 
- 							input.trigger('click');
 
- 						}
 
- 					})
 
- 					.on('mouseenter mouseleave', function(e) {
 
- 						$(this).toggleClass(hover, e.type === 'mouseenter');
 
- 					});
 
- 			},
 
- 			dfrd = $.Deferred(),
 
- 			dialog, dropbox, pastebox, dropUpload, paste, dirs, spinner, uidialog;
 
- 		
 
- 		dropUpload = function(e) {
 
- 			e.stopPropagation();
 
- 			e.preventDefault();
 
- 			var file = false,
 
- 				type = '',
 
- 				elfFrom = null,
 
- 				mycwd = '',
 
- 				data = null,
 
- 				target = e._target || null,
 
- 				trf = e.dataTransfer || null,
 
- 				kind = (trf.items && trf.items.length && trf.items[0].kind)? trf.items[0].kind : '',
 
- 				errors;
 
- 			
 
- 			if (trf) {
 
- 				try {
 
- 					elfFrom = trf.getData('elfinderfrom');
 
- 					if (elfFrom) {
 
- 						mycwd = window.location.href + fm.cwd().hash;
 
- 						if ((!target && elfFrom === mycwd) || target === mycwd) {
 
- 							dfrd.reject();
 
- 							return;
 
- 						}
 
- 					}
 
- 				} catch(e) {}
 
- 				
 
- 				if (kind === 'file' && (trf.items[0].getAsEntry || trf.items[0].webkitGetAsEntry)) {
 
- 					file = trf;
 
- 					type = 'data';
 
- 				} else if (kind !== 'string' && trf.files && trf.files.length && $.inArray('Text', trf.types) === -1) {
 
- 					file = trf.files;
 
- 					type = 'files';
 
- 				} else {
 
- 					try {
 
- 						if ((data = trf.getData('text/html')) && data.match(/<(?:img|a)/i)) {
 
- 							file = [ data ];
 
- 							type = 'html';
 
- 						}
 
- 					} catch(e) {}
 
- 					if (! file) {
 
- 						if (data = trf.getData('text')) {
 
- 							file = [ data ];
 
- 							type = 'text';
 
- 						} else if (trf && trf.files) {
 
- 							// maybe folder uploading but this UA dose not support it
 
- 							kind = 'file';
 
- 						}
 
- 					}
 
- 				}
 
- 			}
 
- 			if (file) {
 
- 				fmUpload({files : file, type : type, target : target, dropEvt : e});
 
- 			} else {
 
- 				errors = ['errUploadNoFiles'];
 
- 				if (kind === 'file') {
 
- 					errors.push('errFolderUpload');
 
- 				}
 
- 				fm.error(errors);
 
- 				dfrd.reject();
 
- 			}
 
- 		};
 
- 		
 
- 		if (!targets && data) {
 
- 			if (data.input || data.files) {
 
- 				data.type = 'files';
 
- 				fmUpload(data);
 
- 			} else if (data.dropEvt) {
 
- 				dropUpload(data.dropEvt);
 
- 			}
 
- 			return dfrd;
 
- 		}
 
- 		
 
- 		paste = function(ev) {
 
- 			var e = ev.originalEvent || ev;
 
- 			var files = [], items = [];
 
- 			var file;
 
- 			if (e.clipboardData) {
 
- 				if (e.clipboardData.items && e.clipboardData.items.length){
 
- 					items = e.clipboardData.items;
 
- 					for (var i=0; i < items.length; i++) {
 
- 						if (e.clipboardData.items[i].kind == 'file') {
 
- 							file = e.clipboardData.items[i].getAsFile();
 
- 							files.push(file);
 
- 						}
 
- 					}
 
- 				} else if (e.clipboardData.files && e.clipboardData.files.length) {
 
- 					files = e.clipboardData.files;
 
- 				}
 
- 				if (files.length) {
 
- 					upload({files : files, type : 'files', clipdata : true});
 
- 					return;
 
- 				}
 
- 			}
 
- 			var my = e.target || e.srcElement;
 
- 			requestAnimationFrame(function() {
 
- 				var type = 'text',
 
- 					src;
 
- 				if (my.innerHTML) {
 
- 					$(my).find('img').each(function(i, v){
 
- 						if (v.src.match(/^webkit-fake-url:\/\//)) {
 
- 							// For Safari's bug.
 
- 							// ref. https://bugs.webkit.org/show_bug.cgi?id=49141
 
- 							//      https://dev.ckeditor.com/ticket/13029
 
- 							$(v).remove();
 
- 						}
 
- 					});
 
- 					
 
- 					if ($(my).find('a,img').length) {
 
- 						type = 'html';
 
- 					}
 
- 					src = my.innerHTML;
 
- 					my.innerHTML = '';
 
- 					upload({files : [ src ], type : type});
 
- 				}
 
- 			});
 
- 		};
 
- 		
 
- 		dialog = $('<div class="elfinder-upload-dialog-wrapper"/>')
 
- 			.append(inputButton('multiple', 'selectForUpload'));
 
- 		
 
- 		if (! fm.UA.Mobile && (function(input) {
 
- 			return (typeof input.webkitdirectory !== 'undefined' || typeof input.directory !== 'undefined');})(document.createElement('input'))) {
 
- 			dialog.append(inputButton('multiple webkitdirectory directory', 'selectFolder'));
 
- 		}
 
- 		
 
- 		if (targetDir.dirs) {
 
- 			if (targetDir.hash === cwdHash || $('#'+fm.navHash2Id(targetDir.hash)).hasClass('elfinder-subtree-loaded')) {
 
- 				getSelector().appendTo(dialog);
 
- 			} else {
 
- 				spinner = $('<div class="elfinder-upload-dirselect" title="' + fm.i18n('nowLoading') + '"/>')
 
- 					.append('<span class="elfinder-button-icon elfinder-button-icon-spinner" />')
 
- 					.appendTo(dialog);
 
- 				fm.request({cmd : 'tree', target : targetDir.hash})
 
- 					.done(function() { 
 
- 						fm.one('treedone', function() {
 
- 							spinner.replaceWith(getSelector());
 
- 							uidialog.elfinderdialog('tabstopsInit');
 
- 						});
 
- 					})
 
- 					.fail(function() {
 
- 						spinner.remove();
 
- 					});
 
- 			}
 
- 		}
 
- 		
 
- 		if (fm.dragUpload) {
 
- 			dropbox = $('<div class="ui-corner-all elfinder-upload-dropbox elfinder-tabstop" contenteditable="true" data-ph="'+fm.i18n('dropPasteFiles')+'"></div>')
 
- 				.on('paste', function(e){
 
- 					paste(e);
 
- 				})
 
- 				.on('mousedown click', function(){
 
- 					$(this).trigger('focus');
 
- 				})
 
- 				.on('focus', function(){
 
- 					this.innerHTML = '';
 
- 				})
 
- 				.on('mouseover', function(){
 
- 					$(this).addClass(hover);
 
- 				})
 
- 				.on('mouseout', function(){
 
- 					$(this).removeClass(hover);
 
- 				})
 
- 				.on('dragenter', function(e) {
 
- 					e.stopPropagation();
 
- 				  	e.preventDefault();
 
- 				  	$(this).addClass(hover);
 
- 				})
 
- 				.on('dragleave', function(e) {
 
- 					e.stopPropagation();
 
- 				  	e.preventDefault();
 
- 				  	$(this).removeClass(hover);
 
- 				})
 
- 				.on('dragover', function(e) {
 
- 					e.stopPropagation();
 
- 				  	e.preventDefault();
 
- 					e.originalEvent.dataTransfer.dropEffect = 'copy';
 
- 					$(this).addClass(hover);
 
- 				})
 
- 				.on('drop', function(e) {
 
- 					dialog.elfinderdialog('close');
 
- 					targets && (e.originalEvent._target = targets[0]);
 
- 					dropUpload(e.originalEvent);
 
- 				})
 
- 				.prependTo(dialog)
 
- 				.after('<div class="elfinder-upload-dialog-or">'+fm.i18n('or')+'</div>')[0];
 
- 			
 
- 		} else {
 
- 			pastebox = $('<div class="ui-corner-all elfinder-upload-dropbox" contenteditable="true">'+fm.i18n('dropFilesBrowser')+'</div>')
 
- 				.on('paste drop', function(e){
 
- 					paste(e);
 
- 				})
 
- 				.on('mousedown click', function(){
 
- 					$(this).trigger('focus');
 
- 				})
 
- 				.on('focus', function(){
 
- 					this.innerHTML = '';
 
- 				})
 
- 				.on('dragenter mouseover', function(){
 
- 					$(this).addClass(hover);
 
- 				})
 
- 				.on('dragleave mouseout', function(){
 
- 					$(this).removeClass(hover);
 
- 				})
 
- 				.prependTo(dialog)
 
- 				.after('<div class="elfinder-upload-dialog-or">'+fm.i18n('or')+'</div>')[0];
 
- 			
 
- 		}
 
- 		
 
- 		uidialog = this.fmDialog(dialog, {
 
- 			title          : this.title + '<span class="elfinder-upload-target">' + (targetDir? ' - ' + fm.escape(targetDir.i18 || targetDir.name) : '') + '</span>',
 
- 			modal          : true,
 
- 			resizable      : false,
 
- 			destroyOnClose : true,
 
- 			propagationEvents : ['mousemove', 'mouseup', 'click'],
 
- 			close          : function() {
 
- 				var cm = fm.getUI('contextmenu');
 
- 				if (cm.is(':visible')) {
 
- 					cm.click();
 
- 				}
 
- 			}
 
- 		});
 
- 		
 
- 		return dfrd;
 
- 	};
 
- };
 
- /*
 
-  * File: /js/commands/view.js
 
-  */
 
- /**
 
-  * @class  elFinder command "view"
 
-  * Change current directory view (icons/list)
 
-  *
 
-  * @author Dmitry (dio) Levashov
 
-  **/
 
- elFinder.prototype.commands.view = function() {
 
- 	"use strict";
 
- 	var self = this,
 
- 		fm = this.fm,
 
- 		subMenuRaw;
 
- 	this.value          = fm.viewType;
 
- 	this.alwaysEnabled  = true;
 
- 	this.updateOnSelect = false;
 
- 	this.options = { ui : 'viewbutton'};
 
- 	
 
- 	this.getstate = function() {
 
- 		return 0;
 
- 	};
 
- 	
 
- 	this.extra = {
 
- 		icon: 'menu',
 
- 		node: $('<span/>')
 
- 			.attr({title: fm.i18n('viewtype')})
 
- 			.on('click touchstart', function(e){
 
- 				if (e.type === 'touchstart' && e.originalEvent.touches.length > 1) {
 
- 					return;
 
- 				}
 
- 				var node = $(this);
 
- 				e.stopPropagation();
 
- 				e.preventDefault();
 
- 				fm.trigger('contextmenu', {
 
- 					raw: getSubMenuRaw(),
 
- 					x: node.offset().left,
 
- 					y: node.offset().top
 
- 				});
 
- 			})
 
- 	};
 
- 	this.exec = function() {
 
- 		var self  = this,
 
- 			value = fm.storage('view', this.value == 'list' ? 'icons' : 'list');
 
- 		return fm.lazy(function() {
 
- 			fm.viewchange();
 
- 			self.update(void(0), value);
 
- 			this.resolve();
 
- 		});
 
- 	};
 
- 	fm.bind('init', function() {
 
- 		subMenuRaw = (function() {
 
- 			var cwd = fm.getUI('cwd'),
 
- 				raws = [],
 
- 				sizeNames = fm.options.uiOptions.cwd.iconsView.sizeNames,
 
- 				max = fm.options.uiOptions.cwd.iconsView.sizeMax,
 
- 				i, size;
 
- 			for (i = 0; i <= max; i++) {
 
- 				raws.push(
 
- 					{
 
- 						label    : fm.i18n(sizeNames[i] || ('Size-' + i + ' icons')),
 
- 						icon     : 'view',
 
- 						callback : (function(s) {
 
- 							return function() {
 
- 								cwd.trigger('iconpref', {size: s});
 
- 								fm.storage('iconsize', s);
 
- 								if (self.value === 'list') {
 
- 									self.exec();
 
- 								}
 
- 							};
 
- 						})(i)
 
- 					}
 
- 				);
 
- 			}
 
- 			raws.push('|');
 
- 			raws.push(
 
- 				{
 
- 					label    : fm.i18n('viewlist'),
 
- 					icon     : 'view-list',
 
- 					callback : function() {
 
- 						if (self.value !== 'list') {
 
- 							self.exec();
 
- 						}
 
- 					}
 
- 				}		
 
- 			);
 
- 			return raws;
 
- 		})();
 
- 	}).bind('contextmenucreate', function() {
 
- 		self.extra = {
 
- 			icon: 'menu',
 
- 			node: $('<span/>')
 
- 				.attr({title: fm.i18n('cmdview')})
 
- 				.on('click touchstart', function(e){
 
- 					if (e.type === 'touchstart' && e.originalEvent.touches.length > 1) {
 
- 						return;
 
- 					}
 
- 					var node = $(this),
 
- 						raw = subMenuRaw.concat(),
 
- 						idx, i;
 
- 					if (self.value === 'list') {
 
- 						idx = subMenuRaw.length - 1;
 
- 					} else {
 
- 						idx = parseInt(fm.storage('iconsize') || 0);
 
- 					}
 
- 					for (i = 0; i < subMenuRaw.length; i++) {
 
- 						if (subMenuRaw[i] !== '|') {
 
- 							subMenuRaw[i].options = (i === idx? {'className': 'ui-state-active'} : void(0))
 
- 							;
 
- 						}
 
- 					}
 
- 					e.stopPropagation();
 
- 					e.preventDefault();
 
- 					fm.trigger('contextmenu', {
 
- 						raw: subMenuRaw,
 
- 						x: node.offset().left,
 
- 						y: node.offset().top
 
- 					});
 
- 				})
 
- 		};
 
- 	});
 
- };
 
- return elFinder;
 
- }));
 
 
  |