elfinder.full.js 287 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519
  1. /*!
  2. * elFinder - file manager for web
  3. * Version 2.1 (Nightly: 093d077) (2013-12-05)
  4. * http://elfinder.org
  5. *
  6. * Copyright 2009-2013, Studio 42
  7. * Licensed under a 3 clauses BSD license
  8. */
  9. (function($) {
  10. /*
  11. * File: /home/osc/elFinder-build/elFinder/js/elFinder.js
  12. */
  13. /**
  14. * @class elFinder - file manager for web
  15. *
  16. * @author Dmitry (dio) Levashov
  17. **/
  18. window.elFinder = function(node, opts) {
  19. this.time('load');
  20. var self = this,
  21. /**
  22. * Node on which elfinder creating
  23. *
  24. * @type jQuery
  25. **/
  26. node = $(node),
  27. /**
  28. * Store node contents.
  29. *
  30. * @see this.destroy
  31. * @type jQuery
  32. **/
  33. prevContent = $('<div/>').append(node.contents()),
  34. /**
  35. * Store node inline styles
  36. *
  37. * @see this.destroy
  38. * @type String
  39. **/
  40. prevStyle = node.attr('style'),
  41. /**
  42. * Instance ID. Required to get/set cookie
  43. *
  44. * @type String
  45. **/
  46. id = node.attr('id') || '',
  47. /**
  48. * Events namespace
  49. *
  50. * @type String
  51. **/
  52. namespace = 'elfinder-'+(id || Math.random().toString().substr(2, 7)),
  53. /**
  54. * Mousedown event
  55. *
  56. * @type String
  57. **/
  58. mousedown = 'mousedown.'+namespace,
  59. /**
  60. * Keydown event
  61. *
  62. * @type String
  63. **/
  64. keydown = 'keydown.'+namespace,
  65. /**
  66. * Keypress event
  67. *
  68. * @type String
  69. **/
  70. keypress = 'keypress.'+namespace,
  71. /**
  72. * Is shortcuts/commands enabled
  73. *
  74. * @type Boolean
  75. **/
  76. enabled = true,
  77. /**
  78. * Store enabled value before ajax requiest
  79. *
  80. * @type Boolean
  81. **/
  82. prevEnabled = true,
  83. /**
  84. * List of build-in events which mapped into methods with same names
  85. *
  86. * @type Array
  87. **/
  88. events = ['enable', 'disable', 'load', 'open', 'reload', 'select', 'add', 'remove', 'change', 'dblclick', 'getfile', 'lockfiles', 'unlockfiles', 'dragstart', 'dragstop'],
  89. /**
  90. * Rules to validate data from backend
  91. *
  92. * @type Object
  93. **/
  94. rules = {},
  95. /**
  96. * Current working directory hash
  97. *
  98. * @type String
  99. **/
  100. cwd = '',
  101. /**
  102. * Current working directory options
  103. *
  104. * @type Object
  105. **/
  106. cwdOptions = {
  107. path : '',
  108. url : '',
  109. tmbUrl : '',
  110. disabled : [],
  111. separator : '/',
  112. archives : [],
  113. extract : [],
  114. copyOverwrite : true,
  115. uploadMaxSize : 0,
  116. tmb : false // old API
  117. },
  118. /**
  119. * Files/dirs cache
  120. *
  121. * @type Object
  122. **/
  123. files = {},
  124. /**
  125. * Selected files hashes
  126. *
  127. * @type Array
  128. **/
  129. selected = [],
  130. /**
  131. * Events listeners
  132. *
  133. * @type Object
  134. **/
  135. listeners = {},
  136. /**
  137. * Shortcuts
  138. *
  139. * @type Object
  140. **/
  141. shortcuts = {},
  142. /**
  143. * Buffer for copied files
  144. *
  145. * @type Array
  146. **/
  147. clipboard = [],
  148. /**
  149. * Copied/cuted files hashes
  150. * Prevent from remove its from cache.
  151. * Required for dispaly correct files names in error messages
  152. *
  153. * @type Array
  154. **/
  155. remember = [],
  156. /**
  157. * Queue for 'open' requests
  158. *
  159. * @type Array
  160. **/
  161. queue = [],
  162. /**
  163. * Commands prototype
  164. *
  165. * @type Object
  166. **/
  167. base = new self.command(self),
  168. /**
  169. * elFinder node width
  170. *
  171. * @type String
  172. * @default "auto"
  173. **/
  174. width = 'auto',
  175. /**
  176. * elFinder node height
  177. *
  178. * @type Number
  179. * @default 400
  180. **/
  181. height = 400,
  182. beeper = $(document.createElement('audio')).hide().appendTo('body')[0],
  183. syncInterval,
  184. open = function(data) {
  185. if (data.init) {
  186. // init - reset cache
  187. files = {};
  188. } else {
  189. // remove only files from prev cwd
  190. for (var i in files) {
  191. if (files.hasOwnProperty(i)
  192. && files[i].mime != 'directory'
  193. && files[i].phash == cwd
  194. && $.inArray(i, remember) === -1) {
  195. delete files[i];
  196. }
  197. }
  198. }
  199. cwd = data.cwd.hash;
  200. cache(data.files);
  201. if (!files[cwd]) {
  202. cache([data.cwd]);
  203. }
  204. self.lastDir(cwd);
  205. },
  206. /**
  207. * Store info about files/dirs in "files" object.
  208. *
  209. * @param Array files
  210. * @return void
  211. **/
  212. cache = function(data) {
  213. var l = data.length, f;
  214. while (l--) {
  215. f = data[l];
  216. if (f.name && f.hash && f.mime) {
  217. if (!f.phash) {
  218. var name = 'volume_'+f.name,
  219. i18 = self.i18n(name);
  220. if (name != i18) {
  221. f.i18 = i18;
  222. }
  223. }
  224. files[f.hash] = f;
  225. }
  226. }
  227. },
  228. /**
  229. * Exec shortcut
  230. *
  231. * @param jQuery.Event keydown/keypress event
  232. * @return void
  233. */
  234. execShortcut = function(e) {
  235. var code = e.keyCode,
  236. ctrlKey = !!(e.ctrlKey || e.metaKey);
  237. if (enabled) {
  238. $.each(shortcuts, function(i, shortcut) {
  239. if (shortcut.type == e.type
  240. && shortcut.keyCode == code
  241. && shortcut.shiftKey == e.shiftKey
  242. && shortcut.ctrlKey == ctrlKey
  243. && shortcut.altKey == e.altKey) {
  244. e.preventDefault()
  245. e.stopPropagation();
  246. shortcut.callback(e, self);
  247. self.debug('shortcut-exec', i+' : '+shortcut.description);
  248. }
  249. });
  250. // prevent tab out of elfinder
  251. if (code == 9 && !$(e.target).is(':input')) {
  252. e.preventDefault();
  253. }
  254. }
  255. },
  256. date = new Date(),
  257. utc,
  258. i18n
  259. ;
  260. /**
  261. * Protocol version
  262. *
  263. * @type String
  264. **/
  265. this.api = null;
  266. /**
  267. * elFinder use new api
  268. *
  269. * @type Boolean
  270. **/
  271. this.newAPI = false;
  272. /**
  273. * elFinder use old api
  274. *
  275. * @type Boolean
  276. **/
  277. this.oldAPI = false;
  278. /**
  279. * User os. Required to bind native shortcuts for open/rename
  280. *
  281. * @type String
  282. **/
  283. this.OS = navigator.userAgent.indexOf('Mac') !== -1 ? 'mac' : navigator.userAgent.indexOf('Win') !== -1 ? 'win' : 'other';
  284. /**
  285. * User browser UA.
  286. * jQuery.browser: version deprecated: 1.3, removed: 1.9
  287. *
  288. * @type Object
  289. **/
  290. this.UA = (function(){
  291. var webkit = !document.uniqueID && !window.opera && !window.sidebar && window.localStorage && typeof window.orientation == "undefined";
  292. return {
  293. // Browser IE <= IE 6
  294. ltIE6:typeof window.addEventListener == "undefined" && typeof document.documentElement.style.maxHeight == "undefined",
  295. // Browser IE <= IE 7
  296. ltIE7:typeof window.addEventListener == "undefined" && typeof document.querySelectorAll == "undefined",
  297. // Browser IE <= IE 8
  298. ltIE8:typeof window.addEventListener == "undefined" && typeof document.getElementsByClassName == "undefined",
  299. IE:document.uniqueID,
  300. Firefox:window.sidebar,
  301. Opera:window.opera,
  302. Webkit:webkit,
  303. Chrome:webkit && window.chrome,
  304. Safari:webkit && !window.chrome,
  305. Mobile:typeof window.orientation != "undefined"
  306. }
  307. })();
  308. /**
  309. * Configuration options
  310. *
  311. * @type Object
  312. **/
  313. this.options = $.extend(true, {}, this._options, opts||{});
  314. if (opts.ui) {
  315. this.options.ui = opts.ui;
  316. }
  317. if (opts.commands) {
  318. this.options.commands = opts.commands;
  319. }
  320. if (opts.uiOptions && opts.uiOptions.toolbar) {
  321. this.options.uiOptions.toolbar = opts.uiOptions.toolbar;
  322. }
  323. $.extend(this.options.contextmenu, opts.contextmenu);
  324. /**
  325. * Ajax request type
  326. *
  327. * @type String
  328. * @default "get"
  329. **/
  330. this.requestType = /^(get|post)$/i.test(this.options.requestType) ? this.options.requestType.toLowerCase() : 'get',
  331. /**
  332. * Any data to send across every ajax request
  333. *
  334. * @type Object
  335. * @default {}
  336. **/
  337. this.customData = $.isPlainObject(this.options.customData) ? this.options.customData : {};
  338. /**
  339. * ID. Required to create unique cookie name
  340. *
  341. * @type String
  342. **/
  343. this.id = id;
  344. /**
  345. * URL to upload files
  346. *
  347. * @type String
  348. **/
  349. this.uploadURL = opts.urlUpload || opts.url;
  350. /**
  351. * Events namespace
  352. *
  353. * @type String
  354. **/
  355. this.namespace = namespace;
  356. /**
  357. * Interface language
  358. *
  359. * @type String
  360. * @default "en"
  361. **/
  362. this.lang = this.i18[this.options.lang] && this.i18[this.options.lang].messages ? this.options.lang : 'en';
  363. i18n = this.lang == 'en'
  364. ? this.i18['en']
  365. : $.extend(true, {}, this.i18['en'], this.i18[this.lang]);
  366. /**
  367. * Interface direction
  368. *
  369. * @type String
  370. * @default "ltr"
  371. **/
  372. this.direction = i18n.direction;
  373. /**
  374. * i18 messages
  375. *
  376. * @type Object
  377. **/
  378. this.messages = i18n.messages;
  379. /**
  380. * Date/time format
  381. *
  382. * @type String
  383. * @default "m.d.Y"
  384. **/
  385. this.dateFormat = this.options.dateFormat || i18n.dateFormat;
  386. /**
  387. * Date format like "Yesterday 10:20:12"
  388. *
  389. * @type String
  390. * @default "{day} {time}"
  391. **/
  392. this.fancyFormat = this.options.fancyDateFormat || i18n.fancyDateFormat;
  393. /**
  394. * Today timestamp
  395. *
  396. * @type Number
  397. **/
  398. this.today = (new Date(date.getFullYear(), date.getMonth(), date.getDate())).getTime()/1000;
  399. /**
  400. * Yesterday timestamp
  401. *
  402. * @type Number
  403. **/
  404. this.yesterday = this.today - 86400;
  405. utc = this.options.UTCDate ? 'UTC' : '';
  406. this.getHours = 'get'+utc+'Hours';
  407. this.getMinutes = 'get'+utc+'Minutes';
  408. this.getSeconds = 'get'+utc+'Seconds';
  409. this.getDate = 'get'+utc+'Date';
  410. this.getDay = 'get'+utc+'Day';
  411. this.getMonth = 'get'+utc+'Month';
  412. this.getFullYear = 'get'+utc+'FullYear';
  413. /**
  414. * Css classes
  415. *
  416. * @type String
  417. **/
  418. this.cssClass = 'ui-helper-reset ui-helper-clearfix ui-widget ui-widget-content ui-corner-all elfinder elfinder-'+(this.direction == 'rtl' ? 'rtl' : 'ltr')+' '+this.options.cssClass;
  419. /**
  420. * Method to store/fetch data
  421. *
  422. * @type Function
  423. **/
  424. this.storage = (function() {
  425. try {
  426. return 'localStorage' in window && window['localStorage'] !== null ? self.localStorage : self.cookie;
  427. } catch (e) {
  428. return self.cookie;
  429. }
  430. })();
  431. this.viewType = this.storage('view') || this.options.defaultView || 'icons';
  432. this.sortType = this.storage('sortType') || this.options.sortType || 'name';
  433. this.sortOrder = this.storage('sortOrder') || this.options.sortOrder || 'asc';
  434. this.sortStickFolders = this.storage('sortStickFolders');
  435. if (this.sortStickFolders === null) {
  436. this.sortStickFolders = !!this.options.sortStickFolders;
  437. } else {
  438. this.sortStickFolders = !!this.sortStickFolders
  439. }
  440. this.sortRules = $.extend(true, {}, this._sortRules, this.options.sortsRules);
  441. $.each(this.sortRules, function(name, method) {
  442. if (typeof method != 'function') {
  443. delete self.sortRules[name];
  444. }
  445. });
  446. this.compare = $.proxy(this.compare, this);
  447. /**
  448. * Delay in ms before open notification dialog
  449. *
  450. * @type Number
  451. * @default 500
  452. **/
  453. this.notifyDelay = this.options.notifyDelay > 0 ? parseInt(this.options.notifyDelay) : 500;
  454. /**
  455. * Base draggable options
  456. *
  457. * @type Object
  458. **/
  459. this.draggable = {
  460. appendTo : 'body',
  461. addClasses : true,
  462. delay : 30,
  463. revert : true,
  464. refreshPositions : true,
  465. cursor : 'move',
  466. cursorAt : {left : 50, top : 47},
  467. drag : function(e, ui) {
  468. if (! ui.helper.data('locked')) {
  469. ui.helper.toggleClass('elfinder-drag-helper-plus', e.shiftKey||e.ctrlKey||e.metaKey);
  470. }
  471. },
  472. start : function(e, ui) {
  473. var targets = $.map(ui.helper.data('files')||[], function(h) { return h || null ;}),
  474. cnt, h;
  475. cnt = targets.length;
  476. while (cnt--) {
  477. h = targets[cnt];
  478. if (files[h].locked) {
  479. ui.helper.addClass('elfinder-drag-helper-plus').data('locked', true);
  480. break;
  481. }
  482. }
  483. },
  484. stop : function() { self.trigger('focus').trigger('dragstop'); },
  485. helper : function(e, ui) {
  486. var element = this.id ? $(this) : $(this).parents('[id]:first'),
  487. helper = $('<div class="elfinder-drag-helper"><span class="elfinder-drag-helper-icon-plus"/></div>'),
  488. icon = function(mime) { return '<div class="elfinder-cwd-icon '+self.mime2class(mime)+' ui-corner-all"/>'; },
  489. hashes, l;
  490. self.trigger('dragstart', {target : element[0], originalEvent : e});
  491. hashes = element.is('.'+self.res('class', 'cwdfile'))
  492. ? self.selected()
  493. : [self.navId2Hash(element.attr('id'))];
  494. helper.append(icon(files[hashes[0]].mime)).data('files', hashes).data('locked', false);
  495. if ((l = hashes.length) > 1) {
  496. helper.append(icon(files[hashes[l-1]].mime) + '<span class="elfinder-drag-num">'+l+'</span>');
  497. }
  498. return helper;
  499. }
  500. };
  501. /**
  502. * Base droppable options
  503. *
  504. * @type Object
  505. **/
  506. this.droppable = {
  507. // greedy : true,
  508. tolerance : 'pointer',
  509. accept : '.elfinder-cwd-file-wrapper,.elfinder-navbar-dir,.elfinder-cwd-file',
  510. hoverClass : this.res('class', 'adroppable'),
  511. drop : function(e, ui) {
  512. var dst = $(this),
  513. targets = $.map(ui.helper.data('files')||[], function(h) { return h || null }),
  514. result = [],
  515. c = 'class',
  516. cnt, hash, i, h;
  517. if (dst.is('.'+self.res(c, 'cwd'))) {
  518. hash = cwd;
  519. } else if (dst.is('.'+self.res(c, 'cwdfile'))) {
  520. hash = dst.attr('id');
  521. } else if (dst.is('.'+self.res(c, 'navdir'))) {
  522. hash = self.navId2Hash(dst.attr('id'));
  523. }
  524. cnt = targets.length;
  525. while (cnt--) {
  526. h = targets[cnt];
  527. // ignore drop into itself or in own location
  528. h != hash && files[h].phash != hash && result.push(h);
  529. }
  530. if (result.length) {
  531. ui.helper.hide();
  532. self.clipboard(result, !(e.ctrlKey||e.shiftKey||e.metaKey||ui.helper.data('locked')));
  533. self.exec('paste', hash);
  534. self.trigger('drop', {files : targets});
  535. }
  536. }
  537. };
  538. /**
  539. * Return true if filemanager is active
  540. *
  541. * @return Boolean
  542. **/
  543. this.enabled = function() {
  544. return node.is(':visible') && enabled;
  545. }
  546. /**
  547. * Return true if filemanager is visible
  548. *
  549. * @return Boolean
  550. **/
  551. this.visible = function() {
  552. return node.is(':visible');
  553. }
  554. /**
  555. * Return root dir hash for current working directory
  556. *
  557. * @return String
  558. */
  559. this.root = function(hash) {
  560. var dir = files[hash || cwd], i;
  561. while (dir && dir.phash) {
  562. dir = files[dir.phash]
  563. }
  564. if (dir) {
  565. return dir.hash;
  566. }
  567. while (i in files && files.hasOwnProperty(i)) {
  568. dir = files[i]
  569. if (!dir.phash && !dir.mime == 'directory' && dir.read) {
  570. return dir.hash
  571. }
  572. }
  573. return '';
  574. }
  575. /**
  576. * Return current working directory info
  577. *
  578. * @return Object
  579. */
  580. this.cwd = function() {
  581. return files[cwd] || {};
  582. }
  583. /**
  584. * Return required cwd option
  585. *
  586. * @param String option name
  587. * @return mixed
  588. */
  589. this.option = function(name) {
  590. return cwdOptions[name]||'';
  591. }
  592. /**
  593. * Return file data from current dir or tree by it's hash
  594. *
  595. * @param String file hash
  596. * @return Object
  597. */
  598. this.file = function(hash) {
  599. return files[hash];
  600. };
  601. /**
  602. * Return all cached files
  603. *
  604. * @return Array
  605. */
  606. this.files = function() {
  607. return $.extend(true, {}, files);
  608. }
  609. /**
  610. * Return list of file parents hashes include file hash
  611. *
  612. * @param String file hash
  613. * @return Array
  614. */
  615. this.parents = function(hash) {
  616. var parents = [],
  617. dir;
  618. while ((dir = this.file(hash))) {
  619. parents.unshift(dir.hash);
  620. hash = dir.phash;
  621. }
  622. return parents;
  623. }
  624. this.path2array = function(hash, i18) {
  625. var file,
  626. path = [];
  627. while (hash && (file = files[hash]) && file.hash) {
  628. path.unshift(i18 && file.i18 ? file.i18 : file.name);
  629. hash = file.phash;
  630. }
  631. return path;
  632. }
  633. /**
  634. * Return file path
  635. *
  636. * @param Object file
  637. * @return String
  638. */
  639. this.path = function(hash, i18) {
  640. return files[hash] && files[hash].path
  641. ? files[hash].path
  642. : this.path2array(hash, i18).join(cwdOptions.separator);
  643. }
  644. /**
  645. * Return file url if set
  646. *
  647. * @param Object file
  648. * @return String
  649. */
  650. this.url = function(hash) {
  651. var file = files[hash];
  652. if (!file || !file.read) {
  653. return '';
  654. }
  655. if (file.url) {
  656. return file.url;
  657. }
  658. if (cwdOptions.url) {
  659. return cwdOptions.url + $.map(this.path2array(hash), function(n) { return encodeURIComponent(n); }).slice(1).join('/')
  660. }
  661. var params = $.extend({}, this.customData, {
  662. cmd: 'file',
  663. target: file.hash
  664. });
  665. if (this.oldAPI) {
  666. params.cmd = 'open';
  667. params.current = file.phash;
  668. }
  669. return this.options.url + (this.options.url.indexOf('?') === -1 ? '?' : '&') + $.param(params, true);
  670. }
  671. /**
  672. * Return thumbnail url
  673. *
  674. * @param String file hash
  675. * @return String
  676. */
  677. this.tmb = function(hash) {
  678. var file = files[hash],
  679. url = file && file.tmb && file.tmb != 1 ? cwdOptions['tmbUrl'] + file.tmb : '';
  680. if (url && (this.UA.Opera || this.UA.IE)) {
  681. url += '?_=' + new Date().getTime();
  682. }
  683. return url;
  684. }
  685. /**
  686. * Return selected files hashes
  687. *
  688. * @return Array
  689. **/
  690. this.selected = function() {
  691. return selected.slice(0);
  692. }
  693. /**
  694. * Return selected files info
  695. *
  696. * @return Array
  697. */
  698. this.selectedFiles = function() {
  699. return $.map(selected, function(hash) { return files[hash] ? $.extend({}, files[hash]) : null });
  700. };
  701. /**
  702. * Return true if file with required name existsin required folder
  703. *
  704. * @param String file name
  705. * @param String parent folder hash
  706. * @return Boolean
  707. */
  708. this.fileByName = function(name, phash) {
  709. var hash;
  710. for (hash in files) {
  711. if (files.hasOwnProperty(hash) && files[hash].phash == phash && files[hash].name == name) {
  712. return files[hash];
  713. }
  714. }
  715. };
  716. /**
  717. * Valid data for required command based on rules
  718. *
  719. * @param String command name
  720. * @param Object cammand's data
  721. * @return Boolean
  722. */
  723. this.validResponse = function(cmd, data) {
  724. return data.error || this.rules[this.rules[cmd] ? cmd : 'defaults'](data);
  725. }
  726. /**
  727. * Return bytes from ini formated size
  728. *
  729. * @param String ini formated size
  730. * @return Integer
  731. */
  732. this.returnBytes = function(val) {
  733. if (val == '-1') val = 0;
  734. if (val) {
  735. // for ex. 1mb, 1KB
  736. val = val.replace(/b$/i, '');
  737. var last = val.charAt(val.length - 1).toLowerCase();
  738. val = val.replace(/[gmk]$/i, '');
  739. if (last == 'g') {
  740. val = val * 1024 * 1024 * 1024;
  741. } else if (last == 'm') {
  742. val = val * 1024 * 1024;
  743. } else if (last == 'k') {
  744. val = val * 1024;
  745. }
  746. }
  747. return val;
  748. };
  749. /**
  750. * Proccess ajax request.
  751. * Fired events :
  752. * @todo
  753. * @example
  754. * @todo
  755. * @return $.Deferred
  756. */
  757. this.request = function(options) {
  758. var self = this,
  759. o = this.options,
  760. dfrd = $.Deferred(),
  761. // request data
  762. data = $.extend({}, o.customData, {mimes : o.onlyMimes}, options.data || options),
  763. // command name
  764. cmd = data.cmd,
  765. // call default fail callback (display error dialog) ?
  766. deffail = !(options.preventDefault || options.preventFail),
  767. // call default success callback ?
  768. defdone = !(options.preventDefault || options.preventDone),
  769. // options for notify dialog
  770. notify = $.extend({}, options.notify),
  771. // do not normalize data - return as is
  772. raw = !!options.raw,
  773. // sync files on request fail
  774. syncOnFail = options.syncOnFail,
  775. // open notify dialog timeout
  776. timeout,
  777. // request options
  778. options = $.extend({
  779. url : o.url,
  780. async : true,
  781. type : this.requestType,
  782. dataType : 'json',
  783. cache : false,
  784. // timeout : 100,
  785. data : data
  786. }, options.options || {}),
  787. /**
  788. * Default success handler.
  789. * Call default data handlers and fire event with command name.
  790. *
  791. * @param Object normalized response data
  792. * @return void
  793. **/
  794. done = function(data) {
  795. data.warning && self.error(data.warning);
  796. cmd == 'open' && open($.extend(true, {}, data));
  797. // fire some event to update cache/ui
  798. data.removed && data.removed.length && self.remove(data);
  799. data.added && data.added.length && self.add(data);
  800. data.changed && data.changed.length && self.change(data);
  801. // fire event with command name
  802. self.trigger(cmd, data);
  803. // force update content
  804. data.sync && self.sync();
  805. },
  806. /**
  807. * Request error handler. Reject dfrd with correct error message.
  808. *
  809. * @param jqxhr request object
  810. * @param String request status
  811. * @return void
  812. **/
  813. error = function(xhr, status) {
  814. var error;
  815. switch (status) {
  816. case 'abort':
  817. error = xhr.quiet ? '' : ['errConnect', 'errAbort'];
  818. break;
  819. case 'timeout':
  820. error = ['errConnect', 'errTimeout'];
  821. break;
  822. case 'parsererror':
  823. error = ['errResponse', 'errDataNotJSON'];
  824. break;
  825. default:
  826. if (xhr.status == 403) {
  827. error = ['errConnect', 'errAccess'];
  828. } else if (xhr.status == 404) {
  829. error = ['errConnect', 'errNotFound'];
  830. } else {
  831. error = 'errConnect';
  832. }
  833. }
  834. dfrd.reject(error, xhr, status);
  835. },
  836. /**
  837. * Request success handler. Valid response data and reject/resolve dfrd.
  838. *
  839. * @param Object response data
  840. * @param String request status
  841. * @return void
  842. **/
  843. success = function(response) {
  844. if (raw) {
  845. return dfrd.resolve(response);
  846. }
  847. if (!response) {
  848. return dfrd.reject(['errResponse', 'errDataEmpty'], xhr);
  849. } else if (!$.isPlainObject(response)) {
  850. return dfrd.reject(['errResponse', 'errDataNotJSON'], xhr);
  851. } else if (response.error) {
  852. return dfrd.reject(response.error, xhr);
  853. } else if (!self.validResponse(cmd, response)) {
  854. return dfrd.reject('errResponse', xhr);
  855. }
  856. response = self.normalize(response);
  857. if (!self.api) {
  858. self.api = response.api || 1;
  859. self.newAPI = self.api >= 2;
  860. self.oldAPI = !self.newAPI;
  861. }
  862. if (response.options) {
  863. cwdOptions = $.extend({}, cwdOptions, response.options);
  864. }
  865. if (response.netDrivers) {
  866. self.netDrivers = response.netDrivers;
  867. }
  868. if (cmd == 'open' && !!data.init) {
  869. self.uplMaxSize = self.returnBytes(response.uplMaxSize);
  870. self.uplMaxFile = !!response.uplMaxFile? parseInt(response.uplMaxFile) : 20;
  871. }
  872. dfrd.resolve(response);
  873. response.debug && self.debug('backend-debug', response.debug);
  874. },
  875. xhr, _xhr
  876. ;
  877. defdone && dfrd.done(done);
  878. dfrd.fail(function(error) {
  879. if (error) {
  880. deffail ? self.error(error) : self.debug('error', self.i18n(error));
  881. }
  882. })
  883. if (!cmd) {
  884. return dfrd.reject('errCmdReq');
  885. }
  886. if (syncOnFail) {
  887. dfrd.fail(function(error) {
  888. error && self.sync();
  889. });
  890. }
  891. if (notify.type && notify.cnt) {
  892. timeout = setTimeout(function() {
  893. self.notify(notify);
  894. dfrd.always(function() {
  895. notify.cnt = -(parseInt(notify.cnt)||0);
  896. self.notify(notify);
  897. })
  898. }, self.notifyDelay)
  899. dfrd.always(function() {
  900. clearTimeout(timeout);
  901. });
  902. }
  903. // quiet abort not completed "open" requests
  904. if (cmd == 'open') {
  905. while ((_xhr = queue.pop())) {
  906. if (_xhr.state() == 'pending') {
  907. _xhr.quiet = true;
  908. _xhr.abort();
  909. }
  910. }
  911. }
  912. delete options.preventFail
  913. xhr = this.transport.send(options).fail(error).done(success);
  914. // this.transport.send(options)
  915. // add "open" xhr into queue
  916. if (cmd == 'open') {
  917. queue.unshift(xhr);
  918. dfrd.always(function() {
  919. var ndx = $.inArray(xhr, queue);
  920. ndx !== -1 && queue.splice(ndx, 1);
  921. });
  922. }
  923. return dfrd;
  924. };
  925. /**
  926. * Compare current files cache with new files and return diff
  927. *
  928. * @param Array new files
  929. * @return Object
  930. */
  931. this.diff = function(incoming) {
  932. var raw = {},
  933. added = [],
  934. removed = [],
  935. changed = [],
  936. isChanged = function(hash) {
  937. var l = changed.length;
  938. while (l--) {
  939. if (changed[l].hash == hash) {
  940. return true;
  941. }
  942. }
  943. };
  944. $.each(incoming, function(i, f) {
  945. raw[f.hash] = f;
  946. });
  947. // find removed
  948. $.each(files, function(hash, f) {
  949. !raw[hash] && removed.push(hash);
  950. });
  951. // compare files
  952. $.each(raw, function(hash, file) {
  953. var origin = files[hash];
  954. if (!origin) {
  955. added.push(file);
  956. } else {
  957. $.each(file, function(prop) {
  958. if (file[prop] != origin[prop]) {
  959. changed.push(file)
  960. return false;
  961. }
  962. });
  963. }
  964. });
  965. // parents of removed dirs mark as changed (required for tree correct work)
  966. $.each(removed, function(i, hash) {
  967. var file = files[hash],
  968. phash = file.phash;
  969. if (phash
  970. && file.mime == 'directory'
  971. && $.inArray(phash, removed) === -1
  972. && raw[phash]
  973. && !isChanged(phash)) {
  974. changed.push(raw[phash]);
  975. }
  976. });
  977. return {
  978. added : added,
  979. removed : removed,
  980. changed : changed
  981. };
  982. }
  983. /**
  984. * Sync content
  985. *
  986. * @return jQuery.Deferred
  987. */
  988. this.sync = function() {
  989. var self = this,
  990. dfrd = $.Deferred().done(function() { self.trigger('sync'); }),
  991. opts1 = {
  992. data : {cmd : 'open', init : 1, target : cwd, tree : this.ui.tree ? 1 : 0},
  993. preventDefault : true
  994. },
  995. opts2 = {
  996. data : {cmd : 'tree', target : (cwd == this.root())? cwd : this.file(cwd).phash},
  997. preventDefault : true
  998. };
  999. $.when(
  1000. this.request(opts1),
  1001. this.request(opts2)
  1002. )
  1003. .fail(function(error) {
  1004. dfrd.reject(error);
  1005. error && self.request({
  1006. data : {cmd : 'open', target : self.lastDir(''), tree : 1, init : 1},
  1007. notify : {type : 'open', cnt : 1, hideCnt : true},
  1008. preventDefault : true
  1009. });
  1010. })
  1011. .done(function(odata, pdata) {
  1012. var diff = self.diff(odata.files.concat(pdata && pdata.tree ? pdata.tree : []));
  1013. diff.added.push(odata.cwd)
  1014. diff.removed.length && self.remove(diff);
  1015. diff.added.length && self.add(diff);
  1016. diff.changed.length && self.change(diff);
  1017. return dfrd.resolve(diff);
  1018. });
  1019. return dfrd;
  1020. }
  1021. this.upload = function(files) {
  1022. return this.transport.upload(files, this);
  1023. }
  1024. /**
  1025. * Attach listener to events
  1026. * To bind to multiply events at once, separate events names by space
  1027. *
  1028. * @param String event(s) name(s)
  1029. * @param Object event handler
  1030. * @return elFinder
  1031. */
  1032. this.bind = function(event, callback) {
  1033. var i;
  1034. if (typeof(callback) == 'function') {
  1035. event = ('' + event).toLowerCase().split(/\s+/);
  1036. for (i = 0; i < event.length; i++) {
  1037. if (listeners[event[i]] === void(0)) {
  1038. listeners[event[i]] = [];
  1039. }
  1040. listeners[event[i]].push(callback);
  1041. }
  1042. }
  1043. return this;
  1044. };
  1045. /**
  1046. * Remove event listener if exists
  1047. *
  1048. * @param String event name
  1049. * @param Function callback
  1050. * @return elFinder
  1051. */
  1052. this.unbind = function(event, callback) {
  1053. var l = listeners[('' + event).toLowerCase()] || [],
  1054. i = l.indexOf(callback);
  1055. i > -1 && l.splice(i, 1);
  1056. //delete callback; // need this?
  1057. callback = null
  1058. return this;
  1059. };
  1060. /**
  1061. * Fire event - send notification to all event listeners
  1062. *
  1063. * @param String event type
  1064. * @param Object data to send across event
  1065. * @return elFinder
  1066. */
  1067. this.trigger = function(event, data) {
  1068. var event = event.toLowerCase(),
  1069. handlers = listeners[event] || [], i, j;
  1070. this.debug('event-'+event, data)
  1071. if (handlers.length) {
  1072. event = $.Event(event);
  1073. for (i = 0; i < handlers.length; i++) {
  1074. // to avoid data modifications. remember about "sharing" passing arguments in js :)
  1075. event.data = $.extend(true, {}, data);
  1076. try {
  1077. if (handlers[i](event, this) === false
  1078. || event.isDefaultPrevented()) {
  1079. this.debug('event-stoped', event.type);
  1080. break;
  1081. }
  1082. } catch (ex) {
  1083. window.console && window.console.log && window.console.log(ex);
  1084. }
  1085. }
  1086. }
  1087. return this;
  1088. }
  1089. /**
  1090. * Bind keybord shortcut to keydown event
  1091. *
  1092. * @example
  1093. * elfinder.shortcut({
  1094. * pattern : 'ctrl+a',
  1095. * description : 'Select all files',
  1096. * callback : function(e) { ... },
  1097. * keypress : true|false (bind to keypress instead of keydown)
  1098. * })
  1099. *
  1100. * @param Object shortcut config
  1101. * @return elFinder
  1102. */
  1103. this.shortcut = function(s) {
  1104. var patterns, pattern, code, i, parts;
  1105. if (this.options.allowShortcuts && s.pattern && $.isFunction(s.callback)) {
  1106. patterns = s.pattern.toUpperCase().split(/\s+/);
  1107. for (i= 0; i < patterns.length; i++) {
  1108. pattern = patterns[i]
  1109. parts = pattern.split('+');
  1110. code = (code = parts.pop()).length == 1
  1111. ? code > 0 ? code : code.charCodeAt(0)
  1112. : $.ui.keyCode[code];
  1113. if (code && !shortcuts[pattern]) {
  1114. shortcuts[pattern] = {
  1115. keyCode : code,
  1116. altKey : $.inArray('ALT', parts) != -1,
  1117. ctrlKey : $.inArray('CTRL', parts) != -1,
  1118. shiftKey : $.inArray('SHIFT', parts) != -1,
  1119. type : s.type || 'keydown',
  1120. callback : s.callback,
  1121. description : s.description,
  1122. pattern : pattern
  1123. };
  1124. }
  1125. }
  1126. }
  1127. return this;
  1128. }
  1129. /**
  1130. * Registered shortcuts
  1131. *
  1132. * @type Object
  1133. **/
  1134. this.shortcuts = function() {
  1135. var ret = [];
  1136. $.each(shortcuts, function(i, s) {
  1137. ret.push([s.pattern, self.i18n(s.description)]);
  1138. });
  1139. return ret;
  1140. };
  1141. /**
  1142. * Get/set clipboard content.
  1143. * Return new clipboard content.
  1144. *
  1145. * @example
  1146. * this.clipboard([]) - clean clipboard
  1147. * this.clipboard([{...}, {...}], true) - put 2 files in clipboard and mark it as cutted
  1148. *
  1149. * @param Array new files hashes
  1150. * @param Boolean cut files?
  1151. * @return Array
  1152. */
  1153. this.clipboard = function(hashes, cut) {
  1154. var map = function() { return $.map(clipboard, function(f) { return f.hash }); }
  1155. if (hashes !== void(0)) {
  1156. clipboard.length && this.trigger('unlockfiles', {files : map()});
  1157. remember = [];
  1158. clipboard = $.map(hashes||[], function(hash) {
  1159. var file = files[hash];
  1160. if (file) {
  1161. remember.push(hash);
  1162. return {
  1163. hash : hash,
  1164. phash : file.phash,
  1165. name : file.name,
  1166. mime : file.mime,
  1167. read : file.read,
  1168. locked : file.locked,
  1169. cut : !!cut
  1170. }
  1171. }
  1172. return null;
  1173. });
  1174. this.trigger('changeclipboard', {clipboard : clipboard.slice(0, clipboard.length)});
  1175. cut && this.trigger('lockfiles', {files : map()});
  1176. }
  1177. // return copy of clipboard instead of refrence
  1178. return clipboard.slice(0, clipboard.length);
  1179. }
  1180. /**
  1181. * Return true if command enabled
  1182. *
  1183. * @param String command name
  1184. * @return Boolean
  1185. */
  1186. this.isCommandEnabled = function(name) {
  1187. return this._commands[name] ? $.inArray(name, cwdOptions.disabled) === -1 : false;
  1188. }
  1189. /**
  1190. * Exec command and return result;
  1191. *
  1192. * @param String command name
  1193. * @param String|Array usualy files hashes
  1194. * @param String|Array command options
  1195. * @return $.Deferred
  1196. */
  1197. this.exec = function(cmd, files, opts) {
  1198. return this._commands[cmd] && this.isCommandEnabled(cmd)
  1199. ? this._commands[cmd].exec(files, opts)
  1200. : $.Deferred().reject('No such command');
  1201. }
  1202. /**
  1203. * Create and return dialog.
  1204. *
  1205. * @param String|DOMElement dialog content
  1206. * @param Object dialog options
  1207. * @return jQuery
  1208. */
  1209. this.dialog = function(content, options) {
  1210. return $('<div/>').append(content).appendTo(node).elfinderdialog(options);
  1211. }
  1212. /**
  1213. * Return UI widget or node
  1214. *
  1215. * @param String ui name
  1216. * @return jQuery
  1217. */
  1218. this.getUI = function(ui) {
  1219. return this.ui[ui] || node;
  1220. }
  1221. this.command = function(name) {
  1222. return name === void(0) ? this._commands : this._commands[name];
  1223. }
  1224. /**
  1225. * Resize elfinder node
  1226. *
  1227. * @param String|Number width
  1228. * @param Number height
  1229. * @return void
  1230. */
  1231. this.resize = function(w, h) {
  1232. node.css('width', w).height(h).trigger('resize');
  1233. this.trigger('resize', {width : node.width(), height : node.height()});
  1234. }
  1235. /**
  1236. * Restore elfinder node size
  1237. *
  1238. * @return elFinder
  1239. */
  1240. this.restoreSize = function() {
  1241. this.resize(width, height);
  1242. }
  1243. this.show = function() {
  1244. node.show();
  1245. this.enable().trigger('show');
  1246. }
  1247. this.hide = function() {
  1248. this.disable().trigger('hide');
  1249. node.hide();
  1250. }
  1251. /**
  1252. * Destroy this elFinder instance
  1253. *
  1254. * @return void
  1255. **/
  1256. this.destroy = function() {
  1257. if (node && node[0].elfinder) {
  1258. this.trigger('destroy').disable();
  1259. listeners = {};
  1260. shortcuts = {};
  1261. $(document).add(node).unbind('.'+this.namespace);
  1262. self.trigger = function() { }
  1263. node.children().remove();
  1264. node.append(prevContent.contents()).removeClass(this.cssClass).attr('style', prevStyle);
  1265. node[0].elfinder = null;
  1266. if (syncInterval) {
  1267. clearInterval(syncInterval);
  1268. }
  1269. }
  1270. }
  1271. /************* init stuffs ****************/
  1272. // check jquery ui
  1273. if (!($.fn.selectable && $.fn.draggable && $.fn.droppable)) {
  1274. return alert(this.i18n('errJqui'));
  1275. }
  1276. // check node
  1277. if (!node.length) {
  1278. return alert(this.i18n('errNode'));
  1279. }
  1280. // check connector url
  1281. if (!this.options.url) {
  1282. return alert(this.i18n('errURL'));
  1283. }
  1284. $.extend($.ui.keyCode, {
  1285. 'F1' : 112,
  1286. 'F2' : 113,
  1287. 'F3' : 114,
  1288. 'F4' : 115,
  1289. 'F5' : 116,
  1290. 'F6' : 117,
  1291. 'F7' : 118,
  1292. 'F8' : 119,
  1293. 'F9' : 120
  1294. });
  1295. this.dragUpload = false;
  1296. this.xhrUpload = (typeof XMLHttpRequestUpload != 'undefined' || typeof XMLHttpRequestEventTarget != 'undefined') && typeof File != 'undefined' && typeof FormData != 'undefined';
  1297. // configure transport object
  1298. this.transport = {}
  1299. if (typeof(this.options.transport) == 'object') {
  1300. this.transport = this.options.transport;
  1301. if (typeof(this.transport.init) == 'function') {
  1302. this.transport.init(this)
  1303. }
  1304. }
  1305. if (typeof(this.transport.send) != 'function') {
  1306. this.transport.send = function(opts) { return $.ajax(opts); }
  1307. }
  1308. if (this.transport.upload == 'iframe') {
  1309. this.transport.upload = $.proxy(this.uploads.iframe, this);
  1310. } else if (typeof(this.transport.upload) == 'function') {
  1311. this.dragUpload = !!this.options.dragUploadAllow;
  1312. } else if (this.xhrUpload && !!this.options.dragUploadAllow) {
  1313. this.transport.upload = $.proxy(this.uploads.xhr, this);
  1314. this.dragUpload = true;
  1315. } else {
  1316. this.transport.upload = $.proxy(this.uploads.iframe, this);
  1317. }
  1318. /**
  1319. * Alias for this.trigger('error', {error : 'message'})
  1320. *
  1321. * @param String error message
  1322. * @return elFinder
  1323. **/
  1324. this.error = function() {
  1325. var arg = arguments[0];
  1326. return arguments.length == 1 && typeof(arg) == 'function'
  1327. ? self.bind('error', arg)
  1328. : self.trigger('error', {error : arg});
  1329. }
  1330. // create bind/trigger aliases for build-in events
  1331. $.each(['enable', 'disable', 'load', 'open', 'reload', 'select', 'add', 'remove', 'change', 'dblclick', 'getfile', 'lockfiles', 'unlockfiles', 'dragstart', 'dragstop', 'search', 'searchend', 'viewchange'], function(i, name) {
  1332. self[name] = function() {
  1333. var arg = arguments[0];
  1334. return arguments.length == 1 && typeof(arg) == 'function'
  1335. ? self.bind(name, arg)
  1336. : self.trigger(name, $.isPlainObject(arg) ? arg : {});
  1337. }
  1338. });
  1339. // bind core event handlers
  1340. this
  1341. .enable(function() {
  1342. if (!enabled && self.visible() && self.ui.overlay.is(':hidden')) {
  1343. enabled = true;
  1344. $('texarea:focus,input:focus,button').blur();
  1345. node.removeClass('elfinder-disabled');
  1346. }
  1347. })
  1348. .disable(function() {
  1349. prevEnabled = enabled;
  1350. enabled = false;
  1351. node.addClass('elfinder-disabled');
  1352. })
  1353. .open(function() {
  1354. selected = [];
  1355. })
  1356. .select(function(e) {
  1357. selected = $.map(e.data.selected || e.data.value|| [], function(hash) { return files[hash] ? hash : null; });
  1358. })
  1359. .error(function(e) {
  1360. var opts = {
  1361. cssClass : 'elfinder-dialog-error',
  1362. title : self.i18n(self.i18n('error')),
  1363. resizable : false,
  1364. destroyOnClose : true,
  1365. buttons : {}
  1366. };
  1367. opts.buttons[self.i18n(self.i18n('btnClose'))] = function() { $(this).elfinderdialog('close'); };
  1368. self.dialog('<span class="elfinder-dialog-icon elfinder-dialog-icon-error"/>'+self.i18n(e.data.error), opts);
  1369. })
  1370. .bind('tree parents', function(e) {
  1371. cache(e.data.tree || []);
  1372. })
  1373. .bind('tmb', function(e) {
  1374. $.each(e.data.images||[], function(hash, tmb) {
  1375. if (files[hash]) {
  1376. files[hash].tmb = tmb;
  1377. }
  1378. })
  1379. })
  1380. .add(function(e) {
  1381. cache(e.data.added||[]);
  1382. })
  1383. .change(function(e) {
  1384. $.each(e.data.changed||[], function(i, file) {
  1385. var hash = file.hash;
  1386. if ((files[hash].width && !file.width) || (files[hash].height && !file.height)) {
  1387. files[hash].width = undefined;
  1388. files[hash].height = undefined;
  1389. }
  1390. files[hash] = files[hash] ? $.extend(files[hash], file) : file;
  1391. });
  1392. })
  1393. .remove(function(e) {
  1394. var removed = e.data.removed||[],
  1395. l = removed.length,
  1396. rm = function(hash) {
  1397. var file = files[hash];
  1398. if (file) {
  1399. if (file.mime == 'directory' && file.dirs) {
  1400. $.each(files, function(h, f) {
  1401. f.phash == hash && rm(h);
  1402. });
  1403. }
  1404. delete files[hash];
  1405. }
  1406. };
  1407. while (l--) {
  1408. rm(removed[l]);
  1409. }
  1410. })
  1411. .bind('search', function(e) {
  1412. cache(e.data.files);
  1413. })
  1414. .bind('rm', function(e) {
  1415. var play = beeper.canPlayType && beeper.canPlayType('audio/wav; codecs="1"');
  1416. play && play != '' && play != 'no' && $(beeper).html('<source src="./sounds/rm.wav" type="audio/wav">')[0].play()
  1417. })
  1418. ;
  1419. // bind external event handlers
  1420. $.each(this.options.handlers, function(event, callback) {
  1421. self.bind(event, callback);
  1422. });
  1423. /**
  1424. * History object. Store visited folders
  1425. *
  1426. * @type Object
  1427. **/
  1428. this.history = new this.history(this);
  1429. // in getFileCallback set - change default actions on double click/enter/ctrl+enter
  1430. if (typeof(this.options.getFileCallback) == 'function' && this.commands.getfile) {
  1431. this.bind('dblclick', function(e) {
  1432. e.preventDefault();
  1433. self.exec('getfile').fail(function() {
  1434. self.exec('open');
  1435. });
  1436. });
  1437. this.shortcut({
  1438. pattern : 'enter',
  1439. description : this.i18n('cmdgetfile'),
  1440. callback : function() { self.exec('getfile').fail(function() { self.exec(self.OS == 'mac' ? 'rename' : 'open') }) }
  1441. })
  1442. .shortcut({
  1443. pattern : 'ctrl+enter',
  1444. description : this.i18n(this.OS == 'mac' ? 'cmdrename' : 'cmdopen'),
  1445. callback : function() { self.exec(self.OS == 'mac' ? 'rename' : 'open') }
  1446. });
  1447. }
  1448. /**
  1449. * Loaded commands
  1450. *
  1451. * @type Object
  1452. **/
  1453. this._commands = {};
  1454. if (!$.isArray(this.options.commands)) {
  1455. this.options.commands = [];
  1456. }
  1457. // check required commands
  1458. $.each(['open', 'reload', 'back', 'forward', 'up', 'home', 'info', 'quicklook', 'getfile', 'help'], function(i, cmd) {
  1459. $.inArray(cmd, self.options.commands) === -1 && self.options.commands.push(cmd);
  1460. });
  1461. // load commands
  1462. $.each(this.options.commands, function(i, name) {
  1463. var cmd = self.commands[name];
  1464. if ($.isFunction(cmd) && !self._commands[name]) {
  1465. cmd.prototype = base;
  1466. self._commands[name] = new cmd();
  1467. self._commands[name].setup(name, self.options.commandsOptions[name]||{});
  1468. }
  1469. });
  1470. // prepare node
  1471. node.addClass(this.cssClass)
  1472. .bind(mousedown, function() {
  1473. !enabled && self.enable();
  1474. });
  1475. /**
  1476. * UI nodes
  1477. *
  1478. * @type Object
  1479. **/
  1480. this.ui = {
  1481. // container for nav panel and current folder container
  1482. workzone : $('<div/>').appendTo(node).elfinderworkzone(this),
  1483. // container for folders tree / places
  1484. navbar : $('<div/>').appendTo(node).elfindernavbar(this, this.options.uiOptions.navbar || {}),
  1485. // contextmenu
  1486. contextmenu : $('<div/>').appendTo(node).elfindercontextmenu(this),
  1487. // overlay
  1488. overlay : $('<div/>').appendTo(node).elfinderoverlay({
  1489. show : function() { self.disable(); },
  1490. hide : function() { prevEnabled && self.enable(); }
  1491. }),
  1492. // current folder container
  1493. cwd : $('<div/>').appendTo(node).elfindercwd(this, this.options.uiOptions.cwd || {}),
  1494. // notification dialog window
  1495. notify : this.dialog('', {
  1496. cssClass : 'elfinder-dialog-notify',
  1497. position : {top : '12px', right : '12px'},
  1498. resizable : false,
  1499. autoOpen : false,
  1500. title : '&nbsp;',
  1501. width : 280
  1502. }),
  1503. statusbar : $('<div class="ui-widget-header ui-helper-clearfix ui-corner-bottom elfinder-statusbar"/>').hide().appendTo(node)
  1504. }
  1505. // load required ui
  1506. $.each(this.options.ui || [], function(i, ui) {
  1507. var name = 'elfinder'+ui,
  1508. opts = self.options.uiOptions[ui] || {};
  1509. if (!self.ui[ui] && $.fn[name]) {
  1510. self.ui[ui] = $('<'+(opts.tag || 'div')+'/>').appendTo(node)[name](self, opts);
  1511. }
  1512. });
  1513. // store instance in node
  1514. node[0].elfinder = this;
  1515. // make node resizable
  1516. this.options.resizable
  1517. && $.fn.resizable
  1518. && node.resizable({
  1519. handles : 'se',
  1520. minWidth : 300,
  1521. minHeight : 200
  1522. });
  1523. if (this.options.width) {
  1524. width = this.options.width;
  1525. }
  1526. if (this.options.height) {
  1527. height = parseInt(this.options.height);
  1528. }
  1529. // update size
  1530. self.resize(width, height);
  1531. // attach events to document
  1532. $(document)
  1533. // disable elfinder on click outside elfinder
  1534. .bind('click.'+this.namespace, function(e) { enabled && !$(e.target).closest(node).length && self.disable(); })
  1535. // exec shortcuts
  1536. .bind(keydown+' '+keypress, execShortcut);
  1537. // send initial request and start to pray >_<
  1538. this.trigger('init')
  1539. .request({
  1540. data : {cmd : 'open', target : self.lastDir(), init : 1, tree : this.ui.tree ? 1 : 0},
  1541. preventDone : true,
  1542. notify : {type : 'open', cnt : 1, hideCnt : true},
  1543. freeze : true
  1544. })
  1545. .fail(function() {
  1546. self.trigger('fail').disable().lastDir('');
  1547. listeners = {};
  1548. shortcuts = {};
  1549. $(document).add(node).unbind('.'+this.namespace);
  1550. self.trigger = function() { };
  1551. })
  1552. .done(function(data) {
  1553. self.load().debug('api', self.api);
  1554. data = $.extend(true, {}, data);
  1555. open(data);
  1556. self.trigger('open', data);
  1557. });
  1558. // update ui's size after init
  1559. this.one('load', function() {
  1560. node.trigger('resize');
  1561. if (self.options.sync > 1000) {
  1562. syncInterval = setInterval(function() {
  1563. self.sync();
  1564. }, self.options.sync)
  1565. }
  1566. });
  1567. // self.timeEnd('load');
  1568. }
  1569. /**
  1570. * Prototype
  1571. *
  1572. * @type Object
  1573. */
  1574. elFinder.prototype = {
  1575. res : function(type, id) {
  1576. return this.resources[type] && this.resources[type][id];
  1577. },
  1578. /**
  1579. * Internationalization object
  1580. *
  1581. * @type Object
  1582. */
  1583. i18 : {
  1584. en : {
  1585. translator : '',
  1586. language : 'English',
  1587. direction : 'ltr',
  1588. dateFormat : 'd.m.Y H:i',
  1589. fancyDateFormat : '$1 H:i',
  1590. messages : {}
  1591. },
  1592. months : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
  1593. monthsShort : ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
  1594. days : ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
  1595. daysShort : ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
  1596. },
  1597. /**
  1598. * File mimetype to kind mapping
  1599. *
  1600. * @type Object
  1601. */
  1602. kinds : {
  1603. 'unknown' : 'Unknown',
  1604. 'directory' : 'Folder',
  1605. 'symlink' : 'Alias',
  1606. 'symlink-broken' : 'AliasBroken',
  1607. 'application/x-empty' : 'TextPlain',
  1608. 'application/postscript' : 'Postscript',
  1609. 'application/vnd.ms-office' : 'MsOffice',
  1610. 'application/vnd.ms-word' : 'MsWord',
  1611. 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' : 'MsWord',
  1612. 'application/vnd.ms-word.document.macroEnabled.12' : 'MsWord',
  1613. 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' : 'MsWord',
  1614. 'application/vnd.ms-word.template.macroEnabled.12' : 'MsWord',
  1615. 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' : 'MsWord',
  1616. 'application/vnd.ms-excel' : 'MsExcel',
  1617. 'application/vnd.ms-excel.sheet.macroEnabled.12' : 'MsExcel',
  1618. 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' : 'MsExcel',
  1619. 'application/vnd.ms-excel.template.macroEnabled.12' : 'MsExcel',
  1620. 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' : 'MsExcel',
  1621. 'application/vnd.ms-excel.addin.macroEnabled.12' : 'MsExcel',
  1622. 'application/vnd.ms-powerpoint' : 'MsPP',
  1623. 'application/vnd.openxmlformats-officedocument.presentationml.presentation' : 'MsPP',
  1624. 'application/vnd.ms-powerpoint.presentation.macroEnabled.12' : 'MsPP',
  1625. 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' : 'MsPP',
  1626. 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' : 'MsPP',
  1627. 'application/vnd.openxmlformats-officedocument.presentationml.template' : 'MsPP',
  1628. 'application/vnd.ms-powerpoint.template.macroEnabled.12' : 'MsPP',
  1629. 'application/vnd.ms-powerpoint.addin.macroEnabled.12' : 'MsPP',
  1630. 'application/vnd.openxmlformats-officedocument.presentationml.slide' : 'MsPP',
  1631. 'application/vnd.ms-powerpoint.slide.macroEnabled.12' : 'MsPP',
  1632. 'application/pdf' : 'PDF',
  1633. 'application/xml' : 'XML',
  1634. 'application/vnd.oasis.opendocument.text' : 'OO',
  1635. 'application/vnd.oasis.opendocument.text-template' : 'OO',
  1636. 'application/vnd.oasis.opendocument.text-web' : 'OO',
  1637. 'application/vnd.oasis.opendocument.text-master' : 'OO',
  1638. 'application/vnd.oasis.opendocument.graphics' : 'OO',
  1639. 'application/vnd.oasis.opendocument.graphics-template' : 'OO',
  1640. 'application/vnd.oasis.opendocument.presentation' : 'OO',
  1641. 'application/vnd.oasis.opendocument.presentation-template' : 'OO',
  1642. 'application/vnd.oasis.opendocument.spreadsheet' : 'OO',
  1643. 'application/vnd.oasis.opendocument.spreadsheet-template' : 'OO',
  1644. 'application/vnd.oasis.opendocument.chart' : 'OO',
  1645. 'application/vnd.oasis.opendocument.formula' : 'OO',
  1646. 'application/vnd.oasis.opendocument.database' : 'OO',
  1647. 'application/vnd.oasis.opendocument.image' : 'OO',
  1648. 'application/vnd.openofficeorg.extension' : 'OO',
  1649. 'application/x-shockwave-flash' : 'AppFlash',
  1650. 'application/flash-video' : 'Flash video',
  1651. 'application/x-bittorrent' : 'Torrent',
  1652. 'application/javascript' : 'JS',
  1653. 'application/rtf' : 'RTF',
  1654. 'application/rtfd' : 'RTF',
  1655. 'application/x-font-ttf' : 'TTF',
  1656. 'application/x-font-otf' : 'OTF',
  1657. 'application/x-rpm' : 'RPM',
  1658. 'application/x-web-config' : 'TextPlain',
  1659. 'application/xhtml+xml' : 'HTML',
  1660. 'application/docbook+xml' : 'DOCBOOK',
  1661. 'application/x-awk' : 'AWK',
  1662. 'application/x-gzip' : 'GZIP',
  1663. 'application/x-bzip2' : 'BZIP',
  1664. 'application/zip' : 'ZIP',
  1665. 'application/x-zip' : 'ZIP',
  1666. 'application/x-rar' : 'RAR',
  1667. 'application/x-tar' : 'TAR',
  1668. 'application/x-7z-compressed' : '7z',
  1669. 'application/x-jar' : 'JAR',
  1670. 'text/plain' : 'TextPlain',
  1671. 'text/x-php' : 'PHP',
  1672. 'text/html' : 'HTML',
  1673. 'text/javascript' : 'JS',
  1674. 'text/css' : 'CSS',
  1675. 'text/rtf' : 'RTF',
  1676. 'text/rtfd' : 'RTF',
  1677. 'text/x-c' : 'C',
  1678. 'text/x-csrc' : 'C',
  1679. 'text/x-chdr' : 'CHeader',
  1680. 'text/x-c++' : 'CPP',
  1681. 'text/x-c++src' : 'CPP',
  1682. 'text/x-c++hdr' : 'CPPHeader',
  1683. 'text/x-shellscript' : 'Shell',
  1684. 'application/x-csh' : 'Shell',
  1685. 'text/x-python' : 'Python',
  1686. 'text/x-java' : 'Java',
  1687. 'text/x-java-source' : 'Java',
  1688. 'text/x-ruby' : 'Ruby',
  1689. 'text/x-perl' : 'Perl',
  1690. 'text/x-sql' : 'SQL',
  1691. 'text/xml' : 'XML',
  1692. 'text/x-comma-separated-values' : 'CSV',
  1693. 'image/x-ms-bmp' : 'BMP',
  1694. 'image/jpeg' : 'JPEG',
  1695. 'image/gif' : 'GIF',
  1696. 'image/png' : 'PNG',
  1697. 'image/tiff' : 'TIFF',
  1698. 'image/x-targa' : 'TGA',
  1699. 'image/vnd.adobe.photoshop' : 'PSD',
  1700. 'image/xbm' : 'XBITMAP',
  1701. 'image/pxm' : 'PXM',
  1702. 'audio/mpeg' : 'AudioMPEG',
  1703. 'audio/midi' : 'AudioMIDI',
  1704. 'audio/ogg' : 'AudioOGG',
  1705. 'audio/mp4' : 'AudioMPEG4',
  1706. 'audio/x-m4a' : 'AudioMPEG4',
  1707. 'audio/wav' : 'AudioWAV',
  1708. 'audio/x-mp3-playlist' : 'AudioPlaylist',
  1709. 'video/x-dv' : 'VideoDV',
  1710. 'video/mp4' : 'VideoMPEG4',
  1711. 'video/mpeg' : 'VideoMPEG',
  1712. 'video/x-msvideo' : 'VideoAVI',
  1713. 'video/quicktime' : 'VideoMOV',
  1714. 'video/x-ms-wmv' : 'VideoWM',
  1715. 'video/x-flv' : 'VideoFlash',
  1716. 'video/x-matroska' : 'VideoMKV',
  1717. 'video/ogg' : 'VideoOGG'
  1718. },
  1719. /**
  1720. * Ajax request data validation rules
  1721. *
  1722. * @type Object
  1723. */
  1724. rules : {
  1725. defaults : function(data) {
  1726. if (!data
  1727. || (data.added && !$.isArray(data.added))
  1728. || (data.removed && !$.isArray(data.removed))
  1729. || (data.changed && !$.isArray(data.changed))) {
  1730. return false;
  1731. }
  1732. return true;
  1733. },
  1734. open : function(data) { return data && data.cwd && data.files && $.isPlainObject(data.cwd) && $.isArray(data.files); },
  1735. tree : function(data) { return data && data.tree && $.isArray(data.tree); },
  1736. parents : function(data) { return data && data.tree && $.isArray(data.tree); },
  1737. tmb : function(data) { return data && data.images && ($.isPlainObject(data.images) || $.isArray(data.images)); },
  1738. upload : function(data) { return data && ($.isPlainObject(data.added) || $.isArray(data.added));},
  1739. search : function(data) { return data && data.files && $.isArray(data.files)}
  1740. },
  1741. /**
  1742. * Commands costructors
  1743. *
  1744. * @type Object
  1745. */
  1746. commands : {},
  1747. parseUploadData : function(text) {
  1748. var data;
  1749. if (!$.trim(text)) {
  1750. return {error : ['errResponse', 'errDataEmpty']};
  1751. }
  1752. try {
  1753. data = $.parseJSON(text);
  1754. } catch (e) {
  1755. return {error : ['errResponse', 'errDataNotJSON']}
  1756. }
  1757. if (!this.validResponse('upload', data)) {
  1758. return {error : ['errResponse']};
  1759. }
  1760. data = this.normalize(data);
  1761. data.removed = $.map(data.added||[], function(f) { return f.hash; })
  1762. return data;
  1763. },
  1764. iframeCnt : 0,
  1765. uploads : {
  1766. // check droped contents
  1767. checkFile : function(data, fm) {
  1768. if (!!data.checked || data.type == 'files') {
  1769. return data.files;
  1770. } else if (data.type == 'data') {
  1771. var dfrd = $.Deferred(),
  1772. files = [],
  1773. paths = [],
  1774. dirctorys = [],
  1775. entries = [],
  1776. processing = 0,
  1777. readEntries = function(dirReader) {
  1778. var toArray = function(list) {
  1779. return Array.prototype.slice.call(list || []);
  1780. };
  1781. var readFile = function(fileEntry, callback) {
  1782. var dfrd = $.Deferred();
  1783. if (typeof fileEntry == 'undefined') {
  1784. dfrd.reject('empty');
  1785. } else if (fileEntry.isFile) {
  1786. fileEntry.file(function (file) {
  1787. dfrd.resolve(file);
  1788. }, function(e){
  1789. dfrd.reject();
  1790. });
  1791. } else {
  1792. dfrd.reject('dirctory');
  1793. }
  1794. return dfrd.promise();
  1795. };
  1796. dirReader.readEntries(function (results) {
  1797. if (!results.length) {
  1798. var len = entries.length - 1;
  1799. var read = function(i) {
  1800. readFile(entries[i]).done(function(file){
  1801. if (! (fm.OS == 'win' && file.name.match(/^(?:desktop\.ini|thumbs\.db)$/i))
  1802. &&
  1803. ! (fm.OS == 'mac' && file.name.match(/^\.ds_store$/i))) {
  1804. paths.push(entries[i].fullPath);
  1805. files.push(file);
  1806. }
  1807. }).fail(function(e){
  1808. if (e == 'dirctory') {
  1809. // dirctory
  1810. dirctorys.push(entries[i]);
  1811. } else if (e == 'empty') {
  1812. // dirctory is empty
  1813. } else {
  1814. // why fail?
  1815. }
  1816. }).always(function(){
  1817. processing--;
  1818. if (i < len) {
  1819. processing++;
  1820. read(++i);
  1821. }
  1822. });
  1823. };
  1824. processing++;
  1825. read(0);
  1826. processing--;
  1827. } else {
  1828. entries = entries.concat(toArray(results));
  1829. readEntries(dirReader);
  1830. }
  1831. });
  1832. },
  1833. doScan = function(items, isEntry) {
  1834. var dirReader, entry;
  1835. entries = [];
  1836. var length = items.length;
  1837. for (var i = 0; i < length; i++) {
  1838. if (! isEntry) {
  1839. entry = !!items[i].getAsEntry? items[i].getAsEntry() : items[i].webkitGetAsEntry();
  1840. } else {
  1841. entry = items[i];
  1842. }
  1843. if (entry) {
  1844. if (entry.isFile) {
  1845. paths.push('');
  1846. files.push(data.files.items[i].getAsFile());
  1847. } else if (entry.isDirectory) {
  1848. if (processing > 0) {
  1849. dirctorys.push(entry);
  1850. } else {
  1851. processing = 0;
  1852. dirReader = entry.createReader();
  1853. processing++;
  1854. readEntries(dirReader);
  1855. }
  1856. }
  1857. }
  1858. }
  1859. };
  1860. doScan(data.files.items);
  1861. setTimeout(function wait() {
  1862. if (processing > 0) {
  1863. setTimeout(wait, 10);
  1864. } else {
  1865. if (dirctorys.length > 0) {
  1866. doScan([dirctorys.shift()], true);
  1867. setTimeout(wait, 10);
  1868. } else {
  1869. dfrd.resolve([files, paths]);
  1870. }
  1871. }
  1872. }, 10);
  1873. return dfrd.promise();
  1874. } else {
  1875. var ret = [];
  1876. var regex;
  1877. var str = data.files[0];
  1878. if (data.type == 'html') {
  1879. regex = /<img[^>]+src=["']?([^"'> ]+)/ig;
  1880. var m = [];
  1881. var url = '';
  1882. var links;
  1883. while (m = regex.exec(str)) {
  1884. url = m[1].replace(/&amp;/g, '&');
  1885. if (url.match(/^http|data:/) && $.inArray(url, ret) == -1) ret.push(url);
  1886. }
  1887. links = str.match(/<\/a>/i);
  1888. if (links && links.length == 1) {
  1889. regex = /<a[^>]+href=["']?([^"'> ]+)((?:.|\s)+)<\/a>/i;
  1890. if (m = regex.exec(str)) {
  1891. if (! m[2].match(/<img/i)) {
  1892. url = m[1].replace(/&amp;/g, '&');
  1893. if (url.match(/^http/) && $.inArray(url, ret) == -1) ret.push(url);
  1894. }
  1895. }
  1896. }
  1897. } else {
  1898. regex = /(http[^<>"{}|\\^\[\]`\s]+)/ig;
  1899. while (m = regex.exec(str)) {
  1900. url = m[1].replace(/&amp;/g, '&');
  1901. if ($.inArray(url, ret) == -1) ret.push(url);
  1902. }
  1903. }
  1904. return ret;
  1905. }
  1906. },
  1907. // upload transport using iframe
  1908. iframe : function(data, fm) {
  1909. var self = fm ? fm : this,
  1910. input = data.input? data.input : false,
  1911. files = !input ? self.uploads.checkFile(data, self) : false,
  1912. dfrd = $.Deferred()
  1913. .fail(function(error) {
  1914. error && self.error(error);
  1915. })
  1916. .done(function(data) {
  1917. data.warning && self.error(data.warning);
  1918. data.removed && self.remove(data);
  1919. data.added && self.add(data);
  1920. data.changed && self.change(data);
  1921. self.trigger('upload', data);
  1922. data.sync && self.sync();
  1923. }),
  1924. name = 'iframe-'+self.namespace+(++self.iframeCnt),
  1925. 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>'),
  1926. msie = this.UA.IE,
  1927. // clear timeouts, close notification dialog, remove form/iframe
  1928. onload = function() {
  1929. abortto && clearTimeout(abortto);
  1930. notifyto && clearTimeout(notifyto);
  1931. notify && self.notify({type : 'upload', cnt : -cnt});
  1932. setTimeout(function() {
  1933. msie && $('<iframe src="javascript:false;"/>').appendTo(form);
  1934. form.remove();
  1935. iframe.remove();
  1936. }, 100);
  1937. },
  1938. iframe = $('<iframe src="'+(msie ? 'javascript:false;' : 'about:blank')+'" name="'+name+'" style="position:absolute;left:-1000px;top:-1000px" />')
  1939. .bind('load', function() {
  1940. iframe.unbind('load')
  1941. .bind('load', function() {
  1942. var data = self.parseUploadData(iframe.contents().text());
  1943. onload();
  1944. data.error ? dfrd.reject(data.error) : dfrd.resolve(data);
  1945. });
  1946. // notify dialog
  1947. notifyto = setTimeout(function() {
  1948. notify = true;
  1949. self.notify({type : 'upload', cnt : cnt});
  1950. }, self.options.notifyDelay);
  1951. // emulate abort on timeout
  1952. if (self.options.iframeTimeout > 0) {
  1953. abortto = setTimeout(function() {
  1954. onload();
  1955. dfrd.reject([errors.connect, errors.timeout]);
  1956. }, self.options.iframeTimeout);
  1957. }
  1958. form.submit();
  1959. }),
  1960. cnt, notify, notifyto, abortto
  1961. ;
  1962. if (files && files.length) {
  1963. $.each(files, function(i, val) {
  1964. form.append('<input type="hidden" name="upload[]" value="'+val+'"/>');
  1965. });
  1966. cnt = 1;
  1967. } else if (input && $(input).is(':file') && $(input).val()) {
  1968. form.append(input);
  1969. cnt = input.files ? input.files.length : 1;
  1970. } else {
  1971. return dfrd.reject();
  1972. }
  1973. form.append('<input type="hidden" name="'+(self.newAPI ? 'target' : 'current')+'" value="'+self.cwd().hash+'"/>')
  1974. .append('<input type="hidden" name="html" value="1"/>')
  1975. .append($(input).attr('name', 'upload[]'));
  1976. $.each(self.options.onlyMimes||[], function(i, mime) {
  1977. form.append('<input type="hidden" name="mimes[]" value="'+mime+'"/>');
  1978. });
  1979. $.each(self.options.customData, function(key, val) {
  1980. form.append('<input type="hidden" name="'+key+'" value="'+val+'"/>');
  1981. });
  1982. form.appendTo('body');
  1983. iframe.appendTo('body');
  1984. return dfrd;
  1985. },
  1986. // upload transport using XMLHttpRequest
  1987. xhr : function(data, fm) {
  1988. var self = fm ? fm : this,
  1989. dfrd = $.Deferred()
  1990. .fail(function(error) {
  1991. error && self.error(error);
  1992. })
  1993. .done(function(data) {
  1994. data.warning && self.error(data.warning);
  1995. data.removed && self.remove(data);
  1996. data.added && self.add(data);
  1997. data.changed && self.change(data);
  1998. self.trigger('upload', data);
  1999. data.sync && self.sync();
  2000. })
  2001. .always(function() {
  2002. notifyto && clearTimeout(notifyto);
  2003. ! data.checked && notify && self.notify({type : 'upload', cnt : -cnt, progress : 100*cnt});
  2004. }),
  2005. xhr = new XMLHttpRequest(),
  2006. formData = new FormData(),
  2007. isDataType = (data.type == 'data'),
  2008. files = data.input ? data.input.files : self.uploads.checkFile(data, self),
  2009. cnt = data.checked? (isDataType? files[0].length : files.length) : files.length,
  2010. loaded = 5,
  2011. notify = false,
  2012. startNotify = function() {
  2013. return setTimeout(function() {
  2014. notify = true;
  2015. self.notify({type : 'upload', cnt : cnt, progress : loaded*cnt});
  2016. }, self.options.notifyDelay);
  2017. },
  2018. notifyto, notifyto2;
  2019. if (!isDataType && !cnt) {
  2020. return dfrd.reject();
  2021. }
  2022. xhr.addEventListener('error', function() {
  2023. dfrd.reject('errConnect');
  2024. }, false);
  2025. xhr.addEventListener('abort', function() {
  2026. dfrd.reject(['errConnect', 'errAbort']);
  2027. }, false);
  2028. xhr.addEventListener('load', function() {
  2029. var status = xhr.status, data;
  2030. if (status > 500) {
  2031. return dfrd.reject('errResponse');
  2032. }
  2033. if (status != 200) {
  2034. return dfrd.reject('errConnect');
  2035. }
  2036. if (xhr.readyState != 4) {
  2037. return dfrd.reject(['errConnect', 'errTimeout']); // am i right?
  2038. }
  2039. if (!xhr.responseText) {
  2040. return dfrd.reject(['errResponse', 'errDataEmpty']);
  2041. }
  2042. data = self.parseUploadData(xhr.responseText);
  2043. data.error ? dfrd.reject(data.error) : dfrd.resolve(data);
  2044. }, false);
  2045. xhr.upload.addEventListener('progress', function(e) {
  2046. var prev = loaded, curr;
  2047. if (e.lengthComputable) {
  2048. curr = parseInt(e.loaded*100 / e.total);
  2049. // to avoid strange bug in safari (not in chrome) with drag&drop.
  2050. // bug: macos finder opened in any folder,
  2051. // reset safari cache (option+command+e), reload elfinder page,
  2052. // drop file from finder
  2053. // on first attempt request starts (progress callback called ones) but never ends.
  2054. // any next drop - successfull.
  2055. if (!data.checked && curr > 0 && !notifyto) {
  2056. notifyto = startNotify();
  2057. }
  2058. if (curr - prev > 4) {
  2059. loaded = curr;
  2060. (data.checked || notify) && self.notify({type : 'upload', cnt : 0, progress : (loaded - prev)*cnt});
  2061. }
  2062. }
  2063. }, false);
  2064. var send = function(files, paths){
  2065. var size = 0, fcnt = 1, sfiles = [], c = 0, total = cnt, maxFileSize;
  2066. if (! data.checked) {
  2067. maxFileSize = fm.option('uploadMaxSize')? fm.option('uploadMaxSize') : fm.uplMaxSize;
  2068. for (var i=0; i < files.length; i++) {
  2069. if (maxFileSize && files[i].size >= maxFileSize) {
  2070. self.error(self.i18n('errUploadFile', files[i].name) + ' ' + self.i18n('errUploadFileSize'));
  2071. continue;
  2072. }
  2073. if ((fm.uplMaxSize && size + files[i].size >= fm.uplMaxSize) || fcnt > fm.uplMaxFile) {
  2074. size = 0;
  2075. fcnt = 1;
  2076. c++;
  2077. }
  2078. if (typeof sfiles[c] == 'undefined') {
  2079. sfiles[c] = [];
  2080. if (isDataType) {
  2081. sfiles[c][0] = [];
  2082. sfiles[c][1] = [];
  2083. }
  2084. }
  2085. if (isDataType) {
  2086. sfiles[c][0].push(files[i]);
  2087. sfiles[c][1].push(paths[i]);
  2088. } else {
  2089. sfiles[c].push(files[i]);
  2090. }
  2091. size += files[i].size;
  2092. fcnt++;
  2093. }
  2094. if (sfiles.length == 0) {
  2095. data.checked = true;
  2096. return false;
  2097. }
  2098. if (sfiles.length > 1) {
  2099. notifyto = startNotify();
  2100. for (var i=0; i < sfiles.length; i++) {
  2101. fm.exec('upload', {type: data.type, files: sfiles[i], checked: true}).always(function() {
  2102. if (notify) {
  2103. var _cnt = (isDataType? this[0] : this).length;
  2104. total -= _cnt;
  2105. if (total < 1) {
  2106. notifyto && clearTimeout(notifyto);
  2107. self.notify({type : 'upload', cnt : -cnt, progress : 100 * cnt});
  2108. }
  2109. }
  2110. }.bind(sfiles[i]));
  2111. }
  2112. return false;
  2113. }
  2114. if (isDataType) {
  2115. files = sfiles[0][0];
  2116. paths = sfiles[0][1];
  2117. } else {
  2118. files = sfiles[0];
  2119. }
  2120. }
  2121. xhr.open('POST', self.uploadURL, true);
  2122. formData.append('cmd', 'upload');
  2123. formData.append(self.newAPI ? 'target' : 'current', self.cwd().hash);
  2124. $.each(self.options.customData, function(key, val) {
  2125. formData.append(key, val);
  2126. });
  2127. $.each(self.options.onlyMimes, function(i, mime) {
  2128. formData.append('mimes['+i+']', mime);
  2129. });
  2130. $.each(files, function(i, file) {
  2131. formData.append('upload[]', file);
  2132. });
  2133. if (isDataType) {
  2134. $.each(paths, function(i, path) {
  2135. formData.append('upload_path[]', path);
  2136. });
  2137. }
  2138. xhr.onreadystatechange = function() {
  2139. if (xhr.readyState == 4 && xhr.status == 0) {
  2140. // ff bug while send zero sized file
  2141. // for safari - send directory
  2142. dfrd.reject(['errConnect', 'errAbort']);
  2143. }
  2144. }
  2145. xhr.send(formData);
  2146. return true;
  2147. };
  2148. if (! isDataType) {
  2149. if (! send(files)) {
  2150. dfrd.reject();
  2151. }
  2152. } else {
  2153. if (!! data.checked) {
  2154. send(files[0], files[1]);
  2155. } else {
  2156. notifyto2 = setTimeout(function() {
  2157. self.notify({type : 'readdir', cnt : 1, hideCnt: true});
  2158. }, self.options.notifyDelay);
  2159. files.done(function(result){
  2160. notifyto2 && clearTimeout(notifyto2);
  2161. self.notify({type : 'readdir', cnt : -1});
  2162. cnt = result[0].length;
  2163. send(result[0], result[1]);
  2164. }).fail(function(){
  2165. dfrd.reject();
  2166. });
  2167. }
  2168. }
  2169. if (!isDataType && !data.checked && (!this.UA.Safari || !data.files)) {
  2170. notifyto = startNotify();
  2171. }
  2172. return dfrd;
  2173. }
  2174. },
  2175. /**
  2176. * Bind callback to event(s) The callback is executed at most once per event.
  2177. * To bind to multiply events at once, separate events names by space
  2178. *
  2179. * @param String event name
  2180. * @param Function callback
  2181. * @return elFinder
  2182. */
  2183. one : function(event, callback) {
  2184. var self = this,
  2185. h = $.proxy(callback, function(event) {
  2186. setTimeout(function() {self.unbind(event.type, h);}, 3);
  2187. return callback.apply(this, arguments);
  2188. });
  2189. return this.bind(event, h);
  2190. },
  2191. /**
  2192. * Set/get data into/from localStorage
  2193. *
  2194. * @param String key
  2195. * @param String|void value
  2196. * @return String
  2197. */
  2198. localStorage : function(key, val) {
  2199. var s = window.localStorage;
  2200. key = 'elfinder-'+key+this.id;
  2201. if (val === null) {
  2202. console.log('remove', key)
  2203. return s.removeItem(key);
  2204. }
  2205. if (val !== void(0)) {
  2206. try {
  2207. s.setItem(key, val);
  2208. } catch (e) {
  2209. s.clear();
  2210. s.setItem(key, val);
  2211. }
  2212. }
  2213. return s.getItem(key);
  2214. },
  2215. /**
  2216. * Get/set cookie
  2217. *
  2218. * @param String cookie name
  2219. * @param String|void cookie value
  2220. * @return String
  2221. */
  2222. cookie : function(name, value) {
  2223. var d, o, c, i;
  2224. name = 'elfinder-'+name+this.id;
  2225. if (value === void(0)) {
  2226. if (document.cookie && document.cookie != '') {
  2227. c = document.cookie.split(';');
  2228. name += '=';
  2229. for (i=0; i<c.length; i++) {
  2230. c[i] = $.trim(c[i]);
  2231. if (c[i].substring(0, name.length) == name) {
  2232. return decodeURIComponent(c[i].substring(name.length));
  2233. }
  2234. }
  2235. }
  2236. return '';
  2237. }
  2238. o = $.extend({}, this.options.cookie);
  2239. if (value === null) {
  2240. value = '';
  2241. o.expires = -1;
  2242. }
  2243. if (typeof(o.expires) == 'number') {
  2244. d = new Date();
  2245. d.setTime(d.getTime()+(o.expires * 86400000));
  2246. o.expires = d;
  2247. }
  2248. document.cookie = name+'='+encodeURIComponent(value)+'; expires='+o.expires.toUTCString()+(o.path ? '; path='+o.path : '')+(o.domain ? '; domain='+o.domain : '')+(o.secure ? '; secure' : '');
  2249. return value;
  2250. },
  2251. /**
  2252. * Get/set last opened directory
  2253. *
  2254. * @param String|undefined dir hash
  2255. * @return String
  2256. */
  2257. lastDir : function(hash) {
  2258. return this.options.rememberLastDir ? this.storage('lastdir', hash) : '';
  2259. },
  2260. /**
  2261. * Node for escape html entities in texts
  2262. *
  2263. * @type jQuery
  2264. */
  2265. _node : $('<span/>'),
  2266. /**
  2267. * Replace not html-safe symbols to html entities
  2268. *
  2269. * @param String text to escape
  2270. * @return String
  2271. */
  2272. escape : function(name) {
  2273. return this._node.text(name).html();
  2274. },
  2275. /**
  2276. * Cleanup ajax data.
  2277. * For old api convert data into new api format
  2278. *
  2279. * @param String command name
  2280. * @param Object data from backend
  2281. * @return Object
  2282. */
  2283. normalize : function(data) {
  2284. var filter = function(file) {
  2285. if (file && file.hash && file.name && file.mime) {
  2286. if (file.mime == 'application/x-empty') {
  2287. file.mime = 'text/plain';
  2288. }
  2289. return file;
  2290. }
  2291. return null;
  2292. return file && file.hash && file.name && file.mime ? file : null;
  2293. };
  2294. if (data.files) {
  2295. data.files = $.map(data.files, filter);
  2296. }
  2297. if (data.tree) {
  2298. data.tree = $.map(data.tree, filter);
  2299. }
  2300. if (data.added) {
  2301. data.added = $.map(data.added, filter);
  2302. }
  2303. if (data.changed) {
  2304. data.changed = $.map(data.changed, filter);
  2305. }
  2306. if (data.api) {
  2307. data.init = true;
  2308. }
  2309. return data;
  2310. },
  2311. /**
  2312. * Update sort options
  2313. *
  2314. * @param {String} sort type
  2315. * @param {String} sort order
  2316. * @param {Boolean} show folder first
  2317. */
  2318. setSort : function(type, order, stickFolders) {
  2319. this.storage('sortType', (this.sortType = this.sortRules[type] ? type : 'name'));
  2320. this.storage('sortOrder', (this.sortOrder = /asc|desc/.test(order) ? order : 'asc'));
  2321. this.storage('sortStickFolders', (this.sortStickFolders = !!stickFolders) ? 1 : '');
  2322. this.trigger('sortchange');
  2323. },
  2324. _sortRules : {
  2325. name : function(file1, file2) { return file1.name.toLowerCase().localeCompare(file2.name.toLowerCase()); },
  2326. size : function(file1, file2) {
  2327. var size1 = parseInt(file1.size) || 0,
  2328. size2 = parseInt(file2.size) || 0;
  2329. return size1 == size2 ? 0 : size1 > size2 ? 1 : -1;
  2330. return (parseInt(file1.size) || 0) > (parseInt(file2.size) || 0) ? 1 : -1; },
  2331. kind : function(file1, file2) { return file1.mime.localeCompare(file2.mime); },
  2332. date : function(file1, file2) {
  2333. var date1 = file1.ts || file1.date,
  2334. date2 = file2.ts || file2.date;
  2335. return date1 == date2 ? 0 : date1 > date2 ? 1 : -1
  2336. }
  2337. },
  2338. /**
  2339. * Compare files based on elFinder.sort
  2340. *
  2341. * @param Object file
  2342. * @param Object file
  2343. * @return Number
  2344. */
  2345. compare : function(file1, file2) {
  2346. var self = this,
  2347. type = self.sortType,
  2348. asc = self.sortOrder == 'asc',
  2349. stick = self.sortStickFolders,
  2350. rules = self.sortRules,
  2351. sort = rules[type],
  2352. d1 = file1.mime == 'directory',
  2353. d2 = file2.mime == 'directory',
  2354. res;
  2355. if (stick) {
  2356. if (d1 && !d2) {
  2357. return -1;
  2358. } else if (!d1 && d2) {
  2359. return 1;
  2360. }
  2361. }
  2362. res = asc ? sort(file1, file2) : sort(file2, file1);
  2363. return type != 'name' && res == 0
  2364. ? res = asc ? rules.name(file1, file2) : rules.name(file2, file1)
  2365. : res;
  2366. },
  2367. /**
  2368. * Sort files based on config
  2369. *
  2370. * @param Array files
  2371. * @return Array
  2372. */
  2373. sortFiles : function(files) {
  2374. return files.sort(this.compare);
  2375. },
  2376. /**
  2377. * Open notification dialog
  2378. * and append/update message for required notification type.
  2379. *
  2380. * @param Object options
  2381. * @example
  2382. * this.notify({
  2383. * type : 'copy',
  2384. * msg : 'Copy files', // not required for known types @see this.notifyType
  2385. * cnt : 3,
  2386. * hideCnt : false, // true for not show count
  2387. * progress : 10 // progress bar percents (use cnt : 0 to update progress bar)
  2388. * })
  2389. * @return elFinder
  2390. */
  2391. notify : function(opts) {
  2392. var type = opts.type,
  2393. msg = this.messages['ntf'+type] ? this.i18n('ntf'+type) : this.i18n('ntfsmth'),
  2394. ndialog = this.ui.notify,
  2395. notify = ndialog.children('.elfinder-notify-'+type),
  2396. ntpl = '<div class="elfinder-notify elfinder-notify-{type}"><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>',
  2397. delta = opts.cnt,
  2398. progress = opts.progress >= 0 ? opts.progress : 0,
  2399. cnt, total, prc;
  2400. if (!type) {
  2401. return this;
  2402. }
  2403. if (!notify.length) {
  2404. notify = $(ntpl.replace(/\{type\}/g, type).replace(/\{msg\}/g, msg))
  2405. .appendTo(ndialog)
  2406. .data('cnt', 0);
  2407. if (progress) {
  2408. notify.data({progress : 0, total : 0});
  2409. }
  2410. }
  2411. cnt = delta + parseInt(notify.data('cnt'));
  2412. if (cnt > 0) {
  2413. !opts.hideCnt && notify.children('.elfinder-notify-cnt').text('('+cnt+')');
  2414. ndialog.is(':hidden') && ndialog.elfinderdialog('open');
  2415. notify.data('cnt', cnt);
  2416. if (progress
  2417. && (total = notify.data('total')) >= 0
  2418. && (prc = notify.data('progress')) >= 0) {
  2419. total = delta + parseInt(notify.data('total'));
  2420. prc = progress + prc;
  2421. progress = parseInt(prc/total);
  2422. notify.data({progress : prc, total : total});
  2423. ndialog.find('.elfinder-notify-progress')
  2424. .animate({
  2425. width : (progress < 100 ? progress : 100)+'%'
  2426. }, 20);
  2427. }
  2428. } else {
  2429. notify.remove();
  2430. !ndialog.children().length && ndialog.elfinderdialog('close');
  2431. }
  2432. return this;
  2433. },
  2434. /**
  2435. * Open confirmation dialog
  2436. *
  2437. * @param Object options
  2438. * @example
  2439. * this.confirm({
  2440. * title : 'Remove files',
  2441. * text : 'Here is question text',
  2442. * accept : { // accept callback - required
  2443. * label : 'Continue',
  2444. * callback : function(applyToAll) { fm.log('Ok') }
  2445. * },
  2446. * cancel : { // cancel callback - required
  2447. * label : 'Cancel',
  2448. * callback : function() { fm.log('Cancel')}
  2449. * },
  2450. * reject : { // reject callback - optionally
  2451. * label : 'No',
  2452. * callback : function(applyToAll) { fm.log('No')}
  2453. * },
  2454. * all : true // display checkbox "Apply to all"
  2455. * })
  2456. * @return elFinder
  2457. */
  2458. confirm : function(opts) {
  2459. var complete = false,
  2460. options = {
  2461. cssClass : 'elfinder-dialog-confirm',
  2462. modal : true,
  2463. resizable : false,
  2464. title : this.i18n(opts.title || 'confirmReq'),
  2465. buttons : {},
  2466. close : function() {
  2467. !complete && opts.cancel.callback();
  2468. $(this).elfinderdialog('destroy');
  2469. }
  2470. },
  2471. apply = this.i18n('apllyAll'),
  2472. label, checkbox;
  2473. if (opts.reject) {
  2474. options.buttons[this.i18n(opts.reject.label)] = function() {
  2475. opts.reject.callback(!!(checkbox && checkbox.prop('checked')))
  2476. complete = true;
  2477. $(this).elfinderdialog('close')
  2478. };
  2479. }
  2480. options.buttons[this.i18n(opts.accept.label)] = function() {
  2481. opts.accept.callback(!!(checkbox && checkbox.prop('checked')))
  2482. complete = true;
  2483. $(this).elfinderdialog('close')
  2484. };
  2485. options.buttons[this.i18n(opts.cancel.label)] = function() {
  2486. $(this).elfinderdialog('close')
  2487. };
  2488. if (opts.all) {
  2489. if (opts.reject) {
  2490. options.width = 370;
  2491. }
  2492. options.create = function() {
  2493. checkbox = $('<input type="checkbox" />');
  2494. $(this).next().children().before($('<label>'+apply+'</label>').prepend(checkbox));
  2495. }
  2496. options.open = function() {
  2497. var pane = $(this).next(),
  2498. width = parseInt(pane.children(':first').outerWidth() + pane.children(':last').outerWidth());
  2499. if (width > parseInt(pane.width())) {
  2500. $(this).closest('.elfinder-dialog').width(width+30);
  2501. }
  2502. }
  2503. }
  2504. return this.dialog('<span class="elfinder-dialog-icon elfinder-dialog-icon-confirm"/>' + this.i18n(opts.text), options);
  2505. },
  2506. /**
  2507. * Create unique file name in required dir
  2508. *
  2509. * @param String file name
  2510. * @param String parent dir hash
  2511. * @return String
  2512. */
  2513. uniqueName : function(prefix, phash) {
  2514. var i = 0, ext = '', p, name;
  2515. prefix = this.i18n(prefix);
  2516. phash = phash || this.cwd().hash;
  2517. if ((p = prefix.indexOf('.txt')) != -1) {
  2518. ext = '.txt';
  2519. prefix = prefix.substr(0, p);
  2520. }
  2521. name = prefix+ext;
  2522. if (!this.fileByName(name, phash)) {
  2523. return name;
  2524. }
  2525. while (i < 10000) {
  2526. name = prefix + ' ' + (++i) + ext;
  2527. if (!this.fileByName(name, phash)) {
  2528. return name;
  2529. }
  2530. }
  2531. return prefix + Math.random() + ext;
  2532. },
  2533. /**
  2534. * Return message translated onto current language
  2535. *
  2536. * @param String|Array message[s]
  2537. * @return String
  2538. **/
  2539. i18n : function() {
  2540. var self = this,
  2541. messages = this.messages,
  2542. input = [],
  2543. ignore = [],
  2544. message = function(m) {
  2545. var file;
  2546. if (m.indexOf('#') === 0) {
  2547. if ((file = self.file(m.substr(1)))) {
  2548. return file.name;
  2549. }
  2550. }
  2551. return m;
  2552. },
  2553. i, j, m;
  2554. for (i = 0; i< arguments.length; i++) {
  2555. m = arguments[i];
  2556. if (typeof m == 'string') {
  2557. input.push(message(m));
  2558. } else if ($.isArray(m)) {
  2559. for (j = 0; j < m.length; j++) {
  2560. if (typeof m[j] == 'string') {
  2561. input.push(message(m[j]));
  2562. }
  2563. }
  2564. }
  2565. }
  2566. for (i = 0; i < input.length; i++) {
  2567. // dont translate placeholders
  2568. if ($.inArray(i, ignore) !== -1) {
  2569. continue;
  2570. }
  2571. m = input[i];
  2572. // translate message
  2573. m = messages[m] || m;
  2574. // replace placeholders in message
  2575. m = m.replace(/\$(\d+)/g, function(match, placeholder) {
  2576. placeholder = i + parseInt(placeholder);
  2577. if (placeholder > 0 && input[placeholder]) {
  2578. ignore.push(placeholder)
  2579. }
  2580. return input[placeholder] || '';
  2581. });
  2582. input[i] = m;
  2583. }
  2584. return $.map(input, function(m, i) { return $.inArray(i, ignore) === -1 ? m : null; }).join('<br>');
  2585. },
  2586. /**
  2587. * Convert mimetype into css classes
  2588. *
  2589. * @param String file mimetype
  2590. * @return String
  2591. */
  2592. mime2class : function(mime) {
  2593. var prefix = 'elfinder-cwd-icon-';
  2594. mime = mime.split('/');
  2595. return prefix+mime[0]+(mime[0] != 'image' && mime[1] ? ' '+prefix+mime[1].replace(/(\.|\+)/g, '-') : '');
  2596. },
  2597. /**
  2598. * Return localized kind of file
  2599. *
  2600. * @param Object|String file or file mimetype
  2601. * @return String
  2602. */
  2603. mime2kind : function(f) {
  2604. var mime = typeof(f) == 'object' ? f.mime : f, kind;
  2605. if (f.alias) {
  2606. kind = 'Alias';
  2607. } else if (this.kinds[mime]) {
  2608. kind = this.kinds[mime];
  2609. } else {
  2610. if (mime.indexOf('text') === 0) {
  2611. kind = 'Text';
  2612. } else if (mime.indexOf('image') === 0) {
  2613. kind = 'Image';
  2614. } else if (mime.indexOf('audio') === 0) {
  2615. kind = 'Audio';
  2616. } else if (mime.indexOf('video') === 0) {
  2617. kind = 'Video';
  2618. } else if (mime.indexOf('application') === 0) {
  2619. kind = 'App';
  2620. } else {
  2621. kind = mime;
  2622. }
  2623. }
  2624. return this.messages['kind'+kind] ? this.i18n('kind'+kind) : mime;
  2625. var mime = typeof(f) == 'object' ? f.mime : f,
  2626. kind = this.kinds[mime]||'unknown';
  2627. if (f.alias) {
  2628. kind = 'Alias';
  2629. } else if (kind == 'unknown') {
  2630. if (mime.indexOf('text') === 0) {
  2631. kind = 'Text';
  2632. } else if (mime.indexOf('image') === 0) {
  2633. kind = 'Image';
  2634. } else if (mime.indexOf('audio') === 0) {
  2635. kind = 'Audio';
  2636. } else if (mime.indexOf('video') === 0) {
  2637. kind = 'Video';
  2638. } else if (mime.indexOf('application') === 0) {
  2639. kind = 'Application';
  2640. }
  2641. }
  2642. return this.i18n(kind);
  2643. },
  2644. /**
  2645. * Return localized date
  2646. *
  2647. * @param Object file object
  2648. * @return String
  2649. */
  2650. formatDate : function(file, ts) {
  2651. var self = this,
  2652. ts = ts || file.ts,
  2653. i18 = self.i18,
  2654. date, format, output, d, dw, m, y, h, g, i, s;
  2655. if (self.options.clientFormatDate && ts > 0) {
  2656. date = new Date(ts*1000);
  2657. h = date[self.getHours]();
  2658. g = h > 12 ? h - 12 : h;
  2659. i = date[self.getMinutes]();
  2660. s = date[self.getSeconds]();
  2661. d = date[self.getDate]();
  2662. dw = date[self.getDay]();
  2663. m = date[self.getMonth]() + 1;
  2664. y = date[self.getFullYear]();
  2665. format = ts >= this.yesterday
  2666. ? this.fancyFormat
  2667. : this.dateFormat;
  2668. output = format.replace(/[a-z]/gi, function(val) {
  2669. switch (val) {
  2670. case 'd': return d > 9 ? d : '0'+d;
  2671. case 'j': return d;
  2672. case 'D': return self.i18n(i18.daysShort[dw]);
  2673. case 'l': return self.i18n(i18.days[dw]);
  2674. case 'm': return m > 9 ? m : '0'+m;
  2675. case 'n': return m;
  2676. case 'M': return self.i18n(i18.monthsShort[m-1]);
  2677. case 'F': return self.i18n(i18.months[m-1]);
  2678. case 'Y': return y;
  2679. case 'y': return (''+y).substr(2);
  2680. case 'H': return h > 9 ? h : '0'+h;
  2681. case 'G': return h;
  2682. case 'g': return g;
  2683. case 'h': return g > 9 ? g : '0'+g;
  2684. case 'a': return h > 12 ? 'pm' : 'am';
  2685. case 'A': return h > 12 ? 'PM' : 'AM';
  2686. case 'i': return i > 9 ? i : '0'+i;
  2687. case 's': return s > 9 ? s : '0'+s;
  2688. }
  2689. return val;
  2690. });
  2691. return ts >= this.yesterday
  2692. ? output.replace('$1', this.i18n(ts >= this.today ? 'Today' : 'Yesterday'))
  2693. : output;
  2694. } else if (file.date) {
  2695. return file.date.replace(/([a-z]+)\s/i, function(a1, a2) { return self.i18n(a2)+' '; });
  2696. }
  2697. return self.i18n('dateUnknown');
  2698. },
  2699. /**
  2700. * Return css class marks file permissions
  2701. *
  2702. * @param Object file
  2703. * @return String
  2704. */
  2705. perms2class : function(o) {
  2706. var c = '';
  2707. if (!o.read && !o.write) {
  2708. c = 'elfinder-na';
  2709. } else if (!o.read) {
  2710. c = 'elfinder-wo';
  2711. } else if (!o.write) {
  2712. c = 'elfinder-ro';
  2713. }
  2714. return c;
  2715. },
  2716. /**
  2717. * Return localized string with file permissions
  2718. *
  2719. * @param Object file
  2720. * @return String
  2721. */
  2722. formatPermissions : function(f) {
  2723. var p = [];
  2724. f.read && p.push(this.i18n('read'));
  2725. f.write && p.push(this.i18n('write'));
  2726. return p.length ? p.join(' '+this.i18n('and')+' ') : this.i18n('noaccess');
  2727. },
  2728. /**
  2729. * Return formated file size
  2730. *
  2731. * @param Number file size
  2732. * @return String
  2733. */
  2734. formatSize : function(s) {
  2735. var n = 1, u = 'b';
  2736. if (s == 'unknown') {
  2737. return this.i18n('unknown');
  2738. }
  2739. if (s > 1073741824) {
  2740. n = 1073741824;
  2741. u = 'GB';
  2742. } else if (s > 1048576) {
  2743. n = 1048576;
  2744. u = 'MB';
  2745. } else if (s > 1024) {
  2746. n = 1024;
  2747. u = 'KB';
  2748. }
  2749. s = s/n;
  2750. return (s > 0 ? n >= 1048576 ? s.toFixed(2) : Math.round(s) : 0) +' '+u;
  2751. },
  2752. navHash2Id : function(hash) {
  2753. return 'nav-'+hash;
  2754. },
  2755. navId2Hash : function(id) {
  2756. return typeof(id) == 'string' ? id.substr(4) : false;
  2757. },
  2758. log : function(m) { window.console && window.console.log && window.console.log(m); return this; },
  2759. debug : function(type, m) {
  2760. var d = this.options.debug;
  2761. if (d == 'all' || d === true || ($.isArray(d) && $.inArray(type, d) != -1)) {
  2762. window.console && window.console.log && window.console.log('elfinder debug: ['+type+'] ['+this.id+']', m);
  2763. }
  2764. return this;
  2765. },
  2766. time : function(l) { window.console && window.console.time && window.console.time(l); },
  2767. timeEnd : function(l) { window.console && window.console.timeEnd && window.console.timeEnd(l); }
  2768. }
  2769. /*
  2770. * File: /home/osc/elFinder-build/elFinder/js/elFinder.version.js
  2771. */
  2772. /**
  2773. * Application version
  2774. *
  2775. * @type String
  2776. **/
  2777. elFinder.prototype.version = '2.1 (Nightly: 093d077)';
  2778. /*
  2779. * File: /home/osc/elFinder-build/elFinder/js/jquery.elfinder.js
  2780. */
  2781. $.fn.elfinder = function(o) {
  2782. if (o == 'instance') {
  2783. return this.getElFinder();
  2784. }
  2785. return this.each(function() {
  2786. var cmd = typeof(o) == 'string' ? o : '';
  2787. if (!this.elfinder) {
  2788. new elFinder(this, typeof(o) == 'object' ? o : {})
  2789. }
  2790. switch(cmd) {
  2791. case 'close':
  2792. case 'hide':
  2793. this.elfinder.hide();
  2794. break;
  2795. case 'open':
  2796. case 'show':
  2797. this.elfinder.show();
  2798. break;
  2799. case'destroy':
  2800. this.elfinder.destroy();
  2801. break;
  2802. }
  2803. })
  2804. }
  2805. $.fn.getElFinder = function() {
  2806. var instance;
  2807. this.each(function() {
  2808. if (this.elfinder) {
  2809. instance = this.elfinder;
  2810. return false;
  2811. }
  2812. });
  2813. return instance;
  2814. }
  2815. /*
  2816. * File: /home/osc/elFinder-build/elFinder/js/elFinder.options.js
  2817. */
  2818. /**
  2819. * Default elFinder config
  2820. *
  2821. * @type Object
  2822. * @autor Dmitry (dio) Levashov
  2823. */
  2824. elFinder.prototype._options = {
  2825. /**
  2826. * Connector url. Required!
  2827. *
  2828. * @type String
  2829. */
  2830. url : '',
  2831. /**
  2832. * Ajax request type.
  2833. *
  2834. * @type String
  2835. * @default "get"
  2836. */
  2837. requestType : 'get',
  2838. /**
  2839. * Transport to send request to backend.
  2840. * Required for future extensions using websockets/webdav etc.
  2841. * Must be an object with "send" method.
  2842. * transport.send must return $.Deferred() object
  2843. *
  2844. * @type Object
  2845. * @default null
  2846. * @example
  2847. * transport : {
  2848. * init : function(elfinderInstance) { },
  2849. * send : function(options) {
  2850. * var dfrd = $.Deferred();
  2851. * // connect to backend ...
  2852. * return dfrd;
  2853. * },
  2854. * upload : function(data) {
  2855. * var dfrd = $.Deferred();
  2856. * // upload ...
  2857. * return dfrd;
  2858. * }
  2859. *
  2860. * }
  2861. **/
  2862. transport : {},
  2863. /**
  2864. * URL to upload file to.
  2865. * If not set - connector URL will be used
  2866. *
  2867. * @type String
  2868. * @default ''
  2869. */
  2870. urlUpload : '',
  2871. /**
  2872. * Allow to drag and drop to upload files
  2873. *
  2874. * @type Boolean|String
  2875. * @default 'auto'
  2876. */
  2877. dragUploadAllow : 'auto',
  2878. /**
  2879. * Timeout for upload using iframe
  2880. *
  2881. * @type Number
  2882. * @default 0 - no timeout
  2883. */
  2884. iframeTimeout : 0,
  2885. /**
  2886. * Data to append to all requests and to upload files
  2887. *
  2888. * @type Object
  2889. * @default {}
  2890. */
  2891. customData : {},
  2892. /**
  2893. * Event listeners to bind on elFinder init
  2894. *
  2895. * @type Object
  2896. * @default {}
  2897. */
  2898. handlers : {},
  2899. /**
  2900. * Interface language
  2901. *
  2902. * @type String
  2903. * @default "en"
  2904. */
  2905. lang : 'en',
  2906. /**
  2907. * Additional css class for filemanager node.
  2908. *
  2909. * @type String
  2910. */
  2911. cssClass : '',
  2912. /**
  2913. * Active commands list
  2914. * If some required commands will be missed here, elFinder will add its
  2915. *
  2916. * @type Array
  2917. */
  2918. commands : [
  2919. 'open', 'reload', 'home', 'up', 'back', 'forward', 'getfile', 'quicklook',
  2920. 'download', 'rm', 'duplicate', 'rename', 'mkdir', 'mkfile', 'upload', 'copy',
  2921. 'cut', 'paste', 'edit', 'extract', 'archive', 'search', 'info', 'view', 'help', 'resize', 'sort', 'netmount'
  2922. ],
  2923. /**
  2924. * Commands options.
  2925. *
  2926. * @type Object
  2927. **/
  2928. commandsOptions : {
  2929. // "getfile" command options.
  2930. getfile : {
  2931. onlyURL : false,
  2932. // allow to return multiple files info
  2933. multiple : false,
  2934. // allow to return filers info
  2935. folders : false,
  2936. // action after callback (""/"close"/"destroy")
  2937. oncomplete : ''
  2938. },
  2939. // "upload" command options.
  2940. upload : {
  2941. ui : 'uploadbutton'
  2942. },
  2943. // "quicklook" command options.
  2944. quicklook : {
  2945. autoplay : true,
  2946. jplayer : 'extensions/jplayer'
  2947. },
  2948. // "quicklook" command options.
  2949. edit : {
  2950. // list of allowed mimetypes to edit
  2951. // if empty - any text files can be edited
  2952. mimes : [],
  2953. // edit files in wysisyg's
  2954. editors : [
  2955. // {
  2956. // /**
  2957. // * files mimetypes allowed to edit in current wysisyg
  2958. // * @type Array
  2959. // */
  2960. // mimes : ['text/html'],
  2961. // /**
  2962. // * Called when "edit" dialog loaded.
  2963. // * Place to init wysisyg.
  2964. // * Can return wysisyg instance
  2965. // *
  2966. // * @param DOMElement textarea node
  2967. // * @return Object
  2968. // */
  2969. // load : function(textarea) { },
  2970. // /**
  2971. // * Called before "edit" dialog closed.
  2972. // * Place to destroy wysisyg instance.
  2973. // *
  2974. // * @param DOMElement textarea node
  2975. // * @param Object wysisyg instance (if was returned by "load" callback)
  2976. // * @return void
  2977. // */
  2978. // close : function(textarea, instance) { },
  2979. // /**
  2980. // * Called before file content send to backend.
  2981. // * Place to update textarea content if needed.
  2982. // *
  2983. // * @param DOMElement textarea node
  2984. // * @param Object wysisyg instance (if was returned by "load" callback)
  2985. // * @return void
  2986. // */
  2987. // save : function(textarea, editor) {}
  2988. //
  2989. // }
  2990. ]
  2991. },
  2992. help : {view : ['about', 'shortcuts', 'help']}
  2993. },
  2994. /**
  2995. * Callback for "getfile" commands.
  2996. * Required to use elFinder with WYSIWYG editors etc..
  2997. *
  2998. * @type Function
  2999. * @default null (command not active)
  3000. */
  3001. getFileCallback : null,
  3002. /**
  3003. * Default directory view. icons/list
  3004. *
  3005. * @type String
  3006. * @default "icons"
  3007. */
  3008. defaultView : 'icons',
  3009. /**
  3010. * UI plugins to load.
  3011. * Current dir ui and dialogs loads always.
  3012. * Here set not required plugins as folders tree/toolbar/statusbar etc.
  3013. *
  3014. * @type Array
  3015. * @default ['toolbar', 'tree', 'path', 'stat']
  3016. * @full ['toolbar', 'places', 'tree', 'path', 'stat']
  3017. */
  3018. ui : ['toolbar', 'tree', 'path', 'stat'],
  3019. /**
  3020. * Some UI plugins options.
  3021. * @type Object
  3022. */
  3023. uiOptions : {
  3024. // toolbar configuration
  3025. toolbar : [
  3026. ['back', 'forward'],
  3027. ['netmount'],
  3028. // ['reload'],
  3029. // ['home', 'up'],
  3030. ['mkdir', 'mkfile', 'upload'],
  3031. ['open', 'download', 'getfile'],
  3032. ['info'],
  3033. ['quicklook'],
  3034. ['copy', 'cut', 'paste'],
  3035. ['rm'],
  3036. ['duplicate', 'rename', 'edit', 'resize'],
  3037. ['extract', 'archive'],
  3038. ['search'],
  3039. ['view', 'sort'],
  3040. ['help']
  3041. ],
  3042. // directories tree options
  3043. tree : {
  3044. // expand current root on init
  3045. openRootOnLoad : true,
  3046. // auto load current dir parents
  3047. syncTree : true
  3048. },
  3049. // navbar options
  3050. navbar : {
  3051. minWidth : 150,
  3052. maxWidth : 500
  3053. },
  3054. cwd : {
  3055. // display parent folder with ".." name :)
  3056. oldSchool : false
  3057. }
  3058. },
  3059. /**
  3060. * Display only required files by types
  3061. *
  3062. * @type Array
  3063. * @default []
  3064. * @example
  3065. * onlyMimes : ["image"] - display all images
  3066. * onlyMimes : ["image/png", "application/x-shockwave-flash"] - display png and flash
  3067. */
  3068. onlyMimes : [],
  3069. /**
  3070. * Custom files sort rules.
  3071. * All default rules (name/size/kind/date) set in elFinder._sortRules
  3072. *
  3073. * @type {Object}
  3074. * @example
  3075. * sortRules : {
  3076. * name : function(file1, file2) { return file1.name.toLowerCase().localeCompare(file2.name.toLowerCase()); }
  3077. * }
  3078. */
  3079. sortRules : {},
  3080. /**
  3081. * Default sort type.
  3082. *
  3083. * @type {String}
  3084. */
  3085. sortType : 'name',
  3086. /**
  3087. * Default sort order.
  3088. *
  3089. * @type {String}
  3090. * @default "asc"
  3091. */
  3092. sortOrder : 'asc',
  3093. /**
  3094. * Display folders first?
  3095. *
  3096. * @type {Boolean}
  3097. * @default true
  3098. */
  3099. sortStickFolders : true,
  3100. /**
  3101. * If true - elFinder will formating dates itself,
  3102. * otherwise - backend date will be used.
  3103. *
  3104. * @type Boolean
  3105. */
  3106. clientFormatDate : true,
  3107. /**
  3108. * Show UTC dates.
  3109. * Required set clientFormatDate to true
  3110. *
  3111. * @type Boolean
  3112. */
  3113. UTCDate : false,
  3114. /**
  3115. * File modification datetime format.
  3116. * Value from selected language data is used by default.
  3117. * Set format here to overwrite it.
  3118. *
  3119. * @type String
  3120. * @default ""
  3121. */
  3122. dateFormat : '',
  3123. /**
  3124. * File modification datetime format in form "Yesterday 12:23:01".
  3125. * Value from selected language data is used by default.
  3126. * Set format here to overwrite it.
  3127. * Use $1 for "Today"/"Yesterday" placeholder
  3128. *
  3129. * @type String
  3130. * @default ""
  3131. * @example "$1 H:m:i"
  3132. */
  3133. fancyDateFormat : '',
  3134. /**
  3135. * elFinder width
  3136. *
  3137. * @type String|Number
  3138. * @default "auto"
  3139. */
  3140. width : 'auto',
  3141. /**
  3142. * elFinder height
  3143. *
  3144. * @type Number
  3145. * @default "auto"
  3146. */
  3147. height : 400,
  3148. /**
  3149. * Make elFinder resizable if jquery ui resizable available
  3150. *
  3151. * @type Boolean
  3152. * @default true
  3153. */
  3154. resizable : true,
  3155. /**
  3156. * Timeout before open notifications dialogs
  3157. *
  3158. * @type Number
  3159. * @default 500 (.5 sec)
  3160. */
  3161. notifyDelay : 500,
  3162. /**
  3163. * Allow shortcuts
  3164. *
  3165. * @type Boolean
  3166. * @default true
  3167. */
  3168. allowShortcuts : true,
  3169. /**
  3170. * Remeber last opened dir to open it after reload or in next session
  3171. *
  3172. * @type Boolean
  3173. * @default true
  3174. */
  3175. rememberLastDir : true,
  3176. /**
  3177. * Lazy load config.
  3178. * How many files display at once?
  3179. *
  3180. * @type Number
  3181. * @default 50
  3182. */
  3183. showFiles : 30,
  3184. /**
  3185. * Lazy load config.
  3186. * Distance in px to cwd bottom edge to start display files
  3187. *
  3188. * @type Number
  3189. * @default 50
  3190. */
  3191. showThreshold : 50,
  3192. /**
  3193. * Additional rule to valid new file name.
  3194. * By default not allowed empty names or '..'
  3195. *
  3196. * @type false|RegExp|function
  3197. * @default false
  3198. * @example
  3199. * disable names with spaces:
  3200. * validName : /^[^\s]$/
  3201. */
  3202. validName : false,
  3203. /**
  3204. * Sync content interval
  3205. * @todo - fix in elFinder
  3206. * @type Number
  3207. * @default 0 (do not sync)
  3208. */
  3209. sync : 0,
  3210. /**
  3211. * How many thumbnails create in one request
  3212. *
  3213. * @type Number
  3214. * @default 5
  3215. */
  3216. loadTmbs : 5,
  3217. /**
  3218. * Cookie option for browsersdoes not suppot localStorage
  3219. *
  3220. * @type Object
  3221. */
  3222. cookie : {
  3223. expires : 30,
  3224. domain : '',
  3225. path : '/',
  3226. secure : false
  3227. },
  3228. /**
  3229. * Contextmenu config
  3230. *
  3231. * @type Object
  3232. */
  3233. contextmenu : {
  3234. // navbarfolder menu
  3235. navbar : ['open', '|', 'copy', 'cut', 'paste', 'duplicate', '|', 'rm', '|', 'info'],
  3236. // current directory menu
  3237. cwd : ['reload', 'back', '|', 'upload', 'mkdir', 'mkfile', 'paste', '|', 'sort', '|', 'info'],
  3238. // current directory file menu
  3239. files : ['getfile', '|','open', 'quicklook', '|', 'download', '|', 'copy', 'cut', 'paste', 'duplicate', '|', 'rm', '|', 'edit', 'rename', 'resize', '|', 'archive', 'extract', '|', 'info']
  3240. },
  3241. /**
  3242. * Debug config
  3243. *
  3244. * @type Array|Boolean
  3245. */
  3246. // debug : true
  3247. debug : ['error', 'warning', 'event-destroy']
  3248. }
  3249. /*
  3250. * File: /home/osc/elFinder-build/elFinder/js/elFinder.history.js
  3251. */
  3252. /**
  3253. * @class elFinder.history
  3254. * Store visited folders
  3255. * and provide "back" and "forward" methods
  3256. *
  3257. * @author Dmitry (dio) Levashov
  3258. */
  3259. elFinder.prototype.history = function(fm) {
  3260. var self = this,
  3261. /**
  3262. * Update history on "open" event?
  3263. *
  3264. * @type Boolean
  3265. */
  3266. update = true,
  3267. /**
  3268. * Directories hashes storage
  3269. *
  3270. * @type Array
  3271. */
  3272. history = [],
  3273. /**
  3274. * Current directory index in history
  3275. *
  3276. * @type Number
  3277. */
  3278. current,
  3279. /**
  3280. * Clear history
  3281. *
  3282. * @return void
  3283. */
  3284. reset = function() {
  3285. history = [fm.cwd().hash];
  3286. current = 0;
  3287. update = true;
  3288. },
  3289. /**
  3290. * Open prev/next folder
  3291. *
  3292. * @Boolen open next folder?
  3293. * @return jQuery.Deferred
  3294. */
  3295. go = function(fwd) {
  3296. if ((fwd && self.canForward()) || (!fwd && self.canBack())) {
  3297. update = false;
  3298. return fm.exec('open', history[fwd ? ++current : --current]).fail(reset);
  3299. }
  3300. return $.Deferred().reject();
  3301. };
  3302. /**
  3303. * Return true if there is previous visited directories
  3304. *
  3305. * @return Boolen
  3306. */
  3307. this.canBack = function() {
  3308. return current > 0;
  3309. }
  3310. /**
  3311. * Return true if can go forward
  3312. *
  3313. * @return Boolen
  3314. */
  3315. this.canForward = function() {
  3316. return current < history.length - 1;
  3317. }
  3318. /**
  3319. * Go back
  3320. *
  3321. * @return void
  3322. */
  3323. this.back = go;
  3324. /**
  3325. * Go forward
  3326. *
  3327. * @return void
  3328. */
  3329. this.forward = function() {
  3330. return go(true);
  3331. }
  3332. // bind to elfinder events
  3333. fm.open(function(e) {
  3334. var l = history.length,
  3335. cwd = fm.cwd().hash;
  3336. if (update) {
  3337. current >= 0 && l > current + 1 && history.splice(current+1);
  3338. history[history.length-1] != cwd && history.push(cwd);
  3339. current = history.length - 1;
  3340. }
  3341. update = true;
  3342. })
  3343. .reload(reset);
  3344. }
  3345. /*
  3346. * File: /home/osc/elFinder-build/elFinder/js/elFinder.command.js
  3347. */
  3348. /**
  3349. * elFinder command prototype
  3350. *
  3351. * @type elFinder.command
  3352. * @author Dmitry (dio) Levashov
  3353. */
  3354. elFinder.prototype.command = function(fm) {
  3355. /**
  3356. * elFinder instance
  3357. *
  3358. * @type elFinder
  3359. */
  3360. this.fm = fm;
  3361. /**
  3362. * Command name, same as class name
  3363. *
  3364. * @type String
  3365. */
  3366. this.name = '';
  3367. /**
  3368. * Short command description
  3369. *
  3370. * @type String
  3371. */
  3372. this.title = '';
  3373. /**
  3374. * Current command state
  3375. *
  3376. * @example
  3377. * this.state = -1; // command disabled
  3378. * this.state = 0; // command enabled
  3379. * this.state = 1; // command active (for example "fullscreen" command while elfinder in fullscreen mode)
  3380. * @default -1
  3381. * @type Number
  3382. */
  3383. this.state = -1;
  3384. /**
  3385. * If true, command can not be disabled by connector.
  3386. * @see this.update()
  3387. *
  3388. * @type Boolen
  3389. */
  3390. this.alwaysEnabled = false;
  3391. /**
  3392. * If true, this means command was disabled by connector.
  3393. * @see this.update()
  3394. *
  3395. * @type Boolen
  3396. */
  3397. this._disabled = false;
  3398. this.disableOnSearch = false;
  3399. this.updateOnSelect = true;
  3400. /**
  3401. * elFinder events defaults handlers.
  3402. * Inside handlers "this" is current command object
  3403. *
  3404. * @type Object
  3405. */
  3406. this._handlers = {
  3407. enable : function() { this.update(void(0), this.value); },
  3408. disable : function() { this.update(-1, this.value); },
  3409. 'open reload load' : function(e) {
  3410. this._disabled = !(this.alwaysEnabled || this.fm.isCommandEnabled(this.name));
  3411. this.update(void(0), this.value)
  3412. this.change();
  3413. }
  3414. };
  3415. /**
  3416. * elFinder events handlers.
  3417. * Inside handlers "this" is current command object
  3418. *
  3419. * @type Object
  3420. */
  3421. this.handlers = {}
  3422. /**
  3423. * Shortcuts
  3424. *
  3425. * @type Array
  3426. */
  3427. this.shortcuts = [];
  3428. /**
  3429. * Command options
  3430. *
  3431. * @type Object
  3432. */
  3433. this.options = {ui : 'button'};
  3434. /**
  3435. * Prepare object -
  3436. * bind events and shortcuts
  3437. *
  3438. * @return void
  3439. */
  3440. this.setup = function(name, opts) {
  3441. var self = this,
  3442. fm = this.fm, i, s;
  3443. this.name = name;
  3444. this.title = fm.messages['cmd'+name] ? fm.i18n('cmd'+name) : name,
  3445. this.options = $.extend({}, this.options, opts);
  3446. this.listeners = [];
  3447. if (this.updateOnSelect) {
  3448. this._handlers.select = function() { this.update(void(0), this.value); }
  3449. }
  3450. $.each($.extend({}, self._handlers, self.handlers), function(cmd, handler) {
  3451. fm.bind(cmd, $.proxy(handler, self));
  3452. });
  3453. for (i = 0; i < this.shortcuts.length; i++) {
  3454. s = this.shortcuts[i];
  3455. s.callback = $.proxy(s.callback || function() { this.exec() }, this);
  3456. !s.description && (s.description = this.title);
  3457. fm.shortcut(s);
  3458. }
  3459. if (this.disableOnSearch) {
  3460. fm.bind('search searchend', function(e) {
  3461. self._disabled = e.type == 'search';
  3462. self.update(void(0), self.value);
  3463. });
  3464. }
  3465. this.init();
  3466. }
  3467. /**
  3468. * Command specific init stuffs
  3469. *
  3470. * @return void
  3471. */
  3472. this.init = function() { }
  3473. /**
  3474. * Exec command
  3475. *
  3476. * @param Array target files hashes
  3477. * @param Array|Object command value
  3478. * @return $.Deferred
  3479. */
  3480. this.exec = function(files, opts) {
  3481. return $.Deferred().reject();
  3482. }
  3483. /**
  3484. * Return true if command disabled.
  3485. *
  3486. * @return Boolen
  3487. */
  3488. this.disabled = function() {
  3489. return this.state < 0;
  3490. }
  3491. /**
  3492. * Return true if command enabled.
  3493. *
  3494. * @return Boolen
  3495. */
  3496. this.enabled = function() {
  3497. return this.state > -1;
  3498. }
  3499. /**
  3500. * Return true if command active.
  3501. *
  3502. * @return Boolen
  3503. */
  3504. this.active = function() {
  3505. return this.state > 0;
  3506. }
  3507. /**
  3508. * Return current command state.
  3509. * Must be overloaded in most commands
  3510. *
  3511. * @return Number
  3512. */
  3513. this.getstate = function() {
  3514. return -1;
  3515. }
  3516. /**
  3517. * Update command state/value
  3518. * and rize 'change' event if smth changed
  3519. *
  3520. * @param Number new state or undefined to auto update state
  3521. * @param mixed new value
  3522. * @return void
  3523. */
  3524. this.update = function(s, v) {
  3525. var state = this.state,
  3526. value = this.value;
  3527. if (this._disabled) {
  3528. this.state = -1;
  3529. } else {
  3530. this.state = s !== void(0) ? s : this.getstate();
  3531. }
  3532. this.value = v;
  3533. if (state != this.state || value != this.value) {
  3534. this.change();
  3535. }
  3536. }
  3537. /**
  3538. * Bind handler / fire 'change' event.
  3539. *
  3540. * @param Function|undefined event callback
  3541. * @return void
  3542. */
  3543. this.change = function(c) {
  3544. var cmd, i;
  3545. if (typeof(c) === 'function') {
  3546. this.listeners.push(c);
  3547. } else {
  3548. for (i = 0; i < this.listeners.length; i++) {
  3549. cmd = this.listeners[i];
  3550. try {
  3551. cmd(this.state, this.value);
  3552. } catch (e) {
  3553. this.fm.debug('error', e)
  3554. }
  3555. }
  3556. }
  3557. return this;
  3558. }
  3559. /**
  3560. * With argument check given files hashes and return list of existed files hashes.
  3561. * Without argument return selected files hashes.
  3562. *
  3563. * @param Array|String|void hashes
  3564. * @return Array
  3565. */
  3566. this.hashes = function(hashes) {
  3567. return hashes
  3568. ? $.map($.isArray(hashes) ? hashes : [hashes], function(hash) { return fm.file(hash) ? hash : null; })
  3569. : fm.selected();
  3570. }
  3571. /**
  3572. * Return only existed files from given fils hashes | selected files
  3573. *
  3574. * @param Array|String|void hashes
  3575. * @return Array
  3576. */
  3577. this.files = function(hashes) {
  3578. var fm = this.fm;
  3579. return hashes
  3580. ? $.map($.isArray(hashes) ? hashes : [hashes], function(hash) { return fm.file(hash) || null })
  3581. : fm.selectedFiles();
  3582. }
  3583. }
  3584. /*
  3585. * File: /home/osc/elFinder-build/elFinder/js/elFinder.resources.js
  3586. */
  3587. /**
  3588. * elFinder resources registry.
  3589. * Store shared data
  3590. *
  3591. * @type Object
  3592. * @author Dmitry (dio) Levashov
  3593. **/
  3594. elFinder.prototype.resources = {
  3595. 'class' : {
  3596. hover : 'ui-state-hover',
  3597. active : 'ui-state-active',
  3598. disabled : 'ui-state-disabled',
  3599. draggable : 'ui-draggable',
  3600. droppable : 'ui-droppable',
  3601. adroppable : 'elfinder-droppable-active',
  3602. cwdfile : 'elfinder-cwd-file',
  3603. cwd : 'elfinder-cwd',
  3604. tree : 'elfinder-tree',
  3605. treeroot : 'elfinder-navbar-root',
  3606. navdir : 'elfinder-navbar-dir',
  3607. navdirwrap : 'elfinder-navbar-dir-wrapper',
  3608. navarrow : 'elfinder-navbar-arrow',
  3609. navsubtree : 'elfinder-navbar-subtree',
  3610. navcollapse : 'elfinder-navbar-collapsed',
  3611. navexpand : 'elfinder-navbar-expanded',
  3612. treedir : 'elfinder-tree-dir',
  3613. placedir : 'elfinder-place-dir',
  3614. searchbtn : 'elfinder-button-search'
  3615. },
  3616. tpl : {
  3617. perms : '<span class="elfinder-perms"/>',
  3618. symlink : '<span class="elfinder-symlink"/>',
  3619. navicon : '<span class="elfinder-nav-icon"/>',
  3620. navspinner : '<span class="elfinder-navbar-spinner"/>',
  3621. navdir : '<div class="elfinder-navbar-wrapper"><span id="{id}" class="ui-corner-all elfinder-navbar-dir {cssclass}"><span class="elfinder-navbar-arrow"/><span class="elfinder-navbar-icon"/>{symlink}{permissions}{name}</span><div class="elfinder-navbar-subtree"/></div>'
  3622. },
  3623. mimes : {
  3624. text : [
  3625. 'application/x-empty',
  3626. 'application/javascript',
  3627. 'application/xhtml+xml',
  3628. 'audio/x-mp3-playlist',
  3629. 'application/x-web-config',
  3630. 'application/docbook+xml',
  3631. 'application/x-php',
  3632. 'application/x-perl',
  3633. 'application/x-awk',
  3634. 'application/x-config',
  3635. 'application/x-csh',
  3636. 'application/xml'
  3637. ]
  3638. },
  3639. mixin : {
  3640. make : function() {
  3641. var fm = this.fm,
  3642. cmd = this.name,
  3643. cwd = fm.getUI('cwd'),
  3644. dfrd = $.Deferred()
  3645. .fail(function(error) {
  3646. cwd.trigger('unselectall');
  3647. error && fm.error(error);
  3648. })
  3649. .always(function() {
  3650. input.remove();
  3651. node.remove();
  3652. fm.enable();
  3653. }),
  3654. id = 'tmp_'+parseInt(Math.random()*100000),
  3655. phash = fm.cwd().hash,
  3656. date = new Date(),
  3657. file = {
  3658. hash : id,
  3659. name : fm.uniqueName(this.prefix),
  3660. mime : this.mime,
  3661. read : true,
  3662. write : true,
  3663. date : 'Today '+date.getHours()+':'+date.getMinutes()
  3664. },
  3665. node = cwd.trigger('create.'+fm.namespace, file).find('#'+id),
  3666. input = $('<input type="text"/>')
  3667. .keydown(function(e) {
  3668. e.stopImmediatePropagation();
  3669. if (e.keyCode == $.ui.keyCode.ESCAPE) {
  3670. dfrd.reject();
  3671. } else if (e.keyCode == $.ui.keyCode.ENTER) {
  3672. input.blur();
  3673. }
  3674. })
  3675. .mousedown(function(e) {
  3676. e.stopPropagation();
  3677. })
  3678. .blur(function() {
  3679. var name = $.trim(input.val()),
  3680. parent = input.parent();
  3681. if (parent.length) {
  3682. if (!name) {
  3683. return dfrd.reject('errInvName');
  3684. }
  3685. if (fm.fileByName(name, phash)) {
  3686. return dfrd.reject(['errExists', name]);
  3687. }
  3688. parent.html(fm.escape(name));
  3689. fm.lockfiles({files : [id]});
  3690. fm.request({
  3691. data : {cmd : cmd, name : name, target : phash},
  3692. notify : {type : cmd, cnt : 1},
  3693. preventFail : true,
  3694. syncOnFail : true
  3695. })
  3696. .fail(function(error) {
  3697. dfrd.reject(error);
  3698. })
  3699. .done(function(data) {
  3700. dfrd.resolve(data);
  3701. });
  3702. }
  3703. });
  3704. if (this.disabled() || !node.length) {
  3705. return dfrd.reject();
  3706. }
  3707. fm.disable();
  3708. node.find('.elfinder-cwd-filename').empty('').append(input.val(file.name));
  3709. input.select().focus();
  3710. input[0].setSelectionRange && input[0].setSelectionRange(0, file.name.replace(/\..+$/, '').length);
  3711. return dfrd;
  3712. }
  3713. }
  3714. }
  3715. /*
  3716. * File: /home/osc/elFinder-build/elFinder/js/jquery.dialogelfinder.js
  3717. */
  3718. /**
  3719. * @class dialogelfinder - open elFinder in dialog window
  3720. *
  3721. * @param Object elFinder options with dialog options
  3722. * @example
  3723. * $(selector).dialogelfinder({
  3724. * // some elfinder options
  3725. * title : 'My files', // dialog title, default = "Files"
  3726. * width : 850, // dialog width, default 840
  3727. * autoOpen : false, // if false - dialog will not be opened after init, default = true
  3728. * destroyOnClose : true // destroy elFinder on close dialog, default = false
  3729. * })
  3730. * @author Dmitry (dio) Levashov
  3731. **/
  3732. $.fn.dialogelfinder = function(opts) {
  3733. var position = 'elfinderPosition',
  3734. destroy = 'elfinderDestroyOnClose';
  3735. this.not('.elfinder').each(function() {
  3736. var doc = $(document),
  3737. toolbar = $('<div class="ui-widget-header dialogelfinder-drag ui-corner-top">'+(opts.title || 'Files')+'</div>'),
  3738. button = $('<a href="#" class="dialogelfinder-drag-close ui-corner-all"><span class="ui-icon ui-icon-closethick"/></a>')
  3739. .appendTo(toolbar)
  3740. .click(function(e) {
  3741. e.preventDefault();
  3742. node.dialogelfinder('close');
  3743. }),
  3744. node = $(this).addClass('dialogelfinder')
  3745. .css('position', 'absolute')
  3746. .hide()
  3747. .appendTo('body')
  3748. .draggable({ handle : '.dialogelfinder-drag',
  3749. containment : 'window' })
  3750. .elfinder(opts)
  3751. .prepend(toolbar),
  3752. elfinder = node.elfinder('instance');
  3753. node.width(parseInt(node.width()) || 840) // fix width if set to "auto"
  3754. .data(destroy, !!opts.destroyOnClose)
  3755. .find('.elfinder-toolbar').removeClass('ui-corner-top');
  3756. opts.position && node.data(position, opts.position);
  3757. opts.autoOpen !== false && $(this).dialogelfinder('open');
  3758. });
  3759. if (opts == 'open') {
  3760. var node = $(this),
  3761. pos = node.data(position) || {
  3762. top : parseInt($(document).scrollTop() + ($(window).height() < node.height() ? 2 : ($(window).height() - node.height())/2)),
  3763. left : parseInt($(document).scrollLeft() + ($(window).width() < node.width() ? 2 : ($(window).width() - node.width())/2))
  3764. },
  3765. zindex = 100;
  3766. if (node.is(':hidden')) {
  3767. $('body').find(':visible').each(function() {
  3768. var $this = $(this), z;
  3769. if (this !== node[0] && $this.css('position') == 'absolute' && (z = parseInt($this.zIndex())) > zindex) {
  3770. zindex = z + 1;
  3771. }
  3772. });
  3773. node.zIndex(zindex).css(pos).show().trigger('resize')
  3774. setTimeout(function() {
  3775. // fix resize icon position and make elfinder active
  3776. node.trigger('resize').mousedown();
  3777. }, 200);
  3778. }
  3779. } else if (opts == 'close') {
  3780. var node = $(this);
  3781. if (node.is(':visible')) {
  3782. !!node.data(destroy)
  3783. ? node.elfinder('destroy').remove()
  3784. : node.elfinder('close');
  3785. }
  3786. } else if (opts == 'instance') {
  3787. return $(this).getElFinder();
  3788. }
  3789. return this;
  3790. }
  3791. /*
  3792. * File: /home/osc/elFinder-build/elFinder/js/i18n/elfinder.en.js
  3793. */
  3794. /**
  3795. * English translation
  3796. * @author Troex Nevelin <troex@fury.scancode.ru>
  3797. * @version 2013-07-03
  3798. */
  3799. if (elFinder && elFinder.prototype && typeof(elFinder.prototype.i18) == 'object') {
  3800. elFinder.prototype.i18.en = {
  3801. translator : 'Troex Nevelin &lt;troex@fury.scancode.ru&gt;',
  3802. language : 'English',
  3803. direction : 'ltr',
  3804. dateFormat : 'M d, Y h:i A', // Mar 13, 2012 05:27 PM
  3805. fancyDateFormat : '$1 h:i A', // will produce smth like: Today 12:25 PM
  3806. messages : {
  3807. /********************************** errors **********************************/
  3808. 'error' : 'Error',
  3809. 'errUnknown' : 'Unknown error.',
  3810. 'errUnknownCmd' : 'Unknown command.',
  3811. 'errJqui' : 'Invalid jQuery UI configuration. Selectable, draggable and droppable components must be included.',
  3812. 'errNode' : 'elFinder requires DOM Element to be created.',
  3813. 'errURL' : 'Invalid elFinder configuration! URL option is not set.',
  3814. 'errAccess' : 'Access denied.',
  3815. 'errConnect' : 'Unable to connect to backend.',
  3816. 'errAbort' : 'Connection aborted.',
  3817. 'errTimeout' : 'Connection timeout.',
  3818. 'errNotFound' : 'Backend not found.',
  3819. 'errResponse' : 'Invalid backend response.',
  3820. 'errConf' : 'Invalid backend configuration.',
  3821. 'errJSON' : 'PHP JSON module not installed.',
  3822. 'errNoVolumes' : 'Readable volumes not available.',
  3823. 'errCmdParams' : 'Invalid parameters for command "$1".',
  3824. 'errDataNotJSON' : 'Data is not JSON.',
  3825. 'errDataEmpty' : 'Data is empty.',
  3826. 'errCmdReq' : 'Backend request requires command name.',
  3827. 'errOpen' : 'Unable to open "$1".',
  3828. 'errNotFolder' : 'Object is not a folder.',
  3829. 'errNotFile' : 'Object is not a file.',
  3830. 'errRead' : 'Unable to read "$1".',
  3831. 'errWrite' : 'Unable to write into "$1".',
  3832. 'errPerm' : 'Permission denied.',
  3833. 'errLocked' : '"$1" is locked and can not be renamed, moved or removed.',
  3834. 'errExists' : 'File named "$1" already exists.',
  3835. 'errInvName' : 'Invalid file name.',
  3836. 'errFolderNotFound' : 'Folder not found.',
  3837. 'errFileNotFound' : 'File not found.',
  3838. 'errTrgFolderNotFound' : 'Target folder "$1" not found.',
  3839. 'errPopup' : 'Browser prevented opening popup window. To open file enable it in browser options.',
  3840. 'errMkdir' : 'Unable to create folder "$1".',
  3841. 'errMkfile' : 'Unable to create file "$1".',
  3842. 'errRename' : 'Unable to rename "$1".',
  3843. 'errCopyFrom' : 'Copying files from volume "$1" not allowed.',
  3844. 'errCopyTo' : 'Copying files to volume "$1" not allowed.',
  3845. 'errUpload' : 'Upload error.', // old name - errUploadCommon
  3846. 'errUploadFile' : 'Unable to upload "$1".', // old name - errUpload
  3847. 'errUploadNoFiles' : 'No files found for upload.',
  3848. 'errUploadTotalSize' : 'Data exceeds the maximum allowed size.', // old name - errMaxSize
  3849. 'errUploadFileSize' : 'File exceeds maximum allowed size.', // old name - errFileMaxSize
  3850. 'errUploadMime' : 'File type not allowed.',
  3851. 'errUploadTransfer' : '"$1" transfer error.',
  3852. 'errNotReplace' : 'Object "$1" already exists at this location and can not be replaced by object with another type.', // new
  3853. 'errReplace' : 'Unable to replace "$1".',
  3854. 'errSave' : 'Unable to save "$1".',
  3855. 'errCopy' : 'Unable to copy "$1".',
  3856. 'errMove' : 'Unable to move "$1".',
  3857. 'errCopyInItself' : 'Unable to copy "$1" into itself.',
  3858. 'errRm' : 'Unable to remove "$1".',
  3859. 'errRmSrc' : 'Unable remove source file(s).',
  3860. 'errExtract' : 'Unable to extract files from "$1".',
  3861. 'errArchive' : 'Unable to create archive.',
  3862. 'errArcType' : 'Unsupported archive type.',
  3863. 'errNoArchive' : 'File is not archive or has unsupported archive type.',
  3864. 'errCmdNoSupport' : 'Backend does not support this command.',
  3865. 'errReplByChild' : 'The folder “$1” can’t be replaced by an item it contains.',
  3866. 'errArcSymlinks' : 'For security reason denied to unpack archives contains symlinks or files with not allowed names.', // edited 24.06.2012
  3867. 'errArcMaxSize' : 'Archive files exceeds maximum allowed size.',
  3868. 'errResize' : 'Unable to resize "$1".',
  3869. 'errResizeDegree' : 'Invalid rotate degree.', // added 7.3.2013
  3870. 'errResizeRotate' : 'Image dose not rotated.', // added 7.3.2013
  3871. 'errResizeSize' : 'Invalid image size.', // added 7.3.2013
  3872. 'errResizeNoChange' : 'Image size not changed.', // added 7.3.2013
  3873. 'errUsupportType' : 'Unsupported file type.',
  3874. 'errNotUTF8Content' : 'File "$1" is not in UTF-8 and cannot be edited.', // added 9.11.2011
  3875. 'errNetMount' : 'Unable to mount "$1".', // added 17.04.2012
  3876. 'errNetMountNoDriver' : 'Unsupported protocol.', // added 17.04.2012
  3877. 'errNetMountFailed' : 'Mount failed.', // added 17.04.2012
  3878. 'errNetMountHostReq' : 'Host required.', // added 18.04.2012
  3879. 'errSessionExpires' : 'Your session has expired due to inactivity.',
  3880. 'errCreatingTempDir' : 'Unable to create temporary directory: "$1"',
  3881. 'errFtpDownloadFile' : 'Unable to download file from FTP: "$1"',
  3882. 'errFtpUploadFile' : 'Unable to upload file to FTP: "$1"',
  3883. 'errFtpMkdir' : 'Unable to create remote directory on FTP: "$1"',
  3884. 'errArchiveExec' : 'Error while archiving files: "$1"',
  3885. 'errExtractExec' : 'Error while extracting files: "$1"',
  3886. /******************************* commands names ********************************/
  3887. 'cmdarchive' : 'Create archive',
  3888. 'cmdback' : 'Back',
  3889. 'cmdcopy' : 'Copy',
  3890. 'cmdcut' : 'Cut',
  3891. 'cmddownload' : 'Download',
  3892. 'cmdduplicate' : 'Duplicate',
  3893. 'cmdedit' : 'Edit file',
  3894. 'cmdextract' : 'Extract files from archive',
  3895. 'cmdforward' : 'Forward',
  3896. 'cmdgetfile' : 'Select files',
  3897. 'cmdhelp' : 'About this software',
  3898. 'cmdhome' : 'Home',
  3899. 'cmdinfo' : 'Get info',
  3900. 'cmdmkdir' : 'New folder',
  3901. 'cmdmkfile' : 'New text file',
  3902. 'cmdopen' : 'Open',
  3903. 'cmdpaste' : 'Paste',
  3904. 'cmdquicklook' : 'Preview',
  3905. 'cmdreload' : 'Reload',
  3906. 'cmdrename' : 'Rename',
  3907. 'cmdrm' : 'Delete',
  3908. 'cmdsearch' : 'Find files',
  3909. 'cmdup' : 'Go to parent directory',
  3910. 'cmdupload' : 'Upload files',
  3911. 'cmdview' : 'View',
  3912. 'cmdresize' : 'Resize & Rotate',
  3913. 'cmdsort' : 'Sort',
  3914. 'cmdnetmount' : 'Mount network volume', // added 18.04.2012
  3915. /*********************************** buttons ***********************************/
  3916. 'btnClose' : 'Close',
  3917. 'btnSave' : 'Save',
  3918. 'btnRm' : 'Remove',
  3919. 'btnApply' : 'Apply',
  3920. 'btnCancel' : 'Cancel',
  3921. 'btnNo' : 'No',
  3922. 'btnYes' : 'Yes',
  3923. 'btnMount' : 'Mount', // added 18.04.2012
  3924. /******************************** notifications ********************************/
  3925. 'ntfopen' : 'Open folder',
  3926. 'ntffile' : 'Open file',
  3927. 'ntfreload' : 'Reload folder content',
  3928. 'ntfmkdir' : 'Creating directory',
  3929. 'ntfmkfile' : 'Creating files',
  3930. 'ntfrm' : 'Delete files',
  3931. 'ntfcopy' : 'Copy files',
  3932. 'ntfmove' : 'Move files',
  3933. 'ntfprepare' : 'Prepare to copy files',
  3934. 'ntfrename' : 'Rename files',
  3935. 'ntfupload' : 'Uploading files',
  3936. 'ntfdownload' : 'Downloading files',
  3937. 'ntfsave' : 'Save files',
  3938. 'ntfarchive' : 'Creating archive',
  3939. 'ntfextract' : 'Extracting files from archive',
  3940. 'ntfsearch' : 'Searching files',
  3941. 'ntfresize' : 'Resizing images',
  3942. 'ntfsmth' : 'Doing something',
  3943. 'ntfloadimg' : 'Loading image',
  3944. 'ntfnetmount' : 'Mounting network volume', // added 18.04.2012
  3945. 'ntfdim' : 'Acquiring image dimension', // added 20.05.2013
  3946. 'ntfreaddir' : 'Reading folder infomation', // added 01.07.2013
  3947. /************************************ dates **********************************/
  3948. 'dateUnknown' : 'unknown',
  3949. 'Today' : 'Today',
  3950. 'Yesterday' : 'Yesterday',
  3951. 'Jan' : 'Jan',
  3952. 'Feb' : 'Feb',
  3953. 'Mar' : 'Mar',
  3954. 'Apr' : 'Apr',
  3955. 'May' : 'May',
  3956. 'Jun' : 'Jun',
  3957. 'Jul' : 'Jul',
  3958. 'Aug' : 'Aug',
  3959. 'Sep' : 'Sep',
  3960. 'Oct' : 'Oct',
  3961. 'Nov' : 'Nov',
  3962. 'Dec' : 'Dec',
  3963. /******************************** sort variants ********************************/
  3964. 'sortname' : 'by name',
  3965. 'sortkind' : 'by kind',
  3966. 'sortsize' : 'by size',
  3967. 'sortdate' : 'by date',
  3968. 'sortFoldersFirst' : 'Folders first',
  3969. /********************************** messages **********************************/
  3970. 'confirmReq' : 'Confirmation required',
  3971. 'confirmRm' : 'Are you sure you want to remove files?<br/>This cannot be undone!',
  3972. 'confirmRepl' : 'Replace old file with new one?',
  3973. 'apllyAll' : 'Apply to all',
  3974. 'name' : 'Name',
  3975. 'size' : 'Size',
  3976. 'perms' : 'Permissions',
  3977. 'modify' : 'Modified',
  3978. 'kind' : 'Kind',
  3979. 'read' : 'read',
  3980. 'write' : 'write',
  3981. 'noaccess' : 'no access',
  3982. 'and' : 'and',
  3983. 'unknown' : 'unknown',
  3984. 'selectall' : 'Select all files',
  3985. 'selectfiles' : 'Select file(s)',
  3986. 'selectffile' : 'Select first file',
  3987. 'selectlfile' : 'Select last file',
  3988. 'viewlist' : 'List view',
  3989. 'viewicons' : 'Icons view',
  3990. 'places' : 'Places',
  3991. 'calc' : 'Calculate',
  3992. 'path' : 'Path',
  3993. 'aliasfor' : 'Alias for',
  3994. 'locked' : 'Locked',
  3995. 'dim' : 'Dimensions',
  3996. 'files' : 'Files',
  3997. 'folders' : 'Folders',
  3998. 'items' : 'Items',
  3999. 'yes' : 'yes',
  4000. 'no' : 'no',
  4001. 'link' : 'Link',
  4002. 'searcresult' : 'Search results',
  4003. 'selected' : 'selected items',
  4004. 'about' : 'About',
  4005. 'shortcuts' : 'Shortcuts',
  4006. 'help' : 'Help',
  4007. 'webfm' : 'Web file manager',
  4008. 'ver' : 'Version',
  4009. 'protocolver' : 'protocol version',
  4010. 'homepage' : 'Project home',
  4011. 'docs' : 'Documentation',
  4012. 'github' : 'Fork us on Github',
  4013. 'twitter' : 'Follow us on twitter',
  4014. 'facebook' : 'Join us on facebook',
  4015. 'team' : 'Team',
  4016. 'chiefdev' : 'chief developer',
  4017. 'developer' : 'developer',
  4018. 'contributor' : 'contributor',
  4019. 'maintainer' : 'maintainer',
  4020. 'translator' : 'translator',
  4021. 'icons' : 'Icons',
  4022. 'dontforget' : 'and don\'t forget to take your towel',
  4023. 'shortcutsof' : 'Shortcuts disabled',
  4024. 'dropFiles' : 'Drop files here',
  4025. 'dropFilesBrowser': 'Drop or paste files from browser', // added 30.05.2012
  4026. 'or' : 'or',
  4027. 'selectForUpload' : 'Select files to upload',
  4028. 'moveFiles' : 'Move files',
  4029. 'copyFiles' : 'Copy files',
  4030. 'rmFromPlaces' : 'Remove from places',
  4031. 'aspectRatio' : 'Aspect ratio',
  4032. 'scale' : 'Scale',
  4033. 'width' : 'Width',
  4034. 'height' : 'Height',
  4035. 'resize' : 'Resize',
  4036. 'crop' : 'Crop',
  4037. 'rotate' : 'Rotate',
  4038. 'rotate-cw' : 'Rotate 90 degrees CW',
  4039. 'rotate-ccw' : 'Rotate 90 degrees CCW',
  4040. 'degree' : '°',
  4041. 'netMountDialogTitle' : 'Mount network volume', // added 18.04.2012
  4042. 'protocol' : 'Protocol', // added 18.04.2012
  4043. 'host' : 'Host', // added 18.04.2012
  4044. 'port' : 'Port', // added 18.04.2012
  4045. 'user' : 'User', // added 18.04.2012
  4046. 'pass' : 'Password', // added 18.04.2012
  4047. /********************************** mimetypes **********************************/
  4048. 'kindUnknown' : 'Unknown',
  4049. 'kindFolder' : 'Folder',
  4050. 'kindAlias' : 'Alias',
  4051. 'kindAliasBroken' : 'Broken alias',
  4052. // applications
  4053. 'kindApp' : 'Application',
  4054. 'kindPostscript' : 'Postscript document',
  4055. 'kindMsOffice' : 'Microsoft Office document',
  4056. 'kindMsWord' : 'Microsoft Word document',
  4057. 'kindMsExcel' : 'Microsoft Excel document',
  4058. 'kindMsPP' : 'Microsoft Powerpoint presentation',
  4059. 'kindOO' : 'Open Office document',
  4060. 'kindAppFlash' : 'Flash application',
  4061. 'kindPDF' : 'Portable Document Format (PDF)',
  4062. 'kindTorrent' : 'Bittorrent file',
  4063. 'kind7z' : '7z archive',
  4064. 'kindTAR' : 'TAR archive',
  4065. 'kindGZIP' : 'GZIP archive',
  4066. 'kindBZIP' : 'BZIP archive',
  4067. 'kindZIP' : 'ZIP archive',
  4068. 'kindRAR' : 'RAR archive',
  4069. 'kindJAR' : 'Java JAR file',
  4070. 'kindTTF' : 'True Type font',
  4071. 'kindOTF' : 'Open Type font',
  4072. 'kindRPM' : 'RPM package',
  4073. // texts
  4074. 'kindText' : 'Text document',
  4075. 'kindTextPlain' : 'Plain text',
  4076. 'kindPHP' : 'PHP source',
  4077. 'kindCSS' : 'Cascading style sheet',
  4078. 'kindHTML' : 'HTML document',
  4079. 'kindJS' : 'Javascript source',
  4080. 'kindRTF' : 'Rich Text Format',
  4081. 'kindC' : 'C source',
  4082. 'kindCHeader' : 'C header source',
  4083. 'kindCPP' : 'C++ source',
  4084. 'kindCPPHeader' : 'C++ header source',
  4085. 'kindShell' : 'Unix shell script',
  4086. 'kindPython' : 'Python source',
  4087. 'kindJava' : 'Java source',
  4088. 'kindRuby' : 'Ruby source',
  4089. 'kindPerl' : 'Perl script',
  4090. 'kindSQL' : 'SQL source',
  4091. 'kindXML' : 'XML document',
  4092. 'kindAWK' : 'AWK source',
  4093. 'kindCSV' : 'Comma separated values',
  4094. 'kindDOCBOOK' : 'Docbook XML document',
  4095. // images
  4096. 'kindImage' : 'Image',
  4097. 'kindBMP' : 'BMP image',
  4098. 'kindJPEG' : 'JPEG image',
  4099. 'kindGIF' : 'GIF Image',
  4100. 'kindPNG' : 'PNG Image',
  4101. 'kindTIFF' : 'TIFF image',
  4102. 'kindTGA' : 'TGA image',
  4103. 'kindPSD' : 'Adobe Photoshop image',
  4104. 'kindXBITMAP' : 'X bitmap image',
  4105. 'kindPXM' : 'Pixelmator image',
  4106. // media
  4107. 'kindAudio' : 'Audio media',
  4108. 'kindAudioMPEG' : 'MPEG audio',
  4109. 'kindAudioMPEG4' : 'MPEG-4 audio',
  4110. 'kindAudioMIDI' : 'MIDI audio',
  4111. 'kindAudioOGG' : 'Ogg Vorbis audio',
  4112. 'kindAudioWAV' : 'WAV audio',
  4113. 'AudioPlaylist' : 'MP3 playlist',
  4114. 'kindVideo' : 'Video media',
  4115. 'kindVideoDV' : 'DV movie',
  4116. 'kindVideoMPEG' : 'MPEG movie',
  4117. 'kindVideoMPEG4' : 'MPEG-4 movie',
  4118. 'kindVideoAVI' : 'AVI movie',
  4119. 'kindVideoMOV' : 'Quick Time movie',
  4120. 'kindVideoWM' : 'Windows Media movie',
  4121. 'kindVideoFlash' : 'Flash movie',
  4122. 'kindVideoMKV' : 'Matroska movie',
  4123. 'kindVideoOGG' : 'Ogg movie'
  4124. }
  4125. }
  4126. }
  4127. /*
  4128. * File: /home/osc/elFinder-build/elFinder/js/ui/button.js
  4129. */
  4130. /**
  4131. * @class elFinder toolbar button widget.
  4132. * If command has variants - create menu
  4133. *
  4134. * @author Dmitry (dio) Levashov
  4135. **/
  4136. $.fn.elfinderbutton = function(cmd) {
  4137. return this.each(function() {
  4138. var c = 'class',
  4139. fm = cmd.fm,
  4140. disabled = fm.res(c, 'disabled'),
  4141. active = fm.res(c, 'active'),
  4142. hover = fm.res(c, 'hover'),
  4143. item = 'elfinder-button-menu-item',
  4144. selected = 'elfinder-button-menu-item-selected',
  4145. menu,
  4146. button = $(this).addClass('ui-state-default elfinder-button')
  4147. .attr('title', cmd.title)
  4148. .append('<span class="elfinder-button-icon elfinder-button-icon-'+cmd.name+'"/>')
  4149. .hover(function(e) { !button.is('.'+disabled) && button[e.type == 'mouseleave' ? 'removeClass' : 'addClass'](hover) /**button.toggleClass(hover);*/ })
  4150. .click(function(e) {
  4151. if (!button.is('.'+disabled)) {
  4152. if (menu && cmd.variants.length > 1) {
  4153. // close other menus
  4154. menu.is(':hidden') && cmd.fm.getUI().click();
  4155. e.stopPropagation();
  4156. menu.slideToggle(100);
  4157. } else {
  4158. cmd.exec();
  4159. }
  4160. }
  4161. }),
  4162. hideMenu = function() {
  4163. menu.hide();
  4164. };
  4165. // if command has variants create menu
  4166. if ($.isArray(cmd.variants)) {
  4167. button.addClass('elfinder-menubutton');
  4168. menu = $('<div class="ui-widget ui-widget-content elfinder-button-menu ui-corner-all"/>')
  4169. .hide()
  4170. .appendTo(button)
  4171. .zIndex(12+button.zIndex())
  4172. .delegate('.'+item, 'hover', function() { $(this).toggleClass(hover) })
  4173. .delegate('.'+item, 'click', function(e) {
  4174. e.preventDefault();
  4175. e.stopPropagation();
  4176. button.removeClass(hover);
  4177. cmd.exec(cmd.fm.selected(), $(this).data('value'));
  4178. });
  4179. cmd.fm.bind('disable select', hideMenu).getUI().click(hideMenu);
  4180. cmd.change(function() {
  4181. menu.html('');
  4182. $.each(cmd.variants, function(i, variant) {
  4183. menu.append($('<div class="'+item+'">'+variant[1]+'</div>').data('value', variant[0]).addClass(variant[0] == cmd.value ? selected : ''));
  4184. });
  4185. });
  4186. }
  4187. cmd.change(function() {
  4188. if (cmd.disabled()) {
  4189. button.removeClass(active+' '+hover).addClass(disabled);
  4190. } else {
  4191. button.removeClass(disabled);
  4192. button[cmd.active() ? 'addClass' : 'removeClass'](active);
  4193. }
  4194. })
  4195. .change();
  4196. });
  4197. }
  4198. /*
  4199. * File: /home/osc/elFinder-build/elFinder/js/ui/contextmenu.js
  4200. */
  4201. /**
  4202. * @class elFinder contextmenu
  4203. *
  4204. * @author Dmitry (dio) Levashov
  4205. **/
  4206. $.fn.elfindercontextmenu = function(fm) {
  4207. return this.each(function() {
  4208. var menu = $(this).addClass('ui-helper-reset ui-widget ui-state-default ui-corner-all elfinder-contextmenu elfinder-contextmenu-'+fm.direction)
  4209. .hide()
  4210. .appendTo('body')
  4211. .delegate('.elfinder-contextmenu-item', 'mouseenter mouseleave', function() {
  4212. $(this).toggleClass('ui-state-hover')
  4213. }),
  4214. subpos = fm.direction == 'ltr' ? 'left' : 'right',
  4215. types = $.extend({}, fm.options.contextmenu),
  4216. tpl = '<div class="elfinder-contextmenu-item"><span class="elfinder-button-icon {icon} elfinder-contextmenu-icon"/><span>{label}</span></div>',
  4217. item = function(label, icon, callback) {
  4218. return $(tpl.replace('{icon}', icon ? 'elfinder-button-icon-'+icon : '').replace('{label}', label))
  4219. .click(function(e) {
  4220. e.stopPropagation();
  4221. e.stopPropagation();
  4222. callback();
  4223. })
  4224. },
  4225. open = function(x, y) {
  4226. var win = $(window),
  4227. width = menu.outerWidth(),
  4228. height = menu.outerHeight(),
  4229. wwidth = win.width(),
  4230. wheight = win.height(),
  4231. scrolltop = win.scrollTop(),
  4232. scrollleft = win.scrollLeft(),
  4233. css = {
  4234. top : (y + height < wheight ? y : y - height > 0 ? y - height : y) + scrolltop,
  4235. left : (x + width < wwidth ? x : x - width) + scrollleft,
  4236. 'z-index' : 100 + fm.getUI('workzone').zIndex()
  4237. };
  4238. menu.css(css)
  4239. .show();
  4240. css = {'z-index' : css['z-index']+10};
  4241. css[subpos] = parseInt(menu.width());
  4242. menu.find('.elfinder-contextmenu-sub').css(css);
  4243. },
  4244. close = function() {
  4245. menu.hide().empty();
  4246. },
  4247. create = function(type, targets) {
  4248. var sep = false;
  4249. $.each(types[type]||[], function(i, name) {
  4250. var cmd, node, submenu;
  4251. if (name == '|' && sep) {
  4252. menu.append('<div class="elfinder-contextmenu-separator"/>');
  4253. sep = false;
  4254. return;
  4255. }
  4256. cmd = fm.command(name);
  4257. if (cmd && cmd.getstate(targets) != -1) {
  4258. if (cmd.variants) {
  4259. if (!cmd.variants.length) {
  4260. return;
  4261. }
  4262. node = item(cmd.title, cmd.name, function() {});
  4263. submenu = $('<div class="ui-corner-all elfinder-contextmenu-sub"/>')
  4264. .appendTo(node.append('<span class="elfinder-contextmenu-arrow"/>'));
  4265. node.addClass('elfinder-contextmenu-group')
  4266. .hover(function() {
  4267. submenu.toggle()
  4268. })
  4269. $.each(cmd.variants, function(i, variant) {
  4270. submenu.append(
  4271. $('<div class="elfinder-contextmenu-item"><span>'+variant[1]+'</span></div>')
  4272. .click(function(e) {
  4273. e.stopPropagation();
  4274. close();
  4275. cmd.exec(targets, variant[0]);
  4276. })
  4277. );
  4278. });
  4279. } else {
  4280. node = item(cmd.title, cmd.name, function() {
  4281. close();
  4282. cmd.exec(targets);
  4283. })
  4284. }
  4285. menu.append(node)
  4286. sep = true;
  4287. }
  4288. })
  4289. },
  4290. createFromRaw = function(raw) {
  4291. $.each(raw, function(i, data) {
  4292. var node;
  4293. if (data.label && typeof data.callback == 'function') {
  4294. node = item(data.label, data.icon, function() {
  4295. close();
  4296. data.callback();
  4297. });
  4298. menu.append(node);
  4299. }
  4300. })
  4301. };
  4302. fm.one('load', function() {
  4303. fm.bind('contextmenu', function(e) {
  4304. var data = e.data;
  4305. close();
  4306. if (data.type && data.targets) {
  4307. create(data.type, data.targets);
  4308. } else if (data.raw) {
  4309. createFromRaw(data.raw);
  4310. }
  4311. menu.children().length && open(data.x, data.y);
  4312. })
  4313. .one('destroy', function() { menu.remove(); })
  4314. .bind('disable select', close)
  4315. .getUI().click(close);
  4316. });
  4317. });
  4318. }
  4319. /*
  4320. * File: /home/osc/elFinder-build/elFinder/js/ui/cwd.js
  4321. */
  4322. /**
  4323. * elFinder current working directory ui.
  4324. *
  4325. * @author Dmitry (dio) Levashov
  4326. **/
  4327. $.fn.elfindercwd = function(fm, options) {
  4328. this.not('.elfinder-cwd').each(function() {
  4329. // fm.time('cwdLoad');
  4330. var
  4331. list = fm.viewType == 'list',
  4332. undef = 'undefined',
  4333. /**
  4334. * Select event full name
  4335. *
  4336. * @type String
  4337. **/
  4338. evtSelect = 'select.'+fm.namespace,
  4339. /**
  4340. * Unselect event full name
  4341. *
  4342. * @type String
  4343. **/
  4344. evtUnselect = 'unselect.'+fm.namespace,
  4345. /**
  4346. * Disable event full name
  4347. *
  4348. * @type String
  4349. **/
  4350. evtDisable = 'disable.'+fm.namespace,
  4351. /**
  4352. * Disable event full name
  4353. *
  4354. * @type String
  4355. **/
  4356. evtEnable = 'enable.'+fm.namespace,
  4357. c = 'class',
  4358. /**
  4359. * File css class
  4360. *
  4361. * @type String
  4362. **/
  4363. clFile = fm.res(c, 'cwdfile'),
  4364. /**
  4365. * Selected css class
  4366. *
  4367. * @type String
  4368. **/
  4369. fileSelector = '.'+clFile,
  4370. /**
  4371. * Selected css class
  4372. *
  4373. * @type String
  4374. **/
  4375. clSelected = 'ui-selected',
  4376. /**
  4377. * Disabled css class
  4378. *
  4379. * @type String
  4380. **/
  4381. clDisabled = fm.res(c, 'disabled'),
  4382. /**
  4383. * Draggable css class
  4384. *
  4385. * @type String
  4386. **/
  4387. clDraggable = fm.res(c, 'draggable'),
  4388. /**
  4389. * Droppable css class
  4390. *
  4391. * @type String
  4392. **/
  4393. clDroppable = fm.res(c, 'droppable'),
  4394. /**
  4395. * Hover css class
  4396. *
  4397. * @type String
  4398. **/
  4399. clHover = fm.res(c, 'hover'),
  4400. /**
  4401. * Hover css class
  4402. *
  4403. * @type String
  4404. **/
  4405. clDropActive = fm.res(c, 'adroppable'),
  4406. /**
  4407. * Css class for temporary nodes (for mkdir/mkfile) commands
  4408. *
  4409. * @type String
  4410. **/
  4411. clTmp = clFile+'-tmp',
  4412. /**
  4413. * Number of thumbnails to load in one request (new api only)
  4414. *
  4415. * @type Number
  4416. **/
  4417. tmbNum = fm.options.loadTmbs > 0 ? fm.options.loadTmbs : 5,
  4418. /**
  4419. * Current search query.
  4420. *
  4421. * @type String
  4422. */
  4423. query = '',
  4424. lastSearch = [],
  4425. /**
  4426. * File templates
  4427. *
  4428. * @type Object
  4429. **/
  4430. templates = {
  4431. icon : '<div id="{hash}" 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="{name}">{name}</div></div>',
  4432. row : '<tr id="{hash}" class="'+clFile+' {permsclass} {dirclass}" title="{tooltip}"><td><div class="elfinder-cwd-file-wrapper"><span class="elfinder-cwd-icon {mime}"/>{marker}<span class="elfinder-cwd-filename">{name}</span></div></td><td>{perms}</td><td>{date}</td><td>{size}</td><td>{kind}</td></tr>'
  4433. },
  4434. permsTpl = fm.res('tpl', 'perms'),
  4435. symlinkTpl = fm.res('tpl', 'symlink'),
  4436. /**
  4437. * Template placeholders replacement rules
  4438. *
  4439. * @type Object
  4440. **/
  4441. replacement = {
  4442. permsclass : function(f) {
  4443. return fm.perms2class(f);
  4444. },
  4445. perms : function(f) {
  4446. return fm.formatPermissions(f);
  4447. },
  4448. dirclass : function(f) {
  4449. return f.mime == 'directory' ? 'directory' : '';
  4450. },
  4451. mime : function(f) {
  4452. return fm.mime2class(f.mime);
  4453. },
  4454. size : function(f) {
  4455. return fm.formatSize(f.size);
  4456. },
  4457. date : function(f) {
  4458. return fm.formatDate(f);
  4459. },
  4460. kind : function(f) {
  4461. return fm.mime2kind(f);
  4462. },
  4463. marker : function(f) {
  4464. return (f.alias || f.mime == 'symlink-broken' ? symlinkTpl : '')+(!f.read || !f.write ? permsTpl : '');
  4465. },
  4466. tooltip : function(f) {
  4467. var title = fm.formatDate(f) + (f.size > 0 ? ' ('+fm.formatSize(f.size)+')' : '');
  4468. return f.tooltip? fm.escape(f.tooltip).replace(/"/g, '&quot;').replace(/\r/g, '&#13;') + '&#13;' + title : title;
  4469. }
  4470. },
  4471. /**
  4472. * Return file html
  4473. *
  4474. * @param Object file info
  4475. * @return String
  4476. **/
  4477. itemhtml = function(f) {
  4478. f.name = fm.escape(f.name);
  4479. return templates[list ? 'row' : 'icon']
  4480. .replace(/\{([a-z]+)\}/g, function(s, e) {
  4481. return replacement[e] ? replacement[e](f) : (f[e] ? f[e] : '');
  4482. });
  4483. },
  4484. /**
  4485. * Flag. Required for msie to avoid unselect files on dragstart
  4486. *
  4487. * @type Boolean
  4488. **/
  4489. selectLock = false,
  4490. /**
  4491. * Move selection to prev/next file
  4492. *
  4493. * @param String move direction
  4494. * @param Boolean append to current selection
  4495. * @return void
  4496. * @rise select
  4497. */
  4498. select = function(keyCode, append) {
  4499. var code = $.ui.keyCode,
  4500. prev = keyCode == code.LEFT || keyCode == code.UP,
  4501. sel = cwd.find('[id].'+clSelected),
  4502. selector = prev ? 'first:' : 'last',
  4503. s, n, sib, top, left;
  4504. function sibling(n, direction) {
  4505. return n[direction+'All']('[id]:not(.'+clDisabled+'):not(.elfinder-cwd-parent):first');
  4506. }
  4507. if (sel.length) {
  4508. s = sel.filter(prev ? ':first' : ':last');
  4509. sib = sibling(s, prev ? 'prev' : 'next');
  4510. if (!sib.length) {
  4511. // there is no sibling on required side - do not move selection
  4512. n = s;
  4513. } else if (list || keyCode == code.LEFT || keyCode == code.RIGHT) {
  4514. // find real prevoius file
  4515. n = sib;
  4516. } else {
  4517. // find up/down side file in icons view
  4518. top = s.position().top;
  4519. left = s.position().left;
  4520. n = s;
  4521. if (prev) {
  4522. do {
  4523. n = n.prev('[id]');
  4524. } while (n.length && !(n.position().top < top && n.position().left <= left));
  4525. if (n.is('.'+clDisabled)) {
  4526. n = sibling(n, 'next');
  4527. }
  4528. } else {
  4529. do {
  4530. n = n.next('[id]');
  4531. } while (n.length && !(n.position().top > top && n.position().left >= left));
  4532. if (n.is('.'+clDisabled)) {
  4533. n = sibling(n, 'prev');
  4534. }
  4535. // there is row before last one - select last file
  4536. if (!n.length) {
  4537. sib = cwd.find('[id]:not(.'+clDisabled+'):last');
  4538. if (sib.position().top > top) {
  4539. n = sib;
  4540. }
  4541. }
  4542. }
  4543. }
  4544. // !append && unselectAll();
  4545. } else {
  4546. // there are no selected file - select first/last one
  4547. n = cwd.find('[id]:not(.'+clDisabled+'):not(.elfinder-cwd-parent):'+(prev ? 'last' : 'first'));
  4548. }
  4549. if (n && n.length && !n.is('.elfinder-cwd-parent')) {
  4550. if (append) {
  4551. // append new files to selected
  4552. n = s.add(s[prev ? 'prevUntil' : 'nextUntil']('#'+n.attr('id'))).add(n);
  4553. } else {
  4554. // unselect selected files
  4555. sel.trigger(evtUnselect);
  4556. }
  4557. // select file(s)
  4558. n.trigger(evtSelect);
  4559. // set its visible
  4560. scrollToView(n.filter(prev ? ':first' : ':last'));
  4561. // update cache/view
  4562. trigger();
  4563. }
  4564. },
  4565. selectedFiles = [],
  4566. selectFile = function(hash) {
  4567. cwd.find('#'+hash).trigger(evtSelect);
  4568. },
  4569. selectAll = function() {
  4570. var phash = fm.cwd().hash;
  4571. cwd.find('[id]:not(.'+clSelected+'):not(.elfinder-cwd-parent)').trigger(evtSelect);
  4572. selectedFiles = $.map(fm.files(), function(f) { return f.phash == phash ? f.hash : null ;});
  4573. trigger();
  4574. },
  4575. /**
  4576. * Unselect all files
  4577. *
  4578. * @return void
  4579. */
  4580. unselectAll = function() {
  4581. selectedFiles = [];
  4582. cwd.find('[id].'+clSelected).trigger(evtUnselect);
  4583. trigger();
  4584. },
  4585. /**
  4586. * Return selected files hashes list
  4587. *
  4588. * @return Array
  4589. */
  4590. selected = function() {
  4591. return selectedFiles;
  4592. },
  4593. /**
  4594. * Fire elfinder "select" event and pass selected files to it
  4595. *
  4596. * @return void
  4597. */
  4598. trigger = function() {
  4599. fm.trigger('select', {selected : selectedFiles});
  4600. },
  4601. /**
  4602. * Scroll file to set it visible
  4603. *
  4604. * @param DOMElement file/dir node
  4605. * @return void
  4606. */
  4607. scrollToView = function(o) {
  4608. var ftop = o.position().top,
  4609. fheight = o.outerHeight(true),
  4610. wtop = wrapper.scrollTop(),
  4611. wheight = wrapper.innerHeight();
  4612. if (ftop + fheight > wtop + wheight) {
  4613. wrapper.scrollTop(parseInt(ftop + fheight - wheight));
  4614. } else if (ftop < wtop) {
  4615. wrapper.scrollTop(ftop);
  4616. }
  4617. },
  4618. /**
  4619. * Files we get from server but not show yet
  4620. *
  4621. * @type Array
  4622. **/
  4623. buffer = [],
  4624. /**
  4625. * Return index of elements with required hash in buffer
  4626. *
  4627. * @param String file hash
  4628. * @return Number
  4629. */
  4630. index = function(hash) {
  4631. var l = buffer.length;
  4632. while (l--) {
  4633. if (buffer[l].hash == hash) {
  4634. return l;
  4635. }
  4636. }
  4637. return -1;
  4638. },
  4639. /**
  4640. * Scroll event name
  4641. *
  4642. * @type String
  4643. **/
  4644. scrollEvent = 'scroll.'+fm.namespace,
  4645. /**
  4646. * Cwd scroll event handler.
  4647. * Lazy load - append to cwd not shown files
  4648. *
  4649. * @return void
  4650. */
  4651. render = function() {
  4652. var html = [],
  4653. dirs = false,
  4654. ltmb = [],
  4655. atmb = {},
  4656. last = cwd.find('[id]:last'),
  4657. top = !last.length,
  4658. place = list ? cwd.children('table').children('tbody') : cwd,
  4659. files;
  4660. if (!buffer.length) {
  4661. return wrapper.unbind(scrollEvent);
  4662. }
  4663. while ((!last.length || last.position().top <= wrapper.height() + wrapper.scrollTop() + fm.options.showThreshold)
  4664. && (files = buffer.splice(0, fm.options.showFiles)).length) {
  4665. html = $.map(files, function(f) {
  4666. if (f.hash && f.name) {
  4667. if (f.mime == 'directory') {
  4668. dirs = true;
  4669. }
  4670. if (f.tmb) {
  4671. f.tmb === 1 ? ltmb.push(f.hash) : (atmb[f.hash] = f.tmb);
  4672. }
  4673. return itemhtml(f);
  4674. }
  4675. return null;
  4676. });
  4677. place.append(html.join(''));
  4678. last = cwd.find('[id]:last');
  4679. // scroll top on dir load to avoid scroll after page reload
  4680. top && cwd.scrollTop(0);
  4681. }
  4682. // load/attach thumbnails
  4683. attachThumbnails(atmb);
  4684. ltmb.length && loadThumbnails(ltmb);
  4685. // make directory droppable
  4686. dirs && makeDroppable();
  4687. if (selectedFiles.length) {
  4688. place.find('[id]:not(.'+clSelected+'):not(.elfinder-cwd-parent)').each(function() {
  4689. var id = this.id;
  4690. $.inArray(id, selectedFiles) !== -1 && $(this).trigger(evtSelect);
  4691. });
  4692. }
  4693. },
  4694. /**
  4695. * Droppable options for cwd.
  4696. * Do not add class on childs file over
  4697. *
  4698. * @type Object
  4699. */
  4700. droppable = $.extend({}, fm.droppable, {
  4701. over : function(e, ui) {
  4702. var hash = fm.cwd().hash;
  4703. $.each(ui.helper.data('files'), function(i, h) {
  4704. if (fm.file(h).phash == hash) {
  4705. cwd.removeClass(clDropActive);
  4706. return false;
  4707. }
  4708. });
  4709. }
  4710. }),
  4711. /**
  4712. * Make directory droppable
  4713. *
  4714. * @return void
  4715. */
  4716. makeDroppable = function() {
  4717. setTimeout(function() {
  4718. cwd.find('.directory:not(.'+clDroppable+',.elfinder-na,.elfinder-ro)').droppable(fm.droppable);
  4719. }, 20);
  4720. },
  4721. /**
  4722. * Preload required thumbnails and on load add css to files.
  4723. * Return false if required file is not visible yet (in buffer) -
  4724. * required for old api to stop loading thumbnails.
  4725. *
  4726. * @param Object file hash -> thumbnail map
  4727. * @return Boolean
  4728. */
  4729. attachThumbnails = function(images) {
  4730. var url = fm.option('tmbUrl'),
  4731. ret = true,
  4732. ndx;
  4733. $.each(images, function(hash, tmb) {
  4734. var node = cwd.find('#'+hash);
  4735. if (node.length) {
  4736. (function(node, tmb) {
  4737. $('<img/>')
  4738. .load(function() { node.find('.elfinder-cwd-icon').css('background', "url('"+tmb+"') center center no-repeat"); })
  4739. .attr('src', tmb);
  4740. })(node, url+tmb);
  4741. } else {
  4742. ret = false;
  4743. if ((ndx = index(hash)) != -1) {
  4744. buffer[ndx].tmb = tmb;
  4745. }
  4746. }
  4747. });
  4748. return ret;
  4749. },
  4750. /**
  4751. * Load thumbnails from backend.
  4752. *
  4753. * @param Array|Boolean files hashes list for new api | true for old api
  4754. * @return void
  4755. */
  4756. loadThumbnails = function(files) {
  4757. var tmbs = [];
  4758. if (fm.oldAPI) {
  4759. fm.request({
  4760. data : {cmd : 'tmb', current : fm.cwd().hash},
  4761. preventFail : true
  4762. })
  4763. .done(function(data) {
  4764. if (attachThumbnails(data.images||[]) && data.tmb) {
  4765. loadThumbnails();
  4766. }
  4767. });
  4768. return;
  4769. }
  4770. tmbs = tmbs = files.splice(0, tmbNum);
  4771. if (tmbs.length) {
  4772. fm.request({
  4773. data : {cmd : 'tmb', targets : tmbs},
  4774. preventFail : true
  4775. })
  4776. .done(function(data) {
  4777. if (attachThumbnails(data.images||[])) {
  4778. loadThumbnails(files);
  4779. }
  4780. });
  4781. }
  4782. },
  4783. /**
  4784. * Add new files to cwd/buffer
  4785. *
  4786. * @param Array new files
  4787. * @return void
  4788. */
  4789. add = function(files) {
  4790. var place = list ? cwd.find('tbody') : cwd,
  4791. l = files.length,
  4792. ltmb = [],
  4793. atmb = {},
  4794. dirs = false,
  4795. findNode = function(file) {
  4796. var pointer = cwd.find('[id]:first'), file2;
  4797. while (pointer.length) {
  4798. file2 = fm.file(pointer.attr('id'));
  4799. if (!pointer.is('.elfinder-cwd-parent') && file2 && fm.compare(file, file2) < 0) {
  4800. return pointer;
  4801. }
  4802. pointer = pointer.next('[id]');
  4803. }
  4804. },
  4805. findIndex = function(file) {
  4806. var l = buffer.length, i;
  4807. for (i =0; i < l; i++) {
  4808. if (fm.compare(file, buffer[i]) < 0) {
  4809. return i;
  4810. }
  4811. }
  4812. return l || -1;
  4813. },
  4814. file, hash, node, ndx;
  4815. while (l--) {
  4816. file = files[l];
  4817. hash = file.hash;
  4818. if (cwd.find('#'+hash).length) {
  4819. continue;
  4820. }
  4821. if ((node = findNode(file)) && node.length) {
  4822. node.before(itemhtml(file));
  4823. } else if ((ndx = findIndex(file)) >= 0) {
  4824. buffer.splice(ndx, 0, file);
  4825. } else {
  4826. place.append(itemhtml(file));
  4827. }
  4828. if (cwd.find('#'+hash).length) {
  4829. if (file.mime == 'directory') {
  4830. dirs = true;
  4831. } else if (file.tmb) {
  4832. file.tmb === 1 ? ltmb.push(hash) : (atmb[hash] = file.tmb);
  4833. }
  4834. }
  4835. }
  4836. attachThumbnails(atmb);
  4837. ltmb.length && loadThumbnails(ltmb);
  4838. dirs && makeDroppable();
  4839. },
  4840. /**
  4841. * Remove files from cwd/buffer
  4842. *
  4843. * @param Array files hashes
  4844. * @return void
  4845. */
  4846. remove = function(files) {
  4847. var l = files.length, hash, n, ndx;
  4848. while (l--) {
  4849. hash = files[l];
  4850. if ((n = cwd.find('#'+hash)).length) {
  4851. try {
  4852. n.detach();
  4853. } catch(e) {
  4854. fm.debug('error', e);
  4855. }
  4856. } else if ((ndx = index(hash)) != -1) {
  4857. buffer.splice(ndx, 1);
  4858. }
  4859. }
  4860. },
  4861. msg = {
  4862. name : fm.i18n('name'),
  4863. perm : fm.i18n('perms'),
  4864. mod : fm.i18n('modify'),
  4865. size : fm.i18n('size'),
  4866. kind : fm.i18n('kind')
  4867. },
  4868. /**
  4869. * Update directory content
  4870. *
  4871. * @param Array files
  4872. * @return void
  4873. */
  4874. content = function(files, any) {
  4875. var phash = fm.cwd().hash;
  4876. // console.log(files)
  4877. unselectAll();
  4878. try {
  4879. // to avoid problem with draggable
  4880. cwd.children('table,'+fileSelector).remove();
  4881. } catch (e) {
  4882. cwd.html('');
  4883. }
  4884. cwd.removeClass('elfinder-cwd-view-icons elfinder-cwd-view-list')
  4885. .addClass('elfinder-cwd-view-'+(list ? 'list' :'icons'));
  4886. wrapper[list ? 'addClass' : 'removeClass']('elfinder-cwd-wrapper-list');
  4887. list && cwd.html('<table><thead><tr class="ui-state-default"><td >'+msg.name+'</td><td>'+msg.perm+'</td><td>'+msg.mod+'</td><td>'+msg.size+'</td><td>'+msg.kind+'</td></tr></thead><tbody/></table>');
  4888. buffer = $.map(files, function(f) { return any || f.phash == phash ? f : null; });
  4889. buffer = fm.sortFiles(buffer);
  4890. wrapper.bind(scrollEvent, render).trigger(scrollEvent);
  4891. phash = fm.cwd().phash;
  4892. if (options.oldSchool && phash && !query) {
  4893. var parent = $.extend(true, {}, fm.file(phash), {name : '..', mime : 'directory'});
  4894. parent = $(itemhtml(parent))
  4895. .addClass('elfinder-cwd-parent')
  4896. .bind('mousedown click mouseup touchstart touchmove touchend dblclick mouseenter', function(e) {
  4897. //.bind('mousedown click mouseup dblclick mouseenter', function(e) {
  4898. e.preventDefault();
  4899. e.stopPropagation();
  4900. })
  4901. .dblclick(function() {
  4902. fm.exec('open', this.id);
  4903. });
  4904. (list ? cwd.find('tbody') : cwd).prepend(parent);
  4905. }
  4906. },
  4907. /**
  4908. * CWD node itself
  4909. *
  4910. * @type JQuery
  4911. **/
  4912. cwd = $(this)
  4913. .addClass('ui-helper-clearfix elfinder-cwd')
  4914. .attr('unselectable', 'on')
  4915. // fix ui.selectable bugs and add shift+click support
  4916. .delegate(fileSelector, 'click.'+fm.namespace, function(e) {
  4917. var p = this.id ? $(this) : $(this).parents('[id]:first'),
  4918. prev = p.prevAll('.'+clSelected+':first'),
  4919. next = p.nextAll('.'+clSelected+':first'),
  4920. pl = prev.length,
  4921. nl = next.length,
  4922. sib;
  4923. e.stopImmediatePropagation();
  4924. if (e.shiftKey && (pl || nl)) {
  4925. sib = pl ? p.prevUntil('#'+prev.attr('id')) : p.nextUntil('#'+next.attr('id'));
  4926. sib.add(p).trigger(evtSelect);
  4927. } else if (e.ctrlKey || e.metaKey) {
  4928. p.trigger(p.is('.'+clSelected) ? evtUnselect : evtSelect);
  4929. } else {
  4930. if ($(this).data('touching') && p.is('.'+clSelected)) {
  4931. $(this).data('touching', null);
  4932. fm.dblclick({file : this.id});
  4933. unselectAll();
  4934. } else {
  4935. unselectAll();
  4936. p.trigger(evtSelect);
  4937. }
  4938. }
  4939. trigger();
  4940. })
  4941. // call fm.open()
  4942. .delegate(fileSelector, 'dblclick.'+fm.namespace, function(e) {
  4943. fm.dblclick({file : this.id});
  4944. })
  4945. // for touch device
  4946. .delegate(fileSelector, 'touchstart.'+fm.namespace, function(e) {
  4947. $(this).data('touching', true);
  4948. var p = this.id ? $(this) : $(this).parents('[id]:first'),
  4949. sel = p.prevAll('.'+clSelected+':first').length +
  4950. p.nextAll('.'+clSelected+':first').length;
  4951. $(this).data('longtap', setTimeout(function(){
  4952. // long tap
  4953. p.trigger(p.is('.'+clSelected) ? evtUnselect : evtSelect);
  4954. trigger();
  4955. if (sel == 0 && p.is('.'+clSelected)) {
  4956. p.trigger('click');
  4957. trigger();
  4958. }
  4959. }, 500));
  4960. })
  4961. .delegate(fileSelector, 'touchmove.'+fm.namespace+' touchend.'+fm.namespace, function(e) {
  4962. clearTimeout($(this).data('longtap'));
  4963. })
  4964. // attach draggable
  4965. .delegate(fileSelector, 'mouseenter.'+fm.namespace, function(e) {
  4966. var $this = $(this),
  4967. target = list ? $this : $this.children();
  4968. if (!$this.is('.'+clTmp) && !target.is('.'+clDraggable+',.'+clDisabled)) {
  4969. target.draggable(fm.draggable);
  4970. }
  4971. })
  4972. // add hover class to selected file
  4973. .delegate(fileSelector, evtSelect, function(e) {
  4974. var $this = $(this),
  4975. id = $this.attr('id');
  4976. if (!selectLock && !$this.is('.'+clDisabled)) {
  4977. $this.addClass(clSelected).children().addClass(clHover);
  4978. if ($.inArray(id, selectedFiles) === -1) {
  4979. selectedFiles.push(id);
  4980. }
  4981. }
  4982. })
  4983. // remove hover class from unselected file
  4984. .delegate(fileSelector, evtUnselect, function(e) {
  4985. var $this = $(this),
  4986. id = $this.attr('id'),
  4987. ndx;
  4988. if (!selectLock) {
  4989. $(this).removeClass(clSelected).children().removeClass(clHover);
  4990. ndx = $.inArray(id, selectedFiles);
  4991. if (ndx !== -1) {
  4992. selectedFiles.splice(ndx, 1);
  4993. }
  4994. }
  4995. })
  4996. // disable files wich removing or moving
  4997. .delegate(fileSelector, evtDisable, function() {
  4998. var $this = $(this).removeClass(clSelected).addClass(clDisabled),
  4999. target = (list ? $this : $this.children()).removeClass(clHover);
  5000. $this.is('.'+clDroppable) && $this.droppable('disable');
  5001. target.is('.'+clDraggable) && target.draggable('disable');
  5002. !list && target.removeClass(clDisabled);
  5003. })
  5004. // if any files was not removed/moved - unlock its
  5005. .delegate(fileSelector, evtEnable, function() {
  5006. var $this = $(this).removeClass(clDisabled),
  5007. target = list ? $this : $this.children();
  5008. $this.is('.'+clDroppable) && $this.droppable('enable');
  5009. target.is('.'+clDraggable) && target.draggable('enable');
  5010. })
  5011. .delegate(fileSelector, 'scrolltoview', function() {
  5012. scrollToView($(this));
  5013. })
  5014. .delegate(fileSelector, 'hover', function(e) {
  5015. fm.trigger('hover', {hash : $(this).attr('id'), type : e.type});
  5016. })
  5017. .bind('contextmenu.'+fm.namespace, function(e) {
  5018. var file = $(e.target).closest('.'+clFile);
  5019. if (file.length) {
  5020. e.stopPropagation();
  5021. e.preventDefault();
  5022. if (!file.is('.'+clDisabled)) {
  5023. if (!file.is('.'+clSelected)) {
  5024. // cwd.trigger('unselectall');
  5025. unselectAll();
  5026. file.trigger(evtSelect);
  5027. trigger();
  5028. }
  5029. fm.trigger('contextmenu', {
  5030. 'type' : 'files',
  5031. 'targets' : fm.selected(),
  5032. 'x' : e.clientX,
  5033. 'y' : e.clientY
  5034. });
  5035. }
  5036. }
  5037. // e.preventDefault();
  5038. })
  5039. // make files selectable
  5040. .selectable({
  5041. filter : fileSelector,
  5042. stop : trigger,
  5043. selected : function(e, ui) { $(ui.selected).trigger(evtSelect); },
  5044. unselected : function(e, ui) { $(ui.unselected).trigger(evtUnselect); }
  5045. })
  5046. // make cwd itself droppable for folders from nav panel
  5047. .droppable(droppable)
  5048. // prepend fake file/dir
  5049. .bind('create.'+fm.namespace, function(e, file) {
  5050. var parent = list ? cwd.find('tbody') : cwd,
  5051. p = parent.find('.elfinder-cwd-parent'),
  5052. file = $(itemhtml(file)).addClass(clTmp);
  5053. unselectAll();
  5054. if (p.length) {
  5055. p.after(file);
  5056. } else {
  5057. parent.prepend(file);
  5058. }
  5059. cwd.scrollTop(0);
  5060. })
  5061. // unselect all selected files
  5062. .bind('unselectall', unselectAll)
  5063. .bind('selectfile', function(e, id) {
  5064. cwd.find('#'+id).trigger(evtSelect);
  5065. trigger();
  5066. }),
  5067. wrapper = $('<div class="elfinder-cwd-wrapper"/>')
  5068. .bind('contextmenu', function(e) {
  5069. e.preventDefault();
  5070. fm.trigger('contextmenu', {
  5071. 'type' : 'cwd',
  5072. 'targets' : [fm.cwd().hash],
  5073. 'x' : e.clientX,
  5074. 'y' : e.clientY
  5075. });
  5076. }),
  5077. resize = function() {
  5078. var h = 0;
  5079. wrapper.siblings('.elfinder-panel:visible').each(function() {
  5080. h += $(this).outerHeight(true);
  5081. });
  5082. wrapper.height(wz.height() - h);
  5083. },
  5084. // elfinder node
  5085. parent = $(this).parent().resize(resize),
  5086. // workzone node
  5087. wz = parent.children('.elfinder-workzone').append(wrapper.append(this))
  5088. ;
  5089. if (fm.dragUpload) {
  5090. wrapper[0].addEventListener('dragenter', function(e) {
  5091. e.preventDefault();
  5092. e.stopPropagation();
  5093. wrapper.addClass(clDropActive);
  5094. }, false);
  5095. wrapper[0].addEventListener('dragleave', function(e) {
  5096. e.preventDefault();
  5097. e.stopPropagation();
  5098. e.target == cwd[0] && wrapper.removeClass(clDropActive);
  5099. }, false);
  5100. wrapper[0].addEventListener('dragover', function(e) {
  5101. e.preventDefault();
  5102. e.stopPropagation();
  5103. }, false);
  5104. wrapper[0].addEventListener('drop', function(e) {
  5105. e.preventDefault();
  5106. wrapper.removeClass(clDropActive);
  5107. var file = false;
  5108. var type = '';
  5109. if (e.dataTransfer.getData('text/html')) {
  5110. file = [ e.dataTransfer.getData('text/html') ];
  5111. type = 'html';
  5112. } else if (e.dataTransfer.getData('text')) {
  5113. file = [ e.dataTransfer.getData('text') ];
  5114. type = 'text';
  5115. } else if (e.dataTransfer && e.dataTransfer.items && e.dataTransfer.items.length) {
  5116. file = e.dataTransfer;
  5117. type = 'data';
  5118. } else if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length) {
  5119. file = e.dataTransfer.files;
  5120. type = 'files';
  5121. }
  5122. if (file) {
  5123. fm.exec('upload', {files : file, type : type});
  5124. }
  5125. }, false);
  5126. }
  5127. fm
  5128. .bind('open', function(e) {
  5129. content(e.data.files);
  5130. })
  5131. .bind('search', function(e) {
  5132. lastSearch = e.data.files;
  5133. content(lastSearch, true);
  5134. })
  5135. .bind('searchend', function() {
  5136. lastSearch = [];
  5137. if (query) {
  5138. query = '';
  5139. content(fm.files());
  5140. }
  5141. })
  5142. .bind('searchstart', function(e) {
  5143. query = e.data.query;
  5144. })
  5145. .bind('sortchange', function() {
  5146. content(query ? lastSearch : fm.files(), !!query);
  5147. })
  5148. .bind('viewchange', function() {
  5149. var sel = fm.selected(),
  5150. l = fm.storage('view') == 'list';
  5151. if (l != list) {
  5152. list = l;
  5153. content(fm.files());
  5154. $.each(sel, function(i, h) {
  5155. selectFile(h);
  5156. });
  5157. trigger();
  5158. }
  5159. resize();
  5160. })
  5161. .add(function(e) {
  5162. var phash = fm.cwd().hash,
  5163. files = query
  5164. ? $.map(e.data.added || [], function(f) { return f.name.indexOf(query) === -1 ? null : f ;})
  5165. : $.map(e.data.added || [], function(f) { return f.phash == phash ? f : null; })
  5166. ;
  5167. add(files);
  5168. })
  5169. .change(function(e) {
  5170. var phash = fm.cwd().hash,
  5171. sel = fm.selected(),
  5172. files;
  5173. if (query) {
  5174. $.each(e.data.changed || [], function(i, file) {
  5175. remove([file.hash]);
  5176. if (file.name.indexOf(query) !== -1) {
  5177. add([file]);
  5178. $.inArray(file.hash, sel) !== -1 && selectFile(file.hash);
  5179. }
  5180. });
  5181. } else {
  5182. $.each($.map(e.data.changed || [], function(f) { return f.phash == phash ? f : null; }), function(i, file) {
  5183. remove([file.hash]);
  5184. add([file]);
  5185. $.inArray(file.hash, sel) !== -1 && selectFile(file.hash);
  5186. });
  5187. }
  5188. trigger();
  5189. })
  5190. .remove(function(e) {
  5191. remove(e.data.removed || []);
  5192. trigger();
  5193. })
  5194. // fix cwd height if it less then wrapper
  5195. .bind('open add search searchend', function() {
  5196. cwd.css('height', 'auto');
  5197. if (cwd.outerHeight(true) < wrapper.height()) {
  5198. cwd.height(wrapper.height() - (cwd.outerHeight(true) - cwd.height()) - 2);
  5199. }
  5200. })
  5201. // select dragged file if no selected, disable selectable
  5202. .dragstart(function(e) {
  5203. var target = $(e.data.target),
  5204. oe = e.data.originalEvent;
  5205. if (target.is(fileSelector)) {
  5206. if (!target.is('.'+clSelected)) {
  5207. !(oe.ctrlKey || oe.metaKey || oe.shiftKey) && unselectAll();
  5208. target.trigger(evtSelect);
  5209. trigger();
  5210. }
  5211. cwd.droppable('disable');
  5212. }
  5213. cwd.selectable('disable').removeClass(clDisabled);
  5214. selectLock = true;
  5215. })
  5216. // enable selectable
  5217. .dragstop(function() {
  5218. cwd.selectable('enable').droppable('enable');
  5219. selectLock = false;
  5220. })
  5221. .bind('lockfiles unlockfiles', function(e) {
  5222. var event = e.type == 'lockfiles' ? evtDisable : evtEnable,
  5223. files = e.data.files || [],
  5224. l = files.length;
  5225. while (l--) {
  5226. cwd.find('#'+files[l]).trigger(event);
  5227. }
  5228. trigger();
  5229. })
  5230. // select new files after some actions
  5231. .bind('mkdir mkfile duplicate upload rename archive extract', function(e) {
  5232. var phash = fm.cwd().hash, files;
  5233. unselectAll();
  5234. $.each(e.data.added || [], function(i, file) {
  5235. file && file.phash == phash && selectFile(file.hash);
  5236. });
  5237. trigger();
  5238. })
  5239. .shortcut({
  5240. pattern :'ctrl+a',
  5241. description : 'selectall',
  5242. callback : selectAll
  5243. })
  5244. .shortcut({
  5245. pattern : 'left right up down shift+left shift+right shift+up shift+down',
  5246. description : 'selectfiles',
  5247. type : 'keydown' , //fm.UA.Firefox || fm.UA.Opera ? 'keypress' : 'keydown',
  5248. callback : function(e) { select(e.keyCode, e.shiftKey); }
  5249. })
  5250. .shortcut({
  5251. pattern : 'home',
  5252. description : 'selectffile',
  5253. callback : function(e) {
  5254. unselectAll();
  5255. scrollToView(cwd.find('[id]:first').trigger(evtSelect));
  5256. trigger();
  5257. }
  5258. })
  5259. .shortcut({
  5260. pattern : 'end',
  5261. description : 'selectlfile',
  5262. callback : function(e) {
  5263. unselectAll();
  5264. scrollToView(cwd.find('[id]:last').trigger(evtSelect)) ;
  5265. trigger();
  5266. }
  5267. });
  5268. });
  5269. // fm.timeEnd('cwdLoad')
  5270. return this;
  5271. }
  5272. /*
  5273. * File: /home/osc/elFinder-build/elFinder/js/ui/dialog.js
  5274. */
  5275. /**
  5276. * @class elFinder dialog
  5277. *
  5278. * @author Dmitry (dio) Levashov
  5279. **/
  5280. $.fn.elfinderdialog = function(opts) {
  5281. var dialog;
  5282. if (typeof(opts) == 'string' && (dialog = this.closest('.ui-dialog')).length) {
  5283. if (opts == 'open') {
  5284. dialog.css('display') == 'none' && dialog.fadeIn(120, function() {
  5285. dialog.trigger('open');
  5286. });
  5287. } else if (opts == 'close') {
  5288. dialog.css('display') != 'none' && dialog.hide().trigger('close');
  5289. } else if (opts == 'destroy') {
  5290. dialog.hide().remove();
  5291. } else if (opts == 'toTop') {
  5292. dialog.trigger('totop');
  5293. }
  5294. }
  5295. opts = $.extend({}, $.fn.elfinderdialog.defaults, opts);
  5296. this.filter(':not(.ui-dialog-content)').each(function() {
  5297. var self = $(this).addClass('ui-dialog-content ui-widget-content'),
  5298. parent = self.parent(),
  5299. clactive = 'elfinder-dialog-active',
  5300. cldialog = 'elfinder-dialog',
  5301. clnotify = 'elfinder-dialog-notify',
  5302. clhover = 'ui-state-hover',
  5303. id = parseInt(Math.random()*1000000),
  5304. overlay = parent.children('.elfinder-overlay'),
  5305. buttonset = $('<div class="ui-dialog-buttonset"/>'),
  5306. buttonpane = $('<div class=" ui-helper-clearfix ui-dialog-buttonpane ui-widget-content"/>')
  5307. .append(buttonset),
  5308. dialog = $('<div class="ui-dialog ui-widget ui-widget-content ui-corner-all ui-draggable std42-dialog '+cldialog+' '+opts.cssClass+'"/>')
  5309. .hide()
  5310. .append(self)
  5311. .appendTo(parent)
  5312. .draggable({ handle : '.ui-dialog-titlebar',
  5313. containment : 'document' })
  5314. .css({
  5315. width : opts.width,
  5316. height : opts.height
  5317. })
  5318. .mousedown(function(e) {
  5319. e.stopPropagation();
  5320. $(document).mousedown();
  5321. if (!dialog.is('.'+clactive)) {
  5322. parent.find('.'+cldialog+':visible').removeClass(clactive);
  5323. dialog.addClass(clactive).zIndex(maxZIndex() + 1);
  5324. }
  5325. })
  5326. .bind('open', function() {
  5327. dialog.trigger('totop');
  5328. typeof(opts.open) == 'function' && $.proxy(opts.open, self[0])();
  5329. if (!dialog.is('.'+clnotify)) {
  5330. parent.find('.'+cldialog+':visible').not('.'+clnotify).each(function() {
  5331. var d = $(this),
  5332. top = parseInt(d.css('top')),
  5333. left = parseInt(d.css('left')),
  5334. _top = parseInt(dialog.css('top')),
  5335. _left = parseInt(dialog.css('left'))
  5336. ;
  5337. if (d[0] != dialog[0] && (top == _top || left == _left)) {
  5338. dialog.css({
  5339. top : (top+10)+'px',
  5340. left : (left+10)+'px'
  5341. });
  5342. }
  5343. });
  5344. }
  5345. })
  5346. .bind('close', function() {
  5347. var dialogs = parent.find('.elfinder-dialog:visible'),
  5348. z = maxZIndex();
  5349. $(this).data('modal') && overlay.elfinderoverlay('hide');
  5350. // get focus to next dialog
  5351. if (dialogs.length) {
  5352. dialogs.each(function() {
  5353. var d = $(this);
  5354. if (d.zIndex() >= z) {
  5355. d.trigger('totop');
  5356. return false;
  5357. }
  5358. })
  5359. } else {
  5360. // return focus to parent
  5361. setTimeout(function() {
  5362. parent.mousedown().click();
  5363. }, 10);
  5364. }
  5365. if (typeof(opts.close) == 'function') {
  5366. $.proxy(opts.close, self[0])();
  5367. } else if (opts.destroyOnClose) {
  5368. dialog.hide().remove();
  5369. }
  5370. })
  5371. .bind('totop', function() {
  5372. $(this).mousedown().find('.ui-button:first').focus().end().find(':text:first').focus();
  5373. $(this).data('modal') && overlay.elfinderoverlay('show');
  5374. overlay.zIndex($(this).zIndex());
  5375. })
  5376. .data({modal: opts.modal}),
  5377. maxZIndex = function() {
  5378. var z = parent.zIndex() + 10;
  5379. parent.find('.'+cldialog+':visible').each(function() {
  5380. var _z;
  5381. if (this != dialog[0]) {
  5382. _z = $(this).zIndex();
  5383. if (_z > z) {
  5384. z = _z;
  5385. }
  5386. }
  5387. })
  5388. return z;
  5389. },
  5390. top
  5391. ;
  5392. if (!opts.position) {
  5393. top = parseInt((parent.height() - dialog.outerHeight())/2 - 42);
  5394. opts.position = {
  5395. top : (top > 0 ? top : 0)+'px',
  5396. left : parseInt((parent.width() - dialog.outerWidth())/2)+'px'
  5397. }
  5398. }
  5399. dialog.css(opts.position);
  5400. if (opts.closeOnEscape) {
  5401. $(document).bind('keyup.'+id, function(e) {
  5402. if (e.keyCode == $.ui.keyCode.ESCAPE && dialog.is('.'+clactive)) {
  5403. self.elfinderdialog('close');
  5404. $(document).unbind('keyup.'+id);
  5405. }
  5406. })
  5407. }
  5408. dialog.prepend(
  5409. $('<div class="ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix">'+opts.title+'</div>')
  5410. .prepend($('<a href="#" class="ui-dialog-titlebar-close ui-corner-all"><span class="ui-icon ui-icon-closethick"/></a>')
  5411. .mousedown(function(e) {
  5412. e.preventDefault();
  5413. self.elfinderdialog('close');
  5414. }))
  5415. );
  5416. $.each(opts.buttons, function(name, cb) {
  5417. var button = $('<button type="button" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"><span class="ui-button-text">'+name+'</span></button>')
  5418. .click($.proxy(cb, self[0]))
  5419. .hover(function(e) { $(this)[e.type == 'mouseenter' ? 'focus' : 'blur']() })
  5420. .focus(function() { $(this).addClass(clhover) })
  5421. .blur(function() { $(this).removeClass(clhover) })
  5422. .keydown(function(e) {
  5423. var next;
  5424. if (e.keyCode == $.ui.keyCode.ENTER) {
  5425. $(this).click();
  5426. } else if (e.keyCode == $.ui.keyCode.TAB) {
  5427. next = $(this).next('.ui-button');
  5428. next.length ? next.focus() : $(this).parent().children('.ui-button:first').focus()
  5429. }
  5430. })
  5431. buttonset.append(button);
  5432. })
  5433. buttonset.children().length && dialog.append(buttonpane);
  5434. if (opts.resizable && $.fn.resizable) {
  5435. dialog.resizable({
  5436. minWidth : opts.minWidth,
  5437. minHeight : opts.minHeight,
  5438. alsoResize : this
  5439. });
  5440. }
  5441. typeof(opts.create) == 'function' && $.proxy(opts.create, this)();
  5442. opts.autoOpen && self.elfinderdialog('open');
  5443. });
  5444. return this;
  5445. }
  5446. $.fn.elfinderdialog.defaults = {
  5447. cssClass : '',
  5448. title : '',
  5449. modal : false,
  5450. resizable : true,
  5451. autoOpen : true,
  5452. closeOnEscape : true,
  5453. destroyOnClose : false,
  5454. buttons : {},
  5455. position : null,
  5456. width : 320,
  5457. height : 'auto',
  5458. minWidth : 200,
  5459. minHeight : 110
  5460. }
  5461. /*
  5462. * File: /home/osc/elFinder-build/elFinder/js/ui/navbar.js
  5463. */
  5464. /**
  5465. * @class elfindernav - elFinder container for diretories tree and places
  5466. *
  5467. * @author Dmitry (dio) Levashov
  5468. **/
  5469. $.fn.elfindernavbar = function(fm, opts) {
  5470. this.not('.elfinder-navbar').each(function() {
  5471. var nav = $(this).addClass('ui-state-default elfinder-navbar'),
  5472. parent = nav.parent()
  5473. .resize(function() {
  5474. nav.height(wz.height() - delta);
  5475. }),
  5476. wz = parent.children('.elfinder-workzone').append(nav),
  5477. delta = nav.outerHeight() - nav.height(),
  5478. ltr = fm.direction == 'ltr',
  5479. handle;
  5480. if ($.fn.resizable) {
  5481. handle = nav.resizable({
  5482. handles : ltr ? 'e' : 'w',
  5483. minWidth : opts.minWidth || 150,
  5484. maxWidth : opts.maxWidth || 500
  5485. })
  5486. .bind('resize scroll', function() {
  5487. var offset = (fm.UA.Opera && nav.scrollLeft())? 20 : 2;
  5488. handle.css({
  5489. top : parseInt(nav.scrollTop())+'px',
  5490. left : ltr ? 'auto' : parseInt(nav.scrollLeft() + offset),
  5491. right: ltr ? parseInt(nav.scrollLeft() - offset) * -1 : 'auto'
  5492. });
  5493. })
  5494. .find('.ui-resizable-handle').zIndex(nav.zIndex() + 10);
  5495. if (!ltr) {
  5496. nav.resize(function() {
  5497. nav.css('left', null).css('right', 0);
  5498. });
  5499. }
  5500. fm.one('open', function() {
  5501. setTimeout(function() {
  5502. nav.trigger('resize');
  5503. }, 150);
  5504. });
  5505. }
  5506. });
  5507. return this;
  5508. };
  5509. /*
  5510. * File: /home/osc/elFinder-build/elFinder/js/ui/overlay.js
  5511. */
  5512. $.fn.elfinderoverlay = function(opts) {
  5513. this.filter(':not(.elfinder-overlay)').each(function() {
  5514. opts = $.extend({}, opts);
  5515. $(this).addClass('ui-widget-overlay elfinder-overlay')
  5516. .hide()
  5517. .mousedown(function(e) {
  5518. e.preventDefault();
  5519. e.stopPropagation();
  5520. })
  5521. .data({
  5522. cnt : 0,
  5523. show : typeof(opts.show) == 'function' ? opts.show : function() { },
  5524. hide : typeof(opts.hide) == 'function' ? opts.hide : function() { }
  5525. });
  5526. });
  5527. if (opts == 'show') {
  5528. var o = this.eq(0),
  5529. cnt = o.data('cnt') + 1,
  5530. show = o.data('show');
  5531. o.data('cnt', cnt);
  5532. if (o.is(':hidden')) {
  5533. o.zIndex(o.parent().zIndex()+1);
  5534. o.show();
  5535. show();
  5536. }
  5537. }
  5538. if (opts == 'hide') {
  5539. var o = this.eq(0),
  5540. cnt = o.data('cnt') - 1,
  5541. hide = o.data('hide');
  5542. o.data('cnt', cnt);
  5543. if (cnt == 0 && o.is(':visible')) {
  5544. o.hide();
  5545. hide();
  5546. }
  5547. }
  5548. return this;
  5549. }
  5550. /*
  5551. * File: /home/osc/elFinder-build/elFinder/js/ui/panel.js
  5552. */
  5553. $.fn.elfinderpanel = function(fm) {
  5554. return this.each(function() {
  5555. var panel = $(this).addClass('elfinder-panel ui-state-default ui-corner-all'),
  5556. margin = 'margin-'+(fm.direction == 'ltr' ? 'left' : 'right');
  5557. fm.one('load', function(e) {
  5558. var navbar = fm.getUI('navbar');
  5559. panel.css(margin, parseInt(navbar.outerWidth(true)));
  5560. navbar.bind('resize', function() {
  5561. panel.is(':visible') && panel.css(margin, parseInt(navbar.outerWidth(true)))
  5562. })
  5563. })
  5564. })
  5565. }
  5566. /*
  5567. * File: /home/osc/elFinder-build/elFinder/js/ui/path.js
  5568. */
  5569. /**
  5570. * @class elFinder ui
  5571. * Display current folder path in statusbar.
  5572. * Click on folder name in path - open folder
  5573. *
  5574. * @author Dmitry (dio) Levashov
  5575. **/
  5576. $.fn.elfinderpath = function(fm) {
  5577. return this.each(function() {
  5578. var path = $(this).addClass('elfinder-path').html('&nbsp;')
  5579. .delegate('a', 'click', function(e) {
  5580. var hash = $(this).attr('href').substr(1);
  5581. e.preventDefault();
  5582. hash != fm.cwd().hash && fm.exec('open', hash);
  5583. })
  5584. .prependTo(fm.getUI('statusbar').show())
  5585. fm.bind('open searchend', function() {
  5586. var dirs = [];
  5587. $.each(fm.parents(fm.cwd().hash), function(i, hash) {
  5588. dirs.push('<a href="#'+hash+'">'+fm.escape(fm.file(hash).name)+'</a>');
  5589. });
  5590. path.html(dirs.join(fm.option('separator')));
  5591. })
  5592. .bind('search', function() {
  5593. path.html(fm.i18n('searcresult'));
  5594. });
  5595. });
  5596. }
  5597. /*
  5598. * File: /home/osc/elFinder-build/elFinder/js/ui/places.js
  5599. */
  5600. /**
  5601. * @class elFinder places/favorites ui
  5602. *
  5603. * @author Dmitry (dio) Levashov
  5604. **/
  5605. $.fn.elfinderplaces = function(fm, opts) {
  5606. return this.each(function() {
  5607. var dirs = [],
  5608. c = 'class',
  5609. navdir = fm.res(c, 'navdir'),
  5610. collapsed = fm.res(c, 'navcollapse'),
  5611. expanded = fm.res(c, 'navexpand'),
  5612. hover = fm.res(c, 'hover'),
  5613. clroot = fm.res(c, 'treeroot'),
  5614. tpl = fm.res('tpl', 'navdir'),
  5615. ptpl = fm.res('tpl', 'perms'),
  5616. spinner = $(fm.res('tpl', 'navspinner')),
  5617. /**
  5618. * Convert places dir node into dir hash
  5619. *
  5620. * @param String directory id
  5621. * @return String
  5622. **/
  5623. id2hash = function(id) { return id.substr(6); },
  5624. /**
  5625. * Convert places dir node into dir hash
  5626. *
  5627. * @param String directory id
  5628. * @return String
  5629. **/
  5630. hash2id = function(hash) { return 'place-'+hash; },
  5631. /**
  5632. * Save current places state
  5633. *
  5634. * @return void
  5635. **/
  5636. save = function() { fm.storage('places', dirs.join(',')); },
  5637. /**
  5638. * Return node for given dir object
  5639. *
  5640. * @param Object directory object
  5641. * @return jQuery
  5642. **/
  5643. create = function(dir) {
  5644. return $(tpl.replace(/\{id\}/, hash2id(dir.hash))
  5645. .replace(/\{name\}/, fm.escape(dir.name))
  5646. .replace(/\{cssclass\}/, fm.perms2class(dir))
  5647. .replace(/\{permissions\}/, !dir.read || !dir.write ? ptpl : '')
  5648. .replace(/\{symlink\}/, ''));
  5649. },
  5650. /**
  5651. * Add new node into places
  5652. *
  5653. * @param Object directory object
  5654. * @return void
  5655. **/
  5656. add = function(dir) {
  5657. var node = create(dir);
  5658. if (subtree.children().length) {
  5659. $.each(subtree.children(), function() {
  5660. var current = $(this);
  5661. if (dir.name.localeCompare(current.children('.'+navdir).text()) < 0) {
  5662. return !node.insertBefore(current);
  5663. }
  5664. });
  5665. }
  5666. dirs.push(dir.hash);
  5667. !node.parent().length && subtree.append(node);
  5668. root.addClass(collapsed);
  5669. node.draggable({
  5670. appendTo : 'body',
  5671. revert : false,
  5672. helper : function() {
  5673. var dir = $(this);
  5674. dir.children().removeClass('ui-state-hover');
  5675. return $('<div class="elfinder-place-drag elfinder-'+fm.direction+'"/>')
  5676. .append(dir.clone())
  5677. .data('hash', id2hash(dir.children(':first').attr('id')));
  5678. },
  5679. start : function() { $(this).hide(); },
  5680. stop : function(e, ui) {
  5681. var top = places.offset().top,
  5682. left = places.offset().left,
  5683. width = places.width(),
  5684. height = places.height(),
  5685. x = e.clientX,
  5686. y = e.clientY;
  5687. if (x > left && x < left+width && y > top && y < y+height) {
  5688. $(this).show();
  5689. } else {
  5690. remove(ui.helper.data('hash'));
  5691. save();
  5692. }
  5693. }
  5694. });
  5695. },
  5696. /**
  5697. * Remove dir from places
  5698. *
  5699. * @param String directory id
  5700. * @return void
  5701. **/
  5702. remove = function(hash) {
  5703. var ndx = $.inArray(hash, dirs);
  5704. if (ndx !== -1) {
  5705. dirs.splice(ndx, 1);
  5706. subtree.find('#'+hash2id(hash)).parent().remove();
  5707. !subtree.children().length && root.removeClass(collapsed+' '+expanded);
  5708. }
  5709. },
  5710. /**
  5711. * Remove all dir from places
  5712. *
  5713. * @return void
  5714. **/
  5715. clear = function() {
  5716. subtree.empty();
  5717. root.removeClass(collapsed+' '+expanded);
  5718. },
  5719. /**
  5720. * Node - wrapper for places root
  5721. *
  5722. * @type jQuery
  5723. **/
  5724. wrapper = create({
  5725. hash : 'root-'+fm.namespace,
  5726. name : fm.i18n(opts.name, 'places'),
  5727. read : true,
  5728. write : true
  5729. }),
  5730. /**
  5731. * Places root node
  5732. *
  5733. * @type jQuery
  5734. **/
  5735. root = wrapper.children('.'+navdir)
  5736. .addClass(clroot)
  5737. .click(function() {
  5738. if (root.is('.'+collapsed)) {
  5739. places.toggleClass(expanded);
  5740. subtree.slideToggle();
  5741. fm.storage('placesState', places.is('.'+expanded)? 1 : 0);
  5742. }
  5743. }),
  5744. /**
  5745. * Container for dirs
  5746. *
  5747. * @type jQuery
  5748. **/
  5749. subtree = wrapper.children('.'+fm.res(c, 'navsubtree')),
  5750. /**
  5751. * Main places container
  5752. *
  5753. * @type jQuery
  5754. **/
  5755. places = $(this).addClass(fm.res(c, 'tree')+' elfinder-places ui-corner-all')
  5756. .hide()
  5757. .append(wrapper)
  5758. .appendTo(fm.getUI('navbar'))
  5759. .delegate('.'+navdir, 'hover', function() {
  5760. $(this).toggleClass('ui-state-hover');
  5761. })
  5762. .delegate('.'+navdir, 'click', function(e) {
  5763. fm.exec('open', $(this).attr('id').substr(6));
  5764. })
  5765. .delegate('.'+navdir+':not(.'+clroot+')', 'contextmenu', function(e) {
  5766. var hash = $(this).attr('id').substr(6);
  5767. e.preventDefault();
  5768. fm.trigger('contextmenu', {
  5769. raw : [{
  5770. label : fm.i18n('rmFromPlaces'),
  5771. icon : 'rm',
  5772. callback : function() { remove(hash); save(); }
  5773. }],
  5774. 'x' : e.clientX,
  5775. 'y' : e.clientY
  5776. })
  5777. })
  5778. .droppable({
  5779. tolerance : 'pointer',
  5780. accept : '.elfinder-cwd-file-wrapper,.elfinder-tree-dir,.elfinder-cwd-file',
  5781. hoverClass : fm.res('class', 'adroppable'),
  5782. drop : function(e, ui) {
  5783. var resolve = true;
  5784. $.each(ui.helper.data('files'), function(i, hash) {
  5785. var dir = fm.file(hash);
  5786. if (dir && dir.mime == 'directory' && $.inArray(dir.hash, dirs) === -1) {
  5787. add(dir);
  5788. } else {
  5789. resolve = false;
  5790. }
  5791. })
  5792. save();
  5793. resolve && ui.helper.hide();
  5794. }
  5795. });
  5796. // on fm load - show places and load files from backend
  5797. fm.one('load', function() {
  5798. if (fm.oldAPI) {
  5799. return;
  5800. }
  5801. places.show().parent().show();
  5802. dirs = $.map(fm.storage('places').split(','), function(hash) { return hash || null});
  5803. if (dirs.length) {
  5804. root.prepend(spinner);
  5805. fm.request({
  5806. data : {cmd : 'info', targets : dirs},
  5807. preventDefault : true
  5808. })
  5809. .done(function(data) {
  5810. dirs = [];
  5811. $.each(data.files, function(i, file) {
  5812. file.mime == 'directory' && add(file);
  5813. });
  5814. save();
  5815. if (fm.storage('placesState') > 0) {
  5816. root.click();
  5817. }
  5818. })
  5819. .always(function() {
  5820. spinner.remove();
  5821. })
  5822. }
  5823. fm.remove(function(e) {
  5824. $.each(e.data.removed, function(i, hash) {
  5825. remove(hash);
  5826. });
  5827. save();
  5828. })
  5829. .change(function(e) {
  5830. $.each(e.data.changed, function(i, file) {
  5831. if ($.inArray(file.hash, dirs) !== -1) {
  5832. remove(file.hash);
  5833. file.mime == 'directory' && add(file);
  5834. }
  5835. });
  5836. save();
  5837. })
  5838. .bind('sync', function() {
  5839. if (dirs.length) {
  5840. root.prepend(spinner);
  5841. fm.request({
  5842. data : {cmd : 'info', targets : dirs},
  5843. preventDefault : true
  5844. })
  5845. .done(function(data) {
  5846. $.each(data.files || [], function(i, file) {
  5847. if ($.inArray(file.hash, dirs) === -1) {
  5848. remove(file.hash);
  5849. }
  5850. });
  5851. save();
  5852. })
  5853. .always(function() {
  5854. spinner.remove();
  5855. });
  5856. }
  5857. })
  5858. })
  5859. });
  5860. }
  5861. /*
  5862. * File: /home/osc/elFinder-build/elFinder/js/ui/searchbutton.js
  5863. */
  5864. /**
  5865. * @class elFinder toolbar search button widget.
  5866. *
  5867. * @author Dmitry (dio) Levashov
  5868. **/
  5869. $.fn.elfindersearchbutton = function(cmd) {
  5870. return this.each(function() {
  5871. var result = false,
  5872. button = $(this).hide().addClass('ui-widget-content elfinder-button '+cmd.fm.res('class', 'searchbtn')+''),
  5873. search = function() {
  5874. var val = $.trim(input.val());
  5875. if (val) {
  5876. cmd.exec(val).done(function() {
  5877. result = true;
  5878. input.focus();
  5879. });
  5880. } else {
  5881. cmd.fm.trigger('searchend')
  5882. }
  5883. },
  5884. abort = function() {
  5885. input.val('');
  5886. if (result) {
  5887. result = false;
  5888. cmd.fm.trigger('searchend');
  5889. }
  5890. },
  5891. input = $('<input type="text" size="42"/>')
  5892. .appendTo(button)
  5893. // to avoid fm shortcuts on arrows
  5894. .keypress(function(e) {
  5895. e.stopPropagation();
  5896. })
  5897. .keydown(function(e) {
  5898. e.stopPropagation();
  5899. e.keyCode == 13 && search();
  5900. if (e.keyCode== 27) {
  5901. e.preventDefault();
  5902. abort();
  5903. }
  5904. });
  5905. $('<span class="ui-icon ui-icon-search" title="'+cmd.title+'"/>')
  5906. .appendTo(button)
  5907. .click(search);
  5908. $('<span class="ui-icon ui-icon-close"/>')
  5909. .appendTo(button)
  5910. .click(abort)
  5911. // wait when button will be added to DOM
  5912. setTimeout(function() {
  5913. button.parent().detach();
  5914. cmd.fm.getUI('toolbar').prepend(button.show());
  5915. // position icons for ie7
  5916. if (cmd.fm.UA.ltIE7) {
  5917. var icon = button.children(cmd.fm.direction == 'ltr' ? '.ui-icon-close' : '.ui-icon-search');
  5918. icon.css({
  5919. right : '',
  5920. left : parseInt(button.width())-icon.outerWidth(true)
  5921. });
  5922. }
  5923. }, 200);
  5924. cmd.fm
  5925. .error(function() {
  5926. input.unbind('keydown');
  5927. })
  5928. .select(function() {
  5929. input.blur();
  5930. })
  5931. .bind('searchend', function() {
  5932. input.val('');
  5933. })
  5934. .viewchange(abort)
  5935. .shortcut({
  5936. pattern : 'ctrl+f f3',
  5937. description : cmd.title,
  5938. callback : function() { input.select().focus(); }
  5939. });
  5940. });
  5941. }
  5942. /*
  5943. * File: /home/osc/elFinder-build/elFinder/js/ui/sortbutton.js
  5944. */
  5945. /**
  5946. * @class elFinder toolbar button menu with sort variants.
  5947. *
  5948. * @author Dmitry (dio) Levashov
  5949. **/
  5950. $.fn.elfindersortbutton = function(cmd) {
  5951. return this.each(function() {
  5952. var fm = cmd.fm,
  5953. name = cmd.name,
  5954. c = 'class',
  5955. disabled = fm.res(c, 'disabled'),
  5956. hover = fm.res(c, 'hover'),
  5957. item = 'elfinder-button-menu-item',
  5958. selected = item+'-selected',
  5959. asc = selected+'-asc',
  5960. desc = selected+'-desc',
  5961. button = $(this).addClass('ui-state-default elfinder-button elfinder-menubutton elfiner-button-'+name)
  5962. .attr('title', cmd.title)
  5963. .append('<span class="elfinder-button-icon elfinder-button-icon-'+name+'"/>')
  5964. .hover(function(e) { !button.is('.'+disabled) && button.toggleClass(hover); })
  5965. .click(function(e) {
  5966. if (!button.is('.'+disabled)) {
  5967. e.stopPropagation();
  5968. menu.is(':hidden') && cmd.fm.getUI().click();
  5969. menu.slideToggle(100);
  5970. }
  5971. }),
  5972. menu = $('<div class="ui-widget ui-widget-content elfinder-button-menu ui-corner-all"/>')
  5973. .hide()
  5974. .appendTo(button)
  5975. .zIndex(12+button.zIndex())
  5976. .delegate('.'+item, 'hover', function() { $(this).toggleClass(hover) })
  5977. .delegate('.'+item, 'click', function(e) {
  5978. e.preventDefault();
  5979. e.stopPropagation();
  5980. hide();
  5981. }),
  5982. update = function() {
  5983. menu.children(':not(:last)').removeClass(selected+' '+asc+' '+desc)
  5984. .filter('[rel="'+fm.sortType+'"]')
  5985. .addClass(selected+' '+(fm.sortOrder == 'asc' ? asc : desc));
  5986. menu.children(':last').toggleClass(selected, fm.sortStickFolders);
  5987. },
  5988. hide = function() { menu.hide(); };
  5989. $.each(fm.sortRules, function(name, value) {
  5990. 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));
  5991. });
  5992. menu.children().click(function(e) {
  5993. var type = $(this).attr('rel');
  5994. cmd.exec([], {
  5995. type : type,
  5996. order : type == fm.sortType ? fm.sortOrder == 'asc' ? 'desc' : 'asc' : fm.sortOrder,
  5997. stick : fm.sortStickFolders
  5998. });
  5999. })
  6000. $('<div class="'+item+' '+item+'-separated"><span class="ui-icon ui-icon-check"/>'+fm.i18n('sortFoldersFirst')+'</div>')
  6001. .appendTo(menu)
  6002. .click(function() {
  6003. cmd.exec([], {type : fm.sortType, order : fm.sortOrder, stick : !fm.sortStickFolders});
  6004. });
  6005. fm.bind('disable select', hide).getUI().click(hide);
  6006. fm.bind('sortchange', update)
  6007. if (menu.children().length > 1) {
  6008. cmd.change(function() {
  6009. button.toggleClass(disabled, cmd.disabled());
  6010. update();
  6011. })
  6012. .change();
  6013. } else {
  6014. button.addClass(disabled);
  6015. }
  6016. });
  6017. }
  6018. /*
  6019. * File: /home/osc/elFinder-build/elFinder/js/ui/stat.js
  6020. */
  6021. /**
  6022. * @class elFinder ui
  6023. * Display number of files/selected files and its size in statusbar
  6024. *
  6025. * @author Dmitry (dio) Levashov
  6026. **/
  6027. $.fn.elfinderstat = function(fm) {
  6028. return this.each(function() {
  6029. var size = $(this).addClass('elfinder-stat-size'),
  6030. sel = $('<div class="elfinder-stat-selected"/>'),
  6031. titlesize = fm.i18n('size').toLowerCase(),
  6032. titleitems = fm.i18n('items').toLowerCase(),
  6033. titlesel = fm.i18n('selected'),
  6034. setstat = function(files, cwd) {
  6035. var c = 0,
  6036. s = 0;
  6037. $.each(files, function(i, file) {
  6038. if (!cwd || file.phash == cwd) {
  6039. c++;
  6040. s += parseInt(file.size)||0;
  6041. }
  6042. })
  6043. size.html(titleitems+': '+c+', '+titlesize+': '+fm.formatSize(s));
  6044. };
  6045. fm.getUI('statusbar').prepend(size).append(sel).show();
  6046. fm
  6047. .bind('open reload add remove change searchend', function() {
  6048. setstat(fm.files(), fm.cwd().hash)
  6049. })
  6050. .search(function(e) {
  6051. setstat(e.data.files);
  6052. })
  6053. .select(function() {
  6054. var s = 0,
  6055. c = 0,
  6056. files = fm.selectedFiles();
  6057. if (files.length == 1) {
  6058. s = files[0].size;
  6059. sel.html(fm.escape(files[0].name)+(s > 0 ? ', '+fm.formatSize(s) : ''));
  6060. return;
  6061. }
  6062. $.each(files, function(i, file) {
  6063. c++;
  6064. s += parseInt(file.size)||0;
  6065. });
  6066. sel.html(c ? titlesel+': '+c+', '+titlesize+': '+fm.formatSize(s) : '&nbsp;');
  6067. })
  6068. ;
  6069. })
  6070. }
  6071. /*
  6072. * File: /home/osc/elFinder-build/elFinder/js/ui/toolbar.js
  6073. */
  6074. /**
  6075. * @class elFinder toolbar
  6076. *
  6077. * @author Dmitry (dio) Levashov
  6078. **/
  6079. $.fn.elfindertoolbar = function(fm, opts) {
  6080. this.not('.elfinder-toolbar').each(function() {
  6081. var commands = fm._commands,
  6082. self = $(this).addClass('ui-helper-clearfix ui-widget-header ui-corner-top elfinder-toolbar'),
  6083. panels = opts || [],
  6084. l = panels.length,
  6085. i, cmd, panel, button;
  6086. self.prev().length && self.parent().prepend(this);
  6087. while (l--) {
  6088. if (panels[l]) {
  6089. panel = $('<div class="ui-widget-content ui-corner-all elfinder-buttonset"/>');
  6090. i = panels[l].length;
  6091. while (i--) {
  6092. if ((cmd = commands[panels[l][i]])) {
  6093. button = 'elfinder'+cmd.options.ui;
  6094. $.fn[button] && panel.prepend($('<div/>')[button](cmd));
  6095. }
  6096. }
  6097. panel.children().length && self.prepend(panel);
  6098. panel.children(':gt(0)').before('<span class="ui-widget-content elfinder-toolbar-button-separator"/>');
  6099. }
  6100. }
  6101. self.children().length && self.show();
  6102. });
  6103. return this;
  6104. }
  6105. /*
  6106. * File: /home/osc/elFinder-build/elFinder/js/ui/tree.js
  6107. */
  6108. /**
  6109. * @class elFinder folders tree
  6110. *
  6111. * @author Dmitry (dio) Levashov
  6112. **/
  6113. $.fn.elfindertree = function(fm, opts) {
  6114. var treeclass = fm.res('class', 'tree');
  6115. this.not('.'+treeclass).each(function() {
  6116. var c = 'class',
  6117. /**
  6118. * Root directory class name
  6119. *
  6120. * @type String
  6121. */
  6122. root = fm.res(c, 'treeroot'),
  6123. /**
  6124. * Open root dir if not opened yet
  6125. *
  6126. * @type Boolean
  6127. */
  6128. openRoot = opts.openRootOnLoad,
  6129. /**
  6130. * Subtree class name
  6131. *
  6132. * @type String
  6133. */
  6134. subtree = fm.res(c, 'navsubtree'),
  6135. /**
  6136. * Directory class name
  6137. *
  6138. * @type String
  6139. */
  6140. navdir = fm.res(c, 'treedir'),
  6141. /**
  6142. * Collapsed arrow class name
  6143. *
  6144. * @type String
  6145. */
  6146. collapsed = fm.res(c, 'navcollapse'),
  6147. /**
  6148. * Expanded arrow class name
  6149. *
  6150. * @type String
  6151. */
  6152. expanded = fm.res(c, 'navexpand'),
  6153. /**
  6154. * Class name to mark arrow for directory with already loaded children
  6155. *
  6156. * @type String
  6157. */
  6158. loaded = 'elfinder-subtree-loaded',
  6159. /**
  6160. * Arraw class name
  6161. *
  6162. * @type String
  6163. */
  6164. arrow = fm.res(c, 'navarrow'),
  6165. /**
  6166. * Current directory class name
  6167. *
  6168. * @type String
  6169. */
  6170. active = fm.res(c, 'active'),
  6171. /**
  6172. * Droppable dirs dropover class
  6173. *
  6174. * @type String
  6175. */
  6176. dropover = fm.res(c, 'adroppable'),
  6177. /**
  6178. * Hover class name
  6179. *
  6180. * @type String
  6181. */
  6182. hover = fm.res(c, 'hover'),
  6183. /**
  6184. * Disabled dir class name
  6185. *
  6186. * @type String
  6187. */
  6188. disabled = fm.res(c, 'disabled'),
  6189. /**
  6190. * Draggable dir class name
  6191. *
  6192. * @type String
  6193. */
  6194. draggable = fm.res(c, 'draggable'),
  6195. /**
  6196. * Droppable dir class name
  6197. *
  6198. * @type String
  6199. */
  6200. droppable = fm.res(c, 'droppable'),
  6201. insideNavbar = function(x) {
  6202. var left = navbar.offset().left;
  6203. return left <= x && x <= left + navbar.width();
  6204. },
  6205. drop = fm.droppable.drop,
  6206. /**
  6207. * Droppable options
  6208. *
  6209. * @type Object
  6210. */
  6211. droppableopts = $.extend(true, {}, fm.droppable, {
  6212. // show subfolders on dropover
  6213. over : function(e) {
  6214. var link = $(this),
  6215. cl = hover+' '+dropover;
  6216. if (insideNavbar(e.clientX)) {
  6217. link.addClass(cl)
  6218. if (link.is('.'+collapsed+':not(.'+expanded+')')) {
  6219. setTimeout(function() {
  6220. link.is('.'+dropover) && link.children('.'+arrow).click();
  6221. }, 500);
  6222. }
  6223. } else {
  6224. link.removeClass(cl);
  6225. }
  6226. },
  6227. out : function() { $(this).removeClass(hover+' '+dropover); },
  6228. drop : function(e, ui) { insideNavbar(e.clientX) && drop.call(this, e, ui); }
  6229. }),
  6230. spinner = $(fm.res('tpl', 'navspinner')),
  6231. /**
  6232. * Directory html template
  6233. *
  6234. * @type String
  6235. */
  6236. tpl = fm.res('tpl', 'navdir'),
  6237. /**
  6238. * Permissions marker html template
  6239. *
  6240. * @type String
  6241. */
  6242. ptpl = fm.res('tpl', 'perms'),
  6243. /**
  6244. * Symlink marker html template
  6245. *
  6246. * @type String
  6247. */
  6248. stpl = fm.res('tpl', 'symlink'),
  6249. /**
  6250. * Html template replacement methods
  6251. *
  6252. * @type Object
  6253. */
  6254. replace = {
  6255. id : function(dir) { return fm.navHash2Id(dir.hash) },
  6256. cssclass : function(dir) { return (dir.phash ? '' : root)+' '+navdir+' '+fm.perms2class(dir)+' '+(dir.dirs && !dir.link ? collapsed : ''); },
  6257. permissions : function(dir) { return !dir.read || !dir.write ? ptpl : ''; },
  6258. symlink : function(dir) { return dir.alias ? stpl : ''; }
  6259. },
  6260. /**
  6261. * Return html for given dir
  6262. *
  6263. * @param Object directory
  6264. * @return String
  6265. */
  6266. itemhtml = function(dir) {
  6267. dir.name = fm.escape(dir.i18 || dir.name);
  6268. return tpl.replace(/(?:\{([a-z]+)\})/ig, function(m, key) {
  6269. return dir[key] || (replace[key] ? replace[key](dir) : '');
  6270. });
  6271. },
  6272. /**
  6273. * Return only dirs from files list
  6274. *
  6275. * @param Array files list
  6276. * @return Array
  6277. */
  6278. filter = function(files) {
  6279. return $.map(files||[], function(f) { return f.mime == 'directory' ? f : null });
  6280. },
  6281. /**
  6282. * Find parent subtree for required directory
  6283. *
  6284. * @param String dir hash
  6285. * @return jQuery
  6286. */
  6287. findSubtree = function(hash) {
  6288. return hash ? tree.find('#'+fm.navHash2Id(hash)).next('.'+subtree) : tree;
  6289. },
  6290. /**
  6291. * Find directory (wrapper) in required node
  6292. * before which we can insert new directory
  6293. *
  6294. * @param jQuery parent directory
  6295. * @param Object new directory
  6296. * @return jQuery
  6297. */
  6298. findSibling = function(subtree, dir) {
  6299. var node = subtree.children(':first'),
  6300. info;
  6301. while (node.length) {
  6302. info = fm.file(fm.navId2Hash(node.children('[id]').attr('id')));
  6303. if ((info = fm.file(fm.navId2Hash(node.children('[id]').attr('id'))))
  6304. && dir.name.toLowerCase().localeCompare(info.name.toLowerCase()) < 0) {
  6305. return node;
  6306. }
  6307. node = node.next();
  6308. }
  6309. return $('');
  6310. },
  6311. /**
  6312. * Add new dirs in tree
  6313. *
  6314. * @param Array dirs list
  6315. * @return void
  6316. */
  6317. updateTree = function(dirs) {
  6318. var length = dirs.length,
  6319. orphans = [],
  6320. i = dirs.length,
  6321. dir, html, parent, sibling;
  6322. var firstVol = true; // check for netmount volume
  6323. while (i--) {
  6324. dir = dirs[i];
  6325. if (tree.find('#'+fm.navHash2Id(dir.hash)).length) {
  6326. continue;
  6327. }
  6328. if ((parent = findSubtree(dir.phash)).length) {
  6329. html = itemhtml(dir);
  6330. if (dir.phash && (sibling = findSibling(parent, dir)).length) {
  6331. sibling.before(html);
  6332. } else {
  6333. parent[firstVol || dir.phash ? 'append' : 'prepend'](html);
  6334. firstVol = false;
  6335. }
  6336. } else {
  6337. orphans.push(dir);
  6338. }
  6339. }
  6340. if (orphans.length && orphans.length < length) {
  6341. return updateTree(orphans);
  6342. }
  6343. setTimeout(function() {
  6344. updateDroppable();
  6345. }, 10);
  6346. },
  6347. /**
  6348. * Mark current directory as active
  6349. * If current directory is not in tree - load it and its parents
  6350. *
  6351. * @param {Boolean} do not recursive call
  6352. * @return void
  6353. */
  6354. sync = function(stopRec) {
  6355. var cwd = fm.cwd().hash,
  6356. current = tree.find('#'+fm.navHash2Id(cwd)),
  6357. rootNode, dir;
  6358. if (openRoot) {
  6359. rootNode = tree.find('#'+fm.navHash2Id(fm.root()));
  6360. rootNode.is('.'+loaded) && rootNode.addClass(expanded).next('.'+subtree).show();
  6361. openRoot = false;
  6362. }
  6363. if (!current.is('.'+active)) {
  6364. tree.find('.'+navdir+'.'+active).removeClass(active);
  6365. current.addClass(active);
  6366. }
  6367. if (opts.syncTree) {
  6368. if (current.length) {
  6369. return current.parentsUntil('.'+root).filter('.'+subtree).show().prev('.'+navdir).addClass(expanded);
  6370. }
  6371. if (fm.newAPI) {
  6372. dir = fm.file(cwd);
  6373. if (dir && dir.phash && tree.find('#'+fm.navHash2Id(dir.phash)).length) {
  6374. updateTree([dir]);
  6375. return sync();
  6376. }
  6377. fm.request({
  6378. data : {cmd : 'parents', target : cwd},
  6379. preventFail : true
  6380. })
  6381. .done(function(data) {
  6382. var dirs = filter(data.tree);
  6383. updateTree(dirs);
  6384. updateArrows(dirs, loaded);
  6385. cwd == fm.cwd().hash && sync(true);
  6386. })
  6387. ;
  6388. }
  6389. }
  6390. },
  6391. /**
  6392. * Make writable and not root dirs droppable
  6393. *
  6394. * @return void
  6395. */
  6396. updateDroppable = function() {
  6397. tree.find('.'+navdir+':not(.'+droppable+',.elfinder-ro,.elfinder-na)').droppable(droppableopts);
  6398. },
  6399. /**
  6400. * Check required folders for subfolders and update arrow classes
  6401. *
  6402. * @param Array folders to check
  6403. * @param String css class
  6404. * @return void
  6405. */
  6406. updateArrows = function(dirs, cls) {
  6407. var sel = cls == loaded
  6408. ? '.'+collapsed+':not(.'+loaded+')'
  6409. : ':not(.'+collapsed+')';
  6410. //tree.find('.'+subtree+':has(*)').prev(':not(.'+collapsed+')').addClass(collapsed)
  6411. $.each(dirs, function(i, dir) {
  6412. tree.find('#'+fm.navHash2Id(dir.phash)+sel)
  6413. .filter(function() { return $(this).next('.'+subtree).children().length > 0 })
  6414. .addClass(cls);
  6415. })
  6416. },
  6417. /**
  6418. * Navigation tree
  6419. *
  6420. * @type JQuery
  6421. */
  6422. tree = $(this).addClass(treeclass)
  6423. // make dirs draggable and toggle hover class
  6424. .delegate('.'+navdir, 'hover', function(e) {
  6425. var link = $(this),
  6426. enter = e.type == 'mouseenter';
  6427. if (!link.is('.'+dropover+' ,.'+disabled)) {
  6428. enter && !link.is('.'+root+',.'+draggable+',.elfinder-na,.elfinder-wo') && link.draggable(fm.draggable);
  6429. link.toggleClass(hover, enter);
  6430. }
  6431. })
  6432. // add/remove dropover css class
  6433. .delegate('.'+navdir, 'dropover dropout drop', function(e) {
  6434. $(this)[e.type == 'dropover' ? 'addClass' : 'removeClass'](dropover+' '+hover);
  6435. })
  6436. // open dir or open subfolders in tree
  6437. .delegate('.'+navdir, 'click', function(e) {
  6438. var link = $(this),
  6439. hash = fm.navId2Hash(link.attr('id')),
  6440. file = fm.file(hash);
  6441. fm.trigger('searchend');
  6442. if (hash != fm.cwd().hash && !link.is('.'+disabled)) {
  6443. fm.exec('open', file.thash || hash);
  6444. } else if (link.is('.'+collapsed)) {
  6445. link.children('.'+arrow).click();
  6446. }
  6447. })
  6448. // toggle subfolders in tree
  6449. .delegate('.'+navdir+'.'+collapsed+' .'+arrow, 'click', function(e) {
  6450. var arrow = $(this),
  6451. link = arrow.parent('.'+navdir),
  6452. stree = link.next('.'+subtree);
  6453. e.stopPropagation();
  6454. if (link.is('.'+loaded)) {
  6455. link.toggleClass(expanded);
  6456. stree.slideToggle()
  6457. } else {
  6458. spinner.insertBefore(arrow);
  6459. link.removeClass(collapsed);
  6460. fm.request({cmd : 'tree', target : fm.navId2Hash(link.attr('id'))})
  6461. .done(function(data) {
  6462. updateTree(filter(data.tree));
  6463. if (stree.children().length) {
  6464. link.addClass(collapsed+' '+expanded);
  6465. stree.slideDown();
  6466. }
  6467. sync();
  6468. })
  6469. .always(function(data) {
  6470. spinner.remove();
  6471. link.addClass(loaded);
  6472. });
  6473. }
  6474. })
  6475. .delegate('.'+navdir, 'contextmenu', function(e) {
  6476. e.preventDefault();
  6477. fm.trigger('contextmenu', {
  6478. 'type' : 'navbar',
  6479. 'targets' : [fm.navId2Hash($(this).attr('id'))],
  6480. 'x' : e.clientX,
  6481. 'y' : e.clientY
  6482. });
  6483. }),
  6484. // move tree into navbar
  6485. navbar = fm.getUI('navbar').append(tree).show()
  6486. ;
  6487. fm.open(function(e) {
  6488. var data = e.data,
  6489. dirs = filter(data.files);
  6490. data.init && tree.empty();
  6491. if (dirs.length) {
  6492. updateTree(dirs);
  6493. updateArrows(dirs, loaded);
  6494. }
  6495. sync();
  6496. })
  6497. // add new dirs
  6498. .add(function(e) {
  6499. var dirs = filter(e.data.added);
  6500. if (dirs.length) {
  6501. updateTree(dirs);
  6502. updateArrows(dirs, collapsed);
  6503. }
  6504. })
  6505. // update changed dirs
  6506. .change(function(e) {
  6507. var dirs = filter(e.data.changed),
  6508. l = dirs.length,
  6509. dir, node, tmp, realParent, reqParent, realSibling, reqSibling, isExpanded, isLoaded;
  6510. while (l--) {
  6511. dir = dirs[l];
  6512. if ((node = tree.find('#'+fm.navHash2Id(dir.hash))).length) {
  6513. if (dir.phash) {
  6514. realParent = node.closest('.'+subtree);
  6515. reqParent = findSubtree(dir.phash);
  6516. realSibling = node.parent().next();
  6517. reqSibling = findSibling(reqParent, dir);
  6518. if (!reqParent.length) {
  6519. continue;
  6520. }
  6521. if (reqParent[0] !== realParent[0] || realSibling.get(0) !== reqSibling.get(0)) {
  6522. reqSibling.length ? reqSibling.before(node) : reqParent.append(node);
  6523. }
  6524. }
  6525. isExpanded = node.is('.'+expanded);
  6526. isLoaded = node.is('.'+loaded);
  6527. tmp = $(itemhtml(dir));
  6528. node.replaceWith(tmp.children('.'+navdir));
  6529. if (dir.dirs
  6530. && (isExpanded || isLoaded)
  6531. && (node = tree.find('#'+fm.navHash2Id(dir.hash)))
  6532. && node.next('.'+subtree).children().length) {
  6533. isExpanded && node.addClass(expanded);
  6534. isLoaded && node.addClass(loaded);
  6535. }
  6536. }
  6537. }
  6538. sync();
  6539. updateDroppable();
  6540. })
  6541. // remove dirs
  6542. .remove(function(e) {
  6543. var dirs = e.data.removed,
  6544. l = dirs.length,
  6545. node, stree;
  6546. while (l--) {
  6547. if ((node = tree.find('#'+fm.navHash2Id(dirs[l]))).length) {
  6548. stree = node.closest('.'+subtree);
  6549. node.parent().detach();
  6550. if (!stree.children().length) {
  6551. stree.hide().prev('.'+navdir).removeClass(collapsed+' '+expanded+' '+loaded);
  6552. }
  6553. }
  6554. }
  6555. })
  6556. // add/remove active class for current dir
  6557. .bind('search searchend', function(e) {
  6558. tree.find('#'+fm.navHash2Id(fm.cwd().hash))[e.type == 'search' ? 'removeClass' : 'addClass'](active);
  6559. })
  6560. // lock/unlock dirs while moving
  6561. .bind('lockfiles unlockfiles', function(e) {
  6562. var lock = e.type == 'lockfiles',
  6563. act = lock ? 'disable' : 'enable',
  6564. dirs = $.map(e.data.files||[], function(h) {
  6565. var dir = fm.file(h);
  6566. return dir && dir.mime == 'directory' ? h : null;
  6567. })
  6568. $.each(dirs, function(i, hash) {
  6569. var dir = tree.find('#'+fm.navHash2Id(hash));
  6570. if (dir.length) {
  6571. dir.is('.'+draggable) && dir.draggable(act);
  6572. dir.is('.'+droppable) && dir.droppable(active);
  6573. dir[lock ? 'addClass' : 'removeClass'](disabled);
  6574. }
  6575. });
  6576. })
  6577. });
  6578. return this;
  6579. }
  6580. /*
  6581. * File: /home/osc/elFinder-build/elFinder/js/ui/uploadButton.js
  6582. */
  6583. /**
  6584. * @class elFinder toolbar's button tor upload file
  6585. *
  6586. * @author Dmitry (dio) Levashov
  6587. **/
  6588. $.fn.elfinderuploadbutton = function(cmd) {
  6589. return this.each(function() {
  6590. var button = $(this).elfinderbutton(cmd)
  6591. .unbind('click'),
  6592. form = $('<form/>').appendTo(button),
  6593. input = $('<input type="file" multiple="true"/>')
  6594. .change(function() {
  6595. var _input = $(this);
  6596. if (_input.val()) {
  6597. cmd.exec({input : _input.remove()[0]});
  6598. input.clone(true).appendTo(form);
  6599. }
  6600. });
  6601. form.append(input.clone(true));
  6602. cmd.change(function() {
  6603. form[cmd.disabled() ? 'hide' : 'show']();
  6604. })
  6605. .change();
  6606. });
  6607. }
  6608. /*
  6609. * File: /home/osc/elFinder-build/elFinder/js/ui/viewbutton.js
  6610. */
  6611. /**
  6612. * @class elFinder toolbar button to switch current directory view.
  6613. *
  6614. * @author Dmitry (dio) Levashov
  6615. **/
  6616. $.fn.elfinderviewbutton = function(cmd) {
  6617. return this.each(function() {
  6618. var button = $(this).elfinderbutton(cmd),
  6619. icon = button.children('.elfinder-button-icon');
  6620. cmd.change(function() {
  6621. var icons = cmd.value == 'icons';
  6622. icon.toggleClass('elfinder-button-icon-view-list', icons);
  6623. button.attr('title', cmd.fm.i18n(icons ? 'viewlist' : 'viewicons'));
  6624. });
  6625. });
  6626. }
  6627. /*
  6628. * File: /home/osc/elFinder-build/elFinder/js/ui/workzone.js
  6629. */
  6630. /**
  6631. * @class elfinderworkzone - elFinder container for nav and current directory
  6632. * @author Dmitry (dio) Levashov
  6633. **/
  6634. $.fn.elfinderworkzone = function(fm) {
  6635. var cl = 'elfinder-workzone';
  6636. this.not('.'+cl).each(function() {
  6637. var wz = $(this).addClass(cl),
  6638. wdelta = wz.outerHeight(true) - wz.height(),
  6639. parent = wz.parent();
  6640. parent.add(window).bind('resize', function() {
  6641. var height = parent.height();
  6642. parent.children(':visible:not(.'+cl+')').each(function() {
  6643. var ch = $(this);
  6644. if (ch.css('position') != 'absolute') {
  6645. height -= ch.outerHeight(true);
  6646. }
  6647. });
  6648. wz.height(height - wdelta);
  6649. });
  6650. });
  6651. return this;
  6652. }
  6653. /*
  6654. * File: /home/osc/elFinder-build/elFinder/js/commands/archive.js
  6655. */
  6656. /**
  6657. * @class elFinder command "archive"
  6658. * Archive selected files
  6659. *
  6660. * @author Dmitry (dio) Levashov
  6661. **/
  6662. elFinder.prototype.commands.archive = function() {
  6663. var self = this,
  6664. fm = self.fm,
  6665. mimes = [];
  6666. this.variants = [];
  6667. this.disableOnSearch = true;
  6668. /**
  6669. * Update mimes on open/reload
  6670. *
  6671. * @return void
  6672. **/
  6673. fm.bind('open reload', function() {
  6674. self.variants = [];
  6675. $.each((mimes = fm.option('archivers')['create'] || []), function(i, mime) {
  6676. self.variants.push([mime, fm.mime2kind(mime)])
  6677. });
  6678. self.change();
  6679. });
  6680. this.getstate = function() {
  6681. return !this._disabled && mimes.length && fm.selected().length && fm.cwd().write ? 0 : -1;
  6682. }
  6683. this.exec = function(hashes, type) {
  6684. var files = this.files(hashes),
  6685. cnt = files.length,
  6686. mime = type || mimes[0],
  6687. cwd = fm.cwd(),
  6688. error = ['errArchive', 'errPerm', 'errCreatingTempDir', 'errFtpDownloadFile', 'errFtpUploadFile', 'errFtpMkdir', 'errArchiveExec', 'errExtractExec', 'errRm'],
  6689. dfrd = $.Deferred().fail(function(error) {
  6690. error && fm.error(error);
  6691. }),
  6692. i;
  6693. if (!(this.enabled() && cnt && mimes.length && $.inArray(mime, mimes) !== -1)) {
  6694. return dfrd.reject();
  6695. }
  6696. if (!cwd.write) {
  6697. return dfrd.reject(error);
  6698. }
  6699. for (i = 0; i < cnt; i++) {
  6700. if (!files[i].read) {
  6701. return dfrd.reject(error);
  6702. }
  6703. }
  6704. return fm.request({
  6705. data : {cmd : 'archive', targets : this.hashes(hashes), type : mime},
  6706. notify : {type : 'archive', cnt : 1},
  6707. syncOnFail : true
  6708. });
  6709. }
  6710. }
  6711. /*
  6712. * File: /home/osc/elFinder-build/elFinder/js/commands/back.js
  6713. */
  6714. /**
  6715. * @class elFinder command "back"
  6716. * Open last visited folder
  6717. *
  6718. * @author Dmitry (dio) Levashov
  6719. **/
  6720. elFinder.prototype.commands.back = function() {
  6721. this.alwaysEnabled = true;
  6722. this.updateOnSelect = false;
  6723. this.shortcuts = [{
  6724. pattern : 'ctrl+left backspace'
  6725. }];
  6726. this.getstate = function() {
  6727. return this.fm.history.canBack() ? 0 : -1;
  6728. }
  6729. this.exec = function() {
  6730. return this.fm.history.back();
  6731. }
  6732. }
  6733. /*
  6734. * File: /home/osc/elFinder-build/elFinder/js/commands/copy.js
  6735. */
  6736. /**
  6737. * @class elFinder command "copy".
  6738. * Put files in filemanager clipboard.
  6739. *
  6740. * @type elFinder.command
  6741. * @author Dmitry (dio) Levashov
  6742. */
  6743. elFinder.prototype.commands.copy = function() {
  6744. this.shortcuts = [{
  6745. pattern : 'ctrl+c ctrl+insert'
  6746. }];
  6747. this.getstate = function(sel) {
  6748. var sel = this.files(sel),
  6749. cnt = sel.length;
  6750. return cnt && $.map(sel, function(f) { return f.phash && f.read ? f : null }).length == cnt ? 0 : -1;
  6751. }
  6752. this.exec = function(hashes) {
  6753. var fm = this.fm,
  6754. dfrd = $.Deferred()
  6755. .fail(function(error) {
  6756. fm.error(error);
  6757. });
  6758. $.each(this.files(hashes), function(i, file) {
  6759. if (!(file.read && file.phash)) {
  6760. return !dfrd.reject(['errCopy', file.name, 'errPerm']);
  6761. }
  6762. });
  6763. return dfrd.state() == 'rejected' ? dfrd : dfrd.resolve(fm.clipboard(this.hashes(hashes)));
  6764. }
  6765. }
  6766. /*
  6767. * File: /home/osc/elFinder-build/elFinder/js/commands/cut.js
  6768. */
  6769. /**
  6770. * @class elFinder command "copy".
  6771. * Put files in filemanager clipboard.
  6772. *
  6773. * @type elFinder.command
  6774. * @author Dmitry (dio) Levashov
  6775. */
  6776. elFinder.prototype.commands.cut = function() {
  6777. this.shortcuts = [{
  6778. pattern : 'ctrl+x shift+insert'
  6779. }];
  6780. this.getstate = function(sel) {
  6781. var sel = this.files(sel),
  6782. cnt = sel.length;
  6783. return cnt && $.map(sel, function(f) { return f.phash && f.read && !f.locked ? f : null }).length == cnt ? 0 : -1;
  6784. }
  6785. this.exec = function(hashes) {
  6786. var fm = this.fm,
  6787. dfrd = $.Deferred()
  6788. .fail(function(error) {
  6789. fm.error(error);
  6790. });
  6791. $.each(this.files(hashes), function(i, file) {
  6792. if (!(file.read && file.phash) ) {
  6793. return !dfrd.reject(['errCopy', file.name, 'errPerm']);
  6794. }
  6795. if (file.locked) {
  6796. return !dfrd.reject(['errLocked', file.name]);
  6797. }
  6798. });
  6799. return dfrd.state() == 'rejected' ? dfrd : dfrd.resolve(fm.clipboard(this.hashes(hashes), true));
  6800. }
  6801. }
  6802. /*
  6803. * File: /home/osc/elFinder-build/elFinder/js/commands/download.js
  6804. */
  6805. /**
  6806. * @class elFinder command "download".
  6807. * Download selected files.
  6808. * Only for new api
  6809. *
  6810. * @author Dmitry (dio) Levashov, dio@std42.ru
  6811. **/
  6812. elFinder.prototype.commands.download = function() {
  6813. var self = this,
  6814. fm = this.fm,
  6815. filter = function(hashes) {
  6816. return $.map(self.files(hashes), function(f) { return f.mime == 'directory' ? null : f });
  6817. };
  6818. this.shortcuts = [{
  6819. pattern : 'shift+enter'
  6820. }];
  6821. this.getstate = function() {
  6822. var sel = this.fm.selected(),
  6823. cnt = sel.length;
  6824. return !this._disabled && cnt && (!fm.UA.IE || cnt == 1) && cnt == filter(sel).length ? 0 : -1;
  6825. }
  6826. this.exec = function(hashes) {
  6827. var fm = this.fm,
  6828. base = fm.options.url,
  6829. files = filter(hashes),
  6830. dfrd = $.Deferred(),
  6831. iframes = '',
  6832. cdata = '',
  6833. i, url;
  6834. if (this.disabled()) {
  6835. return dfrd.reject();
  6836. }
  6837. if (fm.oldAPI) {
  6838. fm.error('errCmdNoSupport');
  6839. return dfrd.reject();
  6840. }
  6841. cdata = $.param(fm.options.customData || {});
  6842. if (cdata) {
  6843. cdata = '&' + cdata;
  6844. }
  6845. base += base.indexOf('?') === -1 ? '?' : '&';
  6846. for (i = 0; i < files.length; i++) {
  6847. iframes += '<iframe class="downloader" id="downloader-' + files[i].hash+'" style="display:none" src="'+base + 'cmd=file&target=' + files[i].hash+'&download=1'+cdata+'"/>';
  6848. }
  6849. $(iframes)
  6850. .appendTo('body')
  6851. .ready(function() {
  6852. setTimeout(function() {
  6853. $(iframes).each(function() {
  6854. $('#' + $(this).attr('id')).remove();
  6855. });
  6856. }, fm.UA.Firefox? (20000 + (10000 * i)) : 1000); // give mozilla 20 sec + 10 sec for each file to be saved
  6857. });
  6858. fm.trigger('download', {files : files});
  6859. return dfrd.resolve(hashes);
  6860. }
  6861. }
  6862. /*
  6863. * File: /home/osc/elFinder-build/elFinder/js/commands/duplicate.js
  6864. */
  6865. /**
  6866. * @class elFinder command "duplicate"
  6867. * Create file/folder copy with suffix "copy Number"
  6868. *
  6869. * @type elFinder.command
  6870. * @author Dmitry (dio) Levashov
  6871. */
  6872. elFinder.prototype.commands.duplicate = function() {
  6873. var fm = this.fm;
  6874. this.getstate = function(sel) {
  6875. var sel = this.files(sel),
  6876. cnt = sel.length;
  6877. return !this._disabled && cnt && fm.cwd().write && $.map(sel, function(f) { return f.phash && f.read ? f : null }).length == cnt ? 0 : -1;
  6878. }
  6879. this.exec = function(hashes) {
  6880. var fm = this.fm,
  6881. files = this.files(hashes),
  6882. cnt = files.length,
  6883. dfrd = $.Deferred()
  6884. .fail(function(error) {
  6885. error && fm.error(error);
  6886. }),
  6887. args = [];
  6888. if (!cnt || this._disabled) {
  6889. return dfrd.reject();
  6890. }
  6891. $.each(files, function(i, file) {
  6892. if (!file.read || !fm.file(file.phash).write) {
  6893. return !dfrd.reject(['errCopy', file.name, 'errPerm']);
  6894. }
  6895. });
  6896. if (dfrd.state() == 'rejected') {
  6897. return dfrd;
  6898. }
  6899. return fm.request({
  6900. data : {cmd : 'duplicate', targets : this.hashes(hashes)},
  6901. notify : {type : 'copy', cnt : cnt}
  6902. });
  6903. }
  6904. }
  6905. /*
  6906. * File: /home/osc/elFinder-build/elFinder/js/commands/edit.js
  6907. */
  6908. /**
  6909. * @class elFinder command "edit".
  6910. * Edit text file in dialog window
  6911. *
  6912. * @author Dmitry (dio) Levashov, dio@std42.ru
  6913. **/
  6914. elFinder.prototype.commands.edit = function() {
  6915. var self = this,
  6916. fm = this.fm,
  6917. mimes = fm.res('mimes', 'text') || [],
  6918. /**
  6919. * Return files acceptable to edit
  6920. *
  6921. * @param Array files hashes
  6922. * @return Array
  6923. **/
  6924. filter = function(files) {
  6925. return $.map(files, function(file) {
  6926. return (file.mime.indexOf('text/') === 0 || $.inArray(file.mime, mimes) !== -1)
  6927. && file.mime.indexOf('text/rtf')
  6928. && (!self.onlyMimes.length || $.inArray(file.mime, self.onlyMimes) !== -1)
  6929. && file.read && file.write ? file : null;
  6930. });
  6931. },
  6932. /**
  6933. * Open dialog with textarea to edit file
  6934. *
  6935. * @param String id dialog id
  6936. * @param Object file file object
  6937. * @param String content file content
  6938. * @return $.Deferred
  6939. **/
  6940. dialog = function(id, file, content) {
  6941. var dfrd = $.Deferred(),
  6942. ta = $('<textarea class="elfinder-file-edit" rows="20" id="'+id+'-ta">'+fm.escape(content)+'</textarea>'),
  6943. save = function() {
  6944. ta.editor && ta.editor.save(ta[0], ta.editor.instance);
  6945. dfrd.resolve(ta.getContent());
  6946. ta.elfinderdialog('close');
  6947. },
  6948. cancel = function() {
  6949. dfrd.reject();
  6950. ta.elfinderdialog('close');
  6951. },
  6952. opts = {
  6953. title : file.name,
  6954. width : self.options.dialogWidth || 450,
  6955. buttons : {},
  6956. close : function() {
  6957. ta.editor && ta.editor.close(ta[0], ta.editor.instance);
  6958. $(this).elfinderdialog('destroy');
  6959. },
  6960. open : function() {
  6961. fm.disable();
  6962. ta.focus();
  6963. ta[0].setSelectionRange && ta[0].setSelectionRange(0, 0);
  6964. ta.editor && ta.editor.load(ta[0]);
  6965. }
  6966. };
  6967. ta.getContent = function() {
  6968. return ta.val()
  6969. }
  6970. $.each(self.options.editors || [], function(i, editor) {
  6971. if ($.inArray(file.mime, editor.mimes || []) !== -1
  6972. && typeof editor.load == 'function'
  6973. && typeof editor.save == 'function') {
  6974. ta.editor = {
  6975. load : editor.load,
  6976. save : editor.save,
  6977. close : typeof editor.close == 'function' ? editor.close : function() {},
  6978. instance : null
  6979. }
  6980. return false;
  6981. }
  6982. });
  6983. if (!ta.editor) {
  6984. ta.keydown(function(e) {
  6985. var code = e.keyCode,
  6986. value, start;
  6987. e.stopPropagation();
  6988. if (code == 9) {
  6989. e.preventDefault();
  6990. // insert tab on tab press
  6991. if (this.setSelectionRange) {
  6992. value = this.value;
  6993. start = this.selectionStart;
  6994. this.value = value.substr(0, start) + "\t" + value.substr(this.selectionEnd);
  6995. start += 1;
  6996. this.setSelectionRange(start, start);
  6997. }
  6998. }
  6999. if (e.ctrlKey || e.metaKey) {
  7000. // close on ctrl+w/q
  7001. if (code == 81 || code == 87) {
  7002. e.preventDefault();
  7003. cancel();
  7004. }
  7005. if (code == 83) {
  7006. e.preventDefault();
  7007. save();
  7008. }
  7009. }
  7010. })
  7011. }
  7012. opts.buttons[fm.i18n('Save')] = save;
  7013. opts.buttons[fm.i18n('Cancel')] = cancel
  7014. fm.dialog(ta, opts).attr('id', id);
  7015. return dfrd.promise();
  7016. },
  7017. /**
  7018. * Get file content and
  7019. * open dialog with textarea to edit file content
  7020. *
  7021. * @param String file hash
  7022. * @return jQuery.Deferred
  7023. **/
  7024. edit = function(file) {
  7025. var hash = file.hash,
  7026. opts = fm.options,
  7027. dfrd = $.Deferred(),
  7028. data = {cmd : 'file', target : hash},
  7029. url = fm.url(hash) || fm.options.url,
  7030. id = 'edit-'+fm.namespace+'-'+file.hash,
  7031. d = fm.getUI().find('#'+id),
  7032. error;
  7033. if (d.length) {
  7034. d.elfinderdialog('toTop');
  7035. return dfrd.resolve();
  7036. }
  7037. if (!file.read || !file.write) {
  7038. error = ['errOpen', file.name, 'errPerm']
  7039. fm.error(error)
  7040. return dfrd.reject(error);
  7041. }
  7042. fm.request({
  7043. data : {cmd : 'get', target : hash},
  7044. notify : {type : 'openfile', cnt : 1},
  7045. syncOnFail : true
  7046. })
  7047. .done(function(data) {
  7048. dialog(id, file, data.content)
  7049. .done(function(content) {
  7050. fm.request({
  7051. options : {type : 'post'},
  7052. data : {
  7053. cmd : 'put',
  7054. target : hash,
  7055. content : content
  7056. },
  7057. notify : {type : 'save', cnt : 1},
  7058. syncOnFail : true
  7059. })
  7060. .fail(function(error) {
  7061. dfrd.reject(error);
  7062. })
  7063. .done(function(data) {
  7064. data.changed && data.changed.length && fm.change(data);
  7065. dfrd.resolve(data);
  7066. });
  7067. })
  7068. })
  7069. .fail(function(error) {
  7070. dfrd.reject(error);
  7071. })
  7072. return dfrd.promise();
  7073. };
  7074. this.shortcuts = [{
  7075. pattern : 'ctrl+e'
  7076. }];
  7077. this.init = function() {
  7078. this.onlyMimes = this.options.mimes || []
  7079. }
  7080. this.getstate = function(sel) {
  7081. var sel = this.files(sel),
  7082. cnt = sel.length;
  7083. return !this._disabled && cnt && filter(sel).length == cnt ? 0 : -1;
  7084. }
  7085. this.exec = function(hashes) {
  7086. var files = filter(this.files(hashes)),
  7087. list = [],
  7088. file;
  7089. if (this.disabled()) {
  7090. return $.Deferred().reject();
  7091. }
  7092. while ((file = files.shift())) {
  7093. list.push(edit(file));
  7094. }
  7095. return list.length
  7096. ? $.when.apply(null, list)
  7097. : $.Deferred().reject();
  7098. }
  7099. }
  7100. /*
  7101. * File: /home/osc/elFinder-build/elFinder/js/commands/extract.js
  7102. */
  7103. /**
  7104. * @class elFinder command "extract"
  7105. * Extract files from archive
  7106. *
  7107. * @author Dmitry (dio) Levashov
  7108. **/
  7109. elFinder.prototype.commands.extract = function() {
  7110. var self = this,
  7111. fm = self.fm,
  7112. mimes = [],
  7113. filter = function(files) {
  7114. return $.map(files, function(file) {
  7115. return file.read && $.inArray(file.mime, mimes) !== -1 ? file : null
  7116. })
  7117. };
  7118. this.disableOnSearch = true;
  7119. // Update mimes list on open/reload
  7120. fm.bind('open reload', function() {
  7121. mimes = fm.option('archivers')['extract'] || [];
  7122. self.change();
  7123. });
  7124. this.getstate = function(sel) {
  7125. var sel = this.files(sel),
  7126. cnt = sel.length;
  7127. return !this._disabled && cnt && this.fm.cwd().write && filter(sel).length == cnt ? 0 : -1;
  7128. }
  7129. this.exec = function(hashes) {
  7130. var files = this.files(hashes),
  7131. dfrd = $.Deferred(),
  7132. cnt = files.length,
  7133. i, error,
  7134. decision;
  7135. var overwriteAll = false;
  7136. var omitAll = false;
  7137. var names = $.map(fm.files(hashes), function(file) { return file.name; });
  7138. var map = {};
  7139. $.map(fm.files(hashes), function(file) { map[file.name] = file; });
  7140. var decide = function(decision) {
  7141. switch (decision) {
  7142. case 'overwrite_all' :
  7143. overwriteAll = true;
  7144. break;
  7145. case 'omit_all':
  7146. omitAll = true;
  7147. break;
  7148. }
  7149. };
  7150. var unpack = function(file) {
  7151. if (!(file.read && fm.file(file.phash).write)) {
  7152. error = ['errExtract', file.name, 'errPerm'];
  7153. fm.error(error);
  7154. dfrd.reject(error);
  7155. } else if ($.inArray(file.mime, mimes) === -1) {
  7156. error = ['errExtract', file.name, 'errNoArchive'];
  7157. fm.error(error);
  7158. dfrd.reject(error);
  7159. } else {
  7160. fm.request({
  7161. data:{cmd:'extract', target:file.hash},
  7162. notify:{type:'extract', cnt:1},
  7163. syncOnFail:true
  7164. })
  7165. .fail(function (error) {
  7166. if (dfrd.state() != 'rejected') {
  7167. dfrd.reject(error);
  7168. }
  7169. })
  7170. .done(function () {
  7171. });
  7172. }
  7173. };
  7174. var confirm = function(files, index) {
  7175. var file = files[index];
  7176. var name = file.name.replace(/\.((tar\.(gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(gz|bz2)|[a-z0-9]{1,4})$/ig, '');
  7177. var existed = ($.inArray(name, names) >= 0);
  7178. if(existed && map[name].mime != 'directory') {
  7179. fm.confirm(
  7180. {
  7181. title : fm.i18n('ntfextract'),
  7182. text : fm.i18n(['errExists', name, 'confirmRepl']),
  7183. accept:{
  7184. label : 'btnYes',
  7185. callback:function (all) {
  7186. decision = all ? 'overwrite_all' : 'overwrite';
  7187. decide(decision);
  7188. if(!overwriteAll && !omitAll) {
  7189. if('overwrite' == decision) {
  7190. unpack(file);
  7191. }
  7192. if((index+1) < cnt) {
  7193. confirm(files, index+1);
  7194. } else {
  7195. dfrd.resolve();
  7196. }
  7197. } else if(overwriteAll) {
  7198. for (i = 0; i < cnt; i++) {
  7199. unpack(files[i]);
  7200. }
  7201. dfrd.resolve();
  7202. }
  7203. }
  7204. },
  7205. reject : {
  7206. label : 'btnNo',
  7207. callback:function (all) {
  7208. decision = all ? 'omit_all' : 'omit';
  7209. decide(decision);
  7210. if(!overwriteAll && !omitAll && (index+1) < cnt) {
  7211. confirm(files, index+1);
  7212. } else if (omitAll) {
  7213. dfrd.resolve();
  7214. }
  7215. }
  7216. },
  7217. cancel : {
  7218. label : 'btnCancel',
  7219. callback:function () {
  7220. dfrd.resolve();
  7221. }
  7222. },
  7223. all : (cnt > 1)
  7224. }
  7225. );
  7226. } else {
  7227. unpack(file);
  7228. if((index+1) < cnt) {
  7229. confirm(files, index+1);
  7230. } else {
  7231. dfrd.resolve();
  7232. }
  7233. }
  7234. };
  7235. if (!(this.enabled() && cnt && mimes.length)) {
  7236. return dfrd.reject();
  7237. }
  7238. if(cnt > 0) {
  7239. confirm(files, 0);
  7240. }
  7241. return dfrd;
  7242. }
  7243. }
  7244. /*
  7245. * File: /home/osc/elFinder-build/elFinder/js/commands/forward.js
  7246. */
  7247. /**
  7248. * @class elFinder command "forward"
  7249. * Open next visited folder
  7250. *
  7251. * @author Dmitry (dio) Levashov
  7252. **/
  7253. elFinder.prototype.commands.forward = function() {
  7254. this.alwaysEnabled = true;
  7255. this.updateOnSelect = true;
  7256. this.shortcuts = [{
  7257. pattern : 'ctrl+right'
  7258. }];
  7259. this.getstate = function() {
  7260. return this.fm.history.canForward() ? 0 : -1;
  7261. }
  7262. this.exec = function() {
  7263. return this.fm.history.forward();
  7264. }
  7265. }
  7266. /*
  7267. * File: /home/osc/elFinder-build/elFinder/js/commands/getfile.js
  7268. */
  7269. /**
  7270. * @class elFinder command "getfile".
  7271. * Return selected files info into outer callback.
  7272. * For use elFinder with wysiwyg editors etc.
  7273. *
  7274. * @author Dmitry (dio) Levashov, dio@std42.ru
  7275. **/
  7276. elFinder.prototype.commands.getfile = function() {
  7277. var self = this,
  7278. fm = this.fm,
  7279. filter = function(files) {
  7280. var o = self.options;
  7281. files = $.map(files, function(file) {
  7282. return file.mime != 'directory' || o.folders ? file : null;
  7283. });
  7284. return o.multiple || files.length == 1 ? files : [];
  7285. };
  7286. this.alwaysEnabled = true;
  7287. this.callback = fm.options.getFileCallback;
  7288. this._disabled = typeof(this.callback) == 'function';
  7289. this.getstate = function(sel) {
  7290. var sel = this.files(sel),
  7291. cnt = sel.length;
  7292. return this.callback && cnt && filter(sel).length == cnt ? 0 : -1;
  7293. }
  7294. this.exec = function(hashes) {
  7295. var fm = this.fm,
  7296. opts = this.options,
  7297. files = this.files(hashes),
  7298. cnt = files.length,
  7299. url = fm.option('url'),
  7300. tmb = fm.option('tmbUrl'),
  7301. dfrd = $.Deferred()
  7302. .done(function(data) {
  7303. fm.trigger('getfile', {files : data});
  7304. self.callback(data, fm);
  7305. if (opts.oncomplete == 'close') {
  7306. fm.hide();
  7307. } else if (opts.oncomplete == 'destroy') {
  7308. fm.destroy();
  7309. }
  7310. }),
  7311. result = function(file) {
  7312. return opts.onlyURL
  7313. ? opts.multiple ? $.map(files, function(f) { return f.url; }) : files[0].url
  7314. : opts.multiple ? files : files[0];
  7315. },
  7316. req = [],
  7317. i, file, dim;
  7318. if (this.getstate() == -1) {
  7319. return dfrd.reject();
  7320. }
  7321. for (i = 0; i < cnt; i++) {
  7322. file = files[i];
  7323. if (file.mime == 'directory' && !opts.folders) {
  7324. return dfrd.reject();
  7325. }
  7326. file.baseUrl = url;
  7327. file.url = fm.url(file.hash);
  7328. file.path = fm.path(file.hash);
  7329. if (file.tmb && file.tmb != 1) {
  7330. file.tmb = tmb + file.tmb;
  7331. }
  7332. if (!file.width && !file.height) {
  7333. if (file.dim) {
  7334. dim = file.dim.split('x');
  7335. file.width = dim[0];
  7336. file.height = dim[1];
  7337. } else if (file.mime.indexOf('image') !== -1) {
  7338. req.push(fm.request({
  7339. data : {cmd : 'dim', target : file.hash},
  7340. notify : {type : 'dim', cnt : 1, hideCnt : true},
  7341. preventDefault : true
  7342. })
  7343. .done(function(data) {
  7344. if (data.dim) {
  7345. var dim = data.dim.split('x');
  7346. var rfile = fm.file(this.hash);
  7347. rfile.width = this.width = dim[0];
  7348. rfile.height = this.height = dim[1];
  7349. }
  7350. }.bind(file)));
  7351. }
  7352. }
  7353. }
  7354. if (req.length) {
  7355. $.when.apply(null, req).always(function() {
  7356. dfrd.resolve(result(files));
  7357. })
  7358. return dfrd;
  7359. }
  7360. return dfrd.resolve(result(files));
  7361. }
  7362. }
  7363. /*
  7364. * File: /home/osc/elFinder-build/elFinder/js/commands/help.js
  7365. */
  7366. /**
  7367. * @class elFinder command "help"
  7368. * "About" dialog
  7369. *
  7370. * @author Dmitry (dio) Levashov
  7371. **/
  7372. elFinder.prototype.commands.help = function() {
  7373. var fm = this.fm,
  7374. self = this,
  7375. linktpl = '<div class="elfinder-help-link"> <a href="{url}">{link}</a></div>',
  7376. linktpltgt = '<div class="elfinder-help-link"> <a href="{url}" target="_blank">{link}</a></div>',
  7377. atpl = '<div class="elfinder-help-team"><div>{author}</div>{work}</div>',
  7378. url = /\{url\}/,
  7379. link = /\{link\}/,
  7380. author = /\{author\}/,
  7381. work = /\{work\}/,
  7382. r = 'replace',
  7383. prim = 'ui-priority-primary',
  7384. sec = 'ui-priority-secondary',
  7385. lic = 'elfinder-help-license',
  7386. tab = '<li class="ui-state-default ui-corner-top"><a href="#{id}">{title}</a></li>',
  7387. html = ['<div class="ui-tabs ui-widget ui-widget-content ui-corner-all elfinder-help">',
  7388. '<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">'],
  7389. stpl = '<div class="elfinder-help-shortcut"><div class="elfinder-help-shortcut-pattern">{pattern}</div> {descrip}</div>',
  7390. sep = '<div class="elfinder-help-separator"/>',
  7391. about = function() {
  7392. html.push('<div id="about" class="ui-tabs-panel ui-widget-content ui-corner-bottom"><div class="elfinder-help-logo"/>')
  7393. html.push('<h3>elFinder</h3>');
  7394. html.push('<div class="'+prim+'">'+fm.i18n('webfm')+'</div>');
  7395. html.push('<div class="'+sec+'">'+fm.i18n('ver')+': '+fm.version+', '+fm.i18n('protocolver')+': <span id="apiver"></span></div>');
  7396. html.push('<div class="'+sec+'">jQuery/jQuery UI: '+$().jquery+'/'+$.ui.version+'</div>');
  7397. html.push(sep);
  7398. html.push(linktpltgt[r](url, 'http://elfinder.org/')[r](link, fm.i18n('homepage')));
  7399. html.push(linktpltgt[r](url, 'https://github.com/Studio-42/elFinder/wiki')[r](link, fm.i18n('docs')));
  7400. html.push(linktpltgt[r](url, 'https://github.com/Studio-42/elFinder')[r](link, fm.i18n('github')));
  7401. html.push(linktpltgt[r](url, 'http://twitter.com/elrte_elfinder')[r](link, fm.i18n('twitter')));
  7402. html.push(sep);
  7403. html.push('<div class="'+prim+'">'+fm.i18n('team')+'</div>');
  7404. html.push(atpl[r](author, 'Dmitry "dio" Levashov &lt;dio@std42.ru&gt;')[r](work, fm.i18n('chiefdev')));
  7405. html.push(atpl[r](author, 'Troex Nevelin &lt;troex@fury.scancode.ru&gt;')[r](work, fm.i18n('maintainer')));
  7406. html.push(atpl[r](author, 'Alexey Sukhotin &lt;strogg@yandex.ru&gt;')[r](work, fm.i18n('contributor')));
  7407. html.push(atpl[r](author, 'Naoki Sawada &lt;hypweb@gmail.com&gt;')[r](work, fm.i18n('contributor')));
  7408. fm.i18[fm.lang].translator && html.push(atpl[r](author, fm.i18[fm.lang].translator)[r](work, fm.i18n('translator')+' ('+fm.i18[fm.lang].language+')'));
  7409. html.push(sep);
  7410. html.push('<div class="'+lic+'">'+fm.i18n('icons')+': Pixelmixer, <a href="http://p.yusukekamiyamane.com" target="_blank">Fugue</a></div>');
  7411. html.push(sep);
  7412. html.push('<div class="'+lic+'">Licence: BSD Licence</div>');
  7413. html.push('<div class="'+lic+'">Copyright © 2009-2011, Studio 42</div>');
  7414. html.push('<div class="'+lic+'">„ …'+fm.i18n('dontforget')+' ”</div>');
  7415. html.push('</div>');
  7416. },
  7417. shortcuts = function() {
  7418. var sh = fm.shortcuts();
  7419. // shortcuts tab
  7420. html.push('<div id="shortcuts" class="ui-tabs-panel ui-widget-content ui-corner-bottom">');
  7421. if (sh.length) {
  7422. html.push('<div class="ui-widget-content elfinder-help-shortcuts">');
  7423. $.each(sh, function(i, s) {
  7424. html.push(stpl.replace(/\{pattern\}/, s[0]).replace(/\{descrip\}/, s[1]));
  7425. });
  7426. html.push('</div>');
  7427. } else {
  7428. html.push('<div class="elfinder-help-disabled">'+fm.i18n('shortcutsof')+'</div>')
  7429. }
  7430. html.push('</div>')
  7431. },
  7432. help = function() {
  7433. // help tab
  7434. html.push('<div id="help" class="ui-tabs-panel ui-widget-content ui-corner-bottom">');
  7435. html.push('<a href="http://elfinder.org/forum/" target="_blank" class="elfinder-dont-panic"><span>DON\'T PANIC</span></a>');
  7436. html.push('</div>');
  7437. // end help
  7438. },
  7439. content;
  7440. this.alwaysEnabled = true;
  7441. this.updateOnSelect = false;
  7442. this.state = 0;
  7443. this.shortcuts = [{
  7444. pattern : 'f1',
  7445. description : this.title
  7446. }];
  7447. setTimeout(function() {
  7448. var parts = self.options.view || ['about', 'shortcuts', 'help'];
  7449. $.each(parts, function(i, title) {
  7450. html.push(tab[r](/\{id\}/, title)[r](/\{title\}/, fm.i18n(title)));
  7451. });
  7452. html.push('</ul>');
  7453. $.inArray('about', parts) !== -1 && about();
  7454. $.inArray('shortcuts', parts) !== -1 && shortcuts();
  7455. $.inArray('help', parts) !== -1 && help();
  7456. html.push('</div>');
  7457. content = $(html.join(''));
  7458. fm.one('load', function setapi() { content.find('#apiver').text(fm.api); });
  7459. content.find('.ui-tabs-nav li')
  7460. .hover(function() {
  7461. $(this).toggleClass('ui-state-hover')
  7462. })
  7463. .children()
  7464. .click(function(e) {
  7465. var link = $(this);
  7466. e.preventDefault();
  7467. e.stopPropagation();
  7468. if (!link.is('.ui-tabs-selected')) {
  7469. link.parent().addClass('ui-tabs-selected ui-state-active').siblings().removeClass('ui-tabs-selected').removeClass('ui-state-active');
  7470. content.find('.ui-tabs-panel').hide().filter(link.attr('href')).show();
  7471. }
  7472. })
  7473. .filter(':first').click();
  7474. }, 200)
  7475. this.getstate = function() {
  7476. return 0;
  7477. }
  7478. this.exec = function() {
  7479. if (!this.dialog) {
  7480. this.dialog = this.fm.dialog(content, {title : this.title, width : 530, autoOpen : false, destroyOnClose : false});
  7481. }
  7482. this.dialog.elfinderdialog('open').find('.ui-tabs-nav li a:first').click();
  7483. }
  7484. }
  7485. /*
  7486. * File: /home/osc/elFinder-build/elFinder/js/commands/home.js
  7487. */
  7488. elFinder.prototype.commands.home = function() {
  7489. this.title = 'Home';
  7490. this.alwaysEnabled = true;
  7491. this.updateOnSelect = false;
  7492. this.shortcuts = [{
  7493. pattern : 'ctrl+home ctrl+shift+up',
  7494. description : 'Home'
  7495. }];
  7496. this.getstate = function() {
  7497. var root = this.fm.root(),
  7498. cwd = this.fm.cwd().hash;
  7499. return root && cwd && root != cwd ? 0: -1;
  7500. }
  7501. this.exec = function() {
  7502. return this.fm.exec('open', this.fm.root());
  7503. }
  7504. }
  7505. /*
  7506. * File: /home/osc/elFinder-build/elFinder/js/commands/info.js
  7507. */
  7508. /**
  7509. * @class elFinder command "info".
  7510. * Display dialog with file properties.
  7511. *
  7512. * @author Dmitry (dio) Levashov, dio@std42.ru
  7513. **/
  7514. elFinder.prototype.commands.info = function() {
  7515. var m = 'msg',
  7516. fm = this.fm,
  7517. spclass = 'elfinder-info-spinner',
  7518. msg = {
  7519. calc : fm.i18n('calc'),
  7520. size : fm.i18n('size'),
  7521. unknown : fm.i18n('unknown'),
  7522. path : fm.i18n('path'),
  7523. aliasfor : fm.i18n('aliasfor'),
  7524. modify : fm.i18n('modify'),
  7525. perms : fm.i18n('perms'),
  7526. locked : fm.i18n('locked'),
  7527. dim : fm.i18n('dim'),
  7528. kind : fm.i18n('kind'),
  7529. files : fm.i18n('files'),
  7530. folders : fm.i18n('folders'),
  7531. items : fm.i18n('items'),
  7532. yes : fm.i18n('yes'),
  7533. no : fm.i18n('no'),
  7534. link : fm.i18n('link')
  7535. };
  7536. this.tpl = {
  7537. main : '<div class="ui-helper-clearfix elfinder-info-title"><span class="elfinder-cwd-icon {class} ui-corner-all"/>{title}</div><table class="elfinder-info-tb">{content}</table>',
  7538. itemTitle : '<strong>{name}</strong><span class="elfinder-info-kind">{kind}</span>',
  7539. groupTitle : '<strong>{items}: {num}</strong>',
  7540. row : '<tr><td>{label} : </td><td>{value}</td></tr>',
  7541. spinner : '<span>{text}</span> <span class="'+spclass+'"/>'
  7542. }
  7543. this.alwaysEnabled = true;
  7544. this.updateOnSelect = false;
  7545. this.shortcuts = [{
  7546. pattern : 'ctrl+i'
  7547. }];
  7548. this.init = function() {
  7549. $.each(msg, function(k, v) {
  7550. msg[k] = fm.i18n(v);
  7551. });
  7552. }
  7553. this.getstate = function() {
  7554. return 0;
  7555. }
  7556. this.exec = function(hashes) {
  7557. var files = this.files(hashes);
  7558. if (! files.length) {
  7559. files = this.files([ this.fm.cwd().hash ]);
  7560. }
  7561. var self = this,
  7562. fm = this.fm,
  7563. tpl = this.tpl,
  7564. row = tpl.row,
  7565. cnt = files.length,
  7566. content = [],
  7567. view = tpl.main,
  7568. l = '{label}',
  7569. v = '{value}',
  7570. opts = {
  7571. title : this.title,
  7572. width : 'auto',
  7573. close : function() { $(this).elfinderdialog('destroy'); }
  7574. },
  7575. count = [],
  7576. replSpinner = function(msg) { dialog.find('.'+spclass).parent().text(msg); },
  7577. id = fm.namespace+'-info-'+$.map(files, function(f) { return f.hash }).join('-'),
  7578. dialog = fm.getUI().find('#'+id),
  7579. size, tmb, file, title, dcnt;
  7580. if (!cnt) {
  7581. return $.Deferred().reject();
  7582. }
  7583. if (dialog.length) {
  7584. dialog.elfinderdialog('toTop');
  7585. return $.Deferred().resolve();
  7586. }
  7587. if (cnt == 1) {
  7588. file = files[0];
  7589. view = view.replace('{class}', fm.mime2class(file.mime));
  7590. title = tpl.itemTitle.replace('{name}', fm.escape(file.i18 || file.name)).replace('{kind}', fm.mime2kind(file));
  7591. if (file.tmb) {
  7592. tmb = fm.option('tmbUrl')+file.tmb;
  7593. }
  7594. if (!file.read) {
  7595. size = msg.unknown;
  7596. } else if (file.mime != 'directory' || file.alias) {
  7597. size = fm.formatSize(file.size);
  7598. } else {
  7599. size = tpl.spinner.replace('{text}', msg.calc);
  7600. count.push(file.hash);
  7601. }
  7602. content.push(row.replace(l, msg.size).replace(v, size));
  7603. file.alias && content.push(row.replace(l, msg.aliasfor).replace(v, file.alias));
  7604. content.push(row.replace(l, msg.path).replace(v, fm.escape(fm.path(file.hash, true))));
  7605. file.read && content.push(row.replace(l, msg.link).replace(v, '<a href="'+fm.url(file.hash)+'" target="_blank">'+file.name+'</a>'));
  7606. if (file.dim) { // old api
  7607. content.push(row.replace(l, msg.dim).replace(v, file.dim));
  7608. } else if (file.mime.indexOf('image') !== -1) {
  7609. if (file.width && file.height) {
  7610. content.push(row.replace(l, msg.dim).replace(v, file.width+'x'+file.height));
  7611. } else {
  7612. content.push(row.replace(l, msg.dim).replace(v, tpl.spinner.replace('{text}', msg.calc)));
  7613. fm.request({
  7614. data : {cmd : 'dim', target : file.hash},
  7615. preventDefault : true
  7616. })
  7617. .fail(function() {
  7618. replSpinner(msg.unknown);
  7619. })
  7620. .done(function(data) {
  7621. replSpinner(data.dim || msg.unknown);
  7622. if (data.dim) {
  7623. var dim = data.dim.split('x');
  7624. var rfile = fm.file(file.hash);
  7625. rfile.width = dim[0];
  7626. rfile.height = dim[1];
  7627. }
  7628. });
  7629. }
  7630. }
  7631. content.push(row.replace(l, msg.modify).replace(v, fm.formatDate(file)));
  7632. content.push(row.replace(l, msg.perms).replace(v, fm.formatPermissions(file)));
  7633. content.push(row.replace(l, msg.locked).replace(v, file.locked ? msg.yes : msg.no));
  7634. } else {
  7635. view = view.replace('{class}', 'elfinder-cwd-icon-group');
  7636. title = tpl.groupTitle.replace('{items}', msg.items).replace('{num}', cnt);
  7637. dcnt = $.map(files, function(f) { return f.mime == 'directory' ? 1 : null }).length;
  7638. if (!dcnt) {
  7639. size = 0;
  7640. $.each(files, function(h, f) {
  7641. var s = parseInt(f.size);
  7642. if (s >= 0 && size >= 0) {
  7643. size += s;
  7644. } else {
  7645. size = 'unknown';
  7646. }
  7647. });
  7648. content.push(row.replace(l, msg.kind).replace(v, msg.files));
  7649. content.push(row.replace(l, msg.size).replace(v, fm.formatSize(size)));
  7650. } else {
  7651. content.push(row.replace(l, msg.kind).replace(v, dcnt == cnt ? msg.folders : msg.folders+' '+dcnt+', '+msg.files+' '+(cnt-dcnt)))
  7652. content.push(row.replace(l, msg.size).replace(v, tpl.spinner.replace('{text}', msg.calc)));
  7653. count = $.map(files, function(f) { return f.hash });
  7654. }
  7655. }
  7656. view = view.replace('{title}', title).replace('{content}', content.join(''));
  7657. dialog = fm.dialog(view, opts);
  7658. dialog.attr('id', id)
  7659. // load thumbnail
  7660. if (tmb) {
  7661. $('<img/>')
  7662. .load(function() { dialog.find('.elfinder-cwd-icon').css('background', 'url("'+tmb+'") center center no-repeat'); })
  7663. .attr('src', tmb);
  7664. }
  7665. // send request to count total size
  7666. if (count.length) {
  7667. fm.request({
  7668. data : {cmd : 'size', targets : count},
  7669. preventDefault : true
  7670. })
  7671. .fail(function() {
  7672. replSpinner(msg.unknown);
  7673. })
  7674. .done(function(data) {
  7675. var size = parseInt(data.size);
  7676. replSpinner(size >= 0 ? fm.formatSize(size) : msg.unknown);
  7677. });
  7678. }
  7679. }
  7680. }
  7681. /*
  7682. * File: /home/osc/elFinder-build/elFinder/js/commands/mkdir.js
  7683. */
  7684. /**
  7685. * @class elFinder command "mkdir"
  7686. * Create new folder
  7687. *
  7688. * @author Dmitry (dio) Levashov
  7689. **/
  7690. elFinder.prototype.commands.mkdir = function() {
  7691. this.disableOnSearch = true;
  7692. this.updateOnSelect = false;
  7693. this.mime = 'directory';
  7694. this.prefix = 'untitled folder';
  7695. this.exec = $.proxy(this.fm.res('mixin', 'make'), this);
  7696. this.shortcuts = [{
  7697. pattern : 'ctrl+shift+n'
  7698. }];
  7699. this.getstate = function() {
  7700. return !this._disabled && this.fm.cwd().write ? 0 : -1;
  7701. }
  7702. }
  7703. /*
  7704. * File: /home/osc/elFinder-build/elFinder/js/commands/mkfile.js
  7705. */
  7706. /**
  7707. * @class elFinder command "mkfile"
  7708. * Create new empty file
  7709. *
  7710. * @author Dmitry (dio) Levashov
  7711. **/
  7712. elFinder.prototype.commands.mkfile = function() {
  7713. this.disableOnSearch = true;
  7714. this.updateOnSelect = false;
  7715. this.mime = 'text/plain';
  7716. this.prefix = 'untitled file.txt';
  7717. this.exec = $.proxy(this.fm.res('mixin', 'make'), this);
  7718. this.getstate = function() {
  7719. return !this._disabled && this.fm.cwd().write ? 0 : -1;
  7720. }
  7721. }
  7722. /*
  7723. * File: /home/osc/elFinder-build/elFinder/js/commands/netmount.js
  7724. */
  7725. /**
  7726. * @class elFinder command "netmount"
  7727. * Mount network volume with user credentials.
  7728. *
  7729. * @author Dmitry (dio) Levashov
  7730. **/
  7731. elFinder.prototype.commands.netmount = function() {
  7732. var self = this;
  7733. this.alwaysEnabled = true;
  7734. this.updateOnSelect = false;
  7735. this.drivers = [];
  7736. this.handlers = {
  7737. load : function() {
  7738. this.drivers = this.fm.netDrivers;
  7739. }
  7740. }
  7741. this.getstate = function() {
  7742. return this.drivers.length ? 0 : -1;
  7743. }
  7744. this.exec = function() {
  7745. var fm = self.fm,
  7746. dfrd = $.Deferred(),
  7747. create = function() {
  7748. var inputs = {
  7749. protocol : $('<select/>'),
  7750. host : $('<input type="text"/>'),
  7751. port : $('<input type="text"/>'),
  7752. path : $('<input type="text" value="/"/>'),
  7753. user : $('<input type="text"/>'),
  7754. pass : $('<input type="password"/>')
  7755. },
  7756. opts = {
  7757. title : fm.i18n('netMountDialogTitle'),
  7758. resizable : false,
  7759. modal : true,
  7760. destroyOnClose : true,
  7761. close : function() {
  7762. delete self.dialog;
  7763. dfrd.state() == 'pending' && dfrd.reject();
  7764. },
  7765. buttons : {}
  7766. },
  7767. content = $('<table class="elfinder-info-tb elfinder-netmount-tb"/>');
  7768. $.each(self.drivers, function(i, protocol) {
  7769. inputs.protocol.append('<option value="'+protocol+'">'+fm.i18n(protocol)+'</option>');
  7770. });
  7771. $.each(inputs, function(name, input) {
  7772. name != 'protocol' && input.addClass('ui-corner-all');
  7773. content.append($('<tr/>').append($('<td>'+fm.i18n(name)+'</td>')).append($('<td/>').append(input)));
  7774. });
  7775. opts.buttons[fm.i18n('btnMount')] = function() {
  7776. var data = {cmd : 'netmount'};
  7777. $.each(inputs, function(name, input) {
  7778. var val = $.trim(input.val());
  7779. if (val) {
  7780. data[name] = val;
  7781. }
  7782. });
  7783. if (!data.host) {
  7784. return self.fm.trigger('error', {error : 'errNetMountHostReq'});
  7785. }
  7786. self.fm.request({data : data, notify : {type : 'netmount', cnt : 1}})
  7787. .done(function() { dfrd.resolve(); })
  7788. .fail(function(error) { dfrd.reject(error); });
  7789. self.dialog.elfinderdialog('close');
  7790. }
  7791. opts.buttons[fm.i18n('btnCancel')] = function() {
  7792. self.dialog.elfinderdialog('close');
  7793. }
  7794. return fm.dialog(content, opts);
  7795. }
  7796. ;
  7797. if (!self.dialog) {
  7798. self.dialog = create()
  7799. }
  7800. return dfrd.promise();
  7801. }
  7802. }
  7803. /*
  7804. * File: /home/osc/elFinder-build/elFinder/js/commands/open.js
  7805. */
  7806. /**
  7807. * @class elFinder command "open"
  7808. * Enter folder or open files in new windows
  7809. *
  7810. * @author Dmitry (dio) Levashov
  7811. **/
  7812. elFinder.prototype.commands.open = function() {
  7813. this.alwaysEnabled = true;
  7814. this._handlers = {
  7815. dblclick : function(e) { e.preventDefault(); this.exec() },
  7816. 'select enable disable reload' : function(e) { this.update(e.type == 'disable' ? -1 : void(0)); }
  7817. }
  7818. this.shortcuts = [{
  7819. pattern : 'ctrl+down numpad_enter'+(this.fm.OS != 'mac' && ' enter')
  7820. }];
  7821. this.getstate = function(sel) {
  7822. var sel = this.files(sel),
  7823. cnt = sel.length;
  7824. return cnt == 1
  7825. ? 0
  7826. : cnt ? ($.map(sel, function(file) { return file.mime == 'directory' ? null : file}).length == cnt ? 0 : -1) : -1
  7827. }
  7828. this.exec = function(hashes) {
  7829. var fm = this.fm,
  7830. dfrd = $.Deferred().fail(function(error) { error && fm.error(error); }),
  7831. files = this.files(hashes),
  7832. cnt = files.length,
  7833. file, url, s, w;
  7834. if (!cnt) {
  7835. return dfrd.reject();
  7836. }
  7837. // open folder
  7838. if (cnt == 1 && (file = files[0]) && file.mime == 'directory') {
  7839. return file && !file.read
  7840. ? dfrd.reject(['errOpen', file.name, 'errPerm'])
  7841. : fm.request({
  7842. data : {cmd : 'open', target : file.thash || file.hash},
  7843. notify : {type : 'open', cnt : 1, hideCnt : true},
  7844. syncOnFail : true
  7845. });
  7846. }
  7847. files = $.map(files, function(file) { return file.mime != 'directory' ? file : null });
  7848. // nothing to open or files and folders selected - do nothing
  7849. if (cnt != files.length) {
  7850. return dfrd.reject();
  7851. }
  7852. // open files
  7853. cnt = files.length;
  7854. while (cnt--) {
  7855. file = files[cnt];
  7856. if (!file.read) {
  7857. return dfrd.reject(['errOpen', file.name, 'errPerm']);
  7858. }
  7859. if (!(url = fm.url(/*file.thash || */file.hash))) {
  7860. url = fm.options.url;
  7861. url = url + (url.indexOf('?') === -1 ? '?' : '&')
  7862. + (fm.oldAPI ? 'cmd=open&current='+file.phash : 'cmd=file')
  7863. + '&target=' + file.hash;
  7864. }
  7865. // set window size for image if set
  7866. if (file.dim) {
  7867. s = file.dim.split('x');
  7868. w = 'width='+(parseInt(s[0])+20) + ',height='+(parseInt(s[1])+20);
  7869. } else {
  7870. w = 'width='+parseInt(2*$(window).width()/3)+',height='+parseInt(2*$(window).height()/3);
  7871. }
  7872. var wnd = window.open('', 'new_window', w + ',top=50,left=50,scrollbars=yes,resizable=yes');
  7873. if (!wnd) {
  7874. return dfrd.reject('errPopup');
  7875. }
  7876. var form = document.createElement("form");
  7877. form.action = fm.options.url;
  7878. form.method = 'POST';
  7879. form.target = 'new_window';
  7880. form.style.display = 'none';
  7881. var params = $.extend({}, fm.options.customData, {
  7882. cmd: 'file',
  7883. target: file.hash
  7884. });
  7885. $.each(params, function(key, val)
  7886. {
  7887. var input = document.createElement("input");
  7888. input.name = key;
  7889. input.value = val;
  7890. form.appendChild(input);
  7891. });
  7892. document.body.appendChild(form);
  7893. form.submit();
  7894. }
  7895. return dfrd.resolve(hashes);
  7896. }
  7897. }
  7898. /*
  7899. * File: /home/osc/elFinder-build/elFinder/js/commands/paste.js
  7900. */
  7901. /**
  7902. * @class elFinder command "paste"
  7903. * Paste filesfrom clipboard into directory.
  7904. * If files pasted in its parent directory - files duplicates will created
  7905. *
  7906. * @author Dmitry (dio) Levashov
  7907. **/
  7908. elFinder.prototype.commands.paste = function() {
  7909. this.updateOnSelect = false;
  7910. this.handlers = {
  7911. changeclipboard : function() { this.update(); }
  7912. }
  7913. this.shortcuts = [{
  7914. pattern : 'ctrl+v shift+insert'
  7915. }];
  7916. this.getstate = function(dst) {
  7917. if (this._disabled) {
  7918. return -1;
  7919. }
  7920. if (dst) {
  7921. if ($.isArray(dst)) {
  7922. if (dst.length != 1) {
  7923. return -1;
  7924. }
  7925. dst = this.fm.file(dst[0]);
  7926. }
  7927. } else {
  7928. dst = this.fm.cwd();
  7929. }
  7930. return this.fm.clipboard().length && dst.mime == 'directory' && dst.write ? 0 : -1;
  7931. }
  7932. this.exec = function(dst) {
  7933. var self = this,
  7934. fm = self.fm,
  7935. dst = dst ? this.files(dst)[0] : fm.cwd(),
  7936. files = fm.clipboard(),
  7937. cnt = files.length,
  7938. cut = cnt ? files[0].cut : false,
  7939. error = cut ? 'errMove' : 'errCopy',
  7940. fpaste = [],
  7941. fcopy = [],
  7942. dfrd = $.Deferred()
  7943. .fail(function(error) {
  7944. error && fm.error(error);
  7945. }),
  7946. copy = function(files) {
  7947. return files.length && fm._commands.duplicate
  7948. ? fm.exec('duplicate', files)
  7949. : $.Deferred().resolve();
  7950. },
  7951. paste = function(files) {
  7952. var dfrd = $.Deferred(),
  7953. existed = [],
  7954. intersect = function(files, names) {
  7955. var ret = [],
  7956. i = files.length;
  7957. while (i--) {
  7958. $.inArray(files[i].name, names) !== -1 && ret.unshift(i);
  7959. }
  7960. return ret;
  7961. },
  7962. confirm = function(ndx) {
  7963. var i = existed[ndx],
  7964. file = files[i],
  7965. last = ndx == existed.length-1;
  7966. if (!file) {
  7967. return;
  7968. }
  7969. fm.confirm({
  7970. title : fm.i18n(cut ? 'moveFiles' : 'copyFiles'),
  7971. text : fm.i18n(['errExists', file.name, 'confirmRepl']),
  7972. all : !last,
  7973. accept : {
  7974. label : 'btnYes',
  7975. callback : function(all) {
  7976. !last && !all
  7977. ? confirm(++ndx)
  7978. : paste(files);
  7979. }
  7980. },
  7981. reject : {
  7982. label : 'btnNo',
  7983. callback : function(all) {
  7984. var i;
  7985. if (all) {
  7986. i = existed.length;
  7987. while (ndx < i--) {
  7988. files[existed[i]].remove = true
  7989. }
  7990. } else {
  7991. files[existed[ndx]].remove = true;
  7992. }
  7993. !last && !all
  7994. ? confirm(++ndx)
  7995. : paste(files);
  7996. }
  7997. },
  7998. cancel : {
  7999. label : 'btnCancel',
  8000. callback : function() {
  8001. dfrd.resolve();
  8002. }
  8003. }
  8004. })
  8005. },
  8006. valid = function(names) {
  8007. existed = intersect(files, names);
  8008. existed.length ? confirm(0) : paste(files);
  8009. },
  8010. paste = function(files) {
  8011. var files = $.map(files, function(file) { return !file.remove ? file : null } ),
  8012. cnt = files.length,
  8013. groups = {},
  8014. args = [],
  8015. src;
  8016. if (!cnt) {
  8017. return dfrd.resolve();
  8018. }
  8019. src = files[0].phash;
  8020. files = $.map(files, function(f) { return f.hash});
  8021. fm.request({
  8022. data : {cmd : 'paste', dst : dst.hash, targets : files, cut : cut ? 1 : 0, src : src},
  8023. notify : {type : cut ? 'move' : 'copy', cnt : cnt}
  8024. })
  8025. .always(function() {
  8026. dfrd.resolve();
  8027. fm.unlockfiles({files : files});
  8028. });
  8029. }
  8030. ;
  8031. if (self._disabled || !files.length) {
  8032. return dfrd.resolve();
  8033. }
  8034. if (fm.oldAPI) {
  8035. paste(files);
  8036. } else {
  8037. if (!fm.option('copyOverwrite')) {
  8038. paste(files);
  8039. } else {
  8040. dst.hash == fm.cwd().hash
  8041. ? valid($.map(fm.files(), function(file) { return file.phash == dst.hash ? file.name : null }))
  8042. : fm.request({
  8043. data : {cmd : 'ls', target : dst.hash},
  8044. notify : {type : 'prepare', cnt : 1, hideCnt : true},
  8045. preventFail : true
  8046. })
  8047. .always(function(data) {
  8048. valid(data.list || [])
  8049. });
  8050. }
  8051. }
  8052. return dfrd;
  8053. },
  8054. parents, fparents;
  8055. if (!cnt || !dst || dst.mime != 'directory') {
  8056. return dfrd.reject();
  8057. }
  8058. if (!dst.write) {
  8059. return dfrd.reject([error, files[0].name, 'errPerm']);
  8060. }
  8061. parents = fm.parents(dst.hash);
  8062. $.each(files, function(i, file) {
  8063. if (!file.read) {
  8064. return !dfrd.reject([error, files[0].name, 'errPerm']);
  8065. }
  8066. if (cut && file.locked) {
  8067. return !dfrd.reject(['errLocked', file.name]);
  8068. }
  8069. if ($.inArray(file.hash, parents) !== -1) {
  8070. return !dfrd.reject(['errCopyInItself', file.name]);
  8071. }
  8072. fparents = fm.parents(file.hash);
  8073. if ($.inArray(dst.hash, fparents) !== -1) {
  8074. if ($.map(fparents, function(h) { var d = fm.file(h); return d.phash == dst.hash && d.name == file.name ? d : null }).length) {
  8075. return !dfrd.reject(['errReplByChild', file.name]);
  8076. }
  8077. }
  8078. if (file.phash == dst.hash) {
  8079. fcopy.push(file.hash);
  8080. } else {
  8081. fpaste.push({
  8082. hash : file.hash,
  8083. phash : file.phash,
  8084. name : file.name
  8085. });
  8086. }
  8087. });
  8088. if (dfrd.state() == 'rejected') {
  8089. return dfrd;
  8090. }
  8091. return $.when(
  8092. copy(fcopy),
  8093. paste(fpaste)
  8094. ).always(function() {
  8095. cut && fm.clipboard([]);
  8096. });
  8097. }
  8098. }
  8099. /*
  8100. * File: /home/osc/elFinder-build/elFinder/js/commands/quicklook.js
  8101. */
  8102. /**
  8103. * @class elFinder command "quicklook"
  8104. * Fast preview for some files types
  8105. *
  8106. * @author Dmitry (dio) Levashov
  8107. **/
  8108. elFinder.prototype.commands.quicklook = function() {
  8109. var self = this,
  8110. fm = self.fm,
  8111. /**
  8112. * window closed state
  8113. *
  8114. * @type Number
  8115. **/
  8116. closed = 0,
  8117. /**
  8118. * window animated state
  8119. *
  8120. * @type Number
  8121. **/
  8122. animated = 1,
  8123. /**
  8124. * window opened state
  8125. *
  8126. * @type Number
  8127. **/
  8128. opened = 2,
  8129. /**
  8130. * window state
  8131. *
  8132. * @type Number
  8133. **/
  8134. state = closed,
  8135. /**
  8136. * next/prev event name (requied to cwd catch it)
  8137. *
  8138. * @type Number
  8139. **/
  8140. // keydown = fm.UA.Firefox || fm.UA.Opera ? 'keypress' : 'keydown',
  8141. /**
  8142. * navbar icon class
  8143. *
  8144. * @type Number
  8145. **/
  8146. navicon = 'elfinder-quicklook-navbar-icon',
  8147. /**
  8148. * navbar "fullscreen" icon class
  8149. *
  8150. * @type Number
  8151. **/
  8152. fullscreen = 'elfinder-quicklook-fullscreen',
  8153. /**
  8154. * Triger keydown/keypress event with left/right arrow key code
  8155. *
  8156. * @param Number left/right arrow key code
  8157. * @return void
  8158. **/
  8159. navtrigger = function(code) {
  8160. $(document).trigger($.Event('keydown', { keyCode: code, ctrlKey : false, shiftKey : false, altKey : false, metaKey : false }));
  8161. },
  8162. /**
  8163. * Return css for closed window
  8164. *
  8165. * @param jQuery file node in cwd
  8166. * @return void
  8167. **/
  8168. closedCss = function(node) {
  8169. return {
  8170. opacity : 0,
  8171. width : 20,//node.width(),
  8172. height : fm.view == 'list' ? 1 : 20,
  8173. top : node.offset().top+'px',
  8174. left : node.offset().left+'px'
  8175. }
  8176. },
  8177. /**
  8178. * Return css for opened window
  8179. *
  8180. * @return void
  8181. **/
  8182. openedCss = function() {
  8183. var win = $(window);
  8184. return {
  8185. opacity : 1,
  8186. width : width,
  8187. height : height,
  8188. top : parseInt((win.height() - height)/2 + win.scrollTop()),
  8189. left : parseInt((win.width() - width)/2 + win.scrollLeft())
  8190. }
  8191. },
  8192. support = function(codec) {
  8193. var media = document.createElement(codec.substr(0, codec.indexOf('/'))),
  8194. value = false;
  8195. try {
  8196. value = media.canPlayType && media.canPlayType(codec);
  8197. } catch (e) {
  8198. }
  8199. return value && value !== '' && value != 'no';
  8200. },
  8201. /**
  8202. * Opened window width (from config)
  8203. *
  8204. * @type Number
  8205. **/
  8206. width,
  8207. /**
  8208. * Opened window height (from config)
  8209. *
  8210. * @type Number
  8211. **/
  8212. height,
  8213. /**
  8214. * elFinder node
  8215. *
  8216. * @type jQuery
  8217. **/
  8218. parent,
  8219. /**
  8220. * elFinder current directory node
  8221. *
  8222. * @type jQuery
  8223. **/
  8224. cwd,
  8225. title = $('<div class="elfinder-quicklook-title"/>'),
  8226. icon = $('<div/>'),
  8227. info = $('<div class="elfinder-quicklook-info"/>'),//.hide(),
  8228. fsicon = $('<div class="'+navicon+' '+navicon+'-fullscreen"/>')
  8229. .mousedown(function(e) {
  8230. var win = self.window,
  8231. full = win.is('.'+fullscreen),
  8232. scroll = 'scroll.'+fm.namespace,
  8233. $window = $(window);
  8234. e.stopPropagation();
  8235. if (full) {
  8236. win.css(win.data('position')).unbind('mousemove');
  8237. $window.unbind(scroll).trigger(self.resize).unbind(self.resize);
  8238. navbar.unbind('mouseenter').unbind('mousemove');
  8239. } else {
  8240. win.data('position', {
  8241. left : win.css('left'),
  8242. top : win.css('top'),
  8243. width : win.width(),
  8244. height : win.height()
  8245. })
  8246. .css({
  8247. width : '100%',
  8248. height : '100%'
  8249. });
  8250. $(window).bind(scroll, function() {
  8251. win.css({
  8252. left : parseInt($(window).scrollLeft())+'px',
  8253. top : parseInt($(window).scrollTop()) +'px'
  8254. })
  8255. })
  8256. .bind(self.resize, function(e) {
  8257. self.preview.trigger('changesize');
  8258. })
  8259. .trigger(scroll)
  8260. .trigger(self.resize);
  8261. win.bind('mousemove', function(e) {
  8262. navbar.stop(true, true).show().delay(3000).fadeOut('slow');
  8263. })
  8264. .mousemove();
  8265. navbar.mouseenter(function() {
  8266. navbar.stop(true, true).show();
  8267. })
  8268. .mousemove(function(e) {
  8269. e.stopPropagation();
  8270. });
  8271. }
  8272. navbar.attr('style', '').draggable(full ? 'destroy' : {});
  8273. win.toggleClass(fullscreen);
  8274. $(this).toggleClass(navicon+'-fullscreen-off');
  8275. $.fn.resizable && parent.add(win).resizable(full ? 'enable' : 'disable').removeClass('ui-state-disabled');
  8276. }),
  8277. navbar = $('<div class="elfinder-quicklook-navbar"/>')
  8278. .append($('<div class="'+navicon+' '+navicon+'-prev"/>').mousedown(function() { navtrigger(37); }))
  8279. .append(fsicon)
  8280. .append($('<div class="'+navicon+' '+navicon+'-next"/>').mousedown(function() { navtrigger(39); }))
  8281. .append('<div class="elfinder-quicklook-navbar-separator"/>')
  8282. .append($('<div class="'+navicon+' '+navicon+'-close"/>').mousedown(function() { self.window.trigger('close'); }))
  8283. ;
  8284. this.resize = 'resize.'+fm.namespace;
  8285. this.info = $('<div class="elfinder-quicklook-info-wrapper"/>')
  8286. .append(icon)
  8287. .append(info);
  8288. this.preview = $('<div class="elfinder-quicklook-preview ui-helper-clearfix"/>')
  8289. // clean info/icon
  8290. .bind('change', function(e) {
  8291. self.info.attr('style', '').hide();
  8292. icon.removeAttr('class').attr('style', '');
  8293. info.html('');
  8294. })
  8295. // update info/icon
  8296. .bind('update', function(e) {
  8297. var fm = self.fm,
  8298. preview = self.preview,
  8299. file = e.file,
  8300. tpl = '<div class="elfinder-quicklook-info-data">{value}</div>',
  8301. tmb;
  8302. if (file) {
  8303. !file.read && e.stopImmediatePropagation();
  8304. self.window.data('hash', file.hash);
  8305. self.preview.unbind('changesize').trigger('change').children().remove();
  8306. title.html(fm.escape(file.name));
  8307. info.html(
  8308. tpl.replace(/\{value\}/, file.name)
  8309. + tpl.replace(/\{value\}/, fm.mime2kind(file))
  8310. + (file.mime == 'directory' ? '' : tpl.replace(/\{value\}/, fm.formatSize(file.size)))
  8311. + tpl.replace(/\{value\}/, fm.i18n('modify')+': '+ fm.formatDate(file))
  8312. )
  8313. icon.addClass('elfinder-cwd-icon ui-corner-all '+fm.mime2class(file.mime));
  8314. if (file.tmb) {
  8315. $('<img/>')
  8316. .hide()
  8317. .appendTo(self.preview)
  8318. .load(function() {
  8319. icon.css('background', 'url("'+tmb+'") center center no-repeat');
  8320. $(this).remove();
  8321. })
  8322. .attr('src', (tmb = fm.tmb(file.hash)));
  8323. }
  8324. self.info.delay(100).fadeIn(10);
  8325. } else {
  8326. e.stopImmediatePropagation();
  8327. }
  8328. });
  8329. this.window = $('<div class="ui-helper-reset ui-widget elfinder-quicklook" style="position:absolute"/>')
  8330. .click(function(e) { e.stopPropagation(); })
  8331. .append(
  8332. $('<div class="elfinder-quicklook-titlebar"/>')
  8333. .append(title)
  8334. .append($('<span class="ui-icon ui-icon-circle-close"/>').mousedown(function(e) {
  8335. e.stopPropagation();
  8336. self.window.trigger('close');
  8337. }))
  8338. )
  8339. .append(this.preview.add(navbar))
  8340. .append(self.info.hide())
  8341. .draggable({handle : 'div.elfinder-quicklook-titlebar'})
  8342. .bind('open', function(e) {
  8343. var win = self.window,
  8344. file = self.value,
  8345. node;
  8346. if (self.closed() && file && (node = cwd.find('#'+file.hash)).length) {
  8347. navbar.attr('style', '');
  8348. state = animated;
  8349. node.trigger('scrolltoview');
  8350. win.css(closedCss(node))
  8351. .show()
  8352. .animate(openedCss(), 550, function() {
  8353. state = opened;
  8354. self.update(1, self.value);
  8355. });
  8356. }
  8357. })
  8358. .bind('close', function(e) {
  8359. var win = self.window,
  8360. preview = self.preview.trigger('change'),
  8361. file = self.value,
  8362. node = cwd.find('#'+win.data('hash')),
  8363. close = function() {
  8364. state = closed;
  8365. win.hide();
  8366. preview.children().remove();
  8367. self.update(0, self.value);
  8368. };
  8369. if (self.opened()) {
  8370. state = animated;
  8371. win.is('.'+fullscreen) && fsicon.mousedown()
  8372. node.length
  8373. ? win.animate(closedCss(node), 500, close)
  8374. : close();
  8375. }
  8376. });
  8377. /**
  8378. * This command cannot be disable by backend
  8379. *
  8380. * @type Boolean
  8381. **/
  8382. this.alwaysEnabled = true;
  8383. /**
  8384. * Selected file
  8385. *
  8386. * @type Object
  8387. **/
  8388. this.value = null;
  8389. this.handlers = {
  8390. // save selected file
  8391. select : function() { this.update(void(0), this.fm.selectedFiles()[0]); },
  8392. error : function() { self.window.is(':visible') && self.window.data('hash', '').trigger('close'); },
  8393. 'searchshow searchhide' : function() { this.opened() && this.window.trigger('close'); }
  8394. }
  8395. this.shortcuts = [{
  8396. pattern : 'space'
  8397. }];
  8398. this.support = {
  8399. audio : {
  8400. ogg : support('audio/ogg; codecs="vorbis"'),
  8401. mp3 : support('audio/mpeg;'),
  8402. wav : support('audio/wav; codecs="1"'),
  8403. m4a : support('audio/x-m4a;') || support('audio/aac;')
  8404. },
  8405. video : {
  8406. ogg : support('video/ogg; codecs="theora"'),
  8407. webm : support('video/webm; codecs="vp8, vorbis"'),
  8408. mp4 : support('video/mp4; codecs="avc1.42E01E"') || support('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')
  8409. }
  8410. }
  8411. /**
  8412. * Return true if quickLoock window is visible and not animated
  8413. *
  8414. * @return Boolean
  8415. **/
  8416. this.closed = function() {
  8417. return state == closed;
  8418. }
  8419. /**
  8420. * Return true if quickLoock window is hidden
  8421. *
  8422. * @return Boolean
  8423. **/
  8424. this.opened = function() {
  8425. return state == opened;
  8426. }
  8427. /**
  8428. * Init command.
  8429. * Add default plugins and init other plugins
  8430. *
  8431. * @return Object
  8432. **/
  8433. this.init = function() {
  8434. var o = this.options,
  8435. win = this.window,
  8436. preview = this.preview,
  8437. i, p;
  8438. width = o.width > 0 ? parseInt(o.width) : 450;
  8439. height = o.height > 0 ? parseInt(o.height) : 300;
  8440. fm.one('load', function() {
  8441. parent = fm.getUI();
  8442. cwd = fm.getUI('cwd');
  8443. win.appendTo('body').zIndex(100 + parent.zIndex());
  8444. // close window on escape
  8445. $(document).keydown(function(e) {
  8446. e.keyCode == 27 && self.opened() && win.trigger('close')
  8447. })
  8448. if ($.fn.resizable) {
  8449. win.resizable({
  8450. handles : 'se',
  8451. minWidth : 350,
  8452. minHeight : 120,
  8453. resize : function() {
  8454. // use another event to avoid recursion in fullscreen mode
  8455. // may be there is clever solution, but i cant find it :(
  8456. preview.trigger('changesize');
  8457. }
  8458. });
  8459. }
  8460. self.change(function() {
  8461. if (self.opened()) {
  8462. self.value ? preview.trigger($.Event('update', {file : self.value})) : win.trigger('close');
  8463. }
  8464. });
  8465. $.each(fm.commands.quicklook.plugins || [], function(i, plugin) {
  8466. if (typeof(plugin) == 'function') {
  8467. new plugin(self)
  8468. }
  8469. });
  8470. preview.bind('update', function() {
  8471. self.info.show();
  8472. });
  8473. });
  8474. }
  8475. this.getstate = function() {
  8476. return this.fm.selected().length == 1 ? state == opened ? 1 : 0 : -1;
  8477. }
  8478. this.exec = function() {
  8479. this.enabled() && this.window.trigger(this.opened() ? 'close' : 'open');
  8480. }
  8481. this.hideinfo = function() {
  8482. this.info.stop(true).hide();
  8483. }
  8484. }
  8485. /*
  8486. * File: /home/osc/elFinder-build/elFinder/js/commands/quicklook.plugins.js
  8487. */
  8488. elFinder.prototype.commands.quicklook.plugins = [
  8489. /**
  8490. * Images preview plugin
  8491. *
  8492. * @param elFinder.commands.quicklook
  8493. **/
  8494. function(ql) {
  8495. var mimes = ['image/jpeg', 'image/png', 'image/gif'],
  8496. preview = ql.preview;
  8497. // what kind of images we can display
  8498. $.each(navigator.mimeTypes, function(i, o) {
  8499. var mime = o.type;
  8500. if (mime.indexOf('image/') === 0 && $.inArray(mime, mimes)) {
  8501. mimes.push(mime);
  8502. }
  8503. });
  8504. preview.bind('update', function(e) {
  8505. var file = e.file,
  8506. img;
  8507. if ($.inArray(file.mime, mimes) !== -1) {
  8508. // this is our file - stop event propagation
  8509. e.stopImmediatePropagation();
  8510. img = $('<img/>')
  8511. .hide()
  8512. .appendTo(preview)
  8513. .load(function() {
  8514. // timeout - because of strange safari bug -
  8515. // sometimes cant get image height 0_o
  8516. setTimeout(function() {
  8517. var prop = (img.width()/img.height()).toFixed(2);
  8518. preview.bind('changesize', function() {
  8519. var pw = parseInt(preview.width()),
  8520. ph = parseInt(preview.height()),
  8521. w, h;
  8522. if (prop < (pw/ph).toFixed(2)) {
  8523. h = ph;
  8524. w = Math.floor(h * prop);
  8525. } else {
  8526. w = pw;
  8527. h = Math.floor(w/prop);
  8528. }
  8529. img.width(w).height(h).css('margin-top', h < ph ? Math.floor((ph - h)/2) : 0);
  8530. })
  8531. .trigger('changesize');
  8532. // hide info/icon
  8533. ql.hideinfo();
  8534. //show image
  8535. img.fadeIn(100);
  8536. }, 1)
  8537. })
  8538. .attr('src', ql.fm.url(file.hash));
  8539. }
  8540. });
  8541. },
  8542. /**
  8543. * HTML preview plugin
  8544. *
  8545. * @param elFinder.commands.quicklook
  8546. **/
  8547. function(ql) {
  8548. var mimes = ['text/html', 'application/xhtml+xml'],
  8549. preview = ql.preview,
  8550. fm = ql.fm;
  8551. preview.bind('update', function(e) {
  8552. var file = e.file, jqxhr;
  8553. if ($.inArray(file.mime, mimes) !== -1) {
  8554. e.stopImmediatePropagation();
  8555. // stop loading on change file if not loaded yet
  8556. preview.one('change', function() {
  8557. jqxhr.state() == 'pending' && jqxhr.reject();
  8558. });
  8559. jqxhr = fm.request({
  8560. data : {cmd : 'get', target : file.hash, current : file.phash},
  8561. preventDefault : true
  8562. })
  8563. .done(function(data) {
  8564. ql.hideinfo();
  8565. doc = $('<iframe class="elfinder-quicklook-preview-html"/>').appendTo(preview)[0].contentWindow.document;
  8566. doc.open();
  8567. doc.write(data.content);
  8568. doc.close();
  8569. });
  8570. }
  8571. })
  8572. },
  8573. /**
  8574. * Texts preview plugin
  8575. *
  8576. * @param elFinder.commands.quicklook
  8577. **/
  8578. function(ql) {
  8579. var fm = ql.fm,
  8580. mimes = fm.res('mimes', 'text'),
  8581. preview = ql.preview;
  8582. preview.bind('update', function(e) {
  8583. var file = e.file,
  8584. mime = file.mime,
  8585. jqxhr;
  8586. if (mime.indexOf('text/') === 0 || $.inArray(mime, mimes) !== -1) {
  8587. e.stopImmediatePropagation();
  8588. // stop loading on change file if not loadin yet
  8589. preview.one('change', function() {
  8590. jqxhr.state() == 'pending' && jqxhr.reject();
  8591. });
  8592. jqxhr = fm.request({
  8593. data : {cmd : 'get', target : file.hash },
  8594. preventDefault : true
  8595. })
  8596. .done(function(data) {
  8597. ql.hideinfo();
  8598. $('<div class="elfinder-quicklook-preview-text-wrapper"><pre class="elfinder-quicklook-preview-text">'+fm.escape(data.content)+'</pre></div>').appendTo(preview);
  8599. });
  8600. }
  8601. });
  8602. },
  8603. /**
  8604. * PDF preview plugin
  8605. *
  8606. * @param elFinder.commands.quicklook
  8607. **/
  8608. function(ql) {
  8609. var fm = ql.fm,
  8610. mime = 'application/pdf',
  8611. preview = ql.preview,
  8612. active = false;
  8613. if ((fm.UA.Safari && fm.OS == 'mac') || fm.UA.IE) {
  8614. active = true;
  8615. } else {
  8616. $.each(navigator.plugins, function(i, plugins) {
  8617. $.each(plugins, function(i, plugin) {
  8618. if (plugin.type == mime) {
  8619. return !(active = true);
  8620. }
  8621. });
  8622. });
  8623. }
  8624. active && preview.bind('update', function(e) {
  8625. var file = e.file, node;
  8626. if (file.mime == mime) {
  8627. e.stopImmediatePropagation();
  8628. preview.one('change', function() {
  8629. node.unbind('load').remove();
  8630. });
  8631. node = $('<iframe class="elfinder-quicklook-preview-pdf"/>')
  8632. .hide()
  8633. .appendTo(preview)
  8634. .load(function() {
  8635. ql.hideinfo();
  8636. node.show();
  8637. })
  8638. .attr('src', fm.url(file.hash));
  8639. }
  8640. })
  8641. },
  8642. /**
  8643. * Flash preview plugin
  8644. *
  8645. * @param elFinder.commands.quicklook
  8646. **/
  8647. function(ql) {
  8648. var fm = ql.fm,
  8649. mime = 'application/x-shockwave-flash',
  8650. preview = ql.preview,
  8651. active = false;
  8652. $.each(navigator.plugins, function(i, plugins) {
  8653. $.each(plugins, function(i, plugin) {
  8654. if (plugin.type == mime) {
  8655. return !(active = true);
  8656. }
  8657. });
  8658. });
  8659. active && preview.bind('update', function(e) {
  8660. var file = e.file,
  8661. node;
  8662. if (file.mime == mime) {
  8663. e.stopImmediatePropagation();
  8664. ql.hideinfo();
  8665. preview.append((node = $('<embed class="elfinder-quicklook-preview-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" src="'+fm.url(file.hash)+'" quality="high" type="application/x-shockwave-flash" />')));
  8666. }
  8667. });
  8668. },
  8669. /**
  8670. * HTML5 audio preview plugin
  8671. *
  8672. * @param elFinder.commands.quicklook
  8673. **/
  8674. function(ql) {
  8675. var preview = ql.preview,
  8676. autoplay = !!ql.options['autoplay'],
  8677. mimes = {
  8678. 'audio/mpeg' : 'mp3',
  8679. 'audio/mpeg3' : 'mp3',
  8680. 'audio/mp3' : 'mp3',
  8681. 'audio/x-mpeg3' : 'mp3',
  8682. 'audio/x-mp3' : 'mp3',
  8683. 'audio/x-wav' : 'wav',
  8684. 'audio/wav' : 'wav',
  8685. 'audio/x-m4a' : 'm4a',
  8686. 'audio/aac' : 'm4a',
  8687. 'audio/mp4' : 'm4a',
  8688. 'audio/x-mp4' : 'm4a',
  8689. 'audio/ogg' : 'ogg'
  8690. },
  8691. node;
  8692. preview.bind('update', function(e) {
  8693. var file = e.file,
  8694. type = mimes[file.mime];
  8695. if (ql.support.audio[type]) {
  8696. e.stopImmediatePropagation();
  8697. node = $('<audio class="elfinder-quicklook-preview-audio" controls preload="auto" autobuffer><source src="'+ql.fm.url(file.hash)+'" /></audio>')
  8698. .appendTo(preview);
  8699. autoplay && node[0].play();
  8700. }
  8701. }).bind('change', function() {
  8702. if (node && node.parent().length) {
  8703. node[0].pause();
  8704. node.remove();
  8705. node= null;
  8706. }
  8707. });
  8708. },
  8709. /**
  8710. * HTML5 video preview plugin
  8711. *
  8712. * @param elFinder.commands.quicklook
  8713. **/
  8714. function(ql) {
  8715. var preview = ql.preview,
  8716. autoplay = !!ql.options['autoplay'],
  8717. mimes = {
  8718. 'video/mp4' : 'mp4',
  8719. 'video/x-m4v' : 'mp4',
  8720. 'video/ogg' : 'ogg',
  8721. 'application/ogg' : 'ogg',
  8722. 'video/webm' : 'webm'
  8723. },
  8724. node;
  8725. preview.bind('update', function(e) {
  8726. var file = e.file,
  8727. type = mimes[file.mime];
  8728. if (ql.support.video[type]) {
  8729. e.stopImmediatePropagation();
  8730. ql.hideinfo();
  8731. node = $('<video class="elfinder-quicklook-preview-video" controls preload="auto" autobuffer><source src="'+ql.fm.url(file.hash)+'" /></video>').appendTo(preview);
  8732. autoplay && node[0].play();
  8733. }
  8734. }).bind('change', function() {
  8735. if (node && node.parent().length) {
  8736. node[0].pause();
  8737. node.remove();
  8738. node= null;
  8739. }
  8740. });
  8741. },
  8742. /**
  8743. * Audio/video preview plugin using browser plugins
  8744. *
  8745. * @param elFinder.commands.quicklook
  8746. **/
  8747. function(ql) {
  8748. var preview = ql.preview,
  8749. mimes = [],
  8750. node;
  8751. $.each(navigator.plugins, function(i, plugins) {
  8752. $.each(plugins, function(i, plugin) {
  8753. (plugin.type.indexOf('audio/') === 0 || plugin.type.indexOf('video/') === 0) && mimes.push(plugin.type);
  8754. });
  8755. });
  8756. preview.bind('update', function(e) {
  8757. var file = e.file,
  8758. mime = file.mime,
  8759. video;
  8760. if ($.inArray(file.mime, mimes) !== -1) {
  8761. e.stopImmediatePropagation();
  8762. (video = mime.indexOf('video/') === 0) && ql.hideinfo();
  8763. node = $('<embed src="'+ql.fm.url(file.hash)+'" type="'+mime+'" class="elfinder-quicklook-preview-'+(video ? 'video' : 'audio')+'"/>')
  8764. .appendTo(preview);
  8765. }
  8766. }).bind('change', function() {
  8767. if (node && node.parent().length) {
  8768. node.remove();
  8769. node= null;
  8770. }
  8771. });
  8772. }
  8773. ]
  8774. /*
  8775. * File: /home/osc/elFinder-build/elFinder/js/commands/reload.js
  8776. */
  8777. /**
  8778. * @class elFinder command "reload"
  8779. * Sync files and folders
  8780. *
  8781. * @author Dmitry (dio) Levashov
  8782. **/
  8783. elFinder.prototype.commands.reload = function() {
  8784. this.alwaysEnabled = true;
  8785. this.updateOnSelect = true;
  8786. this.shortcuts = [{
  8787. pattern : 'ctrl+shift+r f5'
  8788. }];
  8789. this.getstate = function() {
  8790. return 0;
  8791. }
  8792. this.exec = function() {
  8793. var fm = this.fm,
  8794. dfrd = fm.sync(),
  8795. timeout = setTimeout(function() {
  8796. fm.notify({type : 'reload', cnt : 1, hideCnt : true});
  8797. dfrd.always(function() { fm.notify({type : 'reload', cnt : -1}); });
  8798. }, fm.notifyDelay);
  8799. return dfrd.always(function() {
  8800. clearTimeout(timeout);
  8801. fm.trigger('reload');
  8802. });
  8803. }
  8804. }
  8805. /*
  8806. * File: /home/osc/elFinder-build/elFinder/js/commands/rename.js
  8807. */
  8808. /**
  8809. * @class elFinder command "rename".
  8810. * Rename selected file.
  8811. *
  8812. * @author Dmitry (dio) Levashov, dio@std42.ru
  8813. **/
  8814. elFinder.prototype.commands.rename = function() {
  8815. this.shortcuts = [{
  8816. pattern : 'f2'+(this.fm.OS == 'mac' ? ' enter' : '')
  8817. }];
  8818. this.getstate = function() {
  8819. var sel = this.fm.selectedFiles();
  8820. return !this._disabled && sel.length == 1 && sel[0].phash && !sel[0].locked ? 0 : -1;
  8821. }
  8822. this.exec = function() {
  8823. var fm = this.fm,
  8824. cwd = fm.getUI('cwd'),
  8825. sel = fm.selected(),
  8826. cnt = sel.length,
  8827. file = fm.file(sel.shift()),
  8828. filename = '.elfinder-cwd-filename',
  8829. dfrd = $.Deferred()
  8830. .fail(function(error) {
  8831. var parent = input.parent(),
  8832. name = fm.escape(file.name);
  8833. if (parent.length) {
  8834. input.remove();
  8835. parent.html(name);
  8836. } else {
  8837. cwd.find('#'+file.hash).find(filename).html(name);
  8838. setTimeout(function() {
  8839. cwd.find('#'+file.hash).click();
  8840. }, 50);
  8841. }
  8842. error && fm.error(error);
  8843. })
  8844. .always(function() {
  8845. fm.enable();
  8846. }),
  8847. input = $('<input type="text"/>')
  8848. .keydown(function(e) {
  8849. e.stopPropagation();
  8850. e.stopImmediatePropagation();
  8851. if (e.keyCode == $.ui.keyCode.ESCAPE) {
  8852. dfrd.reject();
  8853. } else if (e.keyCode == $.ui.keyCode.ENTER) {
  8854. input.blur();
  8855. }
  8856. })
  8857. .mousedown(function(e) {
  8858. e.stopPropagation();
  8859. })
  8860. .dblclick(function(e) {
  8861. e.stopPropagation();
  8862. e.preventDefault();
  8863. })
  8864. .blur(function() {
  8865. var name = $.trim(input.val()),
  8866. parent = input.parent();
  8867. if (parent.length) {
  8868. if (input[0].setSelectionRange) {
  8869. input[0].setSelectionRange(0, 0)
  8870. }
  8871. if (name == file.name) {
  8872. return dfrd.reject();
  8873. }
  8874. if (!name) {
  8875. return dfrd.reject('errInvName');
  8876. }
  8877. if (fm.fileByName(name, file.phash)) {
  8878. return dfrd.reject(['errExists', name]);
  8879. }
  8880. parent.html(fm.escape(name));
  8881. fm.lockfiles({files : [file.hash]});
  8882. fm.request({
  8883. data : {cmd : 'rename', target : file.hash, name : name},
  8884. notify : {type : 'rename', cnt : 1}
  8885. })
  8886. .fail(function(error) {
  8887. dfrd.reject();
  8888. fm.sync();
  8889. })
  8890. .done(function(data) {
  8891. dfrd.resolve(data);
  8892. })
  8893. .always(function() {
  8894. fm.unlockfiles({files : [file.hash]})
  8895. });
  8896. }
  8897. }),
  8898. node = cwd.find('#'+file.hash).find(filename).empty().append(input.val(file.name)),
  8899. name = input.val().replace(/\.((tar\.(gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(gz|bz2)|[a-z0-9]{1,4})$/ig, '')
  8900. ;
  8901. if (this.disabled()) {
  8902. return dfrd.reject();
  8903. }
  8904. if (!file || cnt > 1 || !node.length) {
  8905. return dfrd.reject('errCmdParams', this.title);
  8906. }
  8907. if (file.locked) {
  8908. return dfrd.reject(['errLocked', file.name]);
  8909. }
  8910. fm.one('select', function() {
  8911. input.parent().length && file && $.inArray(file.hash, fm.selected()) === -1 && input.blur();
  8912. })
  8913. input.select().focus();
  8914. input[0].setSelectionRange && input[0].setSelectionRange(0, name.length);
  8915. return dfrd;
  8916. }
  8917. }
  8918. /*
  8919. * File: /home/osc/elFinder-build/elFinder/js/commands/resize.js
  8920. */
  8921. /**
  8922. * @class elFinder command "resize"
  8923. * Open dialog to resize image
  8924. *
  8925. * @author Dmitry (dio) Levashov
  8926. * @author Alexey Sukhotin
  8927. * @author Naoki Sawada
  8928. * @author Sergio Jovani
  8929. **/
  8930. elFinder.prototype.commands.resize = function() {
  8931. this.updateOnSelect = false;
  8932. this.getstate = function() {
  8933. var sel = this.fm.selectedFiles();
  8934. return !this._disabled && sel.length == 1 && sel[0].read && sel[0].write && sel[0].mime.indexOf('image/') !== -1 ? 0 : -1;
  8935. };
  8936. this.exec = function(hashes) {
  8937. var fm = this.fm,
  8938. files = this.files(hashes),
  8939. dfrd = $.Deferred(),
  8940. open = function(file, id) {
  8941. var dialog = $('<div class="elfinder-dialog-resize"/>'),
  8942. input = '<input type="text" size="5"/>',
  8943. row = '<div class="elfinder-resize-row"/>',
  8944. label = '<div class="elfinder-resize-label"/>',
  8945. control = $('<div class="elfinder-resize-control"/>'),
  8946. preview = $('<div class="elfinder-resize-preview"/>'),
  8947. spinner = $('<div class="elfinder-resize-spinner">'+fm.i18n('ntfloadimg')+'</div>'),
  8948. rhandle = $('<div class="elfinder-resize-handle"/>'),
  8949. rhandlec = $('<div class="elfinder-resize-handle"/>'),
  8950. uiresize = $('<div class="elfinder-resize-uiresize"/>'),
  8951. uicrop = $('<div class="elfinder-resize-uicrop"/>'),
  8952. uibuttonset = '<div class="ui-widget-content ui-corner-all elfinder-buttonset"/>',
  8953. uibutton = '<div class="ui-state-default elfinder-button"/>',
  8954. uiseparator = '<span class="ui-widget-content elfinder-toolbar-button-separator"/>',
  8955. uirotate = $('<div class="elfinder-resize-rotate"/>'),
  8956. uideg270 = $(uibutton).attr('title',fm.i18n('rotate-cw')).append($('<span class="elfinder-button-icon elfinder-button-icon-rotate-l"/>')
  8957. .click(function(){
  8958. rdegree = rdegree - 90;
  8959. rotate.update(rdegree);
  8960. })),
  8961. uideg90 = $(uibutton).attr('title',fm.i18n('rotate-ccw')).append($('<span class="elfinder-button-icon elfinder-button-icon-rotate-r"/>')
  8962. .click(function(){
  8963. rdegree = rdegree + 90;
  8964. rotate.update(rdegree);
  8965. })),
  8966. uiprop = $('<span />'),
  8967. reset = $('<div class="ui-state-default ui-corner-all elfinder-resize-reset"><span class="ui-icon ui-icon-arrowreturnthick-1-w"/></div>'),
  8968. uitype = $('<div class="elfinder-resize-type"/>')
  8969. .append('<input type="radio" name="type" id="'+id+'-resize" value="resize" checked="checked" /><label for="'+id+'-resize">'+fm.i18n('resize')+'</label>')
  8970. .append('<input type="radio" name="type" id="'+id+'-crop" value="crop" /><label for="'+id+'-crop">'+fm.i18n('crop')+'</label>')
  8971. .append('<input type="radio" name="type" id="'+id+'-rotate" value="rotate" /><label for="'+id+'-rotate">'+fm.i18n('rotate')+'</label>'),
  8972. type = $('input', uitype).attr('disabled', 'disabled')
  8973. .change(function() {
  8974. var val = $('input:checked', uitype).val();
  8975. resetView();
  8976. resizable(true);
  8977. croppable(true);
  8978. rotateable(true);
  8979. if (val == 'resize') {
  8980. uiresize.show();
  8981. uirotate.hide();
  8982. uicrop.hide();
  8983. resizable();
  8984. }
  8985. else if (val == 'crop') {
  8986. uirotate.hide();
  8987. uiresize.hide();
  8988. uicrop.show();
  8989. croppable();
  8990. } else if (val == 'rotate') {
  8991. uiresize.hide();
  8992. uicrop.hide();
  8993. uirotate.show();
  8994. rotateable();
  8995. }
  8996. }),
  8997. constr = $('<input type="checkbox" checked="checked"/>')
  8998. .change(function() {
  8999. cratio = !!constr.prop('checked');
  9000. resize.fixHeight();
  9001. resizable(true);
  9002. resizable();
  9003. }),
  9004. width = $(input)
  9005. .change(function() {
  9006. var w = parseInt(width.val()),
  9007. h = parseInt(cratio ? Math.round(w/ratio) : height.val());
  9008. if (w > 0 && h > 0) {
  9009. resize.updateView(w, h);
  9010. height.val(h);
  9011. }
  9012. }),
  9013. height = $(input)
  9014. .change(function() {
  9015. var h = parseInt(height.val()),
  9016. w = parseInt(cratio ? Math.round(h*ratio) : width.val());
  9017. if (w > 0 && h > 0) {
  9018. resize.updateView(w, h);
  9019. width.val(w);
  9020. }
  9021. }),
  9022. pointX = $(input).change(function(){crop.updateView();}),
  9023. pointY = $(input).change(function(){crop.updateView();}),
  9024. offsetX = $(input).change(function(){crop.updateView();}),
  9025. offsetY = $(input).change(function(){crop.updateView();}),
  9026. degree = $('<input type="text" size="3" maxlength="3" value="0" />')
  9027. .change(function() {
  9028. rotate.update();
  9029. }),
  9030. uidegslider = $('<div class="elfinder-resize-rotate-slider"/>')
  9031. .slider({
  9032. min: 0,
  9033. max: 359,
  9034. value: degree.val(),
  9035. animate: true,
  9036. change: function(event, ui) {
  9037. if (ui.value != uidegslider.slider('value')) {
  9038. rotate.update(ui.value);
  9039. }
  9040. },
  9041. slide: function(event, ui) {
  9042. rotate.update(ui.value, false);
  9043. }
  9044. }),
  9045. ratio = 1,
  9046. prop = 1,
  9047. owidth = 0,
  9048. oheight = 0,
  9049. cratio = true,
  9050. pwidth = 0,
  9051. pheight = 0,
  9052. rwidth = 0,
  9053. rheight = 0,
  9054. rdegree = 0,
  9055. img = $('<img/>')
  9056. .load(function() {
  9057. spinner.remove();
  9058. owidth = img.width();
  9059. oheight = img.height();
  9060. ratio = owidth/oheight;
  9061. resize.updateView(owidth, oheight);
  9062. rhandle.append(img.show()).show();
  9063. width.val(owidth);
  9064. height.val(oheight);
  9065. var r_scale = Math.min(pwidth, pheight) / Math.sqrt(Math.pow(owidth, 2) + Math.pow(oheight, 2));
  9066. rwidth = owidth * r_scale;
  9067. rheight = oheight * r_scale;
  9068. type.button('enable');
  9069. control.find('input,select').removeAttr('disabled')
  9070. .filter(':text').keydown(function(e) {
  9071. var c = e.keyCode, i;
  9072. e.stopPropagation();
  9073. if ((c >= 37 && c <= 40)
  9074. || c == $.ui.keyCode.BACKSPACE
  9075. || c == $.ui.keyCode.DELETE
  9076. || (c == 65 && (e.ctrlKey||e.metaKey))
  9077. || c == 27) {
  9078. return;
  9079. }
  9080. if (c == 9) {
  9081. i = $(this).parent()[e.shiftKey ? 'prev' : 'next']('.elfinder-resize-row').children(':text');
  9082. if (i.length) {
  9083. i.focus();
  9084. } else {
  9085. $(this).parent().parent().find(':text:' + (e.shiftKey ? 'last' : 'first')).focus();
  9086. }
  9087. }
  9088. if (c == 13) {
  9089. fm.confirm({
  9090. title : $('input:checked', uitype).val(),
  9091. text : 'confirmReq',
  9092. accept : {
  9093. label : 'btnApply',
  9094. callback : function() {
  9095. save();
  9096. }
  9097. },
  9098. cancel : {
  9099. label : 'btnCancel',
  9100. callback : function(){}
  9101. }
  9102. });
  9103. return;
  9104. }
  9105. if (!((c >= 48 && c <= 57) || (c >= 96 && c <= 105))) {
  9106. e.preventDefault();
  9107. }
  9108. })
  9109. .filter(':first').focus();
  9110. resizable();
  9111. reset.hover(function() { reset.toggleClass('ui-state-hover'); }).click(resetView);
  9112. })
  9113. .error(function() {
  9114. spinner.text('Unable to load image').css('background', 'transparent');
  9115. }),
  9116. basec = $('<div/>'),
  9117. imgc = $('<img/>'),
  9118. coverc = $('<div/>'),
  9119. imgr = $('<img/>'),
  9120. resetView = function() {
  9121. width.val(owidth);
  9122. height.val(oheight);
  9123. resize.updateView(owidth, oheight);
  9124. },
  9125. resize = {
  9126. update : function() {
  9127. width.val(Math.round(img.width()/prop));
  9128. height.val(Math.round(img.height()/prop));
  9129. },
  9130. updateView : function(w, h) {
  9131. if (w > pwidth || h > pheight) {
  9132. if (w / pwidth > h / pheight) {
  9133. prop = pwidth / w;
  9134. img.width(pwidth).height(Math.ceil(h*prop));
  9135. } else {
  9136. prop = pheight / h;
  9137. img.height(pheight).width(Math.ceil(w*prop));
  9138. }
  9139. } else {
  9140. img.width(w).height(h);
  9141. }
  9142. prop = img.width()/w;
  9143. uiprop.text('1 : '+(1/prop).toFixed(2));
  9144. resize.updateHandle();
  9145. },
  9146. updateHandle : function() {
  9147. rhandle.width(img.width()).height(img.height());
  9148. },
  9149. fixWidth : function() {
  9150. var w, h;
  9151. if (cratio) {
  9152. h = height.val();
  9153. h = Math.round(h*ratio);
  9154. resize.updateView(w, h);
  9155. width.val(w);
  9156. }
  9157. },
  9158. fixHeight : function() {
  9159. var w, h;
  9160. if (cratio) {
  9161. w = width.val();
  9162. h = Math.round(w/ratio);
  9163. resize.updateView(w, h);
  9164. height.val(h);
  9165. }
  9166. }
  9167. },
  9168. crop = {
  9169. update : function() {
  9170. offsetX.val(Math.round((rhandlec.data('w')||rhandlec.width())/prop));
  9171. offsetY.val(Math.round((rhandlec.data('h')||rhandlec.height())/prop));
  9172. pointX.val(Math.round(((rhandlec.data('x')||rhandlec.offset().left)-imgc.offset().left)/prop));
  9173. pointY.val(Math.round(((rhandlec.data('y')||rhandlec.offset().top)-imgc.offset().top)/prop));
  9174. },
  9175. updateView : function() {
  9176. var x = parseInt(pointX.val()) * prop + imgc.offset().left;
  9177. var y = parseInt(pointY.val()) * prop + imgc.offset().top;
  9178. var w = offsetX.val() * prop;
  9179. var h = offsetY.val() * prop;
  9180. rhandlec.data({x: x, y: y, w: w, h: h});
  9181. rhandlec.width(Math.round(w));
  9182. rhandlec.height(Math.round(h));
  9183. coverc.width(rhandlec.width());
  9184. coverc.height(rhandlec.height());
  9185. rhandlec.offset({left: Math.round(x), top: Math.round(y)});
  9186. },
  9187. resize_update : function() {
  9188. rhandlec.data({w: null, h: null});
  9189. crop.update();
  9190. coverc.width(rhandlec.width());
  9191. coverc.height(rhandlec.height());
  9192. },
  9193. drag_update : function() {
  9194. rhandlec.data({x: null, y: null});
  9195. crop.update();
  9196. }
  9197. },
  9198. rotate = {
  9199. mouseStartAngle : 0,
  9200. imageStartAngle : 0,
  9201. imageBeingRotated : false,
  9202. update : function(value, animate) {
  9203. if (typeof value == 'undefined') {
  9204. rdegree = value = parseInt(degree.val());
  9205. }
  9206. if (typeof animate == 'undefined') {
  9207. animate = true;
  9208. }
  9209. if (! animate || fm.UA.Opera || fm.UA.ltIE8) {
  9210. imgr.rotate(value);
  9211. } else {
  9212. imgr.animate({rotate: value + 'deg'});
  9213. }
  9214. value = value % 360;
  9215. if (value < 0) {
  9216. value += 360;
  9217. }
  9218. degree.val(parseInt(value));
  9219. uidegslider.slider('value', degree.val());
  9220. },
  9221. execute : function ( e ) {
  9222. if ( !rotate.imageBeingRotated ) return;
  9223. var imageCentre = rotate.getCenter( imgr );
  9224. var mouseXFromCentre = e.pageX - imageCentre[0];
  9225. var mouseYFromCentre = e.pageY - imageCentre[1];
  9226. var mouseAngle = Math.atan2( mouseYFromCentre, mouseXFromCentre );
  9227. var rotateAngle = mouseAngle - rotate.mouseStartAngle + rotate.imageStartAngle;
  9228. rotateAngle = Math.round(parseFloat(rotateAngle) * 180 / Math.PI);
  9229. if ( e.shiftKey ) {
  9230. rotateAngle = Math.round((rotateAngle + 6)/15) * 15;
  9231. }
  9232. imgr.rotate(rotateAngle);
  9233. rotateAngle = rotateAngle % 360;
  9234. if (rotateAngle < 0) {
  9235. rotateAngle += 360;
  9236. }
  9237. degree.val(rotateAngle);
  9238. uidegslider.slider('value', degree.val());
  9239. return false;
  9240. },
  9241. start : function ( e ) {
  9242. rotate.imageBeingRotated = true;
  9243. var imageCentre = rotate.getCenter( imgr );
  9244. var mouseStartXFromCentre = e.pageX - imageCentre[0];
  9245. var mouseStartYFromCentre = e.pageY - imageCentre[1];
  9246. rotate.mouseStartAngle = Math.atan2( mouseStartYFromCentre, mouseStartXFromCentre );
  9247. rotate.imageStartAngle = parseFloat(imgr.rotate()) * Math.PI / 180.0;
  9248. $(document).mousemove( rotate.execute );
  9249. return false;
  9250. },
  9251. stop : function ( e ) {
  9252. if ( !rotate.imageBeingRotated ) return;
  9253. $(document).unbind( 'mousemove' , rotate.execute);
  9254. setTimeout( function() { rotate.imageBeingRotated = false; }, 10 );
  9255. return false;
  9256. },
  9257. getCenter : function ( image ) {
  9258. var currentRotation = imgr.rotate();
  9259. imgr.rotate(0);
  9260. var imageOffset = imgr.offset();
  9261. var imageCentreX = imageOffset.left + imgr.width() / 2;
  9262. var imageCentreY = imageOffset.top + imgr.height() / 2;
  9263. imgr.rotate(currentRotation);
  9264. return Array( imageCentreX, imageCentreY );
  9265. }
  9266. },
  9267. resizable = function(destroy) {
  9268. if ($.fn.resizable) {
  9269. if (destroy) {
  9270. rhandle.filter(':ui-resizable').resizable('destroy');
  9271. rhandle.hide();
  9272. }
  9273. else {
  9274. rhandle.show();
  9275. rhandle.resizable({
  9276. alsoResize : img,
  9277. aspectRatio : cratio,
  9278. resize : resize.update,
  9279. stop : resize.fixHeight
  9280. });
  9281. }
  9282. }
  9283. },
  9284. croppable = function(destroy) {
  9285. if ($.fn.draggable && $.fn.resizable) {
  9286. if (destroy) {
  9287. rhandlec.filter(':ui-resizable').resizable('destroy');
  9288. rhandlec.filter(':ui-draggable').draggable('destroy');
  9289. basec.hide();
  9290. }
  9291. else {
  9292. imgc
  9293. .width(img.width())
  9294. .height(img.height());
  9295. coverc
  9296. .width(img.width())
  9297. .height(img.height());
  9298. rhandlec
  9299. .width(imgc.width())
  9300. .height(imgc.height())
  9301. .offset(imgc.offset())
  9302. .resizable({
  9303. containment : basec,
  9304. resize : crop.resize_update,
  9305. handles : 'all'
  9306. })
  9307. .draggable({
  9308. handle : coverc,
  9309. containment : imgc,
  9310. drag : crop.drag_update
  9311. });
  9312. basec.show()
  9313. .width(img.width())
  9314. .height(img.height());
  9315. crop.update();
  9316. }
  9317. }
  9318. },
  9319. rotateable = function(destroy) {
  9320. if ($.fn.draggable && $.fn.resizable) {
  9321. if (destroy) {
  9322. imgr.hide();
  9323. }
  9324. else {
  9325. imgr.show()
  9326. .width(rwidth)
  9327. .height(rheight)
  9328. .css('margin-top', (pheight-rheight)/2 + 'px')
  9329. .css('margin-left', (pwidth-rwidth)/2 + 'px');
  9330. }
  9331. }
  9332. },
  9333. save = function() {
  9334. var w, h, x, y, d;
  9335. var mode = $('input:checked', uitype).val();
  9336. //width.add(height).change(); // may be unnecessary
  9337. if (mode == 'resize') {
  9338. w = parseInt(width.val()) || 0;
  9339. h = parseInt(height.val()) || 0;
  9340. } else if (mode == 'crop') {
  9341. w = parseInt(offsetX.val()) || 0;
  9342. h = parseInt(offsetY.val()) || 0;
  9343. x = parseInt(pointX.val()) || 0;
  9344. y = parseInt(pointY.val()) || 0;
  9345. } else if (mode == 'rotate') {
  9346. w = owidth;
  9347. h = oheight;
  9348. d = parseInt(degree.val()) || 0;
  9349. if (d < 0 || d > 360) {
  9350. return fm.error('Invalid rotate degree');
  9351. }
  9352. if (d == 0 || d == 360) {
  9353. return fm.error('Image dose not rotated');
  9354. }
  9355. }
  9356. if (mode != 'rotate') {
  9357. if (w <= 0 || h <= 0) {
  9358. return fm.error('Invalid image size');
  9359. }
  9360. if (w == owidth && h == oheight) {
  9361. return fm.error('Image size not changed');
  9362. }
  9363. }
  9364. dialog.elfinderdialog('close');
  9365. fm.request({
  9366. data : {
  9367. cmd : 'resize',
  9368. target : file.hash,
  9369. width : w,
  9370. height : h,
  9371. x : x,
  9372. y : y,
  9373. degree : d,
  9374. mode : mode
  9375. },
  9376. notify : {type : 'resize', cnt : 1}
  9377. })
  9378. .fail(function(error) {
  9379. dfrd.reject(error);
  9380. })
  9381. .done(function() {
  9382. dfrd.resolve();
  9383. });
  9384. },
  9385. buttons = {},
  9386. hline = 'elfinder-resize-handle-hline',
  9387. vline = 'elfinder-resize-handle-vline',
  9388. rpoint = 'elfinder-resize-handle-point',
  9389. src = fm.url(file.hash)
  9390. ;
  9391. imgr.mousedown( rotate.start );
  9392. $(document).mouseup( rotate.stop );
  9393. uiresize.append($(row).append($(label).text(fm.i18n('width'))).append(width).append(reset))
  9394. .append($(row).append($(label).text(fm.i18n('height'))).append(height))
  9395. .append($(row).append($('<label/>').text(fm.i18n('aspectRatio')).prepend(constr)))
  9396. .append($(row).append(fm.i18n('scale')+' ').append(uiprop));
  9397. uicrop.append($(row).append($(label).text('X')).append(pointX))
  9398. .append($(row).append($(label).text('Y')).append(pointY))
  9399. .append($(row).append($(label).text(fm.i18n('width'))).append(offsetX))
  9400. .append($(row).append($(label).text(fm.i18n('height'))).append(offsetY));
  9401. uirotate.append($(row)
  9402. .append($(label).text(fm.i18n('rotate')))
  9403. .append($('<div style="float:left; width: 130px;">')
  9404. .append($('<div style="float:left;">')
  9405. .append(degree)
  9406. .append($('<span/>').text(fm.i18n('degree')))
  9407. )
  9408. .append($(uibuttonset).append(uideg270).append($(uiseparator)).append(uideg90))
  9409. )
  9410. .append(uidegslider)
  9411. );
  9412. dialog.append(uitype);
  9413. control.append($(row))
  9414. .append(uiresize)
  9415. .append(uicrop.hide())
  9416. .append(uirotate.hide())
  9417. .find('input,select').attr('disabled', 'disabled');
  9418. rhandle.append('<div class="'+hline+' '+hline+'-top"/>')
  9419. .append('<div class="'+hline+' '+hline+'-bottom"/>')
  9420. .append('<div class="'+vline+' '+vline+'-left"/>')
  9421. .append('<div class="'+vline+' '+vline+'-right"/>')
  9422. .append('<div class="'+rpoint+' '+rpoint+'-e"/>')
  9423. .append('<div class="'+rpoint+' '+rpoint+'-se"/>')
  9424. .append('<div class="'+rpoint+' '+rpoint+'-s"/>');
  9425. preview.append(spinner).append(rhandle.hide()).append(img.hide());
  9426. rhandlec.css('position', 'absolute')
  9427. .append('<div class="'+hline+' '+hline+'-top"/>')
  9428. .append('<div class="'+hline+' '+hline+'-bottom"/>')
  9429. .append('<div class="'+vline+' '+vline+'-left"/>')
  9430. .append('<div class="'+vline+' '+vline+'-right"/>')
  9431. .append('<div class="'+rpoint+' '+rpoint+'-n"/>')
  9432. .append('<div class="'+rpoint+' '+rpoint+'-e"/>')
  9433. .append('<div class="'+rpoint+' '+rpoint+'-s"/>')
  9434. .append('<div class="'+rpoint+' '+rpoint+'-w"/>')
  9435. .append('<div class="'+rpoint+' '+rpoint+'-ne"/>')
  9436. .append('<div class="'+rpoint+' '+rpoint+'-se"/>')
  9437. .append('<div class="'+rpoint+' '+rpoint+'-sw"/>')
  9438. .append('<div class="'+rpoint+' '+rpoint+'-nw"/>');
  9439. preview.append(basec.css('position', 'absolute').hide().append(imgc).append(rhandlec.append(coverc)));
  9440. preview.append(imgr.hide());
  9441. preview.css('overflow', 'hidden');
  9442. dialog.append(preview).append(control);
  9443. buttons[fm.i18n('btnApply')] = save;
  9444. buttons[fm.i18n('btnCancel')] = function() { dialog.elfinderdialog('close'); };
  9445. fm.dialog(dialog, {
  9446. title : file.name,
  9447. width : 650,
  9448. resizable : false,
  9449. destroyOnClose : true,
  9450. buttons : buttons,
  9451. open : function() { preview.zIndex(1+$(this).parent().zIndex()); }
  9452. }).attr('id', id);
  9453. // for IE < 9 dialog mising at open second+ time.
  9454. if (fm.UA.ltIE8) {
  9455. $('.elfinder-dialog').css('filter', '');
  9456. }
  9457. reset.css('left', width.position().left + width.width() + 12);
  9458. coverc.css({ 'opacity': 0.2, 'background-color': '#fff', 'position': 'absolute'}),
  9459. rhandlec.css('cursor', 'move');
  9460. rhandlec.find('.elfinder-resize-handle-point').css({
  9461. 'background-color' : '#fff',
  9462. 'opacity': 0.5,
  9463. 'border-color':'#000'
  9464. });
  9465. imgr.css('cursor', 'pointer');
  9466. uitype.buttonset();
  9467. pwidth = preview.width() - (rhandle.outerWidth() - rhandle.width());
  9468. pheight = preview.height() - (rhandle.outerHeight() - rhandle.height());
  9469. img.attr('src', src + (src.indexOf('?') === -1 ? '?' : '&')+'_='+Math.random());
  9470. imgc.attr('src', img.attr('src'));
  9471. imgr.attr('src', img.attr('src'));
  9472. },
  9473. id, dialog
  9474. ;
  9475. if (!files.length || files[0].mime.indexOf('image/') === -1) {
  9476. return dfrd.reject();
  9477. }
  9478. id = 'resize-'+fm.namespace+'-'+files[0].hash;
  9479. dialog = fm.getUI().find('#'+id);
  9480. if (dialog.length) {
  9481. dialog.elfinderdialog('toTop');
  9482. return dfrd.resolve();
  9483. }
  9484. open(files[0], id);
  9485. return dfrd;
  9486. };
  9487. };
  9488. (function ($) {
  9489. var findProperty = function (styleObject, styleArgs) {
  9490. var i = 0 ;
  9491. for( i in styleArgs) {
  9492. if (typeof styleObject[styleArgs[i]] != 'undefined')
  9493. return styleArgs[i];
  9494. }
  9495. styleObject[styleArgs[i]] = '';
  9496. return styleArgs[i];
  9497. };
  9498. $.cssHooks.rotate = {
  9499. get: function(elem, computed, extra) {
  9500. return $(elem).rotate();
  9501. },
  9502. set: function(elem, value) {
  9503. $(elem).rotate(value);
  9504. return value;
  9505. }
  9506. };
  9507. $.cssHooks.transform = {
  9508. get: function(elem, computed, extra) {
  9509. var name = findProperty( elem.style ,
  9510. ['WebkitTransform', 'MozTransform', 'OTransform' , 'msTransform' , 'transform'] );
  9511. return elem.style[name];
  9512. },
  9513. set: function(elem, value) {
  9514. var name = findProperty( elem.style ,
  9515. ['WebkitTransform', 'MozTransform', 'OTransform' , 'msTransform' , 'transform'] );
  9516. elem.style[name] = value;
  9517. return value;
  9518. }
  9519. };
  9520. $.fn.rotate = function(val) {
  9521. if (typeof val == 'undefined') {
  9522. if (!!window.opera) {
  9523. var r = this.css('transform').match(/rotate\((.*?)\)/);
  9524. return ( r && r[1])?
  9525. Math.round(parseFloat(r[1]) * 180 / Math.PI) : 0;
  9526. } else {
  9527. var r = this.css('transform').match(/rotate\((.*?)\)/);
  9528. return ( r && r[1])? parseInt(r[1]) : 0;
  9529. }
  9530. }
  9531. this.css('transform',
  9532. this.css('transform').replace(/none|rotate\(.*?\)/, '') + 'rotate(' + parseInt(val) + 'deg)');
  9533. return this;
  9534. };
  9535. $.fx.step.rotate = function(fx) {
  9536. if ( fx.state == 0 ) {
  9537. fx.start = $(fx.elem).rotate();
  9538. fx.now = fx.start;
  9539. }
  9540. $(fx.elem).rotate(fx.now);
  9541. };
  9542. if (typeof window.addEventListener == "undefined" && typeof document.getElementsByClassName == "undefined") { // IE & IE<9
  9543. var GetAbsoluteXY = function(element) {
  9544. var pnode = element;
  9545. var x = pnode.offsetLeft;
  9546. var y = pnode.offsetTop;
  9547. while ( pnode.offsetParent ) {
  9548. pnode = pnode.offsetParent;
  9549. if (pnode != document.body && pnode.currentStyle['position'] != 'static') {
  9550. break;
  9551. }
  9552. if (pnode != document.body && pnode != document.documentElement) {
  9553. x -= pnode.scrollLeft;
  9554. y -= pnode.scrollTop;
  9555. }
  9556. x += pnode.offsetLeft;
  9557. y += pnode.offsetTop;
  9558. }
  9559. return { x: x, y: y };
  9560. };
  9561. var StaticToAbsolute = function (element) {
  9562. if ( element.currentStyle['position'] != 'static') {
  9563. return ;
  9564. }
  9565. var xy = GetAbsoluteXY(element);
  9566. element.style.position = 'absolute' ;
  9567. element.style.left = xy.x + 'px';
  9568. element.style.top = xy.y + 'px';
  9569. };
  9570. var IETransform = function(element,transform){
  9571. var r;
  9572. var m11 = 1;
  9573. var m12 = 1;
  9574. var m21 = 1;
  9575. var m22 = 1;
  9576. if (typeof element.style['msTransform'] != 'undefined'){
  9577. return true;
  9578. }
  9579. StaticToAbsolute(element);
  9580. r = transform.match(/rotate\((.*?)\)/);
  9581. var rotate = ( r && r[1]) ? parseInt(r[1]) : 0;
  9582. rotate = rotate % 360;
  9583. if (rotate < 0) rotate = 360 + rotate;
  9584. var radian= rotate * Math.PI / 180;
  9585. var cosX =Math.cos(radian);
  9586. var sinY =Math.sin(radian);
  9587. m11 *= cosX;
  9588. m12 *= -sinY;
  9589. m21 *= sinY;
  9590. m22 *= cosX;
  9591. element.style.filter = (element.style.filter || '').replace(/progid:DXImageTransform\.Microsoft\.Matrix\([^)]*\)/, "" ) +
  9592. ("progid:DXImageTransform.Microsoft.Matrix(" +
  9593. "M11=" + m11 +
  9594. ",M12=" + m12 +
  9595. ",M21=" + m21 +
  9596. ",M22=" + m22 +
  9597. ",FilterType='bilinear',sizingMethod='auto expand')")
  9598. ;
  9599. var ow = parseInt(element.style.width || element.width || 0 );
  9600. var oh = parseInt(element.style.height || element.height || 0 );
  9601. var radian = rotate * Math.PI / 180;
  9602. var absCosX =Math.abs(Math.cos(radian));
  9603. var absSinY =Math.abs(Math.sin(radian));
  9604. var dx = (ow - (ow * absCosX + oh * absSinY)) / 2;
  9605. var dy = (oh - (ow * absSinY + oh * absCosX)) / 2;
  9606. element.style.marginLeft = Math.floor(dx) + "px";
  9607. element.style.marginTop = Math.floor(dy) + "px";
  9608. return(true);
  9609. };
  9610. var transform_set = $.cssHooks.transform.set;
  9611. $.cssHooks.transform.set = function(elem, value) {
  9612. transform_set.apply(this, [elem, value] );
  9613. IETransform(elem,value);
  9614. return value;
  9615. };
  9616. }
  9617. })(jQuery);
  9618. /*
  9619. * File: /home/osc/elFinder-build/elFinder/js/commands/rm.js
  9620. */
  9621. /**
  9622. * @class elFinder command "rm"
  9623. * Delete files
  9624. *
  9625. * @author Dmitry (dio) Levashov
  9626. **/
  9627. elFinder.prototype.commands.rm = function() {
  9628. this.shortcuts = [{
  9629. pattern : 'delete ctrl+backspace'
  9630. }];
  9631. this.getstate = function(sel) {
  9632. var fm = this.fm;
  9633. sel = sel || fm.selected();
  9634. return !this._disabled && sel.length && $.map(sel, function(h) { var f = fm.file(h); return f && f.phash && !f.locked ? h : null }).length == sel.length
  9635. ? 0 : -1;
  9636. }
  9637. this.exec = function(hashes) {
  9638. var self = this,
  9639. fm = this.fm,
  9640. dfrd = $.Deferred()
  9641. .fail(function(error) {
  9642. error && fm.error(error);
  9643. }),
  9644. files = this.files(hashes),
  9645. cnt = files.length,
  9646. cwd = fm.cwd().hash,
  9647. goroot = false;
  9648. if (!cnt || this._disabled) {
  9649. return dfrd.reject();
  9650. }
  9651. $.each(files, function(i, file) {
  9652. if (!file.phash) {
  9653. return !dfrd.reject(['errRm', file.name, 'errPerm']);
  9654. }
  9655. if (file.locked) {
  9656. return !dfrd.reject(['errLocked', file.name]);
  9657. }
  9658. if (file.hash == cwd) {
  9659. goroot = fm.root(file.hash);
  9660. }
  9661. });
  9662. if (dfrd.state() == 'pending') {
  9663. files = this.hashes(hashes);
  9664. fm.confirm({
  9665. title : self.title,
  9666. text : 'confirmRm',
  9667. accept : {
  9668. label : 'btnRm',
  9669. callback : function() {
  9670. fm.lockfiles({files : files});
  9671. fm.request({
  9672. data : {cmd : 'rm', targets : files},
  9673. notify : {type : 'rm', cnt : cnt},
  9674. preventFail : true
  9675. })
  9676. .fail(function(error) {
  9677. dfrd.reject(error);
  9678. })
  9679. .done(function(data) {
  9680. dfrd.done(data);
  9681. goroot && fm.exec('open', goroot)
  9682. }
  9683. ).always(function() {
  9684. fm.unlockfiles({files : files});
  9685. });
  9686. }
  9687. },
  9688. cancel : {
  9689. label : 'btnCancel',
  9690. callback : function() { dfrd.reject(); }
  9691. }
  9692. });
  9693. }
  9694. return dfrd;
  9695. }
  9696. }
  9697. /*
  9698. * File: /home/osc/elFinder-build/elFinder/js/commands/search.js
  9699. */
  9700. /**
  9701. * @class elFinder command "search"
  9702. * Find files
  9703. *
  9704. * @author Dmitry (dio) Levashov
  9705. **/
  9706. elFinder.prototype.commands.search = function() {
  9707. this.title = 'Find files';
  9708. this.options = {ui : 'searchbutton'}
  9709. this.alwaysEnabled = true;
  9710. this.updateOnSelect = false;
  9711. /**
  9712. * Return command status.
  9713. * Search does not support old api.
  9714. *
  9715. * @return Number
  9716. **/
  9717. this.getstate = function() {
  9718. return 0;
  9719. }
  9720. /**
  9721. * Send search request to backend.
  9722. *
  9723. * @param String search string
  9724. * @return $.Deferred
  9725. **/
  9726. this.exec = function(q) {
  9727. var fm = this.fm;
  9728. if (typeof(q) == 'string' && q) {
  9729. fm.trigger('searchstart', {query : q});
  9730. return fm.request({
  9731. data : {cmd : 'search', q : q},
  9732. notify : {type : 'search', cnt : 1, hideCnt : true}
  9733. });
  9734. }
  9735. fm.getUI('toolbar').find('.'+fm.res('class', 'searchbtn')+' :text').focus();
  9736. return $.Deferred().reject();
  9737. }
  9738. }
  9739. /*
  9740. * File: /home/osc/elFinder-build/elFinder/js/commands/sort.js
  9741. */
  9742. /**
  9743. * @class elFinder command "sort"
  9744. * Change sort files rule
  9745. *
  9746. * @author Dmitry (dio) Levashov
  9747. **/
  9748. elFinder.prototype.commands.sort = function() {
  9749. /**
  9750. * Command options
  9751. *
  9752. * @type Object
  9753. */
  9754. this.options = {ui : 'sortbutton'};
  9755. this.getstate = function() {
  9756. return 0;
  9757. }
  9758. this.exec = function(hashes, sort) {
  9759. var fm = this.fm,
  9760. sort = $.extend({
  9761. type : fm.sortType,
  9762. order : fm.sortOrder,
  9763. stick : fm.sortStickFolders
  9764. }, sort);
  9765. this.fm.setSort(sort.type, sort.order, sort.stick);
  9766. return $.Deferred().resolve();
  9767. }
  9768. }
  9769. /*
  9770. * File: /home/osc/elFinder-build/elFinder/js/commands/up.js
  9771. */
  9772. /**
  9773. * @class elFinder command "up"
  9774. * Go into parent directory
  9775. *
  9776. * @author Dmitry (dio) Levashov
  9777. **/
  9778. elFinder.prototype.commands.up = function() {
  9779. this.alwaysEnabled = true;
  9780. this.updateOnSelect = false;
  9781. this.shortcuts = [{
  9782. pattern : 'ctrl+up'
  9783. }];
  9784. this.getstate = function() {
  9785. return this.fm.cwd().phash ? 0 : -1;
  9786. }
  9787. this.exec = function() {
  9788. return this.fm.cwd().phash ? this.fm.exec('open', this.fm.cwd().phash) : $.Deferred().reject();
  9789. }
  9790. }
  9791. /*
  9792. * File: /home/osc/elFinder-build/elFinder/js/commands/upload.js
  9793. */
  9794. /**
  9795. * @class elFinder command "upload"
  9796. * Upload files using iframe or XMLHttpRequest & FormData.
  9797. * Dialog allow to send files using drag and drop
  9798. *
  9799. * @type elFinder.command
  9800. * @author Dmitry (dio) Levashov
  9801. */
  9802. elFinder.prototype.commands.upload = function() {
  9803. var hover = this.fm.res('class', 'hover');
  9804. this.disableOnSearch = true;
  9805. this.updateOnSelect = false;
  9806. // Shortcut opens dialog
  9807. this.shortcuts = [{
  9808. pattern : 'ctrl+u'
  9809. }];
  9810. /**
  9811. * Return command state
  9812. *
  9813. * @return Number
  9814. **/
  9815. this.getstate = function() {
  9816. return !this._disabled && this.fm.cwd().write ? 0 : -1;
  9817. };
  9818. this.exec = function(data) {
  9819. var fm = this.fm,
  9820. upload = function(data) {
  9821. dialog.elfinderdialog('close');
  9822. fm.upload(data)
  9823. .fail(function(error) {
  9824. dfrd.reject(error);
  9825. })
  9826. .done(function(data) {
  9827. dfrd.resolve(data);
  9828. });
  9829. },
  9830. dfrd, dialog, input, button, dropbox, pastebox;
  9831. if (this.disabled()) {
  9832. return $.Deferred().reject();
  9833. }
  9834. if (data && (data.input || data.files)) {
  9835. return fm.upload(data);
  9836. }
  9837. dfrd = $.Deferred();
  9838. input = $('<input type="file" multiple="true"/>')
  9839. .change(function() {
  9840. upload({input : input[0]});
  9841. });
  9842. button = $('<div class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"><span class="ui-button-text">'+fm.i18n('selectForUpload')+'</span></div>')
  9843. .append($('<form/>').append(input))
  9844. .hover(function() {
  9845. button.toggleClass(hover)
  9846. });
  9847. dialog = $('<div class="elfinder-upload-dialog-wrapper"/>')
  9848. .append(button);
  9849. pastebox = $('<div class="ui-corner-all elfinder-upload-dropbox" contenteditable=true></div>')
  9850. .on('paste drop', function (evt) {
  9851. var e = evt.originalEvent || evt;
  9852. var files = [];
  9853. var file;
  9854. if (e.clipboardData && e.clipboardData.items && e.clipboardData.items.length){
  9855. for (var i=0; i < e.clipboardData.items.length; i++) {
  9856. if (e.clipboardData.items[i].kind == 'file') {
  9857. file = e.clipboardData.items[i].getAsFile();
  9858. files.push(file);
  9859. }
  9860. }
  9861. if (files.length) {
  9862. upload({files : files, type : 'files'});
  9863. return;
  9864. }
  9865. }
  9866. var my = e.target;
  9867. setTimeout(function () {
  9868. if (my.innerHTML) {
  9869. var src = my.innerHTML.replace(/<br[^>]*>/gi, ' ');
  9870. var type = src.match(/<[^>]+>/)? 'html' : 'text';
  9871. my.innerHTML = '';
  9872. upload({files : [ src ], type : type});
  9873. }
  9874. }, 1);
  9875. })
  9876. .on('dragenter mouseover', function(){
  9877. pastebox.addClass(hover);
  9878. })
  9879. .on('dragleave mouseout', function(){
  9880. pastebox.removeClass(hover);
  9881. });
  9882. if (fm.dragUpload) {
  9883. dropbox = $('<div class="ui-corner-all elfinder-upload-dropbox">'+fm.i18n('dropFiles')+'</div>')
  9884. .prependTo(dialog)
  9885. .after('<div class="elfinder-upload-dialog-or">'+fm.i18n('or')+'</div>')
  9886. .after(pastebox)
  9887. .after('<div>'+fm.i18n('dropFilesBrowser')+'</div>')
  9888. .after('<div class="elfinder-upload-dialog-or">'+fm.i18n('or')+'</div>')[0];
  9889. dropbox.addEventListener('dragenter', function(e) {
  9890. e.stopPropagation();
  9891. e.preventDefault();
  9892. $(dropbox).addClass(hover);
  9893. }, false);
  9894. dropbox.addEventListener('dragleave', function(e) {
  9895. e.stopPropagation();
  9896. e.preventDefault();
  9897. $(dropbox).removeClass(hover);
  9898. }, false);
  9899. dropbox.addEventListener('dragover', function(e) {
  9900. e.stopPropagation();
  9901. e.preventDefault();
  9902. $(dropbox).addClass(hover);
  9903. }, false);
  9904. dropbox.addEventListener('drop', function(e) {
  9905. e.stopPropagation();
  9906. e.preventDefault();
  9907. var file = false;
  9908. var type = '';
  9909. if (e.dataTransfer && e.dataTransfer.items && e.dataTransfer.items.length) {
  9910. file = e.dataTransfer.items;
  9911. type = 'data';
  9912. } else if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length) {
  9913. file = e.dataTransfer.files;
  9914. type = 'files';
  9915. } else if (e.dataTransfer.getData('text/html')) {
  9916. file = [ e.dataTransfer.getData('text/html') ];
  9917. type = 'html';
  9918. } else if (e.dataTransfer.getData('text')) {
  9919. file = [ e.dataTransfer.getData('text') ];
  9920. type = 'text';
  9921. }
  9922. if (file) {
  9923. upload({files : file, type : type});
  9924. }
  9925. }, false);
  9926. } else {
  9927. $('<div>'+fm.i18n('dropFilesBrowser')+'</div>')
  9928. .append(pastebox)
  9929. .prependTo(dialog)
  9930. .after('<div class="elfinder-upload-dialog-or">'+fm.i18n('or')+'</div>')[0];
  9931. }
  9932. fm.dialog(dialog, {
  9933. title : this.title,
  9934. modal : true,
  9935. resizable : false,
  9936. destroyOnClose : true
  9937. });
  9938. return dfrd;
  9939. };
  9940. };
  9941. /*
  9942. * File: /home/osc/elFinder-build/elFinder/js/commands/view.js
  9943. */
  9944. /**
  9945. * @class elFinder command "view"
  9946. * Change current directory view (icons/list)
  9947. *
  9948. * @author Dmitry (dio) Levashov
  9949. **/
  9950. elFinder.prototype.commands.view = function() {
  9951. this.value = this.fm.viewType;
  9952. this.alwaysEnabled = true;
  9953. this.updateOnSelect = false;
  9954. this.options = { ui : 'viewbutton'};
  9955. this.getstate = function() {
  9956. return 0;
  9957. }
  9958. this.exec = function() {
  9959. var value = this.fm.storage('view', this.value == 'list' ? 'icons' : 'list');
  9960. this.fm.viewchange();
  9961. this.update(void(0), value);
  9962. }
  9963. }
  9964. })(jQuery);