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;
- }));
|