fl-slideshow.js 235 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641
  1. /**
  2. * Slideshow JS Bundle
  3. */
  4. YUI.add('fl-event-move', function(Y) {
  5. /**
  6. * Adds gesturemovevertical, gesturemoveverticalend, gesturemovehorizontal
  7. * and gesturemovehorizontalend events.
  8. *
  9. * @module fl-event-move
  10. */
  11. var _eventBase = {
  12. _isEndEvent: false,
  13. on: function(node, subscriber, ce)
  14. {
  15. if(this.type.indexOf('end') > -1) {
  16. this._isEndEvent = true;
  17. }
  18. subscriber._direction = this.type.replace('gesturemove', '').replace('end', '');
  19. if(window.navigator.msPointerEnabled) {
  20. subscriber._startHandle = node.on('MSPointerDown', this._onStart, this, node, subscriber, ce);
  21. subscriber._moveHandle = node.on('MSPointerMove', this._onMove, this, node, subscriber, ce);
  22. subscriber._endHandle = node.on('MSPointerUp', this._onEnd, this, node, subscriber, ce);
  23. }
  24. else {
  25. subscriber._startHandle = node.on('gesturemovestart', this._onStart, null, this, node, subscriber, ce);
  26. subscriber._moveHandle = node.on('gesturemove', this._onMove, null, this, node, subscriber, ce);
  27. subscriber._endHandle = node.on('gesturemoveend', this._onEnd, { standAlone: true }, this, node, subscriber, ce);
  28. }
  29. },
  30. detach: function(node, subscriber, ce)
  31. {
  32. subscriber._startHandle.detach();
  33. subscriber._startHandle = null;
  34. subscriber._moveHandle.detach();
  35. subscriber._moveHandle = null;
  36. subscriber._endHandle.detach();
  37. subscriber._endHandle = null;
  38. },
  39. _onStart: function(e, node, subscriber, ce)
  40. {
  41. subscriber._doMove = null;
  42. subscriber._startX = e.pageX;
  43. subscriber._startY = e.pageY;
  44. },
  45. _onMove: function(e, node, subscriber, ce)
  46. {
  47. if(this._checkDirection(e, subscriber)) {
  48. subscriber._doMove = true;
  49. }
  50. else {
  51. subscriber._doMove = false;
  52. }
  53. if(subscriber._doMove && !this._isEndEvent) {
  54. ce.fire(e);
  55. }
  56. },
  57. _onEnd: function(e, node, subscriber, ce)
  58. {
  59. if(subscriber._doMove && this._isEndEvent) {
  60. e.startPageX = subscriber._startX;
  61. e.startPageY = subscriber._startY;
  62. ce.fire(e);
  63. }
  64. subscriber._doMove = null;
  65. },
  66. _checkDirection: function(e, subscriber)
  67. {
  68. var xDelta = Math.abs(subscriber._startX - e.pageX),
  69. yDelta = Math.abs(subscriber._startY - e.pageY);
  70. if(yDelta > xDelta && subscriber._startY > e.pageY && subscriber._direction == 'vertical') {
  71. return true;
  72. }
  73. else if(yDelta > xDelta && subscriber._startY < e.pageY && subscriber._direction == 'vertical') {
  74. return true;
  75. }
  76. else if(yDelta < xDelta && subscriber._startX > e.pageX && subscriber._direction == 'horizontal') {
  77. return true;
  78. }
  79. else if(yDelta < xDelta && subscriber._startX < e.pageX && subscriber._direction == 'horizontal') {
  80. return true;
  81. }
  82. return false;
  83. }
  84. };
  85. /**
  86. * @event gesturemovevertical
  87. * @param type {String} "gesturemovevertical"
  88. * @param fn {Function} The method the event invokes.
  89. * @param ctx {Object} Context for the method the event invokes.
  90. */
  91. Y.Event.define('gesturemovevertical', _eventBase);
  92. /**
  93. * @event gesturemoveverticalend
  94. * @param type {String} "gesturemoveverticalend"
  95. * @param fn {Function} The method the event invokes.
  96. * @param ctx {Object} Context for the method the event invokes.
  97. */
  98. Y.Event.define('gesturemoveverticalend', _eventBase);
  99. /**
  100. * @event gesturemovehorizontal
  101. * @param type {String} "gesturemovehorizontal"
  102. * @param fn {Function} The method the event invokes.
  103. * @param ctx {Object} Context for the method the event invokes.
  104. */
  105. Y.Event.define('gesturemovehorizontal', _eventBase);
  106. /**
  107. * @event gesturemovehorizontalend
  108. * @param type {String} "gesturemovehorizontalend"
  109. * @param fn {Function} The method the event invokes.
  110. * @param ctx {Object} Context for the method the event invokes.
  111. */
  112. Y.Event.define('gesturemovehorizontalend', _eventBase);
  113. }, '2.0.0' ,{requires:['event-move']});
  114. YUI.add('fl-slideshow', function(Y) {
  115. /**
  116. * @module fl-slideshow
  117. */
  118. /**
  119. * Caption widget used in slideshows.
  120. *
  121. * @namespace FL
  122. * @class SlideshowCaption
  123. * @constructor
  124. * @param config {Object} Configuration object
  125. * @extends Widget
  126. */
  127. Y.namespace('FL').SlideshowCaption = Y.Base.create('fl-slideshow-caption', Y.Widget, [Y.WidgetChild], {
  128. /**
  129. * Flag for whether the text has been
  130. * toggled or not.
  131. *
  132. * @property _textToggled
  133. * @type Boolean
  134. * @default false
  135. * @protected
  136. */
  137. _textToggled: false,
  138. /**
  139. * An anchor node used for the toggle link.
  140. *
  141. * @property _textToggleLink
  142. * @type Object
  143. * @default null
  144. * @protected
  145. */
  146. _textToggleLink: null,
  147. /**
  148. * @method renderUI
  149. * @protected
  150. */
  151. renderUI: function()
  152. {
  153. var root = this.get('root'),
  154. bb = this.get('boundingBox');
  155. this._textToggleLink = Y.Node.create('<a href="javascript:void(0);"></a>');
  156. this._textToggleLink.addClass('fl-slideshow-caption-toggle');
  157. this._textToggleLink.set('innerHTML', root.get('captionMoreLinkText'));
  158. bb.appendChild(this._textToggleLink);
  159. },
  160. /**
  161. * @method bindUI
  162. * @protected
  163. */
  164. bindUI: function()
  165. {
  166. this.get('root').on('imageLoadComplete', Y.bind(this._setText, this));
  167. this._textToggleLink.on('click', Y.bind(this._toggleText, this));
  168. },
  169. /**
  170. * Sets the caption text and displays the
  171. * toggle link if necessary.
  172. *
  173. * @method _setText
  174. * @protected
  175. */
  176. _setText: function()
  177. {
  178. var root = this.get('root'),
  179. text = root.imageInfo.caption,
  180. textLength = root.get('captionTextLength'),
  181. cb = this.get('contentBox');
  182. if(!root.imageInfo.caption || root.imageInfo.caption === '') {
  183. cb.set('innerHTML', '');
  184. this._textToggleLink.setStyle('display', 'none');
  185. return;
  186. }
  187. else if(textLength > -1) {
  188. if(!this._textToggled && textLength < text.length) {
  189. text = this._shortenText(text);
  190. this._textToggleLink.setStyle('display', 'inline-block');
  191. }
  192. else if(this._textToggled && textLength < text.length) {
  193. text = this._stripTags(text);
  194. this._textToggleLink.setStyle('display', 'inline-block');
  195. }
  196. else {
  197. text = this._stripTags(text);
  198. this._textToggleLink.setStyle('display', 'none');
  199. }
  200. }
  201. else {
  202. text = this._stripTags(text);
  203. }
  204. cb.set('innerHTML', text);
  205. },
  206. /**
  207. * Shows or hides the full text when the
  208. * toggle link is clicked.
  209. *
  210. * @method _toggleText
  211. * @protected
  212. */
  213. _toggleText: function()
  214. {
  215. var root = this.get('root'),
  216. text = root.imageInfo.caption,
  217. cb = this.get('contentBox');
  218. if(this._textToggled) {
  219. text = this._shortenText(text);
  220. this._textToggleLink.set('innerHTML', root.get('captionMoreLinkText'));
  221. this._textToggled = false;
  222. }
  223. else {
  224. text = this._stripTags(text);
  225. this._textToggleLink.set('innerHTML', root.get('captionLessLinkText'));
  226. this._textToggled = true;
  227. }
  228. cb.set('innerHTML', text);
  229. },
  230. /**
  231. * Strips out HTML tags from the caption text.
  232. *
  233. * @method _stripTags
  234. * @param text {String} The text to strip HTML tags from.
  235. * @param ignoreSettings {Boolean} If true, will strip tags even if
  236. * the stripTags attribute is set to false.
  237. * @protected
  238. */
  239. _stripTags: function(text, ignoreSettings)
  240. {
  241. var root = this.get('root'), textDiv;
  242. if(ignoreSettings || root.get('captionStripTags')) {
  243. textDiv = document.createElement('div');
  244. textDiv.innerHTML = text;
  245. text = textDiv.textContent || textDiv.innerText;
  246. }
  247. return text;
  248. },
  249. /**
  250. * Shortens the caption text to the length of
  251. * the textLength attribute.
  252. *
  253. * @method _shortenText
  254. * @protected
  255. */
  256. _shortenText: function(text)
  257. {
  258. var root = this.get('root');
  259. text = this._stripTags(text, true).substring(0, root.get('captionTextLength'));
  260. return Y.Lang.trim(text.substring(0, text.lastIndexOf(' '))) + ' ...';
  261. }
  262. }, {
  263. /**
  264. * Custom CSS class name for the widget.
  265. *
  266. * @property CSS_PREFIX
  267. * @type String
  268. * @protected
  269. * @static
  270. */
  271. CSS_PREFIX: 'fl-slideshow-caption',
  272. /**
  273. * Static property used to define the default attribute configuration of
  274. * the Widget.
  275. *
  276. * @property ATTRS
  277. * @type Object
  278. * @protected
  279. * @static
  280. */
  281. ATTRS: {
  282. }
  283. });
  284. /**
  285. * A widget for loading and transitioning between SlideshowImage
  286. * instances. Each SlideshowImage instance is a child widget of
  287. * SlideshowFrame. SlideshowFrame is a child widget of the main
  288. * slideshow widget.
  289. *
  290. * @namespace FL
  291. * @class SlideshowFrame
  292. * @constructor
  293. * @param config {Object} Configuration object
  294. * @extends Widget
  295. */
  296. Y.namespace('FL').SlideshowFrame = Y.Base.create('fl-slideshow-frame', Y.Widget, [Y.WidgetParent, Y.WidgetChild], {
  297. /**
  298. * The imageInfo object used to load the active image.
  299. *
  300. * @property info
  301. * @type Object
  302. * @default null
  303. * @protected
  304. */
  305. _imageInfo: null,
  306. /**
  307. * The active FL.SlideshowImage instance in the frame.
  308. *
  309. * @property _activeImage
  310. * @type FL.SlideshowImage
  311. * @default null
  312. * @protected
  313. */
  314. _activeImage: null,
  315. /**
  316. * A FL.SlideshowImage instance used to load the
  317. * next image and transition it into the frame.
  318. *
  319. * @property _nextImage
  320. * @type FL.SlideshowImage
  321. * @default null
  322. * @protected
  323. */
  324. _nextImage: null,
  325. /**
  326. * Used to store imageInfo if a load request is
  327. * made while the frame is transitioning. If not null
  328. * when the transition completes, a new image will
  329. * be loaded using the imageInfo.
  330. *
  331. * @property _loadQueue
  332. * @type Object
  333. * @default false
  334. * @protected
  335. */
  336. _loadQueue: null,
  337. /**
  338. * An instance of FL.SlideshowTransition used for
  339. * the current transition in progress.
  340. *
  341. * @property _transition
  342. * @type FL.SlideshowTransition
  343. * @default null
  344. * @protected
  345. */
  346. _transition: null,
  347. /**
  348. * A flag for whether the frame is currently transitioning or not.
  349. *
  350. * @property _transitioning
  351. * @type Boolean
  352. * @default false
  353. * @protected
  354. */
  355. _transitioning: false,
  356. /**
  357. * Flag for whether to resize when the current transition
  358. * completes. Set to true when a resize request is made
  359. * during a transition.
  360. *
  361. * @property _resizeAfterTransition
  362. * @type Boolean
  363. * @default false
  364. * @protected
  365. */
  366. _resizeAfterTransition: false,
  367. /**
  368. * Provides functionality for gesture based transitions
  369. * between the active and next images.
  370. *
  371. * @property _gestures
  372. * @type FL.SlideshowGestures
  373. * @default null
  374. * @protected
  375. */
  376. _gestures: null,
  377. /**
  378. * Creates new instances of FL.SlideshowImage used in the frame.
  379. *
  380. * @method initializer
  381. * @protected
  382. */
  383. initializer: function()
  384. {
  385. var imageConfig = this.get('imageConfig');
  386. this._activeImage = new Y.FL.SlideshowImage(imageConfig);
  387. this._nextImage = new Y.FL.SlideshowImage(imageConfig);
  388. },
  389. /**
  390. * Renders the FL.SlideshowImage instances used in the frame.
  391. *
  392. * @method renderUI
  393. * @protected
  394. */
  395. renderUI: function()
  396. {
  397. this.add(this._activeImage);
  398. this.add(this._nextImage);
  399. },
  400. /**
  401. * @method bindUI
  402. * @protected
  403. */
  404. bindUI: function()
  405. {
  406. var activeBB = this._activeImage.get('boundingBox'),
  407. nextBB = this._nextImage.get('boundingBox'),
  408. transition = this.get('transition');
  409. if(('ontouchstart' in window || window.navigator.msPointerEnabled) && this.get('touchSupport')) {
  410. this._gestures = new Y.FL.SlideshowGestures({
  411. direction: transition == 'slideVertical' ? 'vertical' : 'horizontal',
  412. activeItem: activeBB,
  413. nextItem: nextBB
  414. });
  415. this._gestures.on('moveStart', this._gesturesMoveStart, this);
  416. this._gestures.on('endComplete', this._gesturesEndComplete, this);
  417. }
  418. },
  419. /**
  420. * Functional styles for the UI.
  421. *
  422. * @method syncUI
  423. * @protected
  424. */
  425. syncUI: function()
  426. {
  427. var activeBB = this._activeImage.get('boundingBox'),
  428. nextBB = this._nextImage.get('boundingBox'),
  429. cb = this.get('contentBox');
  430. activeBB.setStyle('position', 'absolute');
  431. activeBB.setStyle('top', '0px');
  432. activeBB.setStyle('left', '-9999px');
  433. nextBB.setStyle('position', 'absolute');
  434. nextBB.setStyle('top', '0px');
  435. nextBB.setStyle('left', '-9999px');
  436. cb.setStyle('position', 'relative');
  437. cb.setStyle('overflow', 'hidden');
  438. },
  439. /**
  440. * Checks whether the imageInfo should be loaded or queued.
  441. * Initializes a new transition if loading is ok.
  442. *
  443. * @method load
  444. * @param imageInfo {Object} The image info to load.
  445. */
  446. load: function(imageInfo)
  447. {
  448. var activeInfo = this._activeImage._imageInfo;
  449. if(this._transitioning) {
  450. this._loadQueue = imageInfo;
  451. return;
  452. }
  453. else if(activeInfo && activeInfo.largeURL == imageInfo.largeURL) {
  454. return;
  455. }
  456. this._imageInfo = imageInfo;
  457. this._transitionInit(imageInfo);
  458. },
  459. /**
  460. * Preloads the next image using the provided imageInfo.
  461. *
  462. * @method preload
  463. * @param imageInfo {Object} The imageInfo to preload.
  464. * @param width {Number} The width to preload.
  465. * @param height {Number} The height to preload.
  466. */
  467. preload: function(imageInfo, width, height)
  468. {
  469. this._imageInfo = imageInfo;
  470. this._nextImage.preload(imageInfo, width, height);
  471. },
  472. /**
  473. * Unloads the active and next image instances.
  474. *
  475. * @method unload
  476. */
  477. unload: function()
  478. {
  479. this._imageInfo = null;
  480. this._loadQueue = null;
  481. this._transitioning = false;
  482. this._transition = null;
  483. this._activeImage.detachAll();
  484. this._activeImage.unload();
  485. this._activeImage.get('boundingBox').setStyle('left', '-9999px');
  486. this._nextImage.detachAll();
  487. this._nextImage.unload();
  488. this._nextImage.get('boundingBox').setStyle('left', '-9999px');
  489. },
  490. /**
  491. * Resizes the bounding box and active image.
  492. *
  493. * @method resize
  494. * @param width {Number} The width value.
  495. * @param height {Number} The height value.
  496. */
  497. resize: function(width, height)
  498. {
  499. if(!width || !height) {
  500. return;
  501. }
  502. var bb = this.get('boundingBox'),
  503. padding = [
  504. parseInt(bb.getComputedStyle('paddingTop'), 10),
  505. parseInt(bb.getComputedStyle('paddingRight'), 10),
  506. parseInt(bb.getComputedStyle('paddingBottom'), 10),
  507. parseInt(bb.getComputedStyle('paddingLeft'), 10)
  508. ];
  509. width = width - padding[1] - padding[3];
  510. height = height - padding[0] - padding[2];
  511. this.set('width', width);
  512. this.set('height', height);
  513. if(this._transitioning) {
  514. this._resizeAfterTransition = true;
  515. }
  516. else {
  517. this._activeImage.resize(width, height);
  518. this._nextImage.resize(width, height);
  519. }
  520. },
  521. /**
  522. * Gets the current transition to use.
  523. *
  524. * @method _getTransition
  525. * @protected
  526. */
  527. _getTransition: function()
  528. {
  529. var root = this.get('root'),
  530. lastIndex = root.albumInfo.images.length - 1,
  531. direction = 'next',
  532. transition = root.get('transition');
  533. if(root.lastImageIndex === null) {
  534. direction = '';
  535. }
  536. else if(root.imageIndex == lastIndex && root.lastImageIndex === 0) {
  537. direction = 'prev';
  538. }
  539. else if(root.imageIndex === 0 && root.lastImageIndex == lastIndex) {
  540. direction = 'next';
  541. }
  542. else if(root.lastImageIndex > root.imageIndex) {
  543. direction = 'prev';
  544. }
  545. else if(root.lastImageIndex < root.imageIndex) {
  546. direction = 'next';
  547. }
  548. if(direction == 'next') {
  549. transition = transition.replace('slideHorizontal', 'slideLeft');
  550. transition = transition.replace('slideVertical', 'slideUp');
  551. }
  552. else if(direction == 'prev') {
  553. transition = transition.replace('slideHorizontal', 'slideRight');
  554. transition = transition.replace('slideVertical', 'slideDown');
  555. }
  556. return transition;
  557. },
  558. /**
  559. * Fires the transitionInit event and loads the next image.
  560. * The transition starts when the image's loadComplete
  561. * event is fired.
  562. *
  563. * @method _transitionInit
  564. * @param imageInfo {Object} The imageInfo to load before transitioning.
  565. * @protected
  566. */
  567. _transitionInit: function(imageInfo)
  568. {
  569. this._transitioning = true;
  570. // Disable gestures if set.
  571. if(this._gestures) {
  572. this._gestures.disable();
  573. }
  574. /**
  575. * Fires when the next image is loading before a new transition.
  576. *
  577. * @event transitionInit
  578. */
  579. this.fire('transitionInit');
  580. if(imageInfo) {
  581. this._nextImage.once('loadComplete', this._transitionStart, this);
  582. this._nextImage.load(imageInfo);
  583. }
  584. else {
  585. this._transitionStart();
  586. }
  587. },
  588. /**
  589. * Fires the transitionStart event and starts the transition
  590. * using a new instance of FL.SlideshowTransition.
  591. *
  592. * @method _transitionStart
  593. * @protected
  594. */
  595. _transitionStart: function()
  596. {
  597. var root = this.get('root');
  598. /**
  599. * Fires when the next image has finished loading
  600. * and a new transition starts.
  601. *
  602. * @event transitionStart
  603. */
  604. this.fire('transitionStart');
  605. this._transition = new Y.FL.SlideshowTransition({
  606. itemIn: this._nextImage._imageInfo ? this._nextImage.get('boundingBox') : null,
  607. itemOut: this._activeImage._imageInfo ? this._activeImage.get('boundingBox') : null,
  608. type: this._getTransition(),
  609. duration: root.get('transitionDuration'),
  610. easing: root.get('transitionEasing'),
  611. kenBurnsDuration: root.get('speed')/1000,
  612. kenBurnsZoom: root.get('kenBurnsZoom')
  613. });
  614. if(this._nextImage._imageInfo) {
  615. this._nextImage.get('boundingBox').setStyle('left', '0px');
  616. }
  617. this._transition.once('complete', this._transitionComplete, this);
  618. this._transition.run();
  619. },
  620. /**
  621. * Switches the next and active image variables, unloads the
  622. * last image, fires the transitionComplete event and loads
  623. * or resizes if appropriate.
  624. *
  625. * @method _transitionComplete
  626. * @protected
  627. */
  628. _transitionComplete: function()
  629. {
  630. var root = this.get('root');
  631. // Swap image container references.
  632. this._swapImageRefs();
  633. /**
  634. * Fired when the current transition completes.
  635. *
  636. * @event transitionComplete
  637. */
  638. this.fire('transitionComplete');
  639. this._transition = null;
  640. this._transitioning = false;
  641. // Enable gestures if set.
  642. if(this._gestures) {
  643. if(root && root.albumInfo.images.length <= 1) {
  644. this._gestures.disable();
  645. }
  646. else {
  647. this._gestures.enable();
  648. }
  649. }
  650. // Load from the queue?
  651. if(this._loadQueue) {
  652. this.load(this._loadQueue);
  653. this._loadQueue = null;
  654. }
  655. // Resize the active image?
  656. else if(this._resizeAfterTransition) {
  657. this._resizeAfterTransition = false;
  658. this._activeImage.resize(this.get('width'), this.get('height'));
  659. this._nextImage.resize(this.get('width'), this.get('height'));
  660. }
  661. },
  662. /**
  663. * @method _gesturesMoveStart
  664. * @param e {Object} The event object.
  665. * @protected
  666. */
  667. _gesturesMoveStart: function(e)
  668. {
  669. var index = 0,
  670. root = this.get('root');
  671. index = e.direction == 'next' ? root.imageIndex + 1 : root.imageIndex - 1;
  672. index = index < 0 ? root.albumInfo.images.length - 1 : index;
  673. index = index >= root.albumInfo.images.length ? 0 : index;
  674. root.pause();
  675. root._hideLoadingImage();
  676. root._showLoadingImageWithDelay();
  677. Y.FL.SlideshowImageLoader.removeGroup(this._nextImage.get('loadGroup'));
  678. this._nextImage.once('loadComplete', root._hideLoadingImage, root);
  679. this._nextImage.load(root.albumInfo.images[index]);
  680. },
  681. /**
  682. * @method _gesturesEndComplete
  683. * @protected
  684. */
  685. _gesturesEndComplete: function()
  686. {
  687. var root = this.get('root'),
  688. index = 0;
  689. if(this._nextImage._imageInfo){
  690. index = this._nextImage._imageInfo.index;
  691. this._swapImageRefs();
  692. this._imageInfo = root.albumInfo.images[index];
  693. root.loadImage(index);
  694. }
  695. },
  696. /**
  697. * @method _swapImageRefs
  698. * @protected
  699. */
  700. _swapImageRefs: function()
  701. {
  702. var active = this._activeImage;
  703. this._activeImage = this._nextImage;
  704. this._nextImage = active;
  705. if(this._nextImage._imageInfo) {
  706. this._nextImage.unload();
  707. this._nextImage.get('boundingBox').setStyle('left', '-9999px');
  708. }
  709. if(this._gestures) {
  710. this._gestures.set('activeItem', this._activeImage.get('boundingBox'));
  711. this._gestures.set('nextItem', this._nextImage.get('boundingBox'));
  712. }
  713. }
  714. }, {
  715. /**
  716. * Custom CSS class name for the widget.
  717. * @property CSS_PREFIX
  718. * @type String
  719. * @protected
  720. * @static
  721. */
  722. CSS_PREFIX: 'fl-slideshow-frame',
  723. /**
  724. * Static property used to define the default attribute configuration of
  725. * the Widget.
  726. *
  727. * @property ATTRS
  728. * @type Object
  729. * @protected
  730. * @static
  731. */
  732. ATTRS: {
  733. /**
  734. * The configuration object used to create new instances of
  735. * FL.SlideshowImage. See the API docs for {@link FL.SlideshowImage}
  736. * for a complete list of configuration attributes.
  737. *
  738. * @attribute imageConfig
  739. * @type Object
  740. * @default null
  741. */
  742. imageConfig: {
  743. value: null
  744. },
  745. /**
  746. * Whether to use touch gestures, when available,
  747. * to transition between images or not.
  748. *
  749. * @attribute touchSupport
  750. * @type Boolean
  751. * @default false
  752. */
  753. touchSupport: {
  754. value: false
  755. }
  756. }
  757. });
  758. /**
  759. * A plugin for fullscreen slideshow functionality.
  760. *
  761. * @namespace FL
  762. * @class SlideshowFullscreen
  763. * @constructor
  764. * @param config {Object} Configuration object
  765. * @extends Plugin.Base
  766. */
  767. Y.namespace('FL').SlideshowFullscreen = Y.Base.create('fl-slideshow-fullscreen', Y.Plugin.Base, [], {
  768. /**
  769. * Flag for whether the slideshow is in
  770. * fullscreen mode.
  771. *
  772. * @property active
  773. * @type Boolean
  774. * @default false
  775. */
  776. active: false,
  777. /**
  778. * A div containing the close message.
  779. *
  780. * @property _closeMessage
  781. * @type Node
  782. * @default null
  783. * @protected
  784. */
  785. _closeMessage: null,
  786. /**
  787. * A timer for hiding the close message.
  788. *
  789. * @property _closeMessageTimer
  790. * @type Object
  791. * @default null
  792. * @protected
  793. */
  794. _closeMessageTimer: null,
  795. /**
  796. * The initial styles of the host's bounding box
  797. * before entering fullscreen mode.
  798. *
  799. * @property _initialStyles
  800. * @type Object
  801. * @protected
  802. */
  803. _initialStyles: {
  804. position: 'static',
  805. top: '0px',
  806. left: '0px'
  807. },
  808. /**
  809. * @method initializer
  810. * @protected
  811. */
  812. initializer: function()
  813. {
  814. var host = this.get('host'),
  815. bb = host.get('boundingBox'),
  816. self = this;
  817. bb.addClass('fl-fullscreen-enabled');
  818. if(Y.FL.SlideshowFullscreen.OS_SUPPORT) {
  819. document.addEventListener('fullscreenchange', function(){ self._osChange(); }, false);
  820. document.addEventListener('mozfullscreenchange', function(){ self._osChange(); }, false);
  821. document.addEventListener('webkitfullscreenchange', function(){ self._osChange(); }, false);
  822. }
  823. else {
  824. this._renderCloseMessage();
  825. }
  826. },
  827. /**
  828. * Exits fullscreen if it is currently active
  829. * otherwise it enters fullscreen.
  830. *
  831. * @method toggle
  832. */
  833. toggle: function()
  834. {
  835. if(this.active) {
  836. this.exit();
  837. }
  838. else {
  839. this.enter();
  840. }
  841. },
  842. /**
  843. * Enters OS fullscreen mode if supported, otherwise
  844. * the slideshow takes over the browser window.
  845. *
  846. * @method enter
  847. */
  848. enter: function()
  849. {
  850. if(Y.FL.SlideshowFullscreen.OS_SUPPORT) {
  851. this._osEnter();
  852. }
  853. else {
  854. this._browserEnter();
  855. }
  856. },
  857. /**
  858. * Exits fullscreen mode.
  859. *
  860. * @method exit
  861. */
  862. exit: function()
  863. {
  864. if(Y.FL.SlideshowFullscreen.OS_SUPPORT) {
  865. this._osExit();
  866. }
  867. else {
  868. this._browserExit();
  869. }
  870. },
  871. /**
  872. * Enters OS fullscreen mode.
  873. *
  874. * @method _osEnter
  875. * @protected
  876. */
  877. _osEnter: function()
  878. {
  879. var bbNode = this.get('host').get('boundingBox')._node;
  880. if(bbNode.webkitRequestFullScreen) {
  881. bbNode.webkitRequestFullScreen();
  882. }
  883. else if(bbNode.mozRequestFullScreen) {
  884. bbNode.mozRequestFullScreen();
  885. }
  886. else if(bbNode.requestFullScreen) {
  887. bbNode.requestFullScreen();
  888. }
  889. },
  890. /**
  891. * Exits OS fullscreen mode.
  892. *
  893. * @method _osExit
  894. * @protected
  895. */
  896. _osExit: function()
  897. {
  898. if(document.exitFullscreen) {
  899. document.exitFullscreen();
  900. }
  901. else if(document.mozCancelFullScreen) {
  902. document.mozCancelFullScreen();
  903. }
  904. else if(document.webkitCancelFullScreen) {
  905. document.webkitCancelFullScreen();
  906. }
  907. },
  908. /**
  909. * Called when the OS fullscreenchange event fires and enters
  910. * or exits standard fullscreen mode which positions and
  911. * resizes the slideshow.
  912. *
  913. * @method _osChange
  914. * @protected
  915. */
  916. _osChange: function()
  917. {
  918. var host = this.get('host');
  919. // Transitions break on Safari while entering and
  920. // exiting fullscreen. This fixes them!
  921. if(host.frame && host.frame._transitioning) {
  922. host.frame._transitionComplete();
  923. }
  924. if(this.active) {
  925. this._exit();
  926. }
  927. else {
  928. this._enter();
  929. }
  930. },
  931. /**
  932. * Enter browser fullscreen mode.
  933. *
  934. * @method _browserEnter
  935. * @protected
  936. */
  937. _browserEnter: function()
  938. {
  939. var bb = this.get('host').get('boundingBox');
  940. this._initialStyles = {
  941. position: bb.getStyle('position'),
  942. top: bb.getStyle('top'),
  943. left: bb.getStyle('left'),
  944. zIndex: bb.getStyle('zIndex')
  945. };
  946. bb.setStyles({
  947. position: 'fixed',
  948. top: '0px',
  949. left: '0px',
  950. zIndex: 10000
  951. });
  952. Y.Node.one('body').on('fl-fullscreen|keydown', Y.bind(this._onKey, this));
  953. this._showCloseMessage();
  954. this._enter();
  955. },
  956. /**
  957. * Exit browser fullscreen mode.
  958. *
  959. * @method _browserExit
  960. * @protected
  961. */
  962. _browserExit: function()
  963. {
  964. var bb = this.get('host').get('boundingBox');
  965. bb.setStyles({
  966. position: this._initialStyles.position,
  967. top: this._initialStyles.top,
  968. left: this._initialStyles.left,
  969. zIndex: this._initialStyles.zIndex
  970. });
  971. Y.Node.one('body').detach('fl-fullscreen|keydown');
  972. this._hideCloseMessage();
  973. this._exit();
  974. },
  975. /**
  976. * Enters fullscreen mode.
  977. *
  978. * @method _enter
  979. * @protected
  980. */
  981. _enter: function()
  982. {
  983. var host = this.get('host'),
  984. bb = host.get('boundingBox');
  985. bb.addClass('fl-fullscreen-active');
  986. this.active = true;
  987. host.resize();
  988. },
  989. /**
  990. * Exits fullscreen mode.
  991. *
  992. * @method _exit
  993. * @protected
  994. */
  995. _exit: function()
  996. {
  997. var host = this.get('host'),
  998. bb = host.get('boundingBox');
  999. bb.removeClass('fl-fullscreen-active');
  1000. this.active = false;
  1001. host.resize();
  1002. },
  1003. /**
  1004. * Keyboard input for the esc button.
  1005. *
  1006. * @method _onKey
  1007. * @protected
  1008. */
  1009. _onKey: function(e)
  1010. {
  1011. if(e.keyCode == 27) {
  1012. this.exit();
  1013. return false;
  1014. }
  1015. },
  1016. /**
  1017. * Creates the close message if one is
  1018. * not already available in the document.
  1019. *
  1020. * @method _initCloseMessage
  1021. * @protected
  1022. */
  1023. _renderCloseMessage: function()
  1024. {
  1025. this._closeMessage = Y.Node.create('<div class="fl-fullscreen-close-message"></div>');
  1026. this._closeMessage.set('innerHTML', '<span>Press the "esc" button to exit fullscreen mode.</span>');
  1027. this._closeMessage.setStyle('display', 'none');
  1028. this.get('host').get('boundingBox').insert(this._closeMessage);
  1029. },
  1030. /**
  1031. * Shows the close message.
  1032. *
  1033. * @method _showCloseMessage
  1034. * @protected
  1035. */
  1036. _showCloseMessage: function()
  1037. {
  1038. if(this._closeMessageTimer) {
  1039. this._closeMessageTimer.cancel();
  1040. this._closeMessageTimer = null;
  1041. }
  1042. this._closeMessage.show(true);
  1043. this._closeMessageTimer = Y.later(4000, this, this._hideCloseMessage);
  1044. },
  1045. /**
  1046. * Hides the close message.
  1047. *
  1048. * @method _hideCloseMessage
  1049. * @protected
  1050. */
  1051. _hideCloseMessage: function()
  1052. {
  1053. if(this._closeMessageTimer) {
  1054. this._closeMessageTimer.cancel();
  1055. this._closeMessageTimer = null;
  1056. }
  1057. this._closeMessage.hide(true);
  1058. }
  1059. }, {
  1060. /**
  1061. * Namespace for the plugin.
  1062. *
  1063. * @property NS
  1064. * @type String
  1065. * @protected
  1066. * @static
  1067. */
  1068. NS: 'fullscreen',
  1069. OS_SUPPORT: (function(){
  1070. var doc = document.documentElement;
  1071. return doc.webkitRequestFullScreen || doc.mozRequestFullScreen || doc.requestFullScreen;
  1072. })()
  1073. });
  1074. /**
  1075. * Provides functionality for gesture based transitions
  1076. * between two slideshow components.
  1077. *
  1078. * @namespace FL
  1079. * @class SlideshowGestures
  1080. * @constructor
  1081. * @param config {Object} Configuration object
  1082. * @extends Base
  1083. */
  1084. Y.namespace('FL').SlideshowGestures = Y.Base.create('fl-slideshow-gestures', Y.Base, [], {
  1085. /**
  1086. * The x coordinate for where a gesture event starts.
  1087. *
  1088. * @property _startX
  1089. * @type Number
  1090. * @default null
  1091. * @protected
  1092. */
  1093. _startX: null,
  1094. /**
  1095. * The y coordinate for where a gesture event starts.
  1096. *
  1097. * @property _startY
  1098. * @type Number
  1099. * @default null
  1100. * @protected
  1101. */
  1102. _startY: null,
  1103. /**
  1104. * A flag for whether a gesture is moving or not.
  1105. *
  1106. * @property _moving
  1107. * @type Boolean
  1108. * @default false
  1109. * @protected
  1110. */
  1111. _touchMoving: false,
  1112. /**
  1113. * Whether the gesture is moving or not.
  1114. *
  1115. * @property _moving
  1116. * @type Boolean
  1117. * @default false
  1118. * @protected
  1119. */
  1120. _moving: false,
  1121. /**
  1122. * The direction the current gesture event
  1123. * is moving in (either next or prev).
  1124. *
  1125. * @property _movingDirection
  1126. * @type String
  1127. * @default null
  1128. * @protected
  1129. */
  1130. _movingDirection: null,
  1131. /**
  1132. * A flag for whether a gesture gesture is currently
  1133. * transitioning or not.
  1134. *
  1135. * @property _transitioning
  1136. * @type Boolean
  1137. * @default false
  1138. * @protected
  1139. */
  1140. _transitioning: false,
  1141. /**
  1142. * @method initializer
  1143. * @protected
  1144. */
  1145. initializer: function()
  1146. {
  1147. this.enable();
  1148. },
  1149. /**
  1150. * @method enable
  1151. */
  1152. enable: function()
  1153. {
  1154. var id = this.get('id'),
  1155. direction = this.get('direction'),
  1156. active = this.get('activeItem'),
  1157. next = this.get('nextItem');
  1158. active.on(id + '|gesturemovestart', Y.bind(this._onStart, this));
  1159. next.on(id + '|gesturemovestart', Y.bind(this._onStart, this));
  1160. next.on(id + '|transitionend', Y.bind(this._onEndComplete, this) );
  1161. next.on(id + '|oTransitionEnd', Y.bind(this._onEndComplete, this) );
  1162. next.on(id + '|webkitTransitionEnd', Y.bind(this._onEndComplete, this) );
  1163. if(direction == 'horizontal') {
  1164. active.on(id + '|gesturemovehorizontal', Y.bind(this._onMoveHorizontal, this));
  1165. active.on(id + '|gesturemovehorizontalend', Y.bind(this._onEndHorizontal, this));
  1166. next.on(id + '|gesturemovehorizontal', Y.bind(this._onMoveHorizontal, this));
  1167. next.on(id + '|gesturemovehorizontalend', Y.bind(this._onEndHorizontal, this));
  1168. }
  1169. else {
  1170. active.on(id + '|gesturemovevertical', Y.bind(this._onMoveVertical, this));
  1171. active.on(id + '|gesturemoveverticalend', Y.bind(this._onEndVertical, this));
  1172. next.on(id + '|gesturemovevertical', Y.bind(this._onMoveVertical, this));
  1173. next.on(id + '|gesturemoveverticalend', Y.bind(this._onEndVertical, this));
  1174. }
  1175. },
  1176. /**
  1177. * @method disable
  1178. */
  1179. disable: function()
  1180. {
  1181. var id = this.get('id'),
  1182. active = this.get('activeItem'),
  1183. next = this.get('nextItem');
  1184. active.detach(id + '|*');
  1185. next.detach(id + '|*');
  1186. },
  1187. /**
  1188. * @method _onStart
  1189. * @param e {Object} The event object.
  1190. * @protected
  1191. */
  1192. _onStart: function(e)
  1193. {
  1194. var direction = this.get('direction');
  1195. if(this._transitioning) {
  1196. this._onEndComplete();
  1197. }
  1198. if(direction == 'horizontal') {
  1199. this._startX = e.pageX;
  1200. }
  1201. else {
  1202. this._startY = e.pageY;
  1203. }
  1204. /**
  1205. * @event start
  1206. */
  1207. this.fire('start');
  1208. },
  1209. /**
  1210. * @method _onMoveHorizontal
  1211. * @param e {Object} The event object.
  1212. * @protected
  1213. */
  1214. _onMoveHorizontal: function(e)
  1215. {
  1216. var x = this._startX - e.pageX,
  1217. active = this.get('activeItem'),
  1218. next = this.get('nextItem'),
  1219. width = parseInt(active.getComputedStyle('width'), 10),
  1220. translate = x < 0 ? Math.abs(x) : -x,
  1221. direction = x < 0 ? 'prev' : 'next';
  1222. e.preventDefault();
  1223. if(!this._moving || this._movingDirection != direction) {
  1224. active.setStyle('left', 0);
  1225. next.setStyles({
  1226. 'opacity': 1,
  1227. 'left': x < 0 ? -width : width
  1228. });
  1229. this._moving = true;
  1230. this._movingDirection = direction;
  1231. /**
  1232. * @event moveStart
  1233. */
  1234. this.fire('moveStart', { direction: direction });
  1235. }
  1236. active.setStyle('-webkit-transform', 'translate('+ translate +'px, 0px) translateZ(0px)');
  1237. active.setStyle('-ms-transform', 'translate('+ translate +'px, 0px) translateZ(0px)');
  1238. next.setStyle('-webkit-transform', 'translate('+ translate +'px, 0px) translateZ(0px)');
  1239. next.setStyle('-ms-transform', 'translate('+ translate +'px, 0px) translateZ(0px)');
  1240. /**
  1241. * @event move
  1242. */
  1243. this.fire('move');
  1244. },
  1245. /**
  1246. * @method _onMoveVertical
  1247. * @param e {Object} The event object.
  1248. * @protected
  1249. */
  1250. _onMoveVertical: function(e)
  1251. {
  1252. var y = this._startY - e.pageY,
  1253. active = this.get('activeItem'),
  1254. next = this.get('nextItem'),
  1255. height = parseInt(active.getComputedStyle('height'), 10),
  1256. translate = y < 0 ? Math.abs(y) : -y,
  1257. direction = y < 0 ? 'prev' : 'next';
  1258. e.preventDefault();
  1259. if(!this._moving || this._movingDirection != direction) {
  1260. active.setStyle('top', 0);
  1261. next.setStyles({
  1262. 'opacity': 1,
  1263. 'left' : 'auto',
  1264. 'top': y < 0 ? -height : height
  1265. });
  1266. this._moving = true;
  1267. this._movingDirection = direction;
  1268. /**
  1269. * @event moveStart
  1270. */
  1271. this.fire('moveStart', { direction: direction });
  1272. }
  1273. active.setStyle('-webkit-transform', 'translate(0px, '+ translate +'px) translateZ(0px)');
  1274. active.setStyle('-ms-transform', 'translate(0px, '+ translate +'px) translateZ(0px)');
  1275. next.setStyle('-webkit-transform', 'translate(0px, '+ translate +'px) translateZ(0px)');
  1276. next.setStyle('-ms-transform', 'translate(0px, '+ translate +'px) translateZ(0px)');
  1277. /**
  1278. * @event move
  1279. */
  1280. this.fire('move');
  1281. },
  1282. /**
  1283. * @method _onEndHorizontal
  1284. * @param e {Object} The event object.
  1285. * @protected
  1286. */
  1287. _onEndHorizontal: function(e)
  1288. {
  1289. if(!this._moving) {
  1290. return;
  1291. }
  1292. var x = this._startX - e.pageX,
  1293. active = this.get('activeItem'),
  1294. next = this.get('nextItem'),
  1295. width = parseInt(next.getComputedStyle('width'), 10),
  1296. translate = x < 0 ? width : -width;
  1297. active.transition({
  1298. 'transform': 'translate('+ translate +'px, 0px)'
  1299. });
  1300. next.transition({
  1301. 'transform': 'translate('+ translate +'px, 0px)'
  1302. });
  1303. this._transitioning = true;
  1304. /**
  1305. * @event end
  1306. */
  1307. this.fire('end');
  1308. },
  1309. /**
  1310. * @method _onEndVertical
  1311. * @param e {Object} The event object.
  1312. * @protected
  1313. */
  1314. _onEndVertical: function(e)
  1315. {
  1316. if(!this._moving) {
  1317. return;
  1318. }
  1319. var y = this._startY - e.pageY,
  1320. active = this.get('activeItem'),
  1321. next = this.get('nextItem'),
  1322. height = parseInt(next.getComputedStyle('height'), 10),
  1323. translate = y < 0 ? height : -height;
  1324. active.transition({
  1325. 'transform': 'translate(0px, '+ translate +'px)'
  1326. });
  1327. next.transition({
  1328. 'transform': 'translate(0px, '+ translate +'px)'
  1329. });
  1330. this._transitioning = true;
  1331. /**
  1332. * @event end
  1333. */
  1334. this.fire('end');
  1335. },
  1336. /**
  1337. * @method _onEndComplete
  1338. * @protected
  1339. */
  1340. _onEndComplete: function()
  1341. {
  1342. var direction = this.get('direction'),
  1343. active = this.get('activeItem'),
  1344. next = this.get('nextItem');
  1345. active.setStyles({
  1346. 'opacity': 0,
  1347. '-webkit-transform': '',
  1348. '-webkit-transition': '',
  1349. '-ms-transform': '',
  1350. '-ms-transition': ''
  1351. });
  1352. next.setStyles({
  1353. '-webkit-transform': '',
  1354. '-webkit-transition': '',
  1355. '-ms-transform': '',
  1356. '-ms-transition': ''
  1357. });
  1358. if(direction == 'horizontal') {
  1359. active.setStyle('left', '-9999px');
  1360. next.setStyle('left', '0px');
  1361. }
  1362. else {
  1363. active.setStyle('top', '-9999px');
  1364. next.setStyle('top', '0px');
  1365. }
  1366. this.set('activeItem', next);
  1367. this.set('nextItem', active);
  1368. this._moving = false;
  1369. this._movingDirection = null;
  1370. this._transitioning = false;
  1371. /**
  1372. * @event endComplete
  1373. */
  1374. this.fire('endComplete');
  1375. }
  1376. }, {
  1377. /**
  1378. * Static property used to define the default attribute configuration of
  1379. * the Widget.
  1380. *
  1381. * @property ATTRS
  1382. * @type Object
  1383. * @protected
  1384. * @static
  1385. */
  1386. ATTRS: {
  1387. /**
  1388. * The gesture direction to use. Possible values are
  1389. * horizontal and vertical.
  1390. *
  1391. * @attribute direction
  1392. * @type String
  1393. * @default horizontal
  1394. */
  1395. direction: {
  1396. value: 'horizontal'
  1397. },
  1398. /**
  1399. * The Node that is currently visible.
  1400. *
  1401. * @attribute activeItem
  1402. * @type Node
  1403. * @default null
  1404. */
  1405. activeItem: {
  1406. value: null
  1407. },
  1408. /**
  1409. * The Node that will be transitioned in.
  1410. *
  1411. * @attribute nextItem
  1412. * @type Node
  1413. * @default null
  1414. */
  1415. nextItem: {
  1416. value: null
  1417. }
  1418. }
  1419. });
  1420. /**
  1421. * A load queue for slideshow images.
  1422. *
  1423. * @namespace FL
  1424. * @class SlideshowImageLoader
  1425. * @static
  1426. */
  1427. Y.namespace('FL').SlideshowImageLoader = {
  1428. /**
  1429. * Whether an image is being loaded or not.
  1430. *
  1431. * @property _loading
  1432. * @type Boolean
  1433. * @default false
  1434. * @protected
  1435. */
  1436. _loading: false,
  1437. /**
  1438. * An node for loading the next image.
  1439. *
  1440. * @property _currentImage
  1441. * @type Node
  1442. * @default null
  1443. * @protected
  1444. */
  1445. _currentImage: null,
  1446. /**
  1447. * An object containing the group, src and callback
  1448. * for the current image that is being loaded.
  1449. *
  1450. * @property _currentImageData
  1451. * @type Object
  1452. * @default null
  1453. * @protected
  1454. */
  1455. _currentImageData: null,
  1456. /**
  1457. * An array of image data objects that contain the group,
  1458. * src and callback for each image that will be loaded.
  1459. *
  1460. * @property _queue
  1461. * @type Array
  1462. * @default []
  1463. * @protected
  1464. */
  1465. _queue: [],
  1466. /**
  1467. * Adds an image to the queue.
  1468. *
  1469. * @method add
  1470. * @param group {String} The group this image is associated with.
  1471. * Used to remove images in bulk.
  1472. * @param src {String} The image url to load.
  1473. * @param callback {Function} A function to call when the image
  1474. * has finished loading.
  1475. * @param bump {Boolean} If true, the image will be added to
  1476. * the first position in the queue.
  1477. */
  1478. add: function(group, src, callback, bump)
  1479. {
  1480. var imgData = {
  1481. group : group,
  1482. src : src,
  1483. callback : callback
  1484. };
  1485. if(bump) {
  1486. this._queue.unshift(imgData);
  1487. }
  1488. else {
  1489. this._queue.push(imgData);
  1490. }
  1491. if(!this._loading) {
  1492. this._load();
  1493. }
  1494. },
  1495. /**
  1496. * Removes a group of images from the queue.
  1497. *
  1498. * @method removeGroup
  1499. * @param group {String} The group to remove.
  1500. */
  1501. removeGroup: function(group)
  1502. {
  1503. var i = this._queue.length - 1;
  1504. for( ; i > -1 ; i--) {
  1505. if(this._queue[i].group == group) {
  1506. this._queue.splice(i, 1);
  1507. }
  1508. }
  1509. if(this._currentImageData && this._currentImageData.group == group) {
  1510. this._currentImage.detachAll();
  1511. this._currentImage = null;
  1512. this._currentImageData = null;
  1513. if(this._queue.length > 0) {
  1514. this._load();
  1515. }
  1516. else {
  1517. this._loading = false;
  1518. }
  1519. }
  1520. },
  1521. /**
  1522. * Loads the next image in the queue.
  1523. *
  1524. * @method _load
  1525. * @protected
  1526. */
  1527. _load: function()
  1528. {
  1529. this._loading = true;
  1530. this._currentImageData = this._queue.shift();
  1531. this._currentImage = Y.Node.create('<img />');
  1532. this._currentImage.on('error', Y.bind(this._loadComplete, this));
  1533. this._currentImage.on('load', Y.bind(this._loadComplete, this));
  1534. this._currentImage.set('src', this._currentImageData.src);
  1535. },
  1536. /**
  1537. * Calls the current image's callback function if set
  1538. * and loads the next image if the queue is not empty.
  1539. *
  1540. * @method _loadComplete
  1541. * @protected
  1542. */
  1543. _loadComplete: function()
  1544. {
  1545. if(this._currentImageData.callback) {
  1546. this._currentImageData.callback(this._currentImage);
  1547. }
  1548. if(this._queue.length > 0) {
  1549. this._load();
  1550. }
  1551. else {
  1552. this._loading = false;
  1553. this._currentImage = null;
  1554. this._currentImageData = null;
  1555. }
  1556. }
  1557. };
  1558. /**
  1559. * Loads an image or video using the provided imageInfo object.
  1560. *
  1561. * @namespace FL
  1562. * @class SlideshowImage
  1563. * @constructor
  1564. * @param config {Object} Configuration object
  1565. * @extends Widget
  1566. */
  1567. Y.namespace('FL').SlideshowImage = Y.Base.create('fl-slideshow-image', Y.Widget, [Y.WidgetChild], {
  1568. /**
  1569. * The imageInfo object used to load the image and
  1570. * its various sizes.
  1571. *
  1572. * @property info
  1573. * @type Object
  1574. * @default null
  1575. * @protected
  1576. */
  1577. _imageInfo: null,
  1578. /**
  1579. * A reference to the current image node in the bounding box.
  1580. *
  1581. * @property _image
  1582. * @type Node
  1583. * @default null
  1584. * @protected
  1585. */
  1586. _image: null,
  1587. /**
  1588. * Whether or not new imageInfo is loading.
  1589. *
  1590. * @property _loading
  1591. * @type Boolean
  1592. * @default false
  1593. * @protected
  1594. */
  1595. _loading: false,
  1596. /**
  1597. * The URL that is currently being loaded.
  1598. *
  1599. * @property _loadingURL
  1600. * @type Boolean
  1601. * @default null
  1602. * @protected
  1603. */
  1604. _loadingURL: null,
  1605. /**
  1606. * An anchor node used for the video play button.
  1607. *
  1608. * @property _videoButton
  1609. * @type Node
  1610. * @default null
  1611. * @protected
  1612. */
  1613. _videoButton: null,
  1614. /**
  1615. * A div node used to hold the video iframe.
  1616. *
  1617. * @property _videoBox
  1618. * @type Node
  1619. * @default null
  1620. * @protected
  1621. */
  1622. _videoBox: null,
  1623. /**
  1624. * An iframe node used to render the video.
  1625. *
  1626. * @property _video
  1627. * @type Node
  1628. * @default null
  1629. * @protected
  1630. */
  1631. _video: null,
  1632. /**
  1633. * The default content template for the image
  1634. * inherited from Y.Widget. Set to null since
  1635. * only the bounding box is needed.
  1636. *
  1637. * @property CONTENT_TEMPLATE
  1638. * @type String
  1639. * @default null
  1640. * @protected
  1641. */
  1642. CONTENT_TEMPLATE: null,
  1643. /**
  1644. * Initial styling for the bounding box.
  1645. *
  1646. * @method syncUI
  1647. * @protected
  1648. */
  1649. syncUI: function()
  1650. {
  1651. var bb = this.get('boundingBox');
  1652. if(this.get('crop')) {
  1653. bb.setStyle('overflow', 'hidden');
  1654. bb.addClass('fl-slideshow-image-cropped');
  1655. }
  1656. },
  1657. /**
  1658. * Sets the imageInfo object and
  1659. * loads the appropriate image size.
  1660. *
  1661. * @method load
  1662. * @param imageInfo {Object} The imageInfo object.
  1663. */
  1664. load: function(imageInfo)
  1665. {
  1666. this._imageInfo = imageInfo;
  1667. this._loading = true;
  1668. this._load();
  1669. },
  1670. /**
  1671. * Sets the width and height of the bounding box and
  1672. * preloads an image using the provided imageInfo object.
  1673. *
  1674. * @method preload
  1675. * @param imageInfo {Object} The imageInfo to preload.
  1676. * @param width {Number} The width to preload.
  1677. * @param height {Number} The height to preload.
  1678. */
  1679. preload: function(imageInfo, width, height)
  1680. {
  1681. var isVideo = this._isVideo(),
  1682. loadVideos = this.get('loadVideos'),
  1683. showVideoButton = this.get('showVideoButton');
  1684. this.unload();
  1685. this.set('width', width);
  1686. this.set('height', height);
  1687. this._imageInfo = imageInfo;
  1688. if(!isVideo || !loadVideos || (isVideo && loadVideos && showVideoButton)) {
  1689. Y.FL.SlideshowImageLoader.add(
  1690. this.get('loadGroup'),
  1691. this._getImageURL(),
  1692. Y.bind(this._imagePreloaded, this),
  1693. this.get('loadPriority')
  1694. );
  1695. }
  1696. },
  1697. /**
  1698. * Called when preloading completes.
  1699. *
  1700. * @method _imagePreloaded
  1701. * @param img {Object} The image that was preloaded.
  1702. * @protected
  1703. */
  1704. _imagePreloaded: function(img)
  1705. {
  1706. this._image = img;
  1707. },
  1708. /**
  1709. * Unloads the image if there is one loaded
  1710. * and sets the imageInfo object to null.
  1711. *
  1712. * @method unload
  1713. */
  1714. unload: function()
  1715. {
  1716. if(this._image) {
  1717. this._image.remove();
  1718. this._image.detachAll();
  1719. this._image.set('src', '');
  1720. this._image = null;
  1721. }
  1722. if(this._video) {
  1723. this._video.remove();
  1724. this._video = null;
  1725. }
  1726. if(this._videoButton) {
  1727. this._videoButton.remove();
  1728. this._videoButton = null;
  1729. }
  1730. if(this._videoBox) {
  1731. this._removeVideoBox();
  1732. }
  1733. this._imageInfo = null;
  1734. this._loading = false;
  1735. this._loadingURL = null;
  1736. },
  1737. /**
  1738. * Resizes the bounding box and loads the
  1739. * appropriate image size if necessary.
  1740. *
  1741. * @method resize
  1742. * @param width {Number} The width value.
  1743. * @param height {Number} The height value.
  1744. */
  1745. resize: function(width, height)
  1746. {
  1747. var borderWidth = parseInt(this.get('boundingBox').getComputedStyle('borderTopWidth'), 10) * 2,
  1748. bb = this.get('boundingBox');
  1749. this.set('width', width - borderWidth);
  1750. this.set('height', height - borderWidth);
  1751. bb.setStyle('width', width - borderWidth + 'px');
  1752. bb.setStyle('height', height - borderWidth + 'px');
  1753. if(this._videoButton) {
  1754. this._positionVideoButton();
  1755. }
  1756. if(this._videoBox) {
  1757. this._loadVideo();
  1758. }
  1759. if(!this._loading) {
  1760. if(this._imageInfo) {
  1761. this._load();
  1762. }
  1763. if(this._image) {
  1764. this._positionImage();
  1765. }
  1766. }
  1767. },
  1768. /**
  1769. * Loads (or reloads) the image or video.
  1770. *
  1771. * @method _load
  1772. * @protected
  1773. */
  1774. _load: function()
  1775. {
  1776. var loadVideos = this.get('loadVideos'),
  1777. showVideoButton = this.get('showVideoButton');
  1778. if(this._isVideo() && loadVideos && !showVideoButton && !('ontouchstart' in window)) {
  1779. this._loadVideo();
  1780. }
  1781. else {
  1782. this._loadImage();
  1783. }
  1784. },
  1785. /**
  1786. * Loads the appropriate image size if
  1787. * it is not already loading.
  1788. *
  1789. * @method _loadImage
  1790. * @protected
  1791. */
  1792. _loadImage: function()
  1793. {
  1794. var url = this._getImageURL(),
  1795. loadVideos = this.get('loadVideos');
  1796. // Already loading.
  1797. if(url == this._loadingURL) {
  1798. return;
  1799. }
  1800. // New URL to load.
  1801. this._loadingURL = url;
  1802. // Load the new image.
  1803. Y.FL.SlideshowImageLoader.add(
  1804. this.get('loadGroup'),
  1805. this._loadingURL,
  1806. Y.bind(this._loadImageComplete, this),
  1807. this.get('loadPriority')
  1808. );
  1809. // Initial load?
  1810. if(this._loading) {
  1811. if(this._isVideo() && loadVideos) {
  1812. this._insertVideoButton();
  1813. }
  1814. /**
  1815. * Only fires when a new image is being
  1816. * loaded, not a different size.
  1817. *
  1818. * @event loadStart
  1819. */
  1820. this.fire('loadStart');
  1821. }
  1822. },
  1823. /**
  1824. * Fires when the image has finished loading.
  1825. *
  1826. * @method _loadImageComplete
  1827. * @protected
  1828. */
  1829. _loadImageComplete: function(img)
  1830. {
  1831. var bb = this.get('boundingBox'),
  1832. showVideoButton = this.get('showVideoButton');
  1833. this._image = img;
  1834. this._image.setStyle('visibility', 'hidden');
  1835. this._image.addClass('fl-slideshow-image-img');
  1836. // Remove load events.
  1837. this._image.detachAll();
  1838. // Remove previous videos.
  1839. if(this._video && !showVideoButton) {
  1840. this._video.remove();
  1841. this._video = null;
  1842. }
  1843. // Remove the old image.
  1844. bb.all('img').remove();
  1845. // Append the new image.
  1846. bb.append(this._image);
  1847. // Setup, scale and position the new image.
  1848. this._setupImage();
  1849. this._resizeImage();
  1850. this._positionImage();
  1851. this._image.setStyle('visibility', 'visible');
  1852. // Clear the loading url.
  1853. this._loadingURL = null;
  1854. // Finish an initial load?
  1855. if(this._loading) {
  1856. this._loading = false;
  1857. /**
  1858. * Only fires when a new image is being
  1859. * loaded, not a different size.
  1860. *
  1861. * @event loadComplete
  1862. */
  1863. this.fire('loadComplete');
  1864. }
  1865. },
  1866. /**
  1867. * UI setup for the new image.
  1868. *
  1869. * @method _setupImage
  1870. * @protected
  1871. */
  1872. _setupImage: function()
  1873. {
  1874. var bb = this.get('boundingBox');
  1875. // IE interpolation
  1876. if(typeof this._image._node.style.msInterpolationMode != 'undefined') {
  1877. this._image._node.style.msInterpolationMode = 'bicubic';
  1878. }
  1879. // Protection
  1880. if(this.get('protect')) {
  1881. bb.delegate('contextmenu', this._protectImage, 'img');
  1882. bb.delegate('mousedown', this._protectImage, 'img');
  1883. }
  1884. },
  1885. /**
  1886. * Fires on contextmenu or mousedown in attempt
  1887. * to keep the image from being copied.
  1888. *
  1889. * @method _protectImage
  1890. * @return {Boolean} Returns false to prevent the default event.
  1891. * @protected
  1892. */
  1893. _protectImage: function(e)
  1894. {
  1895. e.preventDefault();
  1896. return false;
  1897. },
  1898. /**
  1899. * Resizes the image node.
  1900. *
  1901. * @method _resizeImage
  1902. * @protected
  1903. */
  1904. _resizeImage: function()
  1905. {
  1906. var borderWidth = parseInt(this._image.getComputedStyle('borderTopWidth'), 10) * 2,
  1907. imageWidth = this._image.get('width'),
  1908. imageHeight = this._image.get('height'),
  1909. targetWidth = parseInt(this.get('boundingBox').getComputedStyle('width'), 10),
  1910. targetHeight = parseInt(this.get('boundingBox').getComputedStyle('height'), 10),
  1911. newWidth = 0,
  1912. newHeight = 0,
  1913. xScale = 0,
  1914. yScale = 0,
  1915. cropHorizontalsOnly = this.get('cropHorizontalsOnly'),
  1916. isHorizontal = imageHeight > imageWidth,
  1917. noCrop = false;
  1918. if(this._imageInfo && this.get('checkFilenamesForNoCrop')) {
  1919. noCrop = this._imageInfo.filename.indexOf('nocrop') > -1;
  1920. }
  1921. if(this.get('crop') && !(cropHorizontalsOnly && isHorizontal) && !noCrop) {
  1922. newWidth = targetWidth;
  1923. newHeight = Math.round(imageHeight * targetWidth/imageWidth);
  1924. if(newHeight < targetHeight) {
  1925. newHeight = targetHeight;
  1926. newWidth = Math.round(imageWidth * targetHeight/imageHeight);
  1927. }
  1928. }
  1929. else {
  1930. xScale = imageWidth/targetWidth;
  1931. yScale = imageHeight/targetHeight;
  1932. if (yScale > xScale){
  1933. newWidth = Math.round(imageWidth * (1/yScale));
  1934. newHeight = Math.round(imageHeight * (1/yScale));
  1935. }
  1936. else {
  1937. newWidth = Math.round(imageWidth * (1/xScale));
  1938. newHeight = Math.round(imageHeight * (1/xScale));
  1939. }
  1940. }
  1941. // Don't resize past the original size?
  1942. if(!this.get('crop') && !this.get('upsize') && (newWidth > imageWidth || newHeight > imageHeight)) {
  1943. newWidth = imageWidth;
  1944. newHeight = imageHeight;
  1945. }
  1946. // Compensate for borders.
  1947. newWidth -= borderWidth;
  1948. newHeight -= borderWidth;
  1949. // Resize the image.
  1950. this._image.setStyle('width', newWidth + 'px');
  1951. this._image.setStyle('height', newHeight + 'px');
  1952. // Constrain bounding box to image size.
  1953. if(!this.get('crop') && this.get('constrainWidth')) {
  1954. this.set('width', newWidth + 'px');
  1955. }
  1956. if(!this.get('crop') && this.get('constrainHeight')) {
  1957. this.set('height', newHeight + 'px');
  1958. }
  1959. },
  1960. /**
  1961. * Positions the image within the bounding box.
  1962. *
  1963. * @method _positionImage
  1964. * @protected
  1965. */
  1966. _positionImage: function()
  1967. {
  1968. var pos = this.get('position').split(' '),
  1969. x = pos[0] === '' ? 'center' : pos[0],
  1970. y = pos[1] === '' ? 'center' : pos[1],
  1971. newX = 0,
  1972. newY = 0,
  1973. bbWidth = parseInt(this.get('boundingBox').getComputedStyle('width'), 10),
  1974. bbHeight = parseInt(this.get('boundingBox').getComputedStyle('height'), 10),
  1975. borderWidth = parseInt(this._image.getComputedStyle('borderTopWidth'), 10) * 2,
  1976. imageWidth = parseInt(this._image.getComputedStyle('width'), 10) + borderWidth,
  1977. imageHeight = parseInt(this._image.getComputedStyle('height'), 10) + borderWidth;
  1978. if(isNaN(imageWidth) && isNaN(imageHeight)) {
  1979. return;
  1980. }
  1981. if(x == 'left') {
  1982. newX = 0;
  1983. }
  1984. if(x == 'center') {
  1985. newX = (bbWidth - imageWidth)/2;
  1986. }
  1987. if(x == 'right') {
  1988. newX = bbWidth - imageWidth;
  1989. }
  1990. if(y == 'top') {
  1991. newY = 0;
  1992. }
  1993. if(y == 'center') {
  1994. newY = (bbHeight - imageHeight)/2;
  1995. }
  1996. if(y == 'bottom') {
  1997. newY = bbHeight - imageHeight;
  1998. }
  1999. this._image.setStyles({
  2000. 'left': newX,
  2001. 'top': newY
  2002. });
  2003. },
  2004. /**
  2005. * Gets the appropriate image url based
  2006. * on the size of the bounding box.
  2007. *
  2008. * @method _getImageURL
  2009. * @return {String} The url to load.
  2010. * @protected
  2011. */
  2012. _getImageURL: function()
  2013. {
  2014. var imageWidth = 0,
  2015. imageHeight = 0,
  2016. size = 0,
  2017. targetWidth = this.get('width'),
  2018. targetHeight = this.get('height'),
  2019. useThumbSizes = this.get('useThumbSizes'),
  2020. i = this._imageInfo,
  2021. sizes = [
  2022. i.tinyURL || i.thumbURL || i.largeURL,
  2023. i.thumbURL || i.largeURL,
  2024. i.smallURL || i.largeURL,
  2025. i.mediumURL || i.largeURL || i.smallURL,
  2026. i.largeURL || i.mediumURL || i.smallURL,
  2027. i.xlargeURL || i.largeURL || i.mediumURL || i.smallURL,
  2028. i.x2largeURL || i.largeURL || i.mediumURL || i.smallURL,
  2029. i.x3largeURL || i.x2largeURL || i.largeURL || i.mediumURL || i.smallURL
  2030. ];
  2031. // Width
  2032. if(useThumbSizes && targetWidth <= 100) {
  2033. imageWidth = 0;
  2034. }
  2035. else if(useThumbSizes && targetWidth <= 150) {
  2036. imageWidth = 1;
  2037. }
  2038. else if(targetWidth <= 400) {
  2039. imageWidth = 2;
  2040. }
  2041. else if(targetWidth >= 400 && targetWidth <= 600) {
  2042. imageWidth = 3;
  2043. }
  2044. else if(targetWidth >= 600 && targetWidth <= 800) {
  2045. imageWidth = 4;
  2046. }
  2047. else if(targetWidth >= 800 && targetWidth <= 1024) {
  2048. imageWidth = 5;
  2049. }
  2050. else if(targetWidth >= 1024 && targetWidth <= 1280) {
  2051. imageWidth = 6;
  2052. }
  2053. else {
  2054. imageWidth = 7;
  2055. }
  2056. // Height
  2057. if(useThumbSizes && targetHeight <= 100) {
  2058. imageHeight = 0;
  2059. }
  2060. else if(useThumbSizes && targetHeight <= 150) {
  2061. imageHeight = 1;
  2062. }
  2063. else if(targetHeight <= 300) {
  2064. imageHeight = 2;
  2065. }
  2066. else if(targetHeight >= 300 && targetHeight <= 450) {
  2067. imageHeight = 3;
  2068. }
  2069. else if(targetHeight >= 450 && targetHeight <= 600) {
  2070. imageHeight = 4;
  2071. }
  2072. else if(targetHeight >= 600 && targetHeight <= 768) {
  2073. imageHeight = 5;
  2074. }
  2075. else if(targetHeight >= 768 && targetHeight <= 960) {
  2076. imageHeight = 6;
  2077. }
  2078. else {
  2079. imageHeight = 7;
  2080. }
  2081. // Get the size number.
  2082. size = Math.max(imageWidth, imageHeight);
  2083. return sizes[size];
  2084. },
  2085. /**
  2086. * Checks whether this is a video or not.
  2087. *
  2088. * @method _isVideo
  2089. * @protected
  2090. */
  2091. _isVideo: function()
  2092. {
  2093. if(!this._imageInfo) {
  2094. return false;
  2095. }
  2096. else if(this._imageInfo.format == 'mp4' && this._imageInfo.sourceType == 'smugmug') {
  2097. return true;
  2098. }
  2099. else if(this._imageInfo.iframe !== '') {
  2100. return true;
  2101. }
  2102. return false;
  2103. },
  2104. /**
  2105. * @method _loadVideo
  2106. * @protected
  2107. */
  2108. _loadVideo: function()
  2109. {
  2110. var bb = this.get('boundingBox'),
  2111. showVideoButton = this.get('showVideoButton'),
  2112. autoPlay = showVideoButton ? true : false;
  2113. // Remove previous videos
  2114. if(this._video) {
  2115. this._video.remove();
  2116. this._video = null;
  2117. }
  2118. // Get the video code
  2119. if(this._imageInfo.format == 'mp4' && this._imageInfo.sourceType == 'smugmug') {
  2120. this._video = this._getSmugMugVideoEmbed(this._imageInfo, autoPlay);
  2121. }
  2122. else if(this._imageInfo.iframe !== '') {
  2123. this._video = this._getIframeVideoEmbed(this._imageInfo, autoPlay);
  2124. }
  2125. // Insert the video
  2126. if(this._videoBox) {
  2127. this._videoBox.one('.fl-slideshow-video-wrap').insert(this._video);
  2128. }
  2129. else {
  2130. bb.all('img').remove();
  2131. bb.append(this._video);
  2132. }
  2133. // Finish an initial load?
  2134. if(this._loading) {
  2135. this._loading = false;
  2136. this.fire('loadComplete');
  2137. }
  2138. },
  2139. /**
  2140. * @method _insertVideoButton
  2141. * @protected
  2142. */
  2143. _insertVideoButton: function()
  2144. {
  2145. var bb = this.get('boundingBox'),
  2146. event = 'ontouchstart' in window ? 'touchstart' : 'click';
  2147. this._videoButton = Y.Node.create('<a class="fl-slideshow-video-button" href="javascript:void(0);"></a>');
  2148. this._videoButton.on(event, Y.bind(this._showVideoBox, this));
  2149. bb.insert(this._videoButton);
  2150. this._positionVideoButton();
  2151. },
  2152. /**
  2153. * @method _positionVideoButton
  2154. * @protected
  2155. */
  2156. _positionVideoButton: function()
  2157. {
  2158. var bbWidth = this.get('width'),
  2159. bbHeight = this.get('height'),
  2160. buttonWidth = parseInt(this._videoButton.getStyle('width'), 10),
  2161. buttonHeight = parseInt(this._videoButton.getStyle('height'), 10);
  2162. this._videoButton.setStyles({
  2163. left: (bbWidth - buttonWidth)/2,
  2164. top: (bbHeight - buttonHeight)/2
  2165. });
  2166. },
  2167. /**
  2168. * @method _showVideoBox
  2169. * @protected
  2170. */
  2171. _showVideoBox: function()
  2172. {
  2173. var root = this.get('root'),
  2174. wrap = Y.Node.create('<div class="fl-slideshow-video-wrap"></div>'),
  2175. close = Y.Node.create('<a class="fl-slideshow-video-close" href="javascript:void(0);"></a>'),
  2176. event = 'ontouchstart' in window ? 'touchstart' : 'click';
  2177. this._videoBox = Y.Node.create('<div class="fl-slideshow-video"></div>');
  2178. this._videoBox.setStyle('padding', root.get('boundingBox').getStyle('padding'));
  2179. this._videoBox.insert(wrap);
  2180. this._videoBox.insert(close);
  2181. this._videoBox.on(event, Y.bind(this._removeVideoBox, this));
  2182. close.on(event, Y.bind(this._removeVideoBox, this));
  2183. if(typeof YUI.Env.mods['sm-fonticon'] !== 'undefined') {
  2184. close.addClass('sm-fonticon sm-fonticon-XCrossEncircled sm-button-skin-default sm-button-nochrome');
  2185. }
  2186. Y.one('body').insert(this._videoBox);
  2187. this._loadVideo();
  2188. Y.one('body').on('fl-slideshow-image|keydown', this._onKey, this);
  2189. },
  2190. /**
  2191. * Get the embed code for a SmugMug video.
  2192. *
  2193. * @method _getSmugMugVideoEmbed
  2194. * @param imageInfo {Object} The image info for the embed.
  2195. * @param autoPlay {Boolean} Whether to auto play videos or not.
  2196. * @protected
  2197. */
  2198. _getSmugMugVideoEmbed: function(imageInfo, autoPlay)
  2199. {
  2200. var test = document.createElement('video'),
  2201. width = 0,
  2202. mp4 = '',
  2203. vars = '',
  2204. code = '';
  2205. if(Y.UA.mobile !== null && !!test.canPlayType && test.canPlayType('video/mp4')) {
  2206. width = this.get('width');
  2207. mp4 = 'https://www.smugmug.com/photos/' + imageInfo.id + '_' + imageInfo.key + '-' + width + '.mp4';
  2208. code += '<video width="100%" height="100%" poster="'+ this._getImageURL() +'" controls preload="none"';
  2209. if(autoPlay) {
  2210. code += ' autoplay';
  2211. }
  2212. code += '>';
  2213. code += '<source src="'+ mp4 +'" type="video/mp4" />';
  2214. code += '</video>';
  2215. }
  2216. else {
  2217. vars = 'imageId=' + imageInfo.id;
  2218. vars += '&amp;imageKey=' + imageInfo.key;
  2219. vars += '&amp;albumId=' + imageInfo.albumId;
  2220. vars += '&amp;albumKey=' + imageInfo.albumKey;
  2221. vars += '&amp;apiURL=https://api.smugmug.com/&amp;hostLevel=live&amp;isPro=true';
  2222. if(autoPlay) {
  2223. vars += '&amp;autoPlay=true';
  2224. }
  2225. else {
  2226. vars += '&amp;autoPlay=false';
  2227. }
  2228. code += '<object type="application/x-shockwave-flash" width="100%" height="100%" data="https://cdn.smugmug.com/img/ria/SmugPlayer/2012102601.swf">';
  2229. code += '<param name="movie" value="https://cdn.smugmug.com/img/ria/SmugPlayer/2012102601.swf">';
  2230. code += '<param name="allowFullScreen" value="true">';
  2231. code += '<param name="wmode" value="transparent">';
  2232. code += '<param name="flashVars" value="' + vars + '">';
  2233. code += '<embed src="https://cdn.smugmug.com/img/ria/SmugPlayer/2012102601.swf" flashvars="'+ vars +'" width="100%" height="100%" type="application/x-shockwave-flash" allowfullscreen="true" wmode="transparent">';
  2234. code += '</object>';
  2235. }
  2236. return Y.Node.create(code);
  2237. },
  2238. /**
  2239. * Get the iframe video embed code.
  2240. *
  2241. * @method _getIframeVideoEmbed
  2242. * @param imageInfo {Object} The image info for the embed.
  2243. * @param autoPlay {Boolean} Whether to auto play videos or not.
  2244. * @protected
  2245. */
  2246. _getIframeVideoEmbed: function(imageInfo, autoPlay)
  2247. {
  2248. var code = '<iframe width="100%" height="100%" frameborder="0" allowfullscreen ',
  2249. url = imageInfo.iframe;
  2250. if(autoPlay) {
  2251. url += url.indexOf('?') > -1 ? '&autoplay=1' : '?autoplay=1';
  2252. }
  2253. code += 'src="'+ url +'"></iframe>';
  2254. return Y.Node.create(code);
  2255. },
  2256. /**
  2257. * @method _removeVideoBox
  2258. * @protected
  2259. */
  2260. _removeVideoBox: function(e)
  2261. {
  2262. if(typeof e !== 'undefined' && e.target) {
  2263. if(e.target.get('className').indexOf('fl-slideshow-video') < 0) {
  2264. return;
  2265. }
  2266. }
  2267. if(this._videoBox !== null) {
  2268. this._videoBox.remove();
  2269. this._videoBox = null;
  2270. this._video = null;
  2271. }
  2272. Y.one('body').detach('fl-slideshow-image|keydown', this._onKey);
  2273. },
  2274. /**
  2275. * Keyboard input for the esc button.
  2276. *
  2277. * @method _onKey
  2278. * @protected
  2279. */
  2280. _onKey: function(e)
  2281. {
  2282. if(e.keyCode == 27) {
  2283. this._removeVideoBox();
  2284. return false;
  2285. }
  2286. }
  2287. }, {
  2288. /**
  2289. * Custom CSS class name for the widget.
  2290. * @property CSS_PREFIX
  2291. * @type String
  2292. * @protected
  2293. * @static
  2294. */
  2295. CSS_PREFIX: 'fl-slideshow-image',
  2296. /**
  2297. * Static property used to define the default attribute configuration of
  2298. * the Widget.
  2299. *
  2300. * @property ATTRS
  2301. * @type Object
  2302. * @protected
  2303. * @static
  2304. */
  2305. ATTRS: {
  2306. /**
  2307. * @attribute loadGroup
  2308. * @type String
  2309. * @default none
  2310. */
  2311. loadGroup: {
  2312. value: 'none'
  2313. },
  2314. /**
  2315. * @attribute loadPriority
  2316. * @type Boolean
  2317. * @default false
  2318. */
  2319. loadPriority: {
  2320. value: false
  2321. },
  2322. /**
  2323. * Whether to crop the image.
  2324. *
  2325. * @attribute crop
  2326. * @type Boolean
  2327. * @default false
  2328. */
  2329. crop: {
  2330. value: false
  2331. },
  2332. /**
  2333. * Checks whether the filename has nocrop in it or not.
  2334. * If it does, the image will not be cropped.
  2335. *
  2336. * @attribute checkFilenamesForNoCrop
  2337. * @type Boolean
  2338. * @default true
  2339. */
  2340. checkFilenamesForNoCrop: {
  2341. value: true
  2342. },
  2343. /**
  2344. * Whether to only crop horizontal images or not.
  2345. *
  2346. * @attribute cropHorizontalsOnly
  2347. * @type Boolean
  2348. * @default false
  2349. */
  2350. cropHorizontalsOnly: {
  2351. value: false
  2352. },
  2353. /**
  2354. * The x and y position of the image
  2355. * within the bounding box.
  2356. *
  2357. * @attribute position
  2358. * @type String
  2359. * @default center center
  2360. */
  2361. position: {
  2362. value: 'center center'
  2363. },
  2364. /**
  2365. * Whether to right click protect the image.
  2366. *
  2367. * @attribute protect
  2368. * @type Boolean
  2369. * @default true
  2370. */
  2371. protect: {
  2372. value: true
  2373. },
  2374. /**
  2375. * Whether to resize the image past
  2376. * its original width and height.
  2377. *
  2378. * @attribute upsize
  2379. * @type Boolean
  2380. * @default true
  2381. */
  2382. upsize: {
  2383. value: true
  2384. },
  2385. /**
  2386. * Whether to load thumb sizes. Defaults
  2387. * to false since thumb sizes are square.
  2388. *
  2389. * @attribute useThumbSizes
  2390. * @type Boolean
  2391. * @default false
  2392. */
  2393. useThumbSizes: {
  2394. value: false
  2395. },
  2396. /**
  2397. * Whether to constrain the width of the
  2398. * bounding box to the width of the image.
  2399. *
  2400. * @attribute constrainWidth
  2401. * @type Boolean
  2402. * @default false
  2403. */
  2404. constrainWidth: {
  2405. value: false
  2406. },
  2407. /**
  2408. * Whether to constrain the height of the
  2409. * bounding box to the height of the image.
  2410. *
  2411. * @attribute constrainHeight
  2412. * @type Boolean
  2413. * @default false
  2414. */
  2415. constrainHeight: {
  2416. value: false
  2417. },
  2418. /**
  2419. * Whether to load videos or not. The poster
  2420. * image will be loaded if set to false.
  2421. *
  2422. * @attribute loadVideos
  2423. * @type Boolean
  2424. * @default true
  2425. */
  2426. loadVideos: {
  2427. value: true
  2428. },
  2429. /**
  2430. * Whether to show the video play button or not.
  2431. * When clicked, videos will be displayed in a
  2432. * lightbox instead of the slideshow itself.
  2433. *
  2434. * @attribute showVideoButton
  2435. * @type Boolean
  2436. * @default true
  2437. */
  2438. showVideoButton: {
  2439. value: true
  2440. }
  2441. }
  2442. });
  2443. /**
  2444. * A plugin that turns the cursor into a prev or next arrow when
  2445. * it is over the left or right side of the slideshow.
  2446. *
  2447. * @namespace FL
  2448. * @class SlideshowMouseNav
  2449. * @constructor
  2450. * @param config {Object} Configuration object
  2451. * @extends Plugin.Base
  2452. */
  2453. Y.namespace('FL').SlideshowMouseNav = Y.Base.create('fl-slideshow-mouse-nav', Y.Plugin.Base, [], {
  2454. /**
  2455. * @method initializer
  2456. * @protected
  2457. */
  2458. initializer: function()
  2459. {
  2460. var trigger = this.get('trigger');
  2461. trigger.on('click', this._triggerClick, this);
  2462. trigger.on('mousemove', this._showArrow, this);
  2463. trigger.on('mouseleave', this._hideArrow, this);
  2464. },
  2465. /**
  2466. * @method _triggerClick
  2467. * @protected
  2468. */
  2469. _triggerClick: function(e)
  2470. {
  2471. var host = this.get('host'),
  2472. trigger = this.get('trigger'),
  2473. triggerWidth = parseInt(trigger.getStyle('width'), 10),
  2474. triggerRegion = trigger.get('region'),
  2475. layerX = e.pageX - triggerRegion.left + 5;
  2476. if(layerX >= triggerWidth/2) {
  2477. host.nextImage();
  2478. }
  2479. else {
  2480. host.prevImage();
  2481. }
  2482. },
  2483. /**
  2484. * @method _showArrow
  2485. * @protected
  2486. */
  2487. _showArrow: function(e)
  2488. {
  2489. var host = this.get('host'),
  2490. trigger = this.get('trigger'),
  2491. triggerWidth = parseInt(trigger.getStyle('width'), 10),
  2492. triggerRegion = trigger.get('region'),
  2493. layerX = e.pageX - triggerRegion.left + 5;
  2494. if(host.albumInfo !== null && host.albumInfo.images.length > 1) {
  2495. if(layerX >= triggerWidth/2) {
  2496. trigger.removeClass('fl-slideshow-mouse-nav-prev');
  2497. trigger.addClass('fl-slideshow-mouse-nav-next');
  2498. }
  2499. else {
  2500. trigger.removeClass('fl-slideshow-mouse-nav-next');
  2501. trigger.addClass('fl-slideshow-mouse-nav-prev');
  2502. }
  2503. }
  2504. },
  2505. /**
  2506. * @method _hideArrow
  2507. * @protected
  2508. */
  2509. _hideArrow: function()
  2510. {
  2511. var trigger = this.get('trigger');
  2512. trigger.removeClass('fl-slideshow-mouse-nav-next');
  2513. trigger.removeClass('fl-slideshow-mouse-nav-prev');
  2514. }
  2515. }, {
  2516. /**
  2517. * Namespace for the plugin.
  2518. *
  2519. * @property NS
  2520. * @type String
  2521. * @protected
  2522. * @static
  2523. */
  2524. NS: 'mouseNav',
  2525. /**
  2526. * Static property used to define the default attribute configuration of
  2527. * the Plugin.
  2528. *
  2529. * @property ATTRS
  2530. * @type Object
  2531. * @protected
  2532. * @static
  2533. */
  2534. ATTRS: {
  2535. /**
  2536. * A Node that triggers the arrows.
  2537. *
  2538. * @attribute trigger
  2539. * @type Node
  2540. * @default null
  2541. */
  2542. trigger: {
  2543. value: null
  2544. }
  2545. }
  2546. });
  2547. /**
  2548. * Ken Burns effect for slideshow images.
  2549. *
  2550. * @namespace FL
  2551. * @class SlideshowKenBurns
  2552. * @constructor
  2553. * @param config {Object} Configuration object
  2554. * @extends Base
  2555. */
  2556. Y.namespace('FL').SlideshowKenBurns = Y.Base.create('fl-slideshow-ken-burns', Y.Base, [], {
  2557. /**
  2558. * Runs the Ken Burns effect.
  2559. *
  2560. * @method run
  2561. */
  2562. run: function()
  2563. {
  2564. var imageNode = null,
  2565. transform = null;
  2566. if(Y.FL.Utils.cssSupport('transform')) {
  2567. // Image node
  2568. imageNode = this.get('image').one('img');
  2569. // Transform object
  2570. transform = this._getTransform();
  2571. // Apply the start transform
  2572. imageNode.setStyles({
  2573. '-webkit-transform-origin': transform.origin,
  2574. '-moz-transform-origin': transform.origin,
  2575. '-ms-transform-origin': transform.origin,
  2576. 'transform-origin': transform.origin,
  2577. 'transform': transform.start
  2578. });
  2579. // Transition to the end transform
  2580. imageNode.transition({
  2581. easing: 'ease-out',
  2582. duration : this.get('duration'),
  2583. 'transform' : transform.end
  2584. });
  2585. }
  2586. },
  2587. /**
  2588. * @method _getTransform
  2589. * @protected
  2590. */
  2591. _getTransform: function()
  2592. {
  2593. var zoom = this.get('zoom'),
  2594. image = this.get('image'),
  2595. i = 0,
  2596. zoomDirection = null,
  2597. transform = null;
  2598. // Random zoom direction
  2599. i = Math.floor(Math.random() * Y.FL.SlideshowKenBurns.ZOOM_DIRECTIONS.length);
  2600. zoomDirection = Y.FL.SlideshowKenBurns.ZOOM_DIRECTIONS[i];
  2601. // Random transform
  2602. i = Math.floor(Math.random() * Y.FL.SlideshowKenBurns.TRANSFORMS.length);
  2603. transform = Y.FL.SlideshowKenBurns.TRANSFORMS[i];
  2604. // Get the start and end transforms
  2605. if(!image.hasClass('fl-slideshow-image-cropped') && zoomDirection == 'in') {
  2606. i = Math.floor(Math.random() * 2);
  2607. transform.start = i === 0 ? 'scale(1) translate(100px, 0)' : 'scale(1) translate(-100px, 0)';
  2608. transform.end = 'scale(' + zoom + ') translate(0, 0)';
  2609. transform.origin = 'center center';
  2610. }
  2611. else if(zoomDirection == 'out') {
  2612. transform.start = 'scale(' + zoom + ') ' + transform.translate;
  2613. transform.end = 'scale(1) translate(0, 0)';
  2614. }
  2615. else {
  2616. transform.start = 'scale(1) translate(0, 0)';
  2617. transform.end = 'scale(' + zoom + ') ' + transform.translate;
  2618. }
  2619. return transform;
  2620. }
  2621. }, {
  2622. /**
  2623. * Static property used to define the default attribute configuration of
  2624. * the Widget.
  2625. *
  2626. * @property ATTRS
  2627. * @type Object
  2628. * @protected
  2629. * @static
  2630. */
  2631. ATTRS: {
  2632. /**
  2633. * An instance of FL.Slideshow image to apply the
  2634. * Ken Burns effect on.
  2635. *
  2636. * @attribute image
  2637. * @type FL.Slideshow
  2638. * @default null
  2639. */
  2640. image: {
  2641. value: null
  2642. },
  2643. /**
  2644. * The amount to zoom the image. Zooming
  2645. * in our out is done randomly by this class.
  2646. *
  2647. * @attribute scale
  2648. * @type Number
  2649. * @default 1.2
  2650. */
  2651. zoom: {
  2652. value: 1.2
  2653. },
  2654. /**
  2655. * The duration of the effect in seconds.
  2656. *
  2657. * @attribute duration
  2658. * @type Number
  2659. * @default 2
  2660. */
  2661. duration: {
  2662. value: 2
  2663. }
  2664. },
  2665. /**
  2666. * The zoom directions that can be applied to an image.
  2667. *
  2668. * @property ZOOM_DIRECTIONS
  2669. * @type Object
  2670. * @readOnly
  2671. * @protected
  2672. * @static
  2673. */
  2674. ZOOM_DIRECTIONS: [
  2675. 'in',
  2676. 'out'
  2677. ],
  2678. /**
  2679. * The types of transforms that can be applied to an image.
  2680. *
  2681. * @property TRANSFORMS
  2682. * @type Object
  2683. * @readOnly
  2684. * @protected
  2685. * @static
  2686. */
  2687. TRANSFORMS: [
  2688. {
  2689. origin : 'left top',
  2690. translate : 'translate(-30px, -15px)'
  2691. },{
  2692. origin : 'left center',
  2693. translate : 'translate(-30px, 0)'
  2694. },{
  2695. origin : 'left bottom',
  2696. translate : 'translate(-30px, 15px)'
  2697. },{
  2698. origin : 'right top',
  2699. translate : 'translate(30px, -15px)'
  2700. },{
  2701. origin : 'right center',
  2702. translate : 'translate(30px, 0)'
  2703. },{
  2704. origin : 'right bottom',
  2705. translate : 'translate(30px, 15px)'
  2706. }
  2707. ]
  2708. });
  2709. /**
  2710. * Navigation buttons widget for controlling a slideshow instance
  2711. * and its child widgets.
  2712. *
  2713. * @namespace FL
  2714. * @class SlideshowNav
  2715. * @constructor
  2716. * @param config {Object} Configuration object
  2717. * @extends Widget
  2718. */
  2719. Y.namespace('FL').SlideshowNav = Y.Base.create('fl-slideshow-nav', Y.Widget, [Y.WidgetChild], {
  2720. /**
  2721. * An object containing the anchor nodes for all buttons.
  2722. *
  2723. * @property _buttons
  2724. * @type Object
  2725. * @default null
  2726. * @protected
  2727. */
  2728. _buttons: null,
  2729. /**
  2730. * An div node containing the anchor nodes for the main buttons.
  2731. *
  2732. * @property _buttonsContainer
  2733. * @type Object
  2734. * @default null
  2735. * @protected
  2736. */
  2737. _buttonsContainer: null,
  2738. /**
  2739. * An div node containing the anchor nodes for the left buttons.
  2740. *
  2741. * @property _buttonsLeftContainer
  2742. * @type Object
  2743. * @default null
  2744. * @protected
  2745. */
  2746. _buttonsLeftContainer: null,
  2747. /**
  2748. * An div node containing the anchor nodes for the right buttons.
  2749. *
  2750. * @property _buttonsRightContainer
  2751. * @type Object
  2752. * @default null
  2753. * @protected
  2754. */
  2755. _buttonsRightContainer: null,
  2756. /**
  2757. * Property map for rendering SmugMug font icons.
  2758. *
  2759. * @property _fontIcons
  2760. * @type Object
  2761. * @protected
  2762. */
  2763. _fontIcons: {
  2764. buy: 'Cart',
  2765. caption: 'InfoEncircled',
  2766. close: 'XCrossEncircled',
  2767. fullscreen: 'ScreenExpand',
  2768. next: 'ArrowRight',
  2769. nextPage: 'ArrowRight',
  2770. pause: 'PlayerPause',
  2771. play: 'PlayerPlay',
  2772. prev: 'ArrowLeft',
  2773. prevPage: 'ArrowLeft',
  2774. social: 'Heart',
  2775. thumbs: 'ViewThumbGrid'
  2776. },
  2777. /**
  2778. * The default content template for the nav
  2779. * inherited from Y.Widget. Set to null since
  2780. * only the bounding box is needed.
  2781. *
  2782. * @property CONTENT_TEMPLATE
  2783. * @type String
  2784. * @default null
  2785. * @protected
  2786. */
  2787. CONTENT_TEMPLATE: null,
  2788. /**
  2789. * Renders the buttons.
  2790. *
  2791. * @method renderUI
  2792. * @protected
  2793. */
  2794. renderUI: function()
  2795. {
  2796. this._renderContainers();
  2797. this._renderButtons();
  2798. this._renderFontIcons();
  2799. },
  2800. /**
  2801. * Binds events to the root slideshow for each button.
  2802. *
  2803. * @method bindUI
  2804. * @protected
  2805. */
  2806. bindUI: function()
  2807. {
  2808. var root = this.get('root'),
  2809. id = this.get('id');
  2810. if(this._buttons.prev) {
  2811. this._buttons.prev.on('click', root.prevImage, root);
  2812. }
  2813. if(this._buttons.next) {
  2814. this._buttons.next.on('click', root.nextImage, root);
  2815. }
  2816. if(this._buttons.play) {
  2817. this._buttons.play.on('click', this._playClicked, this);
  2818. root.on(id + '|played', this._showPauseButton, this);
  2819. root.on(id + '|paused', this._showPlayButton, this);
  2820. if(root._playing) {
  2821. this._showPauseButton();
  2822. }
  2823. else {
  2824. this._showPlayButton();
  2825. }
  2826. }
  2827. if(this._buttons.buy) {
  2828. root.on(id + '|albumLoadComplete', this._updateBuy, this);
  2829. if(root.albumInfo !== null) {
  2830. this._updateBuy();
  2831. }
  2832. }
  2833. if(this._buttons.count) {
  2834. root.on(id + '|imageLoadComplete', this._updateCount, this);
  2835. }
  2836. if(this._buttons.thumbs) {
  2837. this._buttons.thumbs.on('click', root._toggleThumbs, root);
  2838. }
  2839. if(this._buttons.caption) {
  2840. root.on(id + '|imageLoadComplete', this._updateCaption, this);
  2841. this._updateCaption();
  2842. }
  2843. if(this._buttons.social) {
  2844. this._buttons.social.on('click', root._toggleSocial, root);
  2845. }
  2846. if(this._buttons.fullscreen && root.fullscreen) {
  2847. this._buttons.fullscreen.on('click', root.fullscreen.toggle, root.fullscreen);
  2848. }
  2849. if(this._buttons.close) {
  2850. this._buttons.close.on('click', root.hide, root);
  2851. }
  2852. },
  2853. /**
  2854. * @method destructor
  2855. * @protected
  2856. */
  2857. destructor: function()
  2858. {
  2859. var root = this.get('root'),
  2860. id = this.get('id');
  2861. root.detach(id + '|*');
  2862. },
  2863. /**
  2864. * Renders the button left, right and main button containers.
  2865. *
  2866. * @method _renderContainers
  2867. * @protected
  2868. */
  2869. _renderContainers: function()
  2870. {
  2871. var cb = this.get('contentBox'),
  2872. buttonsLeft = this.get('buttonsLeft'),
  2873. buttonsRight = this.get('buttonsRight');
  2874. this._buttonsContainer = Y.Node.create('<div></div>');
  2875. this._buttonsContainer.addClass('fl-slideshow-nav-buttons');
  2876. cb.appendChild(this._buttonsContainer);
  2877. if(buttonsLeft.length > 0) {
  2878. this._buttonsLeftContainer = Y.Node.create('<div></div>');
  2879. this._buttonsLeftContainer.addClass('fl-slideshow-nav-buttons-left');
  2880. cb.appendChild(this._buttonsLeftContainer);
  2881. }
  2882. if(buttonsRight.length > 0) {
  2883. this._buttonsRightContainer = Y.Node.create('<div></div>');
  2884. this._buttonsRightContainer.addClass('fl-slideshow-nav-buttons-right');
  2885. cb.appendChild(this._buttonsRightContainer);
  2886. }
  2887. },
  2888. /**
  2889. * Renders the buttons based on the buttons array
  2890. * passed in the configuration object.
  2891. *
  2892. * @method _renderButtons
  2893. * @protected
  2894. */
  2895. _renderButtons: function()
  2896. {
  2897. var name = '',
  2898. i = 0,
  2899. k = 0,
  2900. b = [
  2901. {
  2902. names: this.get('buttons'),
  2903. container: this._buttonsContainer
  2904. },
  2905. {
  2906. names: this.get('buttonsLeft'),
  2907. container: this._buttonsLeftContainer
  2908. },
  2909. {
  2910. names: this.get('buttonsRight'),
  2911. container: this._buttonsRightContainer
  2912. }
  2913. ];
  2914. this._buttons = {};
  2915. for( ; i < b.length; i++) {
  2916. for(k = 0; k < b[i].names.length; k++) {
  2917. name = b[i].names[k];
  2918. if(name.indexOf('count') > -1) {
  2919. this._buttons[name] = Y.Node.create('<span></span>');
  2920. this._updateCount();
  2921. }
  2922. else {
  2923. this._buttons[name] = Y.Node.create('<a href="javascript:void(0);"></a>');
  2924. }
  2925. if(name.indexOf('buy') > -1) {
  2926. this._buttons[name].setStyle('display', 'none');
  2927. }
  2928. this._buttons[name].set('name', name);
  2929. this._buttons[name].addClass('fl-slideshow-nav-' + name);
  2930. b[i].container.appendChild(this._buttons[name]);
  2931. }
  2932. }
  2933. },
  2934. /**
  2935. * Renders SmugMug font icons for each button.
  2936. *
  2937. * @method _renderFontIcons
  2938. * @protected
  2939. */
  2940. _renderFontIcons: function()
  2941. {
  2942. var name = null;
  2943. if(this.get('useFontIcons') && typeof YUI.Env.mods['sm-fonticon'] !== 'undefined') {
  2944. for(name in this._buttons) {
  2945. if(typeof this._buttons[name] !== 'undefined' && typeof this._fontIcons[name] !== 'undefined') {
  2946. this._buttons[name].addClass('sm-fonticon-' + this._fontIcons[name]);
  2947. this._buttons[name].addClass('sm-fonticon sm-button-skin-default sm-button-nochrome');
  2948. }
  2949. else if(name.indexOf('count') > -1) {
  2950. this._buttons[name].addClass('fonticons-enabled');
  2951. }
  2952. }
  2953. }
  2954. },
  2955. /**
  2956. * Updates the image count.
  2957. *
  2958. * @method _updateCount
  2959. * @protected
  2960. */
  2961. _updateCount: function()
  2962. {
  2963. var html = '',
  2964. countText = Y.FL.SlideshowNav.COUNT_TEXT,
  2965. current = 1,
  2966. total = 1;
  2967. if(this.get('root').albumInfo) {
  2968. current = this.get('root').imageInfo.index + 1;
  2969. total = this.get('root').albumInfo.images.length;
  2970. }
  2971. html = countText.replace('{current}', current).replace('{total}', total);
  2972. this._buttons.count.set('innerHTML', html);
  2973. },
  2974. /**
  2975. * Shows the caption button if the current image
  2976. * has a caption, hides it if the image does not
  2977. * have a caption.
  2978. *
  2979. * @method _updateCaption
  2980. * @protected
  2981. */
  2982. _updateCaption: function()
  2983. {
  2984. var root = this.get('root'),
  2985. imageInfo = root.imageInfo;
  2986. if(imageInfo && imageInfo.caption === '') {
  2987. root.caption.slideshowOverlay.enable();
  2988. root.caption.slideshowOverlay.hide();
  2989. this._buttons.caption.detach('click');
  2990. this._buttons.caption.addClass('fl-slideshow-nav-caption-disabled');
  2991. }
  2992. else {
  2993. this._buttons.caption.on('click', root._toggleCaption, root);
  2994. this._buttons.caption.removeClass('fl-slideshow-nav-caption-disabled');
  2995. }
  2996. },
  2997. /**
  2998. * Checks if buying has been enabled for the current album.
  2999. *
  3000. * @method _updateBuy
  3001. * @protected
  3002. */
  3003. _updateBuy: function()
  3004. {
  3005. var sm = null,
  3006. root = this.get('root'),
  3007. rootSource = root.get('source')[root.albumIndex],
  3008. albumIndex = root.albumIndex,
  3009. source = root.get('source')[albumIndex];
  3010. if(rootSource && rootSource.type == 'smugmug') {
  3011. if(typeof root.albumInfo.printable !== 'undefined') {
  3012. this._updateBuyComplete();
  3013. }
  3014. else {
  3015. sm = new Y.FL.SmugMugAPI();
  3016. sm.addParam('method', 'smugmug.albums.getInfo');
  3017. sm.addParam('AlbumID', source.id);
  3018. sm.addParam('AlbumKey', source.key);
  3019. sm.on('complete', this._updateBuyComplete, this);
  3020. sm.request();
  3021. }
  3022. }
  3023. },
  3024. /**
  3025. * Shows the buy button and updates the buy url
  3026. * if buying has been enabled.
  3027. *
  3028. * @method _updateBuyComplete
  3029. * @param e {Object} The custom event object passed to this function.
  3030. * @protected
  3031. */
  3032. _updateBuyComplete: function(e)
  3033. {
  3034. var root = this.get('root'),
  3035. printable = typeof e == 'undefined' ? root.albumInfo.printable : e.Album.Printable,
  3036. link = root.albumInfo.link;
  3037. if(printable) {
  3038. root.albumInfo.printable = true;
  3039. this._buttons.buy.set('href', 'https://secure.smugmug.com/cart/batchadd/?url=' + encodeURIComponent(link));
  3040. this._buttons.buy.setStyle('display', 'inline-block');
  3041. }
  3042. else {
  3043. root.albumInfo.printable = false;
  3044. this._buttons.buy.setStyle('display', 'none');
  3045. }
  3046. this.fire('resize');
  3047. },
  3048. /**
  3049. * Pauses the slideshow if it is playing and
  3050. * plays the slideshow if it is paused.
  3051. *
  3052. * @method _playClicked
  3053. * @protected
  3054. */
  3055. _playClicked: function()
  3056. {
  3057. var root = this.get('root');
  3058. if(root._playing) {
  3059. root.pause();
  3060. }
  3061. else {
  3062. root.play();
  3063. }
  3064. },
  3065. /**
  3066. * Toggles the button class for the play button
  3067. * so pause is hidden and play is shown.
  3068. *
  3069. * @method _showPlayButton
  3070. * @protected
  3071. */
  3072. _showPlayButton: function()
  3073. {
  3074. this._buttons.play.removeClass('fl-slideshow-nav-pause');
  3075. this._buttons.play.addClass('fl-slideshow-nav-play');
  3076. if(this.get('useFontIcons') && typeof YUI.Env.mods['sm-fonticon'] !== 'undefined') {
  3077. this._buttons.play.removeClass('sm-fonticon-PlayerPause');
  3078. this._buttons.play.addClass('sm-fonticon-PlayerPlay');
  3079. }
  3080. },
  3081. /**
  3082. * Toggles the button class for the play button
  3083. * so pause is shown and play is hidden.
  3084. *
  3085. * @method _showPauseButton
  3086. * @protected
  3087. */
  3088. _showPauseButton: function()
  3089. {
  3090. this._buttons.play.removeClass('fl-slideshow-nav-play');
  3091. this._buttons.play.addClass('fl-slideshow-nav-pause');
  3092. if(this.get('useFontIcons') && typeof YUI.Env.mods['sm-fonticon'] !== 'undefined') {
  3093. this._buttons.play.removeClass('sm-fonticon-PlayerPlay');
  3094. this._buttons.play.addClass('sm-fonticon-PlayerPause');
  3095. }
  3096. }
  3097. }, {
  3098. /**
  3099. * Custom CSS class name for the widget.
  3100. *
  3101. * @property CSS_PREFIX
  3102. * @type String
  3103. * @protected
  3104. * @static
  3105. */
  3106. CSS_PREFIX: 'fl-slideshow-nav',
  3107. /**
  3108. * Static string used for displaying the image count. Use {current}
  3109. * for the current image and {total} for the total number of images.
  3110. * Those placeholders will be replaced when the count node is created.
  3111. *
  3112. * @property COUNT_TEXT
  3113. * @type String
  3114. * @protected
  3115. * @static
  3116. */
  3117. COUNT_TEXT: '{current} of {total}',
  3118. /**
  3119. * Static property used to define the default attribute configuration of
  3120. * the Widget.
  3121. *
  3122. * @property ATTRS
  3123. * @type Object
  3124. * @protected
  3125. * @static
  3126. */
  3127. ATTRS: {
  3128. /**
  3129. * An array of button names that is used to render the main buttons.
  3130. *
  3131. * @attribute buttons
  3132. * @type Array
  3133. * @default []
  3134. * @writeOnce
  3135. */
  3136. buttons: {
  3137. value: [],
  3138. writeOnce: true
  3139. },
  3140. /**
  3141. * An array of button names that is used to render the left buttons.
  3142. *
  3143. * @attribute buttonsLeft
  3144. * @type Array
  3145. * @default []
  3146. * @writeOnce
  3147. */
  3148. buttonsLeft: {
  3149. value: [],
  3150. writeOnce: true
  3151. },
  3152. /**
  3153. * An array of button names that is used to render the right buttons.
  3154. *
  3155. * @attribute buttonsRight
  3156. * @type Array
  3157. * @default []
  3158. * @writeOnce
  3159. */
  3160. buttonsRight: {
  3161. value: [],
  3162. writeOnce: true
  3163. },
  3164. /**
  3165. * Whether to use font icons when available.
  3166. *
  3167. * @attribute useFontIcons
  3168. * @type Boolean
  3169. * @default true
  3170. * @writeOnce
  3171. */
  3172. useFontIcons: {
  3173. value: true,
  3174. writeOnce: true
  3175. }
  3176. }
  3177. });
  3178. /**
  3179. * A plugin for overlaying widgets in a slideshow
  3180. * with specialized show and hide functionality.
  3181. *
  3182. * @namespace FL
  3183. * @class SlideshowOverlay
  3184. * @constructor
  3185. * @param config {Object} Configuration object
  3186. * @extends Plugin.Base
  3187. */
  3188. Y.namespace('FL').SlideshowOverlay = Y.Base.create('fl-slideshow-overlay', Y.Plugin.Base, [], {
  3189. /**
  3190. * Flag for whether the mouse has entered
  3191. * the host's bounding box.
  3192. *
  3193. * @property _focus
  3194. * @type Boolean
  3195. * @default false
  3196. * @protected
  3197. */
  3198. _focus: false,
  3199. /**
  3200. * Flag for whether the host's bounding box is visible.
  3201. *
  3202. * @property _visible
  3203. * @type Boolean
  3204. * @default true
  3205. * @protected
  3206. */
  3207. _visible: true,
  3208. /**
  3209. * Flag for whether show and hide functionality
  3210. * has been disabled.
  3211. *
  3212. * @property _disabled
  3213. * @type Boolean
  3214. * @default false
  3215. * @protected
  3216. */
  3217. _disabled: false,
  3218. /**
  3219. * An object containing properties for the show transition.
  3220. *
  3221. * @property _showProps
  3222. * @type Object
  3223. * @protected
  3224. */
  3225. _showProps: {
  3226. duration: 0.5,
  3227. easing: 'ease-out',
  3228. opacity: 1
  3229. },
  3230. /**
  3231. * An object containing properties for the hide transition.
  3232. *
  3233. * @property _hideProps
  3234. * @type Object
  3235. * @protected
  3236. */
  3237. _hideProps: {
  3238. duration: 0.5,
  3239. easing: 'ease-out',
  3240. opacity: 0
  3241. },
  3242. /**
  3243. * A timer object for delaying the hide transition.
  3244. *
  3245. * @property _hideTimer
  3246. * @type Object
  3247. * @default null
  3248. * @protected
  3249. */
  3250. _hideTimer: null,
  3251. /**
  3252. * @method initializer
  3253. * @protected
  3254. */
  3255. initializer: function()
  3256. {
  3257. var bb = this.get('host').get('boundingBox');
  3258. this.afterHostEvent('render', this._initFocus);
  3259. this.afterHostEvent('render', this._initVisibility);
  3260. if(this.get('closeButton')) {
  3261. this._initCloseButton();
  3262. }
  3263. bb.addClass('fl-slideshow-overlay');
  3264. },
  3265. /**
  3266. * @method destructor
  3267. * @protected
  3268. */
  3269. destructor: function()
  3270. {
  3271. this._hideTimerCancel();
  3272. },
  3273. /**
  3274. * Binds the mouseenter and mouseleave events for setting focus.
  3275. *
  3276. * @method _initFocus
  3277. * @protected
  3278. */
  3279. _initFocus: function()
  3280. {
  3281. var bb = this.get('host').get('boundingBox');
  3282. bb.on('mouseenter', Y.bind(this._setFocusOnMouseenter, this));
  3283. bb.on('mouseleave', Y.bind(this._setFocusOnMouseleave, this));
  3284. },
  3285. /**
  3286. * Sets the initial visibility of the host's bounding box.
  3287. *
  3288. * @method _initVisibility
  3289. * @protected
  3290. */
  3291. _initVisibility: function()
  3292. {
  3293. var bb = this.get('host').get('boundingBox'),
  3294. hideStyle = this.get('hideStyle');
  3295. if(!this.get('visible')) {
  3296. if(hideStyle == 'display') {
  3297. bb.setStyle('display', 'none');
  3298. }
  3299. else if(hideStyle == 'left') {
  3300. bb.setStyle('left', '-99999px');
  3301. }
  3302. bb.setStyle('opacity', '0');
  3303. this._visible = false;
  3304. }
  3305. },
  3306. /**
  3307. * Creates and inserts the close button.
  3308. *
  3309. * @method _initCloseButton
  3310. * @protected
  3311. */
  3312. _initCloseButton: function()
  3313. {
  3314. var bb = this.get('host').get('boundingBox'),
  3315. closeButton = null;
  3316. closeButton = Y.Node.create('<a class="fl-slideshow-overlay-close" href="javascript:void(0);"></a>');
  3317. closeButton.on('click', Y.bind(this._closeButtonClick, this));
  3318. if(typeof YUI.Env.mods['sm-fonticon'] !== 'undefined') {
  3319. closeButton.addClass('sm-fonticon sm-fonticon-XCrossEncircled sm-button-skin-default sm-button-nochrome');
  3320. }
  3321. bb.insert(closeButton);
  3322. },
  3323. /**
  3324. * Hides the overlay when the close button is clicked.
  3325. *
  3326. * @method _closeButtonClick
  3327. * @protected
  3328. */
  3329. _closeButtonClick: function()
  3330. {
  3331. var bb = this.get('host').get('boundingBox');
  3332. bb.transition(this._hideProps, Y.bind(this._hideComplete, this));
  3333. },
  3334. /**
  3335. * Sets the focus flag to true.
  3336. *
  3337. * @method _setFocusOnMouseenter
  3338. * @protected
  3339. */
  3340. _setFocusOnMouseenter: function()
  3341. {
  3342. this._focus = true;
  3343. },
  3344. /**
  3345. * Sets the focus flag to false.
  3346. *
  3347. * @method _setFocusOnMouseleave
  3348. * @protected
  3349. */
  3350. _setFocusOnMouseleave: function()
  3351. {
  3352. this._focus = false;
  3353. },
  3354. /**
  3355. * Disables show and hide functionality.
  3356. *
  3357. * @method disable
  3358. * @public
  3359. */
  3360. disable: function()
  3361. {
  3362. this._disabled = true;
  3363. },
  3364. /**
  3365. * Enables show and hide functionality.
  3366. *
  3367. * @method enable
  3368. * @public
  3369. */
  3370. enable: function()
  3371. {
  3372. this._disabled = false;
  3373. },
  3374. /**
  3375. * Shows the host's bounding box with a fade in transition.
  3376. *
  3377. * @method show
  3378. * @public
  3379. */
  3380. show: function()
  3381. {
  3382. var bb = this.get('host').get('boundingBox'),
  3383. hideStyle = this.get('hideStyle');
  3384. if(this._disabled) {
  3385. return;
  3386. }
  3387. if(hideStyle == 'display') {
  3388. bb.setStyle('display', 'block');
  3389. }
  3390. else if(hideStyle == 'left') {
  3391. bb.setStyle('left', 'auto');
  3392. }
  3393. bb.transition(this._showProps, Y.bind(this._showComplete, this));
  3394. /**
  3395. * @event hideStart
  3396. */
  3397. this.fire('showStart');
  3398. },
  3399. /**
  3400. * @method _showComplete
  3401. * @protected
  3402. */
  3403. _showComplete: function()
  3404. {
  3405. this._visible = true;
  3406. this.hideWithTimer();
  3407. /**
  3408. * @event showComplete
  3409. */
  3410. this.fire('showComplete');
  3411. },
  3412. /**
  3413. * Hides the host's bounding box with a fade out transition.
  3414. *
  3415. * @method hide
  3416. * @public
  3417. */
  3418. hide: function()
  3419. {
  3420. if(this._focus || this._disabled) {
  3421. return;
  3422. }
  3423. var bb = this.get('host').get('boundingBox');
  3424. bb.transition(this._hideProps, Y.bind(this._hideComplete, this));
  3425. /**
  3426. * @event hideStart
  3427. */
  3428. this.fire('hideStart');
  3429. },
  3430. /**
  3431. * Hides the host's bounding box with a fade out transition
  3432. * after a timer completes.
  3433. *
  3434. * @method hideWithTimer
  3435. * @public
  3436. */
  3437. hideWithTimer: function()
  3438. {
  3439. this._hideTimerCancel();
  3440. this._hideTimer = Y.later(this.get('hideDelay'), this, this.hide);
  3441. },
  3442. /**
  3443. * Cancels the hide timer.
  3444. *
  3445. * @method _hideTimerCancel
  3446. * @protected
  3447. */
  3448. _hideTimerCancel: function()
  3449. {
  3450. if(this._hideTimer) {
  3451. this._hideTimer.cancel();
  3452. this._hideTimer = null;
  3453. }
  3454. },
  3455. /**
  3456. * @method _hideComplete
  3457. * @protected
  3458. */
  3459. _hideComplete: function()
  3460. {
  3461. var bb = this.get('host').get('boundingBox'),
  3462. hideStyle = this.get('hideStyle');
  3463. if(hideStyle == 'display') {
  3464. bb.setStyle('display', 'none');
  3465. }
  3466. else if(hideStyle == 'left') {
  3467. bb.setStyle('left', '-99999px');
  3468. }
  3469. this._visible = false;
  3470. /**
  3471. * @event hideComplete
  3472. */
  3473. this.fire('hideComplete');
  3474. }
  3475. }, {
  3476. /**
  3477. * Namespace for the plugin.
  3478. *
  3479. * @property NS
  3480. * @type String
  3481. * @protected
  3482. * @static
  3483. */
  3484. NS: 'slideshowOverlay',
  3485. /**
  3486. * Static property used to define the default attribute configuration of
  3487. * the plugin.
  3488. *
  3489. * @property ATTRS
  3490. * @type Object
  3491. * @protected
  3492. * @static
  3493. */
  3494. ATTRS: {
  3495. /**
  3496. * Whether to use the close button or not.
  3497. *
  3498. * @attribute closeButton
  3499. * @type Boolean
  3500. * @default false
  3501. * @writeOnce
  3502. */
  3503. closeButton: {
  3504. value: false,
  3505. writeOnce: true
  3506. },
  3507. /**
  3508. * The time to wait before hiding the host's bounding box.
  3509. * Measured in milliseconds.
  3510. *
  3511. * @attribute hideDelay
  3512. * @type Number
  3513. * @default 3000
  3514. * @writeOnce
  3515. */
  3516. hideDelay: {
  3517. value: 3000,
  3518. writeOnce: true
  3519. },
  3520. /**
  3521. * The style to use for hiding the image. Possible
  3522. * values are display and left.
  3523. *
  3524. * @attribute hideStyle
  3525. * @type String
  3526. * @default display
  3527. * @writeOnce
  3528. */
  3529. hideStyle: {
  3530. value: 'display',
  3531. writeOnce: true
  3532. },
  3533. /**
  3534. * Sets the initial visibility of the host's boudning box.
  3535. *
  3536. * @attribute visible
  3537. * @type Boolean
  3538. * @default true
  3539. * @writeOnce
  3540. */
  3541. visible: {
  3542. value: true,
  3543. writeOnce: true
  3544. }
  3545. }
  3546. });
  3547. /**
  3548. * Social buttons widget used in slideshows.
  3549. *
  3550. * @namespace FL
  3551. * @class SlideshowSocial
  3552. * @constructor
  3553. * @param config {Object} Configuration object
  3554. * @extends Widget
  3555. */
  3556. Y.namespace('FL').SlideshowSocial = Y.Base.create('fl-slideshow-social', Y.Widget, [Y.WidgetChild], {
  3557. /**
  3558. * An object containing the social button nodes.
  3559. *
  3560. * @property _buttons
  3561. * @type Object
  3562. * @default null
  3563. * @protected
  3564. */
  3565. _buttons: null,
  3566. /**
  3567. * @method renderUI
  3568. * @protected
  3569. */
  3570. renderUI: function()
  3571. {
  3572. this._buttons = {};
  3573. if(this.get('root').get('googlePlusButtonEnabled')) {
  3574. this._renderGooglePlusButton();
  3575. }
  3576. },
  3577. /**
  3578. * @method bindUI
  3579. * @protected
  3580. */
  3581. bindUI: function()
  3582. {
  3583. var root = this.get('root');
  3584. if(root.get('likeButtonEnabled')) {
  3585. root.on('imageLoadComplete', Y.bind(this._updateLikeButton, this));
  3586. }
  3587. if(root.get('tweetButtonEnabled')) {
  3588. root.on('imageLoadComplete', Y.bind(this._updateTweetButton, this));
  3589. }
  3590. if(root.get('googlePlusButtonEnabled')) {
  3591. root.on('imageLoadComplete', Y.bind(this._updateGooglePlusButton, this));
  3592. }
  3593. if(root.get('pinterestButtonEnabled')) {
  3594. root.on('imageLoadComplete', Y.bind(this._updatePinterestButton, this));
  3595. }
  3596. },
  3597. /**
  3598. * @method _updateLikeButton
  3599. * @protected
  3600. */
  3601. _updateLikeButton: function()
  3602. {
  3603. var src = null,
  3604. cb = this.get('contentBox'),
  3605. root = this.get('root'),
  3606. albumIndex = root.albumIndex,
  3607. rootSource = root.get('source')[albumIndex],
  3608. imageInfo = root.imageInfo;
  3609. if(this._buttons.like) {
  3610. this._buttons.like.remove();
  3611. this._buttons.like = null;
  3612. }
  3613. if(rootSource.type == 'smugmug') {
  3614. src = 'https://www.facebook.com/plugins/like.php?';
  3615. src += 'href=' + 'https://www.smugmug.com/services/graph/gallery/';
  3616. src += rootSource.id + '_' + rootSource.key +'/' + imageInfo.id + '_' + imageInfo.key;
  3617. }
  3618. else {
  3619. src = 'https://www.facebook.com/plugins/like.php?';
  3620. src += 'href=' + encodeURIComponent(imageInfo.largeURL);
  3621. }
  3622. src += '&send=false';
  3623. src += '&layout=button_count';
  3624. src += '&width=90';
  3625. src += '&show_faces=false';
  3626. src += '&action=like';
  3627. src += '&colorscheme=light';
  3628. src += '&height=21';
  3629. this._buttons.like = Y.Node.create('<iframe src="'+ src +'" scrolling="no" frameborder="0" allowTransparency="true"></iframe>');
  3630. this._buttons.like.setStyles({
  3631. overflow: 'hidden',
  3632. width: '90px',
  3633. height: '21px'
  3634. });
  3635. cb.appendChild(this._buttons.like);
  3636. },
  3637. /**
  3638. * @method _updateTweetButton
  3639. * @protected
  3640. */
  3641. _updateTweetButton: function()
  3642. {
  3643. var src = null,
  3644. imageInfo = this.get('root').imageInfo,
  3645. cb = this.get('contentBox');
  3646. if(this._buttons.tweet) {
  3647. this._buttons.tweet.remove();
  3648. this._buttons.tweet = null;
  3649. }
  3650. src = 'https://platform.twitter.com/widgets/tweet_button.html?';
  3651. src += 'url=' + encodeURIComponent(imageInfo.largeURL);
  3652. src += '&count=none';
  3653. this._buttons.tweet = Y.Node.create('<iframe src="'+ src +'" scrolling="no" frameborder="0" allowTransparency="true"></iframe>');
  3654. this._buttons.tweet.setStyles({
  3655. overflow: 'hidden',
  3656. width: '90px',
  3657. height: '21px'
  3658. });
  3659. cb.appendChild(this._buttons.tweet);
  3660. },
  3661. /**
  3662. * @method _renderGooglePlusButton
  3663. * @protected
  3664. */
  3665. _renderGooglePlusButton: function()
  3666. {
  3667. var po, head;
  3668. po = document.createElement('script');
  3669. po.type = 'text/javascript';
  3670. po.src = 'https://apis.google.com/js/plusone.js';
  3671. head = document.getElementsByTagName('head')[0];
  3672. head.parentNode.appendChild(po);
  3673. },
  3674. /**
  3675. * @method _updateGooglePlusButton
  3676. * @protected
  3677. */
  3678. _updateGooglePlusButton: function()
  3679. {
  3680. if(typeof gapi == 'undefined') {
  3681. setTimeout(Y.bind(this._updateGooglePlusButtonCallback, this), 500);
  3682. }
  3683. else {
  3684. this._updateGooglePlusButtonCallback();
  3685. }
  3686. },
  3687. /**
  3688. * @method _updateGooglePlusButtonCallback
  3689. * @protected
  3690. */
  3691. _updateGooglePlusButtonCallback: function()
  3692. {
  3693. var imageInfo = this.get('root').imageInfo,
  3694. cb = this.get('contentBox');
  3695. if(this._buttons.plus) {
  3696. this._buttons.plus.remove();
  3697. this._buttons.plus = null;
  3698. }
  3699. if(typeof gapi != 'undefined') {
  3700. this._buttons.plus = Y.Node.create('<div></div>');
  3701. cb.appendChild(this._buttons.plus);
  3702. gapi.plusone.render(this._buttons.plus._node, {
  3703. href: encodeURIComponent(imageInfo.largeURL),
  3704. annotation: 'bubble',
  3705. size: 'medium'
  3706. });
  3707. }
  3708. },
  3709. /**
  3710. * @method _updatePinterestButton
  3711. * @protected
  3712. */
  3713. _updatePinterestButton: function()
  3714. {
  3715. var href = 'https://pinterest.com/pin/create/button/',
  3716. imageInfo = this.get('root').imageInfo,
  3717. cb = this.get('contentBox');
  3718. if(this._buttons.pin) {
  3719. this._buttons.pin.remove();
  3720. this._buttons.pin = null;
  3721. }
  3722. href += '?url=' + encodeURIComponent(window.location.href);
  3723. href += '&media='+ encodeURIComponent(imageInfo.mediumURL);
  3724. href += '&description='+ encodeURIComponent(imageInfo.caption);
  3725. this._buttons.pin = Y.Node.create('<a></a>');
  3726. this._buttons.pin.setAttribute('data-pin-config', 'none');
  3727. this._buttons.pin.setAttribute('data-pin-do', 'buttonPin');
  3728. this._buttons.pin.setAttribute('href', href);
  3729. this._buttons.pin.setAttribute('target', '_blank');
  3730. this._buttons.pin.set('innerHTML', '<img src="https://assets.pinterest.com/images/pidgets/pin_it_button.png" border="0" />');
  3731. cb.appendChild(this._buttons.pin);
  3732. }
  3733. }, {
  3734. /**
  3735. * Custom CSS class name for the widget.
  3736. *
  3737. * @property CSS_PREFIX
  3738. * @type String
  3739. * @protected
  3740. * @static
  3741. */
  3742. CSS_PREFIX: 'fl-slideshow-social',
  3743. /**
  3744. * Static property used to define the default attribute configuration of
  3745. * the Widget.
  3746. *
  3747. * @property ATTRS
  3748. * @type Object
  3749. * @protected
  3750. * @static
  3751. */
  3752. ATTRS: {
  3753. }
  3754. });
  3755. /**
  3756. * Creates a grid of FL.SlideshowImage instances.
  3757. *
  3758. * @namespace FL
  3759. * @class SlideshowThumbs
  3760. * @constructor
  3761. * @param config {Object} Configuration object
  3762. * @extends Widget
  3763. */
  3764. Y.namespace('FL').SlideshowThumbs = Y.Base.create('fl-slideshow-thumbs', Y.Widget, [Y.WidgetParent, Y.WidgetChild], {
  3765. /**
  3766. * A div node used to hide the overflow when
  3767. * transitioning between pages.
  3768. *
  3769. * @property _clipBox
  3770. * @type Object
  3771. * @default null
  3772. * @protected
  3773. */
  3774. _clipBox: null,
  3775. /**
  3776. * A div node used to hold the pages.
  3777. *
  3778. * @property _pagesBox
  3779. * @type Object
  3780. * @default null
  3781. * @protected
  3782. */
  3783. _pagesBox: null,
  3784. /**
  3785. * A reference to the active page div node. Holds a grid
  3786. * of FL.SlideshowImage instances.
  3787. *
  3788. * @property _activePageBox
  3789. * @type Object
  3790. * @default null
  3791. * @protected
  3792. */
  3793. _activePageBox: null,
  3794. /**
  3795. * The index of the active page of thumbs.
  3796. *
  3797. * @property _activePageIndex
  3798. * @type Number
  3799. * @default 0
  3800. * @protected
  3801. */
  3802. _activePageIndex: 0,
  3803. /**
  3804. * A reference to the next page div node. Holds a grid
  3805. * of FL.SlideshowImage instances.
  3806. *
  3807. * @property _nextPageBox
  3808. * @type Object
  3809. * @default null
  3810. * @protected
  3811. */
  3812. _nextPageBox: null,
  3813. /**
  3814. * An array of FL.SlideshowImage instances in the active page.
  3815. *
  3816. * @property _activeImages
  3817. * @type Array
  3818. * @default null
  3819. * @protected
  3820. */
  3821. _activeImages: null,
  3822. /**
  3823. * An array of FL.SlideshowImage instances used to
  3824. * preload the next page of images.
  3825. *
  3826. * @property _nextImages
  3827. * @type Array
  3828. * @default null
  3829. * @protected
  3830. */
  3831. _nextImages: null,
  3832. /**
  3833. * An array of FL.SlideshowImage instances used to
  3834. * preload the previous page of images.
  3835. *
  3836. * @property _prevImages
  3837. * @type Array
  3838. * @default null
  3839. * @protected
  3840. */
  3841. _prevImages: null,
  3842. /**
  3843. * An instance of FL.SlideshowNav used for the left nav.
  3844. *
  3845. * @property _leftNav
  3846. * @type Object
  3847. * @default null
  3848. * @protected
  3849. */
  3850. _leftNav: null,
  3851. /**
  3852. * An instance of FL.SlideshowNav used for the right nav.
  3853. *
  3854. * @property _rightNav
  3855. * @type Object
  3856. * @default null
  3857. * @protected
  3858. */
  3859. _rightNav: null,
  3860. /**
  3861. * An instance of FL.SlideshowNav used for the top nav.
  3862. *
  3863. * @property _topNav
  3864. * @type Object
  3865. * @default null
  3866. * @protected
  3867. */
  3868. _topNav: null,
  3869. /**
  3870. * An instance of FL.SlideshowNav used for the bottom nav.
  3871. *
  3872. * @property _bottomNav
  3873. * @type Object
  3874. * @default null
  3875. * @protected
  3876. */
  3877. _bottomNav: null,
  3878. /**
  3879. * Height of the bounding box.
  3880. *
  3881. * @property _bbHeight
  3882. * @type Number
  3883. * @default 0
  3884. * @protected
  3885. */
  3886. _bbHeight: 0,
  3887. /**
  3888. * Width of the bounding box.
  3889. *
  3890. * @property _bbWidth
  3891. * @type Number
  3892. * @default 0
  3893. * @protected
  3894. */
  3895. _bbWidth: 0,
  3896. /**
  3897. * Width of the content box.
  3898. *
  3899. * @property _cbWidth
  3900. * @type Number
  3901. * @default 0
  3902. * @protected
  3903. */
  3904. _cbWidth: 0,
  3905. /**
  3906. * Left margin of the clip box.
  3907. *
  3908. * @property _clipBoxMarginLeft
  3909. * @type Number
  3910. * @default 0
  3911. * @protected
  3912. */
  3913. _clipBoxMarginLeft: 0,
  3914. /**
  3915. * Top position of the clip box.
  3916. *
  3917. * @property _clipBoxTop
  3918. * @type Number
  3919. * @default 0
  3920. * @protected
  3921. */
  3922. _clipBoxTop: 0,
  3923. /**
  3924. * The number of columns per page.
  3925. *
  3926. * @property _colsPerPage
  3927. * @type Number
  3928. * @default 0
  3929. * @protected
  3930. */
  3931. _colsPerPage: 0,
  3932. /**
  3933. * The number of rows per page.
  3934. *
  3935. * @property _rowsPerPage
  3936. * @type Number
  3937. * @default 0
  3938. * @protected
  3939. */
  3940. _rowsPerPage: 0,
  3941. /**
  3942. * The number of images per page.
  3943. *
  3944. * @property _imagesPerPage
  3945. * @type Number
  3946. * @default 0
  3947. * @protected
  3948. */
  3949. _imagesPerPage: 0,
  3950. /**
  3951. * The number of pages.
  3952. *
  3953. * @property _numPages
  3954. * @type Number
  3955. * @default 0
  3956. * @protected
  3957. */
  3958. _numPages: 0,
  3959. /**
  3960. * Height of the pages.
  3961. *
  3962. * @property _pageHeight
  3963. * @type Number
  3964. * @default 0
  3965. * @protected
  3966. */
  3967. _pageHeight: 0,
  3968. /**
  3969. * Width of the pages.
  3970. *
  3971. * @property _pageWidth
  3972. * @type Number
  3973. * @default 0
  3974. * @protected
  3975. */
  3976. _pageWidth: 0,
  3977. /**
  3978. * The horizontal spacing between thumbs.
  3979. *
  3980. * @property _horizontalSpacing
  3981. * @type Number
  3982. * @default 0
  3983. * @protected
  3984. */
  3985. _horizontalSpacing: 0,
  3986. /**
  3987. * The vertical spacing between thumbs.
  3988. *
  3989. * @property _verticalSpacing
  3990. * @type Number
  3991. * @default 0
  3992. * @protected
  3993. */
  3994. _verticalSpacing: 0,
  3995. /**
  3996. * Width of the left nav.
  3997. *
  3998. * @property _leftNavWidth
  3999. * @type Number
  4000. * @default 0
  4001. * @protected
  4002. */
  4003. _leftNavWidth: 0,
  4004. /**
  4005. * Width of the right nav.
  4006. *
  4007. * @property _rightNavWidth
  4008. * @type Number
  4009. * @default 0
  4010. * @protected
  4011. */
  4012. _rightNavWidth: 0,
  4013. /**
  4014. * An instance of FL.SlideshowTransition for the current transition.
  4015. *
  4016. * @property _transition
  4017. * @type FL.SlideshowTransition
  4018. * @default null
  4019. * @protected
  4020. */
  4021. _transition: null,
  4022. /**
  4023. * Whether the pages are currently transitioning or not.
  4024. *
  4025. * @property _verticalSpacing
  4026. * @type Boolean
  4027. * @default false
  4028. * @protected
  4029. */
  4030. _transitioning: false,
  4031. /**
  4032. * Direction of the current transition.
  4033. *
  4034. * @property _transitionDirection
  4035. * @type String
  4036. * @default next
  4037. * @protected
  4038. */
  4039. _transitionDirection: 'next',
  4040. /**
  4041. * Provides functionality for gesture based transitions
  4042. * between the active and next pages.
  4043. *
  4044. * @property _gestures
  4045. * @type FL.SlideshowGestures
  4046. * @default null
  4047. * @protected
  4048. */
  4049. _gestures: null,
  4050. /**
  4051. * Initialize image vars.
  4052. *
  4053. * @method initializer
  4054. * @protected
  4055. */
  4056. initializer: function()
  4057. {
  4058. this._activeImages = [];
  4059. this._nextImages = [];
  4060. this._prevImages = [];
  4061. },
  4062. /**
  4063. * Renders the UI boxes.
  4064. *
  4065. * @method renderUI
  4066. * @protected
  4067. */
  4068. renderUI: function()
  4069. {
  4070. this._renderBoxes();
  4071. this._renderNavs();
  4072. },
  4073. /**
  4074. * Binds the UI events.
  4075. *
  4076. * @method bindUI
  4077. * @protected
  4078. */
  4079. bindUI: function()
  4080. {
  4081. var root = this.get('root'),
  4082. id = this.get('id'),
  4083. transition = this.get('transition');
  4084. root.on(id + '|albumLoadComplete', this._albumLoadComplete, this);
  4085. if('ontouchstart' in window && this.get('touchSupport')) {
  4086. this._gestures = new Y.FL.SlideshowGestures({
  4087. direction: transition == 'slideVertical' ? 'vertical' : 'horizontal',
  4088. activeItem: this._activePageBox,
  4089. nextItem: this._nextPageBox
  4090. });
  4091. this._gestures.on('moveStart', this._gesturesMoveStart, this);
  4092. this._gestures.on('endComplete', this._gesturesEndComplete, this);
  4093. }
  4094. },
  4095. /**
  4096. * Syncs the UI boxes.
  4097. *
  4098. * @method syncUI
  4099. * @protected
  4100. */
  4101. syncUI: function()
  4102. {
  4103. this._syncBoxes();
  4104. this._syncNavs();
  4105. },
  4106. /**
  4107. * @method destructor
  4108. * @protected
  4109. */
  4110. destructor: function()
  4111. {
  4112. var root = this.get('root'),
  4113. id = this.get('id');
  4114. root.detach(id + '|*');
  4115. Y.FL.SlideshowImageLoader.removeGroup('thumbs');
  4116. },
  4117. /**
  4118. * Unload all images.
  4119. *
  4120. * @method unload
  4121. */
  4122. unload: function()
  4123. {
  4124. var root = this.get('root'),
  4125. id = this.get('id'),
  4126. i = 0;
  4127. root.detach(id + '|imageLoadComplete');
  4128. Y.FL.SlideshowImageLoader.removeGroup('thumbs');
  4129. for( ; i < this._activeImages.length; i++) {
  4130. this._activeImages[i].unload();
  4131. }
  4132. },
  4133. /**
  4134. * Resizes the UI boxes.
  4135. *
  4136. * @method resize
  4137. */
  4138. resize: function()
  4139. {
  4140. this._setSizeInfo();
  4141. this._togglePageButtons();
  4142. this._resizeBoxes();
  4143. this._resizeNavs();
  4144. if(this.get('root').albumInfo) {
  4145. Y.FL.SlideshowImageLoader.removeGroup('thumbs');
  4146. this._renderActivePage();
  4147. this._preloadNextPage();
  4148. this._preloadPrevPage();
  4149. }
  4150. // Enable or disable gestures.
  4151. if(this._gestures && this._numPages < 2) {
  4152. this._gestures.disable();
  4153. }
  4154. else if(this._gestures) {
  4155. this._gestures.enable();
  4156. }
  4157. },
  4158. /**
  4159. * Transitions to the previous page.
  4160. *
  4161. * @method prevPage
  4162. * @protected
  4163. */
  4164. prevPage: function()
  4165. {
  4166. if(this._transitioning) {
  4167. return;
  4168. }
  4169. this._transitionStart('prev');
  4170. },
  4171. /**
  4172. * Transitions to the next page.
  4173. *
  4174. * @method nextPage
  4175. * @protected
  4176. */
  4177. nextPage: function()
  4178. {
  4179. if(this._transitioning) {
  4180. return;
  4181. }
  4182. this._transitionStart('next');
  4183. },
  4184. /**
  4185. * Called when an album is loaded into the root slideshow widget.
  4186. *
  4187. * @method _albumLoadComplete
  4188. * @protected
  4189. */
  4190. _albumLoadComplete: function()
  4191. {
  4192. var root = this.get('root'),
  4193. id = this.get('id');
  4194. root.once(id + '|imageLoadComplete', this.resize, this);
  4195. root.on(id + '|imageLoadComplete', this._imageLoadComplete, this);
  4196. },
  4197. /**
  4198. * Called when an image is loaded into the root slideshow widget.
  4199. *
  4200. * @method _imageLoadComplete
  4201. * @protected
  4202. */
  4203. _imageLoadComplete: function()
  4204. {
  4205. var albumInfo = this.get('root').albumInfo,
  4206. lastActive = Y.one('.fl-slideshow-image-active'),
  4207. lastInfo = lastActive ? lastActive._imageInfo : null,
  4208. nextActive = null,
  4209. nextInfo = this.get('root').imageInfo;
  4210. this._setActiveImage(this._activeImages);
  4211. nextActive = Y.one('.fl-slideshow-image-active');
  4212. if(lastActive && !nextActive) {
  4213. if(nextInfo.index === 0 && lastInfo.index === albumInfo.images.length - 1) {
  4214. this.nextPage();
  4215. }
  4216. else if(lastInfo.index === 0 && nextInfo.index === albumInfo.images.length - 1) {
  4217. this.prevPage();
  4218. }
  4219. else if(lastInfo.index < nextInfo.index) {
  4220. this.nextPage();
  4221. }
  4222. else if(lastInfo.index > nextInfo.index) {
  4223. this.prevPage();
  4224. }
  4225. }
  4226. },
  4227. /**
  4228. * Renders the boxes.
  4229. *
  4230. * @method _renderBoxes
  4231. * @protected
  4232. */
  4233. _renderBoxes: function()
  4234. {
  4235. // Clip box
  4236. this._clipBox = Y.Node.create('<div></div>');
  4237. this._clipBox.addClass('fl-slideshow-thumbs-clip');
  4238. this.get('contentBox').insert(this._clipBox);
  4239. // Pages box
  4240. this._pagesBox = Y.Node.create('<div></div>');
  4241. this._pagesBox.addClass('fl-slideshow-thumbs-pages');
  4242. this._clipBox.insert(this._pagesBox);
  4243. // Active page box
  4244. this._activePageBox = Y.Node.create('<div></div>');
  4245. this._activePageBox.addClass('fl-slideshow-thumbs-page');
  4246. this._pagesBox.insert(this._activePageBox);
  4247. // Next page box
  4248. this._nextPageBox = Y.Node.create('<div></div>');
  4249. this._nextPageBox.addClass('fl-slideshow-thumbs-page');
  4250. this._pagesBox.insert(this._nextPageBox);
  4251. },
  4252. /**
  4253. * Syncs the boxes.
  4254. *
  4255. * @method _syncBoxes
  4256. * @protected
  4257. */
  4258. _syncBoxes: function()
  4259. {
  4260. // Active page box
  4261. this._activePageBox.setStyle('left', '0');
  4262. // Next page box
  4263. this._nextPageBox.setStyle('left', '-9999px');
  4264. },
  4265. /**
  4266. * Resizes the boxes.
  4267. *
  4268. * @method _resizeBoxes
  4269. * @protected
  4270. */
  4271. _resizeBoxes: function()
  4272. {
  4273. this.set('width', this._bbWidth);
  4274. this.set('height', this._bbHeight);
  4275. this.get('contentBox').setStyle('width', this._cbWidth + 'px');
  4276. this._clipBox.setStyle('width', this._pageWidth + 'px');
  4277. this._clipBox.setStyle('height', this._pageHeight + 'px');
  4278. this._clipBox.setStyle('padding', this._verticalSpacing + 'px 0 0 ' + this._horizontalSpacing + 'px ');
  4279. this._clipBox.setStyle('margin', '0 0 0 ' + this._clipBoxMarginLeft + 'px');
  4280. this._clipBox.setStyle('top', this._clipBoxTop);
  4281. this._pagesBox.setStyle('width', this._pageWidth + 'px');
  4282. this._pagesBox.setStyle('height', this._pageHeight + 'px');
  4283. this._activePageBox.setStyle('width', this._pageWidth + 'px');
  4284. this._activePageBox.setStyle('height', this._pageHeight + 'px');
  4285. this._nextPageBox.setStyle('width', this._pageWidth + 'px');
  4286. this._nextPageBox.setStyle('height', this._pageHeight + 'px');
  4287. },
  4288. /**
  4289. * Renders the active page of images.
  4290. *
  4291. * @method _renderActivePage
  4292. * @protected
  4293. */
  4294. _renderActivePage: function()
  4295. {
  4296. var i = 0,
  4297. root = this.get('root'),
  4298. imageIndex = this._imagesPerPage * this._activePageIndex,
  4299. endIndex = imageIndex + this._imagesPerPage,
  4300. images = root.albumInfo.images;
  4301. this._clearActiveImage();
  4302. // Remove current images
  4303. for( ; i < this._activeImages.length; i++) {
  4304. this._activeImages[i].remove();
  4305. this._activeImages[i].unload();
  4306. this._activeImages[i].get('boundingBox')._imageInfo = null;
  4307. this._activeImages[i].get('boundingBox').remove();
  4308. }
  4309. // Draw images
  4310. for(i = 0; imageIndex < endIndex; imageIndex++) {
  4311. if(!images[imageIndex]) {
  4312. break;
  4313. }
  4314. this._renderImage(this._activeImages, i, this._activePageBox, images[imageIndex]);
  4315. i++;
  4316. }
  4317. this._setActiveImage(this._activeImages);
  4318. },
  4319. /**
  4320. * Renders the next page of images.
  4321. *
  4322. * @method _renderNextPage
  4323. * @protected
  4324. */
  4325. _renderNextPage: function()
  4326. {
  4327. var i = 0,
  4328. imageArray = this._transitionDirection == 'next' ? this._nextImages : this._prevImages;
  4329. this._nextPageBox.get('children').remove();
  4330. for( ; i < imageArray.length; i++) {
  4331. if(imageArray[i]._imageInfo) {
  4332. this._renderImage(imageArray, i, this._nextPageBox, imageArray[i]._imageInfo);
  4333. }
  4334. else {
  4335. break;
  4336. }
  4337. }
  4338. this._setActiveImage(imageArray);
  4339. },
  4340. /**
  4341. * Preloads the next page of images.
  4342. *
  4343. * @method _preloadNextPage
  4344. * @protected
  4345. */
  4346. _preloadNextPage: function()
  4347. {
  4348. var pageIndex = this._activePageIndex + 1 >= this._numPages ? 0 : this._activePageIndex + 1;
  4349. this._preloadPage(pageIndex, this._nextImages);
  4350. },
  4351. /**
  4352. * Preloads the previous page of images.
  4353. *
  4354. * @method _preloadPrevPage
  4355. * @protected
  4356. */
  4357. _preloadPrevPage: function()
  4358. {
  4359. var pageIndex = this._activePageIndex - 1 < 0 ? this._numPages - 1 : this._activePageIndex - 1;
  4360. this._preloadPage(pageIndex, this._prevImages);
  4361. },
  4362. /**
  4363. * Preloads a page of images.
  4364. *
  4365. * @method _preloadPage
  4366. * @param imageIndex {Number} The image index to start preloading from.
  4367. * @param imageArray {Array} The array to store the preloaded images.
  4368. * @protected
  4369. */
  4370. _preloadPage: function(pageIndex, imageArray)
  4371. {
  4372. var i = 0,
  4373. root = this.get('root'),
  4374. images = root.albumInfo.images,
  4375. imageIndex = pageIndex * this._imagesPerPage,
  4376. endIndex = imageIndex + this._imagesPerPage,
  4377. imageConfig = this.get('imageConfig'),
  4378. width = imageConfig.width,
  4379. height = imageConfig.height;
  4380. if(this._numPages > 1) {
  4381. // Unload existing images
  4382. for( ; i < imageArray.length; i++) {
  4383. imageArray[i].remove();
  4384. imageArray[i].unload();
  4385. }
  4386. // Preload the images
  4387. for(i = 0; imageIndex < endIndex; imageIndex++) {
  4388. if(!images[imageIndex]) {
  4389. continue;
  4390. }
  4391. this._renderImage(imageArray, i);
  4392. imageArray[i].preload(images[imageIndex], width, height);
  4393. i++;
  4394. }
  4395. }
  4396. },
  4397. /**
  4398. * Renders an image.
  4399. *
  4400. * @method _renderImage
  4401. * @protected
  4402. */
  4403. _renderImage: function(imageArray, i, page, imageInfo)
  4404. {
  4405. var imageBB = null,
  4406. imageConfig = this.get('imageConfig');
  4407. // Create the image?
  4408. if(typeof imageArray[i] == 'undefined') {
  4409. imageConfig.loadGroup = 'thumbs';
  4410. imageConfig.useThumbSizes = true;
  4411. imageConfig.loadVideos = false;
  4412. imageArray[i] = new Y.FL.SlideshowImage(imageConfig);
  4413. imageBB = imageArray[i].get('boundingBox');
  4414. imageBB.on('click', this._imageClick, this);
  4415. imageBB.on('mouseover', this._imageMouseover, this);
  4416. imageBB.on('mouseout', this._imageMouseout, this);
  4417. }
  4418. // Image bounding box
  4419. imageBB = imageArray[i].get('boundingBox');
  4420. imageBB.setStyle('margin', '0 ' + this._horizontalSpacing + 'px ' + this._verticalSpacing + 'px 0');
  4421. // Add the image to a page?
  4422. if(page) {
  4423. this._childrenContainer = page;
  4424. this.add(imageArray[i]);
  4425. imageArray[i].resize(imageConfig.width, imageConfig.height);
  4426. }
  4427. // Load the image?
  4428. if(imageInfo) {
  4429. imageArray[i].load(imageInfo);
  4430. imageBB._imageInfo = imageInfo;
  4431. }
  4432. },
  4433. /**
  4434. * Overrides the WidgetParent _uiAddChild method so _renderImage
  4435. * will render to the appropriate page.
  4436. *
  4437. * @method _uiAddChild
  4438. * @protected
  4439. * @param child {Widget} The child Widget instance to render.
  4440. * @param parentNode {Object} The Node under which the
  4441. * child Widget is to be rendered. Set to the appropriate page
  4442. * in the _renderImage method by setting _childrenContainer.
  4443. */
  4444. _uiAddChild: function (child, parentNode)
  4445. {
  4446. child.render(parentNode);
  4447. parentNode.appendChild(child.get('boundingBox'));
  4448. },
  4449. /**
  4450. * Called when an image is clicked.
  4451. *
  4452. * @method _imageClick
  4453. * @protected
  4454. */
  4455. _imageClick: function(e)
  4456. {
  4457. var root = this.get('root');
  4458. if(this.get('pauseOnClick')) {
  4459. root.pause();
  4460. }
  4461. root.loadImage(e.currentTarget._imageInfo.index);
  4462. /**
  4463. * Fires when an image is clicked.
  4464. *
  4465. * @event imageClick
  4466. */
  4467. this.fire('imageClick');
  4468. },
  4469. /**
  4470. * Sets the active image.
  4471. *
  4472. * @method _setActiveImage
  4473. * @param imageArray {Array} The image array to check for the active image.
  4474. * @protected
  4475. */
  4476. _setActiveImage: function(imageArray)
  4477. {
  4478. var i = 0;
  4479. this._clearActiveImage();
  4480. for( ; i < imageArray.length; i++) {
  4481. if(imageArray[i]._imageInfo) {
  4482. if(imageArray[i]._imageInfo.index == this.get('root').imageInfo.index) {
  4483. imageArray[i].get('boundingBox').addClass('fl-slideshow-image-active');
  4484. break;
  4485. }
  4486. }
  4487. }
  4488. },
  4489. /**
  4490. * Removes the class name 'fl-slideshow-image-active'
  4491. * from the active image.
  4492. *
  4493. * @method _clearActiveImage
  4494. * @protected
  4495. */
  4496. _clearActiveImage: function()
  4497. {
  4498. var active = Y.one('.fl-slideshow-image-active');
  4499. if(active) {
  4500. active.removeClass('fl-slideshow-image-active');
  4501. }
  4502. },
  4503. /**
  4504. * Gets the transition type.
  4505. *
  4506. * @method _getTransition
  4507. * @protected
  4508. */
  4509. _getTransition: function()
  4510. {
  4511. var transition = this.get('transition');
  4512. if(transition == 'slideHorizontal' && this._transitionDirection == 'next') {
  4513. return 'slideLeft';
  4514. }
  4515. else if(transition == 'slideHorizontal' && this._transitionDirection == 'prev') {
  4516. return 'slideRight';
  4517. }
  4518. else if(transition == 'slideVertical' && this._transitionDirection == 'next') {
  4519. return 'slideUp';
  4520. }
  4521. else if(transition == 'slideVertical' && this._transitionDirection == 'prev') {
  4522. return 'slideDown';
  4523. }
  4524. return transition;
  4525. },
  4526. /**
  4527. * Starts the transition, moving in the provided direction.
  4528. *
  4529. * @method _transitionStart
  4530. * @param direction {String} The direction to transition.
  4531. * @protected
  4532. */
  4533. _transitionStart: function(direction)
  4534. {
  4535. if(this._numPages > 1) {
  4536. Y.FL.SlideshowImageLoader.removeGroup('thumbs');
  4537. this._transitionDirection = direction;
  4538. this._transitioning = true;
  4539. this._nextPageBox.setStyle('left', '0px');
  4540. this._renderNextPage();
  4541. this._transition = new Y.FL.SlideshowTransition({
  4542. itemIn: this._nextPageBox,
  4543. itemOut: this._activePageBox,
  4544. type: this._getTransition(),
  4545. duration: this.get('transitionDuration'),
  4546. easing: this.get('transitionEasing')
  4547. });
  4548. this._transition.once('complete', this._transitionComplete, this);
  4549. this._transition.run();
  4550. // Disable gestures if set.
  4551. if(this._gestures) {
  4552. this._gestures.disable();
  4553. }
  4554. }
  4555. },
  4556. /**
  4557. * Transition cleanup called when the current transition ends.
  4558. *
  4559. * @method _transitionComplete
  4560. * @protected
  4561. */
  4562. _transitionComplete: function()
  4563. {
  4564. this._swapPageRefs();
  4565. this._transitioning = false;
  4566. this._transitionDirection = '';
  4567. this._transition = null;
  4568. // Enable gestures if set.
  4569. if(this._gestures) {
  4570. this._gestures.enable();
  4571. }
  4572. /**
  4573. * Fires when a page transition completes.
  4574. *
  4575. * @event transitionComplete
  4576. */
  4577. this.fire('transitionComplete');
  4578. },
  4579. /**
  4580. * @method _gesturesMoveStart
  4581. * @param e {Object} The event object.
  4582. * @protected
  4583. */
  4584. _gesturesMoveStart: function(e)
  4585. {
  4586. Y.FL.SlideshowImageLoader.removeGroup('thumbs');
  4587. this._transitionDirection = e.direction;
  4588. this._renderNextPage();
  4589. },
  4590. /**
  4591. * @method _gesturesEndComplete
  4592. * @protected
  4593. */
  4594. _gesturesEndComplete: function()
  4595. {
  4596. this._swapPageRefs();
  4597. this._transitionDirection = '';
  4598. this.fire('transitionComplete');
  4599. },
  4600. /**
  4601. * Swaps the active page and next page references when
  4602. * a transition completes and sets the active page index.
  4603. *
  4604. * @method _swapPageRefs
  4605. * @protected
  4606. */
  4607. _swapPageRefs: function()
  4608. {
  4609. var lastBox = this._activePageBox,
  4610. lastImages = this._activeImages;
  4611. this._activePageBox = this._nextPageBox;
  4612. this._nextPageBox = lastBox;
  4613. this._nextPageBox.setStyle('left', '-9999px');
  4614. if(this._transitionDirection == 'next') {
  4615. this._activeImages = this._nextImages;
  4616. this._nextImages = lastImages;
  4617. }
  4618. else {
  4619. this._activeImages = this._prevImages;
  4620. this._prevImages = lastImages;
  4621. }
  4622. // Active page index
  4623. if(this._transitionDirection == 'next' && this._activePageIndex + 1 < this._numPages) {
  4624. this._activePageIndex++;
  4625. }
  4626. else if(this._transitionDirection == 'next') {
  4627. this._activePageIndex = 0;
  4628. }
  4629. else if(this._transitionDirection == 'prev' && this._activePageIndex - 1 > -1) {
  4630. this._activePageIndex--;
  4631. }
  4632. else if(this._transitionDirection == 'prev') {
  4633. this._activePageIndex = this._numPages - 1;
  4634. }
  4635. // Swap gesture refs
  4636. if(this._gestures) {
  4637. this._gestures.set('activeItem', this._activePageBox);
  4638. this._gestures.set('nextItem', this._nextPageBox);
  4639. }
  4640. this._preloadNextPage();
  4641. this._preloadPrevPage();
  4642. },
  4643. /**
  4644. * Renders the enabled navs.
  4645. *
  4646. * @method _renderNavs
  4647. * @protected
  4648. */
  4649. _renderNavs: function()
  4650. {
  4651. var topNavButtons = this.get('topNavButtons'),
  4652. rightNavButtons = this.get('rightNavButtons'),
  4653. bottomNavButtons = this.get('bottomNavButtons'),
  4654. leftNavButtons = this.get('leftNavButtons');
  4655. if(this.get('topNavEnabled') && topNavButtons.length > 0) {
  4656. this._topNav = new Y.FL.SlideshowNav({ buttons: topNavButtons });
  4657. this._topNav.get('boundingBox').addClass('fl-slideshow-thumbs-top-nav');
  4658. this.add(this._topNav);
  4659. this._topNav.render(this.get('contentBox'));
  4660. this._clipBox.insert(this._topNav.get('boundingBox'), 'before');
  4661. this._bindNavEvents(this._topNav);
  4662. }
  4663. if(this.get('rightNavEnabled') && rightNavButtons.length > 0) {
  4664. this._rightNav = new Y.FL.SlideshowNav({ buttons: rightNavButtons });
  4665. this._rightNav.get('boundingBox').addClass('fl-slideshow-thumbs-right-nav');
  4666. this.add(this._rightNav);
  4667. this._rightNav.render(this.get('contentBox'));
  4668. this._bindNavEvents(this._rightNav);
  4669. }
  4670. if(this.get('bottomNavEnabled') && bottomNavButtons.length > 0) {
  4671. this._bottomNav = new Y.FL.SlideshowNav({ buttons: bottomNavButtons });
  4672. this._bottomNav.get('boundingBox').addClass('fl-slideshow-thumbs-bottom-nav');
  4673. this.add(this._bottomNav);
  4674. this._bottomNav.render(this.get('contentBox'));
  4675. this._bindNavEvents(this._bottomNav);
  4676. }
  4677. if(this.get('leftNavEnabled') && leftNavButtons.length > 0) {
  4678. this._leftNav = new Y.FL.SlideshowNav({ buttons: leftNavButtons });
  4679. this._leftNav.get('boundingBox').addClass('fl-slideshow-thumbs-left-nav');
  4680. this.add(this._leftNav);
  4681. this._leftNav.render(this.get('contentBox'));
  4682. this._bindNavEvents(this._leftNav);
  4683. }
  4684. },
  4685. /**
  4686. * Syncs the navs.
  4687. *
  4688. * @method _syncNavs
  4689. * @protected
  4690. */
  4691. _syncNavs: function()
  4692. {
  4693. var rightNavBB, bottomNavBB, leftNavBB;
  4694. if(this._rightNav) {
  4695. rightNavBB = this._rightNav.get('boundingBox');
  4696. rightNavBB.setStyle('position', 'absolute');
  4697. rightNavBB.setStyle('top', '0px');
  4698. rightNavBB.setStyle('right', '0px');
  4699. }
  4700. if(this._bottomNav) {
  4701. bottomNavBB = this._bottomNav.get('boundingBox');
  4702. bottomNavBB.setStyle('position', 'absolute');
  4703. bottomNavBB.setStyle('bottom', '0px');
  4704. bottomNavBB.setStyle('width', '100%');
  4705. }
  4706. if(this._leftNav) {
  4707. leftNavBB = this._leftNav.get('boundingBox');
  4708. leftNavBB.setStyle('position', 'absolute');
  4709. leftNavBB.setStyle('top', '0px');
  4710. leftNavBB.setStyle('left', '0px');
  4711. }
  4712. },
  4713. /**
  4714. * Resizes the navs.
  4715. *
  4716. * @method _resizeNavs
  4717. * @protected
  4718. */
  4719. _resizeNavs: function()
  4720. {
  4721. var rightNavBB,
  4722. leftNavBB,
  4723. marginTop;
  4724. if(this._rightNav) {
  4725. rightNavBB = this._rightNav.get('boundingBox');
  4726. marginTop = this._bbHeight/2 - parseInt(rightNavBB.getComputedStyle('height'), 10)/2;
  4727. rightNavBB.setStyle('marginTop', marginTop + 'px');
  4728. }
  4729. if(this._leftNav) {
  4730. leftNavBB = this._leftNav.get('boundingBox');
  4731. marginTop = this._bbHeight/2 - parseInt(leftNavBB.getComputedStyle('height'), 10)/2;
  4732. leftNavBB.setStyle('marginTop', marginTop + 'px');
  4733. }
  4734. },
  4735. /**
  4736. * Binds events to the provided nav.
  4737. *
  4738. * @method _bindNavEvents
  4739. * @param nav {Object} The nav to bind to.
  4740. * @protected
  4741. */
  4742. _bindNavEvents: function(nav)
  4743. {
  4744. if(nav._buttons.prevPage) {
  4745. nav._buttons.prevPage.on('click', this.prevPage, this);
  4746. }
  4747. if(nav._buttons.nextPage) {
  4748. nav._buttons.nextPage.on('click', this.nextPage, this);
  4749. }
  4750. nav.on('resize', this.resize, this);
  4751. },
  4752. /**
  4753. * Hides the prev page and next page buttons
  4754. * if there is only one page of thumbs.
  4755. *
  4756. * @method _togglePageButtons
  4757. * @protected
  4758. */
  4759. _togglePageButtons: function()
  4760. {
  4761. var buttons = this.get('boundingBox').all('.fl-slideshow-nav-prevPage, .fl-slideshow-nav-nextPage'),
  4762. display = buttons.getStyle('display')[0];
  4763. if(this._numPages == 1 && display == 'inline-block') {
  4764. buttons.setStyle('display', 'none');
  4765. this._setSizeInfo();
  4766. }
  4767. else if(this._numPages > 1 && display == 'none') {
  4768. buttons.setStyle('display', 'inline-block');
  4769. this._setSizeInfo();
  4770. }
  4771. },
  4772. /**
  4773. * Sets the size info used when resizing and loading pages.
  4774. *
  4775. * @method _setSizeInfo
  4776. * @protected
  4777. */
  4778. _setSizeInfo: function()
  4779. {
  4780. var root = this.get('root'),
  4781. bb = this.get('boundingBox'),
  4782. bbPosition = bb.getStyle('position'),
  4783. bbLeftMargin = parseInt(bb.getStyle('marginLeft'), 10),
  4784. bbRightMargin = parseInt(bb.getStyle('marginRight'), 10),
  4785. bbTopMargin = parseInt(bb.getStyle('marginTop'), 10),
  4786. bbBottomMargin = parseInt(bb.getStyle('marginBottom'), 10),
  4787. bbLeftPadding = parseInt(bb.getStyle('paddingLeft'), 10),
  4788. bbRightPadding = parseInt(bb.getStyle('paddingRight'), 10),
  4789. bbTopPadding = parseInt(bb.getStyle('paddingTop'), 10),
  4790. bbBottomPadding = parseInt(bb.getStyle('paddingBottom'), 10),
  4791. parent = bb.get('parentNode'),
  4792. parentWidth = parseInt(parent.getComputedStyle('width'), 10),
  4793. parentHeight = parseInt(parent.getComputedStyle('height'), 10),
  4794. bbWidth = parentWidth - bbLeftPadding - bbRightPadding - bbLeftMargin - bbRightMargin,
  4795. bbHeight = parentHeight - bbTopPadding - bbBottomPadding - bbTopMargin - bbBottomMargin,
  4796. cbWidth = bbWidth,
  4797. pageWidth = bbWidth,
  4798. pageHeight = bbHeight,
  4799. columns = this.get('columns'),
  4800. rows = this.get('rows'),
  4801. imageConfig = this.get('imageConfig'),
  4802. horizontalSpacing = this.get('horizontalSpacing'),
  4803. verticalSpacing = this.get('verticalSpacing'),
  4804. spaceEvenly = this.get('spaceEvenly'),
  4805. centerSinglePage = this.get('centerSinglePage'),
  4806. leftNavWidth = 0,
  4807. rightNavWidth = 0,
  4808. topNavHeight = 0,
  4809. bottomNavHeight = 0,
  4810. colsPerPage = columns,
  4811. rowsPerPage = rows,
  4812. imagesPerPage = 0,
  4813. numPages = 1,
  4814. clipBoxMarginLeft = 0,
  4815. clipBoxTop = 0,
  4816. availHorizSpace = 0,
  4817. availVerticalSpace = 0;
  4818. // Position absolute causes some resizing bugs.
  4819. bb.setStyle('position', 'relative');
  4820. // Bounding box width
  4821. if(!isNaN(columns)) {
  4822. bbWidth = pageWidth = columns * (imageConfig.width + horizontalSpacing) + horizontalSpacing;
  4823. }
  4824. // Bounding box height
  4825. if(!isNaN(rows)) {
  4826. bbHeight = pageHeight = rows * (imageConfig.height + verticalSpacing) + verticalSpacing;
  4827. }
  4828. // Compensate for the navs
  4829. if(this._leftNav) {
  4830. leftNavWidth = parseInt(this._leftNav.get('boundingBox').getComputedStyle('width'), 10);
  4831. if(isNaN(columns)) {
  4832. pageWidth -= leftNavWidth;
  4833. }
  4834. else {
  4835. bbWidth += leftNavWidth;
  4836. }
  4837. }
  4838. if(this._rightNav) {
  4839. rightNavWidth = parseInt(this._rightNav.get('boundingBox').getComputedStyle('width'), 10);
  4840. if(isNaN(columns)) {
  4841. pageWidth -= rightNavWidth;
  4842. }
  4843. else {
  4844. bbWidth += rightNavWidth;
  4845. }
  4846. }
  4847. if(this._topNav) {
  4848. topNavHeight = parseInt(this._topNav.get('boundingBox').getComputedStyle('height'), 10);
  4849. if(isNaN(rows)) {
  4850. pageHeight -= topNavHeight;
  4851. }
  4852. else {
  4853. bbHeight += topNavHeight;
  4854. }
  4855. }
  4856. if(this._bottomNav) {
  4857. bottomNavHeight = parseInt(this._bottomNav.get('boundingBox').getComputedStyle('height'), 10);
  4858. if(isNaN(rows)) {
  4859. pageHeight -= bottomNavHeight;
  4860. }
  4861. else {
  4862. bbHeight += bottomNavHeight;
  4863. }
  4864. }
  4865. // Columns per page
  4866. if(isNaN(columns)) {
  4867. colsPerPage = Math.floor(pageWidth/(imageConfig.width + horizontalSpacing));
  4868. colsPerPage = colsPerPage < 1 ? 1 : colsPerPage;
  4869. }
  4870. // Rows per page
  4871. if(isNaN(rows)) {
  4872. rowsPerPage = Math.floor(pageHeight/(imageConfig.height + verticalSpacing));
  4873. rowsPerPage = rowsPerPage < 1 ? 1 : rowsPerPage;
  4874. }
  4875. // Images per page
  4876. imagesPerPage = colsPerPage * rowsPerPage;
  4877. // Number of pages
  4878. if(root.albumInfo) {
  4879. numPages = Math.ceil(root.albumInfo.images.length/imagesPerPage);
  4880. }
  4881. // Horizontal spacing
  4882. if(isNaN(columns) && spaceEvenly) {
  4883. horizontalSpacing = Math.floor((pageWidth - (imageConfig.width * colsPerPage))/(colsPerPage + 1));
  4884. }
  4885. // Vertical spacing
  4886. if(isNaN(rows) && spaceEvenly) {
  4887. verticalSpacing = Math.floor((pageHeight - (imageConfig.height * rowsPerPage))/(rowsPerPage + 1));
  4888. }
  4889. // Content container width
  4890. if(root.albumInfo && centerSinglePage && numPages == 1 && rowsPerPage == 1) {
  4891. cbWidth = root.albumInfo.images.length * imageConfig.width;
  4892. cbWidth += horizontalSpacing * (root.albumInfo.images.length + 1);
  4893. if(this._leftNav) {
  4894. cbWidth += leftNavWidth;
  4895. }
  4896. if(this._rightNav) {
  4897. cbWidth += rightNavWidth;
  4898. }
  4899. }
  4900. else {
  4901. cbWidth = bbWidth;
  4902. }
  4903. // Final page width and height
  4904. if(root.albumInfo && centerSinglePage && numPages == 1 && rowsPerPage == 1) {
  4905. pageWidth = root.albumInfo.images.length * imageConfig.width;
  4906. pageWidth += horizontalSpacing * root.albumInfo.images.length;
  4907. }
  4908. else {
  4909. pageWidth = colsPerPage * (imageConfig.width + horizontalSpacing);
  4910. }
  4911. pageHeight = rowsPerPage * (imageConfig.height + verticalSpacing);
  4912. // Clip box margin left
  4913. if(numPages < 2) {
  4914. clipBoxMarginLeft = leftNavWidth;
  4915. }
  4916. else {
  4917. availHorizSpace = bbWidth;
  4918. if(this._rightNav) {
  4919. availHorizSpace -= rightNavWidth;
  4920. }
  4921. if(this._leftNav) {
  4922. availHorizSpace -= leftNavWidth;
  4923. clipBoxMarginLeft = leftNavWidth + (availHorizSpace - pageWidth - horizontalSpacing)/2;
  4924. }
  4925. else {
  4926. clipBoxMarginLeft = (availHorizSpace - pageWidth - horizontalSpacing)/2;
  4927. }
  4928. }
  4929. // Clip box margin top
  4930. if(numPages > 1 && !spaceEvenly) {
  4931. availVerticalSpace = bbHeight;
  4932. if(this._topNav) {
  4933. availVerticalSpace -= topNavHeight;
  4934. }
  4935. if(this._bottomNav) {
  4936. availVerticalSpace -= bottomNavHeight;
  4937. }
  4938. clipBoxTop = (availVerticalSpace - (verticalSpacing + pageHeight))/2;
  4939. }
  4940. // Set the info
  4941. this._bbHeight = bbHeight;
  4942. this._bbWidth = bbWidth;
  4943. this._cbWidth = cbWidth;
  4944. this._clipBoxMarginLeft = clipBoxMarginLeft;
  4945. this._clipBoxTop = clipBoxTop;
  4946. this._colsPerPage = colsPerPage;
  4947. this._rowsPerPage = rowsPerPage;
  4948. this._imagesPerPage = imagesPerPage;
  4949. this._numPages = numPages;
  4950. this._pageHeight = pageHeight;
  4951. this._pageWidth = pageWidth;
  4952. this._leftNavWidth = leftNavWidth;
  4953. this._rightNavWidth = rightNavWidth;
  4954. this._horizontalSpacing = horizontalSpacing;
  4955. this._verticalSpacing = verticalSpacing;
  4956. this._activePageIndex = Math.floor(root.imageIndex/this._imagesPerPage);
  4957. // Set back to the initial position.
  4958. bb.setStyle('position', bbPosition);
  4959. }
  4960. }, {
  4961. /**
  4962. * Custom CSS class name for the widget.
  4963. *
  4964. * @property CSS_PREFIX
  4965. * @type String
  4966. * @protected
  4967. * @static
  4968. */
  4969. CSS_PREFIX: 'fl-slideshow-thumbs',
  4970. /**
  4971. * Static property used to define the default attribute configuration of
  4972. * the Widget.
  4973. *
  4974. * @property ATTRS
  4975. * @type Object
  4976. * @protected
  4977. * @static
  4978. */
  4979. ATTRS: {
  4980. /**
  4981. * The number of thumbnail columns. If set to auto, the number of
  4982. * columns will be calculated based on the width of the parent node.
  4983. *
  4984. * @attribute columns
  4985. * @type String or Number
  4986. * @default auto
  4987. */
  4988. columns: {
  4989. value: 'auto'
  4990. },
  4991. /**
  4992. * The number of thumbnail rows. If set to auto, the number of
  4993. * rows will be calculated based on the height of the parent node.
  4994. *
  4995. * @attribute rows
  4996. * @type String or Number
  4997. * @default auto
  4998. */
  4999. rows: {
  5000. value: 'auto'
  5001. },
  5002. /**
  5003. * The horizontal spacing between thumbs.
  5004. *
  5005. * @attribute horizontalSpacing
  5006. * @type Number
  5007. * @default 15
  5008. */
  5009. horizontalSpacing: {
  5010. value: 15
  5011. },
  5012. /**
  5013. * The vertical spacing between thumbs.
  5014. *
  5015. * @attribute verticalSpacing
  5016. * @type Number
  5017. * @default 15
  5018. */
  5019. verticalSpacing: {
  5020. value: 15
  5021. },
  5022. /**
  5023. * Whether to space the thumbs evenly within a page.
  5024. *
  5025. * @attribute spaceEvenly
  5026. * @type Boolean
  5027. * @default true
  5028. */
  5029. spaceEvenly: {
  5030. value: true
  5031. },
  5032. /**
  5033. * Whether to center single pages of thumbs.
  5034. *
  5035. * @attribute centerSinglePage
  5036. * @type Boolean
  5037. * @default false
  5038. */
  5039. centerSinglePage: {
  5040. value: true
  5041. },
  5042. /**
  5043. * Whether to pause the parent slideshow when a thumb is clicked.
  5044. *
  5045. * @attribute pauseOnClick
  5046. * @type Boolean
  5047. * @default false
  5048. */
  5049. pauseOnClick: {
  5050. value: false
  5051. },
  5052. /**
  5053. * The type of transition to use between pages.
  5054. *
  5055. * @attribute transition
  5056. * @type String
  5057. * @default slideHorizontal
  5058. */
  5059. transition: {
  5060. value: 'slideHorizontal'
  5061. },
  5062. /**
  5063. * The duration of the transition between pages.
  5064. *
  5065. * @attribute transitionDuration
  5066. * @type Number
  5067. * @default 0.8
  5068. */
  5069. transitionDuration: {
  5070. value: 0.8
  5071. },
  5072. /**
  5073. * The type of transition easing to use between pages.
  5074. *
  5075. * @attribute transitionEasing
  5076. * @type String
  5077. * @default ease-out
  5078. */
  5079. transitionEasing: {
  5080. value: 'ease-out'
  5081. },
  5082. /**
  5083. * The configuration object used to create new instances of
  5084. * FL.SlideshowImage. See the API docs for {@link FL.SlideshowImage}
  5085. * for a complete list of configuration attributes.
  5086. *
  5087. * @attribute imageConfig
  5088. * @type Object
  5089. * @default {}
  5090. */
  5091. imageConfig: {
  5092. value: {
  5093. crop: true,
  5094. width: 50,
  5095. height: 50
  5096. }
  5097. },
  5098. /**
  5099. * Whether to use the top nav or not.
  5100. *
  5101. * @attribute topNavEnabled
  5102. * @type Boolean
  5103. * @default false
  5104. */
  5105. topNavEnabled: {
  5106. value: false
  5107. },
  5108. /**
  5109. * An array of button names used to render the top nav buttons.
  5110. *
  5111. * @attribute topNavButtons
  5112. * @type Array
  5113. * @default prevPage, nextPage
  5114. */
  5115. topNavButtons: {
  5116. value: ['prevPage', 'nextPage']
  5117. },
  5118. /**
  5119. * Whether to use the right nav or not.
  5120. *
  5121. * @attribute rightNavEnabled
  5122. * @type Boolean
  5123. * @default true
  5124. */
  5125. rightNavEnabled: {
  5126. value: true
  5127. },
  5128. /**
  5129. * An array of button names used to render the right nav buttons.
  5130. *
  5131. * @attribute rightNavButtons
  5132. * @type Array
  5133. * @default nextPage
  5134. */
  5135. rightNavButtons: {
  5136. value: ['nextPage']
  5137. },
  5138. /**
  5139. * Whether to use the bottom nav or not.
  5140. *
  5141. * @attribute bottomNavEnabled
  5142. * @type Boolean
  5143. * @default false
  5144. */
  5145. bottomNavEnabled: {
  5146. value: false
  5147. },
  5148. /**
  5149. * An array of button names used to render the bottom nav buttons.
  5150. *
  5151. * @attribute bottomNavButtons
  5152. * @type Array
  5153. * @default prevPage, nextPage
  5154. */
  5155. bottomNavButtons:{
  5156. value: ['prevPage', 'nextPage']
  5157. },
  5158. /**
  5159. * Whether to use the left nav or not.
  5160. *
  5161. * @attribute leftNavEnabled
  5162. * @type Boolean
  5163. * @default true
  5164. */
  5165. leftNavEnabled: {
  5166. value: true
  5167. },
  5168. /**
  5169. * An array of button names used to render the left nav buttons.
  5170. *
  5171. * @attribute leftNavButtons
  5172. * @type Array
  5173. * @default prevPage
  5174. */
  5175. leftNavButtons:{
  5176. value: ['prevPage']
  5177. },
  5178. /**
  5179. * Whether to use touch gestures, when available,
  5180. * to transition between pages or not.
  5181. *
  5182. * @attribute touchSupport
  5183. * @type Boolean
  5184. * @default false
  5185. */
  5186. touchSupport: {
  5187. value: false
  5188. }
  5189. }
  5190. });
  5191. /**
  5192. * Provides functionality for transitions between slideshow components.
  5193. *
  5194. * @namespace FL
  5195. * @class SlideshowTransition
  5196. * @constructor
  5197. * @param config {Object} Configuration object
  5198. * @extends Base
  5199. */
  5200. Y.namespace('FL').SlideshowTransition = Y.Base.create('fl-slideshow-transition', Y.Base, [], {
  5201. /**
  5202. * The transition function to use when run is called.
  5203. *
  5204. * @property _transitionFunction
  5205. * @type String
  5206. * @default _transitionFade
  5207. * @protected
  5208. */
  5209. _transitionFunction: '_transitionFade',
  5210. /**
  5211. * The current transition type.
  5212. *
  5213. * @property _type
  5214. * @type String
  5215. * @default fade
  5216. * @protected
  5217. */
  5218. _type: 'fade',
  5219. /**
  5220. * Parses the transition type and sets the _transitionFunction
  5221. * used when run is called.
  5222. *
  5223. * @method initializer
  5224. * @protected
  5225. */
  5226. initializer: function()
  5227. {
  5228. var type = this.get('type'),
  5229. typeArray = [],
  5230. types = Y.FL.SlideshowTransition.TYPES,
  5231. slideshowImageTypes = Y.FL.SlideshowTransition.SLIDESHOW_IMAGE_TYPES,
  5232. isSlideshowImageTransition = Y.Array.indexOf(slideshowImageTypes, type) > -1,
  5233. isSlideshowImage = this._isSlideshowImage(),
  5234. itemIn = this.get('itemIn'),
  5235. itemOut = this.get('itemOut');
  5236. // Check for random transitions.
  5237. if(type.indexOf(',') > -1) {
  5238. typeArray = type.split(',');
  5239. typeArray.sort(function() { return 0.5 - Math.random(); });
  5240. type = typeArray[0];
  5241. }
  5242. // Make sure we can run this transition, otherwise set a fallback.
  5243. if(!isSlideshowImage && isSlideshowImageTransition) {
  5244. type = 'fade';
  5245. }
  5246. else if(isSlideshowImage) {
  5247. if((itemIn && itemIn.one('img') === null) || (itemOut && itemOut.one('img') === null)) {
  5248. type = 'none';
  5249. }
  5250. else if(isSlideshowImageTransition) {
  5251. if((Y.UA.gecko && Y.UA.gecko < 5) || Y.UA.opera > 0 || (Y.UA.ie > 0 && Y.UA.ie < 9)) {
  5252. type = 'fade';
  5253. }
  5254. }
  5255. }
  5256. // Set the transition function and type.
  5257. if(Y.FL.SlideshowTransition.TYPES[type]) {
  5258. this._transitionFunction = types[type];
  5259. this._type = type;
  5260. }
  5261. // Setup the items.
  5262. this._setupItems();
  5263. },
  5264. /**
  5265. * Fires the start event and calls the transition function.
  5266. *
  5267. * @method run
  5268. */
  5269. run: function()
  5270. {
  5271. /**
  5272. * Fires when the transition starts.
  5273. *
  5274. * @event start
  5275. */
  5276. this.fire('start');
  5277. this[this._transitionFunction].call(this);
  5278. },
  5279. /**
  5280. * Set initial styles for the items.
  5281. *
  5282. * @method _setupItems
  5283. * @protected
  5284. */
  5285. _setupItems: function()
  5286. {
  5287. var itemIn = this.get('itemIn'),
  5288. itemOut = this.get('itemOut');
  5289. if(itemIn) {
  5290. itemIn.setStyle('zIndex', 2);
  5291. itemIn.setStyle('opacity', 1);
  5292. if(Y.FL.Utils.cssSupport('transform')) {
  5293. itemIn.setStyle('transform', 'translate(0, 0)');
  5294. }
  5295. else {
  5296. itemIn.setStyle('top', '0');
  5297. itemIn.setStyle('left', '0');
  5298. }
  5299. }
  5300. if(itemOut) {
  5301. itemOut.setStyle('zIndex', 1);
  5302. }
  5303. },
  5304. /**
  5305. * Checks if the transition is being run
  5306. * on an instance of FL.SlideshowImage or not.
  5307. *
  5308. * @method _isSlideshowImage
  5309. * @protected
  5310. */
  5311. _isSlideshowImage: function()
  5312. {
  5313. var itemIn = this.get('itemIn'),
  5314. itemOut = this.get('itemOut');
  5315. if(itemIn && itemIn.hasClass('fl-slideshow-image')) {
  5316. return true;
  5317. }
  5318. else if(itemOut && itemOut.hasClass('fl-slideshow-image')) {
  5319. return true;
  5320. }
  5321. return false;
  5322. },
  5323. /**
  5324. * Starts the transtion using the provided property objects.
  5325. *
  5326. * @method _transitionStart
  5327. * @param propsIn {Object} The properties to animate in.
  5328. * @param propsOut {Object} The properties to animate out.
  5329. * @protected
  5330. */
  5331. _transitionStart: function(propsIn, propsOut)
  5332. {
  5333. var itemIn = this.get('itemIn'),
  5334. itemOut = this.get('itemOut'),
  5335. itemInCallback = Y.bind(this._transitionComplete, this),
  5336. itemOutCallback = !itemIn ? itemInCallback : null,
  5337. duration = this.get('duration'),
  5338. easing = this.get('easing');
  5339. if(itemIn) {
  5340. propsIn.duration = propsIn.duration || duration;
  5341. propsIn.easing = propsIn.easing || easing;
  5342. itemIn.transition(propsIn);
  5343. }
  5344. if(itemOut) {
  5345. propsOut.duration = propsOut.duration || duration;
  5346. propsOut.easing = propsOut.easing || easing;
  5347. itemOut.transition(propsOut);
  5348. }
  5349. if(itemInCallback) {
  5350. Y.later(propsIn.duration * 1000 + 100, null, itemInCallback);
  5351. }
  5352. else if(itemOutCallback) {
  5353. Y.later(propsOut.duration * 1000 + 100, null, itemOutCallback);
  5354. }
  5355. },
  5356. /**
  5357. * Clean up method called when the transition completes.
  5358. *
  5359. * @method _transitionComplete
  5360. * @protected
  5361. */
  5362. _transitionComplete: function()
  5363. {
  5364. this._set('itemIn', null);
  5365. this._set('itemOut', null);
  5366. /**
  5367. * Fires when the transition completes.
  5368. *
  5369. * @event complete
  5370. */
  5371. this.fire('complete');
  5372. },
  5373. /**
  5374. * No transition.
  5375. *
  5376. * @method _transitionNone
  5377. * @protected
  5378. */
  5379. _transitionNone: function()
  5380. {
  5381. var itemIn = this.get('itemIn'),
  5382. itemOut = this.get('itemOut');
  5383. if(itemIn) {
  5384. itemIn.setStyle('opacity', 1);
  5385. }
  5386. if(itemOut) {
  5387. itemOut.setStyle('opacity', 0);
  5388. }
  5389. this._transitionComplete();
  5390. },
  5391. /**
  5392. * Fade transition.
  5393. *
  5394. * @method _transitionFade
  5395. * @protected
  5396. */
  5397. _transitionFade: function()
  5398. {
  5399. var itemIn = this.get('itemIn');
  5400. if(itemIn) {
  5401. itemIn.setStyle('opacity', 0);
  5402. }
  5403. this._transitionStart({ opacity: 1 },{ opacity: 0 });
  5404. },
  5405. /**
  5406. * Slide left transition.
  5407. *
  5408. * @method _transitionSlideLeft
  5409. * @protected
  5410. */
  5411. _transitionSlideLeft: function()
  5412. {
  5413. if(Y.FL.Utils.cssSupport('transform')) {
  5414. this._cssTransitionSlide({
  5415. inStart: 'translate(100%, 0)',
  5416. inEnd: 'translate(0, 0)',
  5417. outStart: 'translate(0, 0)',
  5418. outEnd: 'translate(-100%, 0)'
  5419. });
  5420. }
  5421. else {
  5422. this._jsTransitionSlide('left');
  5423. }
  5424. },
  5425. /**
  5426. * Slide right transition.
  5427. *
  5428. * @method _transitionSlideRight
  5429. * @protected
  5430. */
  5431. _transitionSlideRight: function()
  5432. {
  5433. if(Y.FL.Utils.cssSupport('transform')) {
  5434. this._cssTransitionSlide({
  5435. inStart: 'translate(-100%, 0)',
  5436. inEnd: 'translate(0, 0)',
  5437. outStart: 'translate(0, 0)',
  5438. outEnd: 'translate(100%, 0)'
  5439. });
  5440. }
  5441. else {
  5442. this._jsTransitionSlide('right');
  5443. }
  5444. },
  5445. /**
  5446. * Slide up transition.
  5447. *
  5448. * @method _transitionSlideUp
  5449. * @protected
  5450. */
  5451. _transitionSlideUp: function()
  5452. {
  5453. if(Y.FL.Utils.cssSupport('transform')) {
  5454. this._cssTransitionSlide({
  5455. inStart: 'translate(0, 100%)',
  5456. inEnd: 'translate(0, 0)',
  5457. outStart: 'translate(0, 0)',
  5458. outEnd: 'translate(0, -100%)'
  5459. });
  5460. }
  5461. else {
  5462. this._jsTransitionSlide('up');
  5463. }
  5464. },
  5465. /**
  5466. * Slide down transition.
  5467. *
  5468. * @method _transitionSlideDown
  5469. * @protected
  5470. */
  5471. _transitionSlideDown: function()
  5472. {
  5473. if(Y.FL.Utils.cssSupport('transform')) {
  5474. this._cssTransitionSlide({
  5475. inStart: 'translate(0, -100%)',
  5476. inEnd: 'translate(0, 0)',
  5477. outStart: 'translate(0, 0)',
  5478. outEnd: 'translate(0, 100%)'
  5479. });
  5480. }
  5481. else {
  5482. this._jsTransitionSlide('down');
  5483. }
  5484. },
  5485. /**
  5486. * JavaScript slide transition.
  5487. *
  5488. * @method _jsTransitionSlide
  5489. * @protected
  5490. */
  5491. _jsTransitionSlide: function(direction)
  5492. {
  5493. var itemIn = this.get('itemIn'),
  5494. itemOut = this.get('itemOut'),
  5495. itemOutEnd = 0;
  5496. // Item Out
  5497. if(itemOut && direction == 'left') {
  5498. itemOutEnd = -parseInt(itemOut.getStyle('width'), 10);
  5499. }
  5500. if(itemOut && direction == 'right') {
  5501. itemOutEnd = parseInt(itemOut.getStyle('width'), 10);
  5502. }
  5503. if(itemOut && direction == 'up') {
  5504. itemOutEnd = -parseInt(itemOut.getStyle('height'), 10);
  5505. }
  5506. if(itemOut && direction == 'down') {
  5507. itemOutEnd = parseInt(itemOut.getStyle('height'), 10);
  5508. }
  5509. // Item In
  5510. if(itemIn) {
  5511. itemIn.setStyle('opacity', 1);
  5512. }
  5513. if(itemIn && direction == 'left') {
  5514. itemIn.setStyle('left', itemIn.getStyle('width'));
  5515. }
  5516. if(itemIn && direction == 'right') {
  5517. itemIn.setStyle('left', '-' + itemIn.getStyle('width'));
  5518. }
  5519. if(itemIn && direction == 'up') {
  5520. itemIn.setStyle('top', itemIn.getStyle('height'));
  5521. }
  5522. if(itemIn && direction == 'down') {
  5523. itemIn.setStyle('top', '-' + itemIn.getStyle('height'));
  5524. }
  5525. // Transition Start
  5526. if(direction == 'left' || direction == 'right') {
  5527. this._transitionStart({ left: 0 },{ left: itemOutEnd });
  5528. }
  5529. else {
  5530. this._transitionStart({ top: 0 },{ top: itemOutEnd });
  5531. }
  5532. },
  5533. /**
  5534. * CSS slide transition.
  5535. *
  5536. * @method _cssTransitionSlide
  5537. * @protected
  5538. */
  5539. _cssTransitionSlide: function(props)
  5540. {
  5541. var itemIn = this.get('itemIn'),
  5542. itemOut = this.get('itemOut'),
  5543. transformProp = Y.UA.chrome < 36 ? 'transform' : '-webkit-transform',
  5544. inProps = {},
  5545. outProps = {};
  5546. inProps[transformProp] = props.inEnd;
  5547. outProps[transformProp] = props.outEnd;
  5548. if(itemIn) {
  5549. itemIn.setStyle('transition', '');
  5550. itemIn.setStyle('opacity', 1);
  5551. itemIn.setStyle(transformProp, props.inStart);
  5552. }
  5553. if(itemOut) {
  5554. itemOut.setStyle('transition', '');
  5555. itemOut.setStyle(transformProp, props.outStart);
  5556. }
  5557. this._transitionStart(inProps, outProps);
  5558. },
  5559. /**
  5560. * Bars and blinds transition.
  5561. *
  5562. * @method _transitionBars
  5563. * @protected
  5564. */
  5565. _transitionBars: function()
  5566. {
  5567. // Hide the image until the slices have transitioned in.
  5568. this.get('itemIn').one('.fl-slideshow-image-img').setStyle('opacity', 0);
  5569. var numBars = this.get('bars'),
  5570. slices = this._renderSlices(1, numBars),
  5571. duration = this.get('duration'),
  5572. delay = 0,
  5573. increment = 100,
  5574. last = false,
  5575. i = 0,
  5576. clone = null,
  5577. props = {
  5578. duration: duration,
  5579. opacity: 1
  5580. };
  5581. // barsRandom
  5582. if(this._type == 'barsRandom') {
  5583. slices = this._randomizeSlices(slices);
  5584. }
  5585. // Transition the slices.
  5586. for( ; i < slices.length; i++) {
  5587. // Make a clone of our transition properties.
  5588. clone = Y.clone(props);
  5589. // blinds
  5590. if(this._type == 'blinds') {
  5591. clone.width = parseFloat(slices[i].getComputedStyle('width'), 10) + 'px';
  5592. slices[i].setStyle('width', '0px');
  5593. increment = 50;
  5594. }
  5595. // Run the transition.
  5596. last = i == slices.length - 1 ? true : false;
  5597. Y.later(delay, this, this._transitionSlice, [slices[i], clone, last]);
  5598. delay += increment;
  5599. }
  5600. this._transitionSlicesFadeLast(delay);
  5601. },
  5602. /**
  5603. * Boxes transition.
  5604. *
  5605. * @method _transitionBoxes
  5606. * @protected
  5607. */
  5608. _transitionBoxes: function()
  5609. {
  5610. // Hide the image until the slices have transitioned in.
  5611. this.get('itemIn').one('.fl-slideshow-image-img').setStyle('opacity', 0);
  5612. var numCols = this.get('boxCols'),
  5613. numRows = this.get('boxRows'),
  5614. numSlices = numCols * numRows,
  5615. multi = this._type != 'boxesRandom',
  5616. slices = this._renderSlices(numRows, numCols, multi),
  5617. duration = this.get('duration'),
  5618. delay = 0,
  5619. increment = 150,
  5620. last = false,
  5621. i = 0,
  5622. row = 0,
  5623. col = 0,
  5624. startCol = -1,
  5625. clone = null,
  5626. props = {
  5627. duration: duration,
  5628. opacity: 1
  5629. };
  5630. // boxesRandom
  5631. if(!multi) {
  5632. slices = this._randomizeSlices(slices);
  5633. increment = 30;
  5634. for( ; i < slices.length; i++) {
  5635. clone = Y.clone(props);
  5636. last = i == slices.length - 1 ? true : false;
  5637. Y.later(delay, this, this._transitionSlice, [slices[i], clone, last]);
  5638. delay += increment;
  5639. }
  5640. }
  5641. // boxes
  5642. else {
  5643. while(i < numSlices) {
  5644. for(row = 0; row < numRows; row++) {
  5645. if(row === 0) {
  5646. startCol++;
  5647. col = startCol;
  5648. }
  5649. if(col > -1 && col < numCols) {
  5650. i++;
  5651. clone = Y.clone(props);
  5652. // boxesGrow
  5653. if(this._type == 'boxesGrow') {
  5654. clone.height = parseFloat(slices[row][col].getComputedStyle('height'), 10) + 'px';
  5655. clone.width = parseFloat(slices[row][col].getComputedStyle('width'), 10) + 'px';
  5656. slices[row][col].setStyle('height', '0px');
  5657. slices[row][col].setStyle('width', '0px');
  5658. increment = 50;
  5659. }
  5660. last = i == numSlices - 1 ? true : false;
  5661. Y.later(delay, this, this._transitionSlice, [slices[row][col], clone, last]);
  5662. }
  5663. col--;
  5664. }
  5665. delay += increment;
  5666. }
  5667. }
  5668. this._transitionSlicesFadeLast(delay);
  5669. },
  5670. /**
  5671. * Renders the divs for slice based transitions.
  5672. *
  5673. * @method _renderSlices
  5674. * @protected
  5675. */
  5676. _renderSlices: function(numRows, numCols, multidimensional)
  5677. {
  5678. var itemIn = this.get('itemIn'),
  5679. itemHeight = parseFloat(itemIn.getComputedStyle('height'), 10),
  5680. itemWidth = parseFloat(itemIn.getComputedStyle('width'), 10),
  5681. img = itemIn.one('img'),
  5682. imgSrc = img.get('src'),
  5683. imgHeight = parseFloat(img.getComputedStyle('height'), 10),
  5684. imgWidth = parseFloat(img.getComputedStyle('width'), 10),
  5685. imgLeft = parseFloat(img.getComputedStyle('left'), 10),
  5686. imgTop = parseFloat(img.getComputedStyle('top'), 10),
  5687. col = 0,
  5688. row = 0,
  5689. sliceHeight = Math.round(itemHeight/numRows),
  5690. sliceWidth = Math.round(itemWidth/numCols),
  5691. slice = null,
  5692. sliceImg = null,
  5693. slices = [];
  5694. for( ; row < numRows; row++) {
  5695. if(typeof multidimensional !== 'undefined' && multidimensional) {
  5696. slices[row] = [];
  5697. }
  5698. for(col = 0; col < numCols; col++) {
  5699. slice = Y.Node.create('<div class="fl-slideshow-transition-slice"></div>');
  5700. sliceImg = Y.Node.create('<img src="'+ imgSrc +'" />');
  5701. slice.setStyles({
  5702. left: (sliceWidth * col) + 'px',
  5703. top: (sliceHeight * row) + 'px',
  5704. width: col == numCols - 1 ? (itemWidth - (sliceWidth * col)) + 'px' : sliceWidth + 'px',
  5705. height: row == numRows - 1 ? (itemHeight - (sliceHeight * row)) + 'px' : sliceHeight + 'px',
  5706. opacity: 0
  5707. });
  5708. sliceImg.setStyles({
  5709. height: imgHeight + 'px',
  5710. width: imgWidth + 'px',
  5711. top: imgTop - ((sliceHeight + (row * sliceHeight)) - sliceHeight) + 'px',
  5712. left: imgLeft - ((sliceWidth + (col * sliceWidth)) - sliceWidth) + 'px'
  5713. });
  5714. slice.append(sliceImg);
  5715. itemIn.append(slice);
  5716. if(typeof multidimensional !== 'undefined' && multidimensional) {
  5717. slices[row].push(slice);
  5718. }
  5719. else {
  5720. slices.push(slice);
  5721. }
  5722. }
  5723. }
  5724. return slices;
  5725. },
  5726. /**
  5727. * Fade the itemOut node.
  5728. *
  5729. * @method _transitionSlicesFadeLast
  5730. * @protected
  5731. */
  5732. _transitionSlicesFadeLast: function(delay)
  5733. {
  5734. var itemOut = this.get('itemOut');
  5735. if(itemOut && !itemOut.hasClass('fl-slideshow-image-cropped')) {
  5736. itemOut.transition({
  5737. duration: delay/1000 + this.get('duration'),
  5738. opacity: 0
  5739. });
  5740. }
  5741. },
  5742. /**
  5743. * Transitions a single slice.
  5744. *
  5745. * @method _transitionSlice
  5746. * @protected
  5747. */
  5748. _transitionSlice: function(slice, props, last)
  5749. {
  5750. var callback = last ? Y.bind(this._transitionSlicesComplete, this) : null;
  5751. slice.transition(props, callback);
  5752. },
  5753. /**
  5754. * Complete callback for slice based transitions.
  5755. *
  5756. * @method _transitionSlicesComplete
  5757. * @protected
  5758. */
  5759. _transitionSlicesComplete: function()
  5760. {
  5761. var itemIn = this.get('itemIn');
  5762. itemIn.all('.fl-slideshow-transition-slice').remove();
  5763. itemIn.one('.fl-slideshow-image-img').setStyle('opacity', 1);
  5764. this._transitionComplete();
  5765. },
  5766. /**
  5767. * Randomizes a slices array.
  5768. *
  5769. * @method _radomizeSlices
  5770. * @protected
  5771. */
  5772. _randomizeSlices: function(slices)
  5773. {
  5774. var i = slices.length, j, temp;
  5775. if(i === 0) {
  5776. return;
  5777. }
  5778. while(--i) {
  5779. j = Math.floor( Math.random() * ( i + 1 ) );
  5780. temp = slices[i];
  5781. slices[i] = slices[j];
  5782. slices[j] = temp;
  5783. }
  5784. return slices;
  5785. },
  5786. _transitionKenBurns: function()
  5787. {
  5788. var kbDuration = this.get('kenBurnsDuration'),
  5789. duration = this.get('duration'),
  5790. itemIn = this.get('itemIn'),
  5791. zoom = this.get('kenBurnsZoom');
  5792. this._transitionFade();
  5793. (new Y.FL.SlideshowKenBurns({
  5794. duration: kbDuration + duration + 4,
  5795. image: itemIn,
  5796. zoom: zoom
  5797. })).run();
  5798. }
  5799. }, {
  5800. /**
  5801. * Static property used to define the default attribute configuration of
  5802. * the Widget.
  5803. *
  5804. * @property ATTRS
  5805. * @type Object
  5806. * @protected
  5807. * @static
  5808. */
  5809. ATTRS: {
  5810. /**
  5811. * The Node to transition in.
  5812. *
  5813. * @attribute itemIn
  5814. * @type Node
  5815. * @default null
  5816. */
  5817. itemIn: {
  5818. value: null
  5819. },
  5820. /**
  5821. * The Node to transition out.
  5822. *
  5823. * @attribute itemOut
  5824. * @type Node
  5825. * @default null
  5826. */
  5827. itemOut: {
  5828. value: null
  5829. },
  5830. /**
  5831. * The duration of the transition in seconds.
  5832. *
  5833. * @attribute duration
  5834. * @type Number
  5835. * @default 0.5
  5836. */
  5837. duration: {
  5838. value: 0.5
  5839. },
  5840. /**
  5841. * The type of easing to use.
  5842. *
  5843. * @attribute easing
  5844. * @type String
  5845. * @default ease-out
  5846. */
  5847. easing: {
  5848. value: 'ease-out'
  5849. },
  5850. /**
  5851. * The type of transition to use.
  5852. *
  5853. * @attribute type
  5854. * @type String
  5855. * @default fade
  5856. */
  5857. type: {
  5858. value: 'fade'
  5859. },
  5860. /**
  5861. * The number of bars to use for
  5862. * transitions such as blinds.
  5863. *
  5864. * @attribute bars
  5865. * @type Number
  5866. * @default 15
  5867. */
  5868. bars: {
  5869. value: 15
  5870. },
  5871. /**
  5872. * The number of columns to use for
  5873. * transitions such as boxes.
  5874. *
  5875. * @attribute boxCols
  5876. * @type Number
  5877. * @default 8
  5878. */
  5879. boxCols: {
  5880. value: 8
  5881. },
  5882. /**
  5883. * The number of rows to use for
  5884. * transitions such as boxes.
  5885. *
  5886. * @attribute boxRows
  5887. * @type Number
  5888. * @default 4
  5889. */
  5890. boxRows: {
  5891. value: 4
  5892. },
  5893. /**
  5894. * The duration the ken burns effect will
  5895. * last, measured in seconds.
  5896. *
  5897. * @attribute kenBurnsDuration
  5898. * @type Number
  5899. * @default 4
  5900. */
  5901. kenBurnsDuration: {
  5902. value: 4
  5903. },
  5904. /**
  5905. * The amount of zoom to use for the Ken Burns effect.
  5906. *
  5907. * @attribute kenBurnsZoom
  5908. * @type Number
  5909. * @default 1.2
  5910. */
  5911. kenBurnsZoom: {
  5912. value: 1.2
  5913. }
  5914. },
  5915. /**
  5916. * The types of transitions and associated functions.
  5917. *
  5918. * @property TYPES
  5919. * @type Object
  5920. * @readOnly
  5921. * @protected
  5922. * @static
  5923. */
  5924. TYPES: {
  5925. fade: '_transitionFade',
  5926. none: '_transitionNone',
  5927. slideLeft: '_transitionSlideLeft',
  5928. slideRight: '_transitionSlideRight',
  5929. slideUp: '_transitionSlideUp',
  5930. slideDown: '_transitionSlideDown',
  5931. blinds: '_transitionBars',
  5932. bars: '_transitionBars',
  5933. barsRandom: '_transitionBars',
  5934. boxes: '_transitionBoxes',
  5935. boxesRandom: '_transitionBoxes',
  5936. boxesGrow: '_transitionBoxes',
  5937. kenBurns: '_transitionKenBurns'
  5938. },
  5939. /**
  5940. * The types of transitions that can only be
  5941. * run on FL.SlideshowImage widgets.
  5942. *
  5943. * @property SLIDESHOW_IMAGE_TYPES
  5944. * @type Object
  5945. * @readOnly
  5946. * @protected
  5947. * @static
  5948. */
  5949. SLIDESHOW_IMAGE_TYPES: [
  5950. 'blinds',
  5951. 'bars',
  5952. 'barsRandom',
  5953. 'boxes',
  5954. 'boxesRandom',
  5955. 'boxesGrow',
  5956. 'kenBurns'
  5957. ]
  5958. });
  5959. /**
  5960. * A highly configurable slideshow widget.
  5961. *
  5962. * @namespace FL
  5963. * @class Slideshow
  5964. * @constructor
  5965. * @param config {Object} Configuration object
  5966. * @extends FL.SlideshowBase
  5967. */
  5968. Y.namespace('FL').Slideshow = Y.Base.create('fl-slideshow', Y.FL.SlideshowBase, [], {
  5969. /**
  5970. * A FL.SlideshowFrame instance used for the main image.
  5971. *
  5972. * @property frame
  5973. * @type FL.SlideshowFrame
  5974. * @default null
  5975. */
  5976. frame: null,
  5977. /**
  5978. * A FL.SlideshowNav instance used for the main nav.
  5979. *
  5980. * @property nav
  5981. * @type FL.SlideshowNav
  5982. * @default null
  5983. */
  5984. nav: null,
  5985. /**
  5986. * A FL.SlideshowNav instance used for the image nav's left button.
  5987. *
  5988. * @property imageNavLeft
  5989. * @type FL.SlideshowNav
  5990. * @default null
  5991. */
  5992. imageNavLeft: null,
  5993. /**
  5994. * A FL.SlideshowNav instance used for the image nav's right button.
  5995. *
  5996. * @property imageNavRight
  5997. * @type FL.SlideshowNav
  5998. * @default null
  5999. */
  6000. imageNavRight: null,
  6001. /**
  6002. * A FL.SlideshowThumbs instance used for the thumbnail grid.
  6003. *
  6004. * @property thumbs
  6005. * @type FL.SlideshowThumbs
  6006. * @default null
  6007. */
  6008. thumbs: null,
  6009. /**
  6010. * A FL.SlideshowThumbs instance used for the vertical thumbnail grid.
  6011. *
  6012. * @property verticalThumbs
  6013. * @type FL.SlideshowThumbs
  6014. * @default null
  6015. */
  6016. verticalThumbs: null,
  6017. /**
  6018. * A FL.SlideshowCaption instance.
  6019. *
  6020. * @property caption
  6021. * @type FL.SlideshowCaption
  6022. * @default null
  6023. */
  6024. caption: null,
  6025. /**
  6026. * A FL.SlideshowSocial instance.
  6027. *
  6028. * @property social
  6029. * @type FL.SlideshowSocial
  6030. * @default null
  6031. */
  6032. social: null,
  6033. /**
  6034. * A FL.SlideshowImage instance used to preload
  6035. * the next image.
  6036. *
  6037. * @property _nextImagePreloader
  6038. * @type FL.SlideshowImage
  6039. * @default null
  6040. * @protected
  6041. */
  6042. _nextImagePreloader: null,
  6043. /**
  6044. * An object that holds the initial nav settings
  6045. * when the mini nav has been enabled for a responsive layout.
  6046. *
  6047. * @property _initialNavSettings
  6048. * @type Object
  6049. * @default null
  6050. * @protected
  6051. */
  6052. _initialNavSettings: null,
  6053. /**
  6054. * Initializes the preloaders, nav buttons, fullscreen and captions.
  6055. *
  6056. * @method initializer
  6057. * @protected
  6058. */
  6059. initializer: function()
  6060. {
  6061. // Preloader config
  6062. var imageConfig = {
  6063. loadGroup: 'main-preload',
  6064. crop: this.get('crop'),
  6065. position: this.get('position'),
  6066. protect: this.get('protect'),
  6067. upsize: this.get('upsize')
  6068. };
  6069. // Preloader
  6070. this._nextImagePreloader = new Y.FL.SlideshowImage(imageConfig);
  6071. // Nav buttons not needed for touch
  6072. if(this._isMobile()) {
  6073. this._removeNavButton('prevPage');
  6074. this._removeNavButton('nextPage');
  6075. this._removeNavButton('fullscreen');
  6076. }
  6077. // Fullscreen
  6078. if(this._hasNavButton('fullscreen')) {
  6079. if(Y.FL.SlideshowFullscreen.OS_SUPPORT) {
  6080. this.plug(Y.FL.SlideshowFullscreen);
  6081. }
  6082. else {
  6083. this._removeNavButton('fullscreen');
  6084. }
  6085. }
  6086. },
  6087. /**
  6088. * Calls the FL.SlideshowBase superclass renderUI method
  6089. * and renders the child widgets.
  6090. *
  6091. * @method renderUI
  6092. * @protected
  6093. */
  6094. renderUI: function()
  6095. {
  6096. Y.FL.Slideshow.superclass.renderUI.apply(this, arguments);
  6097. this._renderFrame();
  6098. this._renderVerticalThumbs();
  6099. this._renderNavAndThumbs();
  6100. this._renderImageNav();
  6101. this._renderMouseNav();
  6102. this._renderCaption();
  6103. this._renderSocial();
  6104. },
  6105. /**
  6106. * Calls the FL.SlideshowBase superclass bindUI method, binds
  6107. * _resizeChildWidgets to fire after the resize method inherited
  6108. * from FL.SlideshowBase, shows the loading image, binds overlay events
  6109. * and binds an event to load an image into the frame.
  6110. *
  6111. * @method bindUI
  6112. * @protected
  6113. */
  6114. bindUI: function()
  6115. {
  6116. var ssBB = this.get('boundingBox'),
  6117. frameBB = this.frame.get('boundingBox'),
  6118. navOverlay = this.get('navOverlay'),
  6119. navType = this.get('navType'),
  6120. nav = this._getNav(),
  6121. clickAction = this.get('clickAction');
  6122. // Call superclass bindUI
  6123. Y.FL.Slideshow.superclass.bindUI.apply(this, arguments);
  6124. // Resize child widgets after the superclass resize method.
  6125. Y.Do.after(this._resizeChildWidgets, this, 'resize');
  6126. // Loading events
  6127. this.on('albumLoadStart', this._albumLoadStart, this);
  6128. this.on('albumLoadComplete', this._albumLoadComplete, this);
  6129. this.on('imageLoadComplete', this._loadFrame, this);
  6130. // Loading image
  6131. if(this.get('loadingImageAlwaysEnabled')) {
  6132. this.frame.on('transitionInit', Y.bind(this._showLoadingImageWithDelay, this));
  6133. this.frame.on('transitionStart', Y.bind(this._hideLoadingImage, this));
  6134. }
  6135. // Overlay events
  6136. if(this.get('overlayHideOnMousemove')) {
  6137. if(nav && navOverlay) {
  6138. this.frame.once('transitionComplete', nav.slideshowOverlay.hideWithTimer, nav.slideshowOverlay);
  6139. ssBB.on('mousemove', Y.bind(this._toggleNav, this));
  6140. }
  6141. if(navType == 'buttons' || navType == 'thumbs' || navType == 'custom') {
  6142. ssBB.on('mouseenter', Y.bind(this._checkOverlaysOnMouseenter, this));
  6143. ssBB.on('mouseleave', Y.bind(this._hideAllOverlays, this));
  6144. }
  6145. }
  6146. ssBB.delegate('click', Y.bind(this._overlayCloseClick, this), '.fl-slideshow-overlay-close');
  6147. // Click action
  6148. if(clickAction == 'gallery' || clickAction == 'url') {
  6149. frameBB.delegate('click', Y.bind(this._frameClick, this), '.fl-slideshow-image-img');
  6150. }
  6151. },
  6152. /**
  6153. * Calls the FL.SlideshowBase superclass syncUI method
  6154. * and makes the bounding box unselectable.
  6155. *
  6156. * @method syncUI
  6157. * @protected
  6158. */
  6159. syncUI: function()
  6160. {
  6161. var bb = this.get('boundingBox');
  6162. Y.FL.Slideshow.superclass.syncUI.apply(this, arguments);
  6163. bb._node.onselectstart = function() { return false; };
  6164. bb._node.unselectable = "on";
  6165. bb._node.style.MozUserSelect = "none";
  6166. if(this.get('clickAction') != 'none') {
  6167. this.frame.get('boundingBox').addClass('fl-click-action-enabled');
  6168. }
  6169. },
  6170. /**
  6171. * Checks to see if the current device is mobile.
  6172. *
  6173. * @since 1.9.3
  6174. * @access private
  6175. * @method _isMobile
  6176. * @return {Boolean}
  6177. */
  6178. _isMobile: function()
  6179. {
  6180. return /Mobile|Android|Silk\/|Kindle|BlackBerry|Opera Mini|Opera Mobi|webOS/i.test( navigator.userAgent );
  6181. },
  6182. /**
  6183. * Unload all slideshow images and pause
  6184. * the slideshow.
  6185. *
  6186. * @method unload
  6187. */
  6188. unload: function()
  6189. {
  6190. this.pause();
  6191. this.frame.unload();
  6192. if(this.thumbs !== null) {
  6193. this.thumbs.unload();
  6194. }
  6195. },
  6196. /**
  6197. * @method _albumLoadStart
  6198. * @protected
  6199. */
  6200. _albumLoadStart: function()
  6201. {
  6202. this._showLoadingImage();
  6203. },
  6204. /**
  6205. * @method _albumLoadComplete
  6206. * @protected
  6207. */
  6208. _albumLoadComplete: function()
  6209. {
  6210. this.frame.once('transitionStart', Y.bind(this._hideLoadingImage, this));
  6211. },
  6212. /**
  6213. * Resizes all enabled child widgets.
  6214. *
  6215. * @method _resizeChildWidgets
  6216. * @protected
  6217. */
  6218. _resizeChildWidgets: function()
  6219. {
  6220. var bb = this.get('boundingBox'),
  6221. cb = this.get('contentBox'),
  6222. imageNavEnabled = this.get('imageNavEnabled');
  6223. this._renderNavAndThumbs();
  6224. if(this.get('verticalThumbsOverlay')) {
  6225. this._resizeFrame(cb.get('offsetWidth'), bb.get('offsetHeight'));
  6226. this._resizeVerticalThumbs();
  6227. }
  6228. else {
  6229. this._resizeVerticalThumbs();
  6230. this._resizeFrame(cb.get('offsetWidth'), bb.get('offsetHeight'));
  6231. }
  6232. if(imageNavEnabled) {
  6233. this._positionImageNav();
  6234. }
  6235. this._positionLoadingImage();
  6236. },
  6237. /**
  6238. * @method _renderVerticalThumbs
  6239. * @protected
  6240. */
  6241. _renderVerticalThumbs: function()
  6242. {
  6243. var threshold = this.get('responsiveThreshold'),
  6244. ssBB = this.get('boundingBox'),
  6245. bbWidth = ssBB.get('offsetWidth'),
  6246. vtBB;
  6247. if(this.get('verticalThumbsEnabled') && bbWidth > threshold) {
  6248. this.verticalThumbs = new Y.FL.SlideshowThumbs(this._getVerticalThumbsConfig());
  6249. this.add(this.verticalThumbs);
  6250. this.verticalThumbs.render(ssBB);
  6251. vtBB = this.verticalThumbs.get('boundingBox');
  6252. vtBB.addClass('fl-slideshow-vertical-thumbs');
  6253. vtBB.setStyle(this.get('verticalThumbsPosition'), 0);
  6254. ssBB.append(vtBB);
  6255. if(this.get('verticalThumbsOverlay')) {
  6256. this.verticalThumbs.plug(Y.FL.SlideshowOverlay, {
  6257. hideDelay: this.get('overlayHideDelay'),
  6258. hideStyle: 'left'
  6259. });
  6260. this.frame.get('boundingBox').append(vtBB);
  6261. this.verticalThumbs.resize();
  6262. }
  6263. else {
  6264. this.verticalThumbs.resize();
  6265. this._adjustContentForVerticalThumbs();
  6266. }
  6267. this._bindVerticalThumbs();
  6268. }
  6269. },
  6270. /**
  6271. * Prepares and returns the vertical thumbs config object.
  6272. *
  6273. * @method _getVerticalThumbsConfig
  6274. * @protected
  6275. * @returns Object
  6276. */
  6277. _getVerticalThumbsConfig: function()
  6278. {
  6279. var attrs = this.getAttrs(),
  6280. config = {
  6281. columns: attrs.verticalThumbsColumns,
  6282. rows: 'auto',
  6283. centerSinglePage: false,
  6284. horizontalSpacing: attrs.verticalThumbsHorizontalSpacing,
  6285. verticalSpacing: attrs.verticalThumbsVerticalSpacing,
  6286. spaceEvenly: attrs.verticalThumbsSpaceEvenly,
  6287. rightNavEnabled: false,
  6288. leftNavEnabled: false,
  6289. topNavEnabled: attrs.verticalThumbsTopNavEnabled,
  6290. topNavButtons: attrs.verticalThumbsTopNavButtons,
  6291. bottomNavEnabled: attrs.verticalThumbsBottomNavEnabled,
  6292. bottomNavButtons: attrs.verticalThumbsBottomNavButtons,
  6293. pauseOnClick: attrs.verticalThumbsPauseOnClick,
  6294. transition: attrs.verticalThumbsTransition,
  6295. transitionDirection: attrs.verticalThumbsTransitionDirection,
  6296. transitionEasing: attrs.verticalThumbsTransitionEasing,
  6297. touchSupport: true,
  6298. imageConfig: {
  6299. crop: attrs.verticalThumbsImageCrop,
  6300. width: attrs.verticalThumbsImageWidth,
  6301. height: attrs.verticalThumbsImageHeight
  6302. }
  6303. };
  6304. return config;
  6305. },
  6306. _bindVerticalThumbs: function()
  6307. {
  6308. var ssBB = this.get('boundingBox'),
  6309. hideOnMouse = this.get('overlayHideOnMousemove'),
  6310. vtOverlay = this.get('verticalThumbsOverlay'),
  6311. vt = this.verticalThumbs;
  6312. if(vt && hideOnMouse && vtOverlay) {
  6313. this.frame.once('transitionComplete', vt.slideshowOverlay.hideWithTimer, vt.slideshowOverlay);
  6314. ssBB.on('mousemove', Y.bind(this._toggleVerticalThumbs, this));
  6315. ssBB.on('mouseenter', Y.bind(this._toggleVerticalThumbs, this));
  6316. }
  6317. },
  6318. /**
  6319. * Resizes the vertical thumbs.
  6320. *
  6321. * @method _resizeVerticalThumbs
  6322. * @protected
  6323. */
  6324. _resizeVerticalThumbs: function()
  6325. {
  6326. var vtEnabled = this.get('verticalThumbsEnabled'),
  6327. vtOverlay,
  6328. threshold,
  6329. ssBB,
  6330. bbWidth,
  6331. navOverlay,
  6332. navType,
  6333. nav,
  6334. navBB;
  6335. if(vtEnabled) {
  6336. vtOverlay = this.get('verticalThumbsOverlay');
  6337. threshold = this.get('responsiveThreshold');
  6338. ssBB = this.get('boundingBox');
  6339. bbWidth = ssBB.get('offsetWidth');
  6340. navOverlay = this.get('navOverlay');
  6341. navType = this.get('navType');
  6342. nav = this._getNav();
  6343. if(this.verticalThumbs && bbWidth > threshold) {
  6344. this.verticalThumbs.get('boundingBox').setStyle('display', 'block');
  6345. this.verticalThumbs.resize();
  6346. if(!vtOverlay) {
  6347. this._adjustContentForVerticalThumbs();
  6348. }
  6349. else if(nav && navOverlay) {
  6350. navBB = nav.get('boundingBox');
  6351. if(navType == 'thumbs') {
  6352. this._adjustOverlayForVerticalThumbs(navBB, true);
  6353. this.thumbs.resize();
  6354. }
  6355. else {
  6356. this._adjustOverlayForVerticalThumbs(navBB);
  6357. }
  6358. }
  6359. }
  6360. else if(!this.verticalThumbs && bbWidth > threshold) {
  6361. this._renderVerticalThumbs();
  6362. }
  6363. else if(this.verticalThumbs && bbWidth <= threshold) {
  6364. this.verticalThumbs.get('boundingBox').setStyle('display', 'none');
  6365. if(!vtOverlay) {
  6366. this.get('contentBox').setStyles({
  6367. left: 'auto',
  6368. position: 'relative',
  6369. right: 'auto',
  6370. width: 'auto'
  6371. });
  6372. }
  6373. }
  6374. }
  6375. },
  6376. /**
  6377. * Toggles the visibility of the vertical thumbs.
  6378. *
  6379. * @method _toggleVerticalThumbs
  6380. * @protected
  6381. */
  6382. _toggleVerticalThumbs: function()
  6383. {
  6384. if(this.verticalThumbs) {
  6385. if(this.verticalThumbs.slideshowOverlay._visible) {
  6386. this.verticalThumbs.slideshowOverlay.hideWithTimer();
  6387. }
  6388. else {
  6389. this.verticalThumbs.slideshowOverlay.show();
  6390. }
  6391. }
  6392. },
  6393. /**
  6394. * Adjusts the content position and width
  6395. * for the vertical thumbs.
  6396. *
  6397. * @method _adjustContentForVerticalThumbs
  6398. * @protected
  6399. */
  6400. _adjustContentForVerticalThumbs: function()
  6401. {
  6402. var ssBB = this.get('boundingBox'),
  6403. vtBB = this.verticalThumbs.get('boundingBox'),
  6404. vtPos = this.get('verticalThumbsPosition'),
  6405. ssCB = this.get('contentBox'),
  6406. cbPos = vtPos == 'left' ? 'right' : 'left',
  6407. cbWidth = ssBB.get('offsetWidth') - vtBB.get('offsetWidth');
  6408. ssCB.setStyle('position', 'absolute');
  6409. ssCB.setStyle(cbPos, 0);
  6410. ssCB.setStyle('width', cbWidth);
  6411. },
  6412. /**
  6413. * Adjusts an overlay's position for the vertical
  6414. * thumbs when they are overlaid as well.
  6415. *
  6416. * @method _adjustOverlayForVerticalThumbs
  6417. * @protected
  6418. */
  6419. _adjustOverlayForVerticalThumbs: function(node, useMargin)
  6420. {
  6421. var vtEnabled = this.get('verticalThumbsEnabled'),
  6422. vtOverlay = this.get('verticalThumbsOverlay'),
  6423. vtBB = null,
  6424. vtPos = null,
  6425. margin = typeof useMargin === 'undefined' ? '' : 'margin-',
  6426. vtWidth = 0;
  6427. if(this.verticalThumbs && vtEnabled && vtOverlay) {
  6428. vtBB = this.verticalThumbs.get('boundingBox');
  6429. vtWidth = vtBB.get('offsetWidth');
  6430. vtPos = this.get('verticalThumbsPosition');
  6431. if(vtPos == 'left') {
  6432. node.setStyle(margin + 'left', vtWidth + 'px');
  6433. }
  6434. else {
  6435. node.setStyle(margin + 'right', vtWidth + 'px');
  6436. }
  6437. }
  6438. },
  6439. /**
  6440. * Creates and renders a new instance of FL.SlideshowFrame
  6441. * used for the main image.
  6442. *
  6443. * @method _renderFrame
  6444. * @protected
  6445. */
  6446. _renderFrame: function()
  6447. {
  6448. this.frame = new Y.FL.SlideshowFrame({
  6449. imageConfig: {
  6450. loadGroup: 'main',
  6451. loadPriority: true,
  6452. crop: this.get('crop'),
  6453. cropHorizontalsOnly: this.get('cropHorizontalsOnly'),
  6454. position: this.get('position'),
  6455. protect: this.get('protect'),
  6456. upsize: this.get('upsize'),
  6457. showVideoButton: this.get('navOverlay')
  6458. },
  6459. touchSupport: this.get('touchSupport')
  6460. });
  6461. this.add(this.frame);
  6462. this.frame.render(this.get('contentBox'));
  6463. this.frame.get('boundingBox').addClass('fl-slideshow-main-image');
  6464. this._setPlayingTimerEvent(this.frame, 'transitionComplete');
  6465. this._loadingImageContainer = this.frame.get('contentBox');
  6466. },
  6467. /**
  6468. * Resizes the frame used for the main image.
  6469. *
  6470. * @method _resizeMainImage
  6471. * @param width {Number} The width to resize to.
  6472. * @param height {Number} The height to resize to.
  6473. * @protected
  6474. */
  6475. _resizeFrame: function(width, height)
  6476. {
  6477. var navOverlay = this.get('navOverlay'),
  6478. nav = this._getNav();
  6479. if(nav && !navOverlay) {
  6480. height -= parseInt(nav.get('boundingBox').getComputedStyle('height'), 10);
  6481. }
  6482. this.frame.resize(width, height);
  6483. },
  6484. /**
  6485. * Called when the imageLoadComplete event fires.
  6486. * Loads an image into the frame and preloads the next image.
  6487. *
  6488. * @method _loadFrame
  6489. * @param e {Object} Event object containing the image info.
  6490. * @protected
  6491. */
  6492. _loadFrame: function(e)
  6493. {
  6494. var activeIndex = this.imageInfo.index,
  6495. images = this.albumInfo.images,
  6496. nextIndex = activeIndex + 1 >= images.length ? 0 : activeIndex + 1,
  6497. width = this.frame.get('width'),
  6498. height = this.frame.get('height');
  6499. // Load the frame.
  6500. this.frame.load(e.imageInfo);
  6501. // Remove main preload images from the load queue.
  6502. Y.FL.SlideshowImageLoader.removeGroup('main-preload');
  6503. // Preload the next image.
  6504. this._nextImagePreloader.preload(images[nextIndex], width, height);
  6505. },
  6506. /**
  6507. * Fired when the frame img tag is clicked.
  6508. *
  6509. * @method _frameClick
  6510. * @protected
  6511. */
  6512. _frameClick: function()
  6513. {
  6514. var clickAction = this.get('clickAction'),
  6515. clickActionUrl = this.get('clickActionUrl');
  6516. if(clickAction == 'url') {
  6517. window.location.href = clickActionUrl;
  6518. }
  6519. else if(clickAction == 'gallery') {
  6520. window.location.href = this.imageInfo.link;
  6521. }
  6522. },
  6523. /**
  6524. * Sets attributes to display a compact nav
  6525. * for responsive layouts.
  6526. *
  6527. * @method _initMiniNav
  6528. * @protected
  6529. */
  6530. _initMiniNav: function()
  6531. {
  6532. var buttons = [];
  6533. if(this._hasNavButton('prev')) {
  6534. buttons.push('prev');
  6535. }
  6536. if(this._hasNavButton('thumbs') || this.get('navType') == 'thumbs') {
  6537. buttons.push('thumbs');
  6538. }
  6539. if(this._hasNavButton('caption')) {
  6540. buttons.push('caption');
  6541. }
  6542. if(this._hasNavButton('social')) {
  6543. buttons.push('social');
  6544. }
  6545. if(this._hasNavButton('buy')) {
  6546. buttons.push('buy');
  6547. }
  6548. if(this._hasNavButton('play')) {
  6549. buttons.push('play');
  6550. }
  6551. if(this._hasNavButton('fullscreen') && !('ontouchstart' in window)) {
  6552. buttons.push('fullscreen');
  6553. }
  6554. if(this._hasNavButton('next')) {
  6555. buttons.push('next');
  6556. }
  6557. this._initialNavSettings = {
  6558. buttons: this.get('navButtons'),
  6559. buttonsLeft: this.get('navButtonsLeft'),
  6560. buttonsRight: this.get('navButtonsRight'),
  6561. type: this.get('navType')
  6562. };
  6563. this._set('navButtons', buttons);
  6564. this._set('navButtonsLeft', []);
  6565. this._set('navButtonsRight', []);
  6566. this._set('navType', 'buttons');
  6567. },
  6568. /**
  6569. * Renders the nav and thumbs layout based on the
  6570. * current window size.
  6571. *
  6572. * @method _renderNavAndThumbs
  6573. * @protected
  6574. */
  6575. _renderNavAndThumbs: function()
  6576. {
  6577. var navType = this.get('navType'),
  6578. renderNav = false,
  6579. bbWidth,
  6580. threshold;
  6581. if(navType == 'buttons' || navType == 'thumbs') {
  6582. bbWidth = this.get('boundingBox').get('offsetWidth');
  6583. threshold = this.get('responsiveThreshold');
  6584. if(bbWidth <= threshold && this._initialNavSettings === null) {
  6585. this._initMiniNav();
  6586. renderNav = true;
  6587. }
  6588. else if(bbWidth > threshold && this._initialNavSettings !== null) {
  6589. this._set('navButtons', this._initialNavSettings.buttons);
  6590. this._set('navButtonsLeft', this._initialNavSettings.buttonsLeft);
  6591. this._set('navButtonsRight', this._initialNavSettings.buttonsRight);
  6592. this._set('navType', this._initialNavSettings.type);
  6593. this._initialNavSettings = null;
  6594. renderNav = true;
  6595. }
  6596. // Button nav
  6597. if(renderNav || this.nav === null) {
  6598. this._renderNav();
  6599. }
  6600. // Thumbs nav
  6601. if(renderNav || this.thumbs === null) {
  6602. this._renderThumbs();
  6603. }
  6604. else if(this._thumbsEnabled()) {
  6605. this._resizeThumbs();
  6606. }
  6607. // Caption
  6608. if(renderNav && this.caption !== null) {
  6609. this._syncCaption();
  6610. }
  6611. // Social
  6612. if(renderNav && this.social !== null) {
  6613. this._syncSocial();
  6614. }
  6615. }
  6616. },
  6617. /**
  6618. * Creates and renders a new instance of FL.SlideshowNav
  6619. * used for the main nav.
  6620. *
  6621. * @method _renderNav
  6622. * @protected
  6623. */
  6624. _renderNav: function()
  6625. {
  6626. var frameBB = this.frame.get('boundingBox'),
  6627. navBB = null,
  6628. navOverlay = this.get('navOverlay'),
  6629. navPosition = this.get('navPosition');
  6630. // Destroy old instances
  6631. this._destroyNav();
  6632. // Create a new instance
  6633. if(this.get('navType') == 'buttons') {
  6634. // Create the nav
  6635. this.nav = new Y.FL.SlideshowNav({
  6636. buttons: this.get('navButtons'),
  6637. buttonsLeft: this.get('navButtonsLeft'),
  6638. buttonsRight: this.get('navButtonsRight')
  6639. });
  6640. // Add to widget parent and render
  6641. this.add(this.nav);
  6642. this.nav.render(this.get('contentBox'));
  6643. navBB = this.nav.get('boundingBox');
  6644. // Plug overlay?
  6645. if(navOverlay) {
  6646. this.nav.plug(Y.FL.SlideshowOverlay, {
  6647. hideDelay: this.get('overlayHideDelay')
  6648. });
  6649. navBB.setStyle('position', 'absolute');
  6650. navBB.setStyle(navPosition, '0px');
  6651. }
  6652. // Insert
  6653. if(navPosition == 'top') {
  6654. frameBB.insert(navBB, 'before');
  6655. }
  6656. else {
  6657. frameBB.insert(navBB, 'after');
  6658. }
  6659. // CSS class name
  6660. navBB.addClass('fl-slideshow-main-nav');
  6661. }
  6662. },
  6663. /**
  6664. * Destroy the current nav instance.
  6665. *
  6666. * @method _destroyNav
  6667. * @protected
  6668. */
  6669. _destroyNav: function()
  6670. {
  6671. if(this.nav !== null) {
  6672. if(this.nav.slideshowOverlay) {
  6673. this.nav.slideshowOverlay.destroy();
  6674. }
  6675. this.nav.get('boundingBox').remove();
  6676. this.remove(this.nav);
  6677. try { this.nav.destroy(true); } catch(e) {}
  6678. this.nav = null;
  6679. }
  6680. },
  6681. /**
  6682. * Returns the nav object or null if navType is
  6683. * set to none or custom.
  6684. *
  6685. * @method _getNav
  6686. * @protected
  6687. */
  6688. _getNav: function()
  6689. {
  6690. var navType = this.get('navType');
  6691. if(navType == 'buttons') {
  6692. return this.nav;
  6693. }
  6694. else if(navType == 'thumbs') {
  6695. return this.thumbs;
  6696. }
  6697. else {
  6698. return null;
  6699. }
  6700. },
  6701. /**
  6702. * Toggles the visibility of the nav or thumbs nav
  6703. * if navOverlay is set to true.
  6704. *
  6705. * @method _toggleNav
  6706. * @protected
  6707. */
  6708. _toggleNav: function()
  6709. {
  6710. var nav = this._getNav();
  6711. if(nav.slideshowOverlay) {
  6712. if(nav.slideshowOverlay._visible) {
  6713. nav.slideshowOverlay.hideWithTimer();
  6714. }
  6715. else {
  6716. nav.slideshowOverlay.show();
  6717. }
  6718. }
  6719. },
  6720. /**
  6721. * Creates and renders two instances of FL.SlideshowNav for the
  6722. * prev and next button that will be overlaid on the main image.
  6723. *
  6724. * @method _renderImageNav
  6725. * @protected
  6726. */
  6727. _renderImageNav: function()
  6728. {
  6729. var ssBB;
  6730. if(this.get('imageNavEnabled')) {
  6731. if(this._isMobile()) {
  6732. this._set('imageNavEnabled', false);
  6733. }
  6734. else {
  6735. ssBB = this.get('boundingBox');
  6736. this.imageNavLeft = new Y.FL.SlideshowNav({
  6737. buttons: ['prev'],
  6738. useFontIcons: false
  6739. });
  6740. this.imageNavRight = new Y.FL.SlideshowNav({
  6741. buttons: ['next'],
  6742. useFontIcons: false
  6743. });
  6744. this.add(this.imageNavLeft);
  6745. this.add(this.imageNavRight);
  6746. this.imageNavLeft.render(this.frame.get('boundingBox'));
  6747. this.imageNavRight.render(this.frame.get('boundingBox'));
  6748. this.imageNavLeft.plug(Y.FL.SlideshowOverlay, { hideDelay: this.get('overlayHideDelay') });
  6749. this.imageNavRight.plug(Y.FL.SlideshowOverlay, { hideDelay: this.get('overlayHideDelay') });
  6750. if(this.get('overlayHideOnMousemove')) {
  6751. this.frame.once('transitionComplete', this.imageNavLeft.slideshowOverlay.hideWithTimer, this.imageNavLeft.slideshowOverlay);
  6752. this.frame.once('transitionComplete', this.imageNavRight.slideshowOverlay.hideWithTimer, this.imageNavRight.slideshowOverlay);
  6753. ssBB.on('mousemove', Y.bind(this._toggleImageNav, this));
  6754. ssBB.on('mouseenter', Y.bind(this._toggleImageNav, this));
  6755. }
  6756. this.imageNavLeft.get('boundingBox').addClass('fl-slideshow-image-nav-left');
  6757. this.imageNavRight.get('boundingBox').addClass('fl-slideshow-image-nav-right');
  6758. }
  6759. }
  6760. },
  6761. /**
  6762. * @method _positionImageNav
  6763. * @protected
  6764. */
  6765. _positionImageNav: function()
  6766. {
  6767. var leftBB = this.imageNavLeft.get('boundingBox'),
  6768. rightBB = this.imageNavRight.get('boundingBox'),
  6769. imageNavHeight = leftBB.get('offsetHeight'),
  6770. frameHeight = this.frame.get('boundingBox').get('offsetHeight'),
  6771. top = frameHeight/2 - imageNavHeight/2,
  6772. styles = {
  6773. top: top + 'px',
  6774. display: 'block'
  6775. };
  6776. leftBB.setStyles(styles);
  6777. rightBB.setStyles(styles);
  6778. this._adjustOverlayForVerticalThumbs(leftBB);
  6779. this._adjustOverlayForVerticalThumbs(rightBB);
  6780. },
  6781. /**
  6782. * Toggles the visibility of the image nav buttons.
  6783. *
  6784. * @method _toggleImageNav
  6785. * @protected
  6786. */
  6787. _toggleImageNav: function()
  6788. {
  6789. if(this.imageNavLeft.slideshowOverlay._visible) {
  6790. this.imageNavLeft.slideshowOverlay.hideWithTimer();
  6791. }
  6792. else {
  6793. this.imageNavLeft.slideshowOverlay.show();
  6794. }
  6795. if(this.imageNavRight.slideshowOverlay._visible) {
  6796. this.imageNavRight.slideshowOverlay.hideWithTimer();
  6797. }
  6798. else {
  6799. this.imageNavRight.slideshowOverlay.show();
  6800. }
  6801. },
  6802. /**
  6803. * @method _renderMouseNav
  6804. * @protected
  6805. */
  6806. _renderMouseNav: function()
  6807. {
  6808. if(this.get('mouseNavEnabled') && !('ontouchstart' in window) && !window.navigator.msPointerEnabled) {
  6809. this.plug(Y.FL.SlideshowMouseNav, {
  6810. trigger: this.frame.get('boundingBox')
  6811. });
  6812. }
  6813. },
  6814. /**
  6815. * Checks whether the thumbs are enabled.
  6816. *
  6817. * @method _thumbsEnabled
  6818. * @protected
  6819. * @returns Boolean
  6820. */
  6821. _thumbsEnabled: function()
  6822. {
  6823. var navType = this.get('navType');
  6824. if(navType == 'thumbs') {
  6825. return true;
  6826. }
  6827. if((navType == 'buttons' || navType == 'custom') && this._hasNavButton('thumbs')) {
  6828. return true;
  6829. }
  6830. else {
  6831. return false;
  6832. }
  6833. },
  6834. /**
  6835. * Creates and renders a new instance of FL.SlideshowThumbs.
  6836. *
  6837. * @method _renderThumbs
  6838. * @protected
  6839. */
  6840. _renderThumbs: function()
  6841. {
  6842. var frameBB, navOverlay, navPosition, navType;
  6843. // Destroy old instances
  6844. this._destroyThumbs();
  6845. // Create a new instance
  6846. if(this._thumbsEnabled()) {
  6847. frameBB = this.frame.get('boundingBox');
  6848. navOverlay = this.get('navOverlay');
  6849. navPosition = this.get('navPosition');
  6850. navType = this.get('navType');
  6851. // Create the thumbs
  6852. this.thumbs = new Y.FL.SlideshowThumbs(this._getThumbsConfig());
  6853. // This breaks sometimes on SM Next. Try/catch bandaid for now.
  6854. try { this.add(this.thumbs); } catch(e) {}
  6855. // Overlay setup
  6856. if(navType == 'buttons' || navType == 'custom') {
  6857. this.thumbs.plug(Y.FL.SlideshowOverlay, {
  6858. hideDelay: this.get('overlayHideDelay'),
  6859. hideStyle: 'left',
  6860. visible: false
  6861. });
  6862. }
  6863. else if(navType == 'thumbs' && navOverlay) {
  6864. this.thumbs.plug(Y.FL.SlideshowOverlay, {
  6865. hideDelay: this.get('overlayHideDelay'),
  6866. hideStyle: 'left'
  6867. });
  6868. }
  6869. // Insert
  6870. this.thumbs.render(this.get('contentBox'));
  6871. if(navPosition == 'top') {
  6872. frameBB.insert(this.thumbs.get('boundingBox'), 'before');
  6873. }
  6874. else {
  6875. frameBB.insert(this.thumbs.get('boundingBox'), 'after');
  6876. }
  6877. // Hide overlay thumbs on click
  6878. if(this.get('thumbsHideOnClick') && navType != 'thumbs') {
  6879. this.thumbs.on('imageClick', Y.bind(this._hideThumbsOnImageClick, this));
  6880. }
  6881. this._syncThumbs();
  6882. }
  6883. },
  6884. /**
  6885. * Destroy the current thumbs instance.
  6886. *
  6887. * @method _destroyThumbs
  6888. * @protected
  6889. */
  6890. _destroyThumbs: function()
  6891. {
  6892. if(this.thumbs !== null) {
  6893. if(this.thumbs.slideshowOverlay) {
  6894. this.thumbs.slideshowOverlay.destroy();
  6895. }
  6896. this.thumbs.get('boundingBox').remove();
  6897. this.remove(this.thumbs);
  6898. try { this.thumbs.destroy(true); } catch(e) {}
  6899. this.thumbs = null;
  6900. }
  6901. },
  6902. /**
  6903. * Syncs the thumbs UI styles.
  6904. *
  6905. * @method _syncThumbs
  6906. * @protected
  6907. */
  6908. _syncThumbs: function()
  6909. {
  6910. var thumbsBB = this.thumbs.get('boundingBox'),
  6911. navOverlay = this.get('navOverlay'),
  6912. navPosition = this.get('navPosition'),
  6913. navType = this.get('navType'),
  6914. paddingType = 'padding' + navPosition.charAt(0).toUpperCase() + navPosition.slice(1),
  6915. navHeight = 0;
  6916. if(navType == 'buttons') {
  6917. navHeight = parseInt(this.nav.get('boundingBox').getComputedStyle('height'), 10);
  6918. thumbsBB.setStyle('position', 'absolute');
  6919. if(navOverlay) {
  6920. thumbsBB.setStyle(paddingType, navHeight + 'px');
  6921. thumbsBB.setStyle(navPosition, '0px');
  6922. }
  6923. else {
  6924. thumbsBB.setStyle(navPosition, navHeight + 'px');
  6925. }
  6926. }
  6927. if(navType == 'custom' || (navType == 'thumbs' && navOverlay)) {
  6928. thumbsBB.setStyle('position', 'absolute');
  6929. thumbsBB.setStyle(navPosition, '0px');
  6930. }
  6931. this.thumbs.resize();
  6932. },
  6933. /**
  6934. * Prepares and returns the thumbs config object.
  6935. *
  6936. * @method _getThumbsConfig
  6937. * @protected
  6938. * @returns Object
  6939. */
  6940. _getThumbsConfig: function()
  6941. {
  6942. var attrs = this.getAttrs(),
  6943. navType = this.get('navType'),
  6944. imageConfig = {
  6945. crop: attrs.thumbsImageCrop,
  6946. width: attrs.thumbsImageWidth,
  6947. height: attrs.thumbsImageHeight
  6948. },
  6949. config = {
  6950. columns: 'auto',
  6951. rows: 1,
  6952. horizontalSpacing: attrs.thumbsHorizontalSpacing,
  6953. verticalSpacing: attrs.thumbsVerticalSpacing,
  6954. spaceEvenly: attrs.thumbsSpaceEvenly,
  6955. centerSinglePage: attrs.thumbsCenterSinglePage,
  6956. pauseOnClick: attrs.thumbsPauseOnClick,
  6957. transition: attrs.thumbsTransition,
  6958. transitionDirection: attrs.thumbsTransitionDirection,
  6959. transitionEasing: attrs.thumbsTransitionEasing,
  6960. leftNavButtons: attrs.navButtonsLeft,
  6961. rightNavButtons: attrs.navButtonsRight,
  6962. imageConfig: imageConfig,
  6963. touchSupport: true
  6964. };
  6965. if(navType == 'buttons' || navType == 'custom') {
  6966. if('ontouchstart' in window) {
  6967. config.leftNavEnabled = false;
  6968. config.rightNavEnabled = false;
  6969. }
  6970. else {
  6971. config.centerSinglePage = false;
  6972. config.leftNavButtons = ['prevPage'];
  6973. config.rightNavButtons = ['nextPage'];
  6974. }
  6975. }
  6976. return config;
  6977. },
  6978. /**
  6979. * Resizes the thumbs.
  6980. *
  6981. * @method _resizeThumbs
  6982. * @protected
  6983. */
  6984. _resizeThumbs: function()
  6985. {
  6986. if(this.thumbs) {
  6987. this.thumbs.resize();
  6988. }
  6989. },
  6990. /**
  6991. * Shows or hides the thumbs.
  6992. *
  6993. * @method _toggleThumbs
  6994. * @protected
  6995. */
  6996. _toggleThumbs: function()
  6997. {
  6998. this._toggleOverlay(this.thumbs.slideshowOverlay);
  6999. },
  7000. /**
  7001. * Hides the thumbs when a thumb image is clicked.
  7002. *
  7003. * @method _hideThumbsOnImageClick
  7004. * @protected
  7005. */
  7006. _hideThumbsOnImageClick: function()
  7007. {
  7008. if(this.thumbs.slideshowOverlay) {
  7009. this.thumbs.slideshowOverlay._focus = false;
  7010. this.thumbs.slideshowOverlay.enable();
  7011. this.thumbs.slideshowOverlay.hide();
  7012. if(this.nav && this.nav.slideshowOverlay) {
  7013. this.nav.slideshowOverlay.enable();
  7014. }
  7015. }
  7016. },
  7017. /**
  7018. * Creates and renders a new instance of FL.SlideshowCaption.
  7019. *
  7020. * @method _renderCaption
  7021. * @protected
  7022. */
  7023. _renderCaption: function()
  7024. {
  7025. if(this._hasNavButton('caption')) {
  7026. this.caption = new Y.FL.SlideshowCaption({
  7027. lessLinkText: this.get('captionLessLinkText'),
  7028. moreLinkText: this.get('captionMoreLinkText'),
  7029. textLength: this.get('captionTextLength'),
  7030. stripTags: this.get('captionStripTags')
  7031. });
  7032. this.add(this.caption);
  7033. this.caption.plug(Y.FL.SlideshowOverlay, {
  7034. hideDelay: this.get('overlayHideDelay'),
  7035. visible: false,
  7036. closeButton: true
  7037. });
  7038. this._syncCaption();
  7039. }
  7040. },
  7041. /**
  7042. * Syncs the caption UI styles.
  7043. *
  7044. * @method _syncCaption
  7045. * @protected
  7046. */
  7047. _syncCaption: function()
  7048. {
  7049. var captionBB = this.caption.get('boundingBox'),
  7050. navOverlay = this.get('navOverlay'),
  7051. navPosition = this.get('navPosition'),
  7052. nav = this._getNav(),
  7053. paddingType = 'padding' + navPosition.charAt(0).toUpperCase() + navPosition.slice(1),
  7054. navHeight = 0;
  7055. captionBB.setStyle('position', 'absolute');
  7056. if(nav) {
  7057. navHeight = parseInt(nav.get('boundingBox').getComputedStyle('height'), 10);
  7058. }
  7059. if(nav && navOverlay) {
  7060. captionBB.setStyle(paddingType, navHeight + 'px');
  7061. captionBB.setStyle(navPosition, '0px');
  7062. }
  7063. else {
  7064. captionBB.setStyle(navPosition, navHeight + 'px');
  7065. }
  7066. },
  7067. /**
  7068. * Shows or hides the caption.
  7069. *
  7070. * @method _toggleCaption
  7071. * @protected
  7072. */
  7073. _toggleCaption: function()
  7074. {
  7075. this._toggleOverlay(this.caption.slideshowOverlay);
  7076. },
  7077. /**
  7078. * Creates and renders a new instance of FL.SlideshowSocial.
  7079. *
  7080. * @method _renderSocial
  7081. * @protected
  7082. */
  7083. _renderSocial: function()
  7084. {
  7085. if(this._hasNavButton('social')) {
  7086. this.social = new Y.FL.SlideshowSocial();
  7087. this.add(this.social);
  7088. this.social.plug(Y.FL.SlideshowOverlay, {
  7089. hideDelay: this.get('overlayHideDelay'),
  7090. visible: false,
  7091. closeButton: true
  7092. });
  7093. this._syncSocial();
  7094. }
  7095. },
  7096. /**
  7097. * Syncs the social UI styles.
  7098. *
  7099. * @method _syncSocial
  7100. * @protected
  7101. */
  7102. _syncSocial: function()
  7103. {
  7104. var socialBB = this.social.get('boundingBox'),
  7105. navOverlay = this.get('navOverlay'),
  7106. navPosition = this.get('navPosition'),
  7107. nav = this._getNav(),
  7108. paddingType = 'padding' + navPosition.charAt(0).toUpperCase() + navPosition.slice(1),
  7109. navHeight = 0;
  7110. socialBB.setStyle('position', 'absolute');
  7111. if(nav) {
  7112. navHeight = parseInt(nav.get('boundingBox').getComputedStyle('height'), 10);
  7113. }
  7114. if(nav && navOverlay) {
  7115. socialBB.setStyle(paddingType, navHeight + 'px');
  7116. socialBB.setStyle(navPosition, '0px');
  7117. }
  7118. else {
  7119. socialBB.setStyle(navPosition, navHeight + 'px');
  7120. }
  7121. },
  7122. /**
  7123. * Shows or hides the social buttons.
  7124. *
  7125. * @method _toggleSocial
  7126. * @protected
  7127. */
  7128. _toggleSocial: function()
  7129. {
  7130. this._toggleOverlay(this.social.slideshowOverlay);
  7131. },
  7132. /**
  7133. * Shows or hides an overlaid widget based
  7134. * on its current visibility.
  7135. *
  7136. * @method _toggleOverlay
  7137. * @param overlay {Object} The overlay to toggle.
  7138. * @protected
  7139. */
  7140. _toggleOverlay: function(overlay)
  7141. {
  7142. var navType = this.get('navType'),
  7143. nav = this._getNav();
  7144. if(overlay._visible) {
  7145. if(nav && nav.slideshowOverlay) {
  7146. nav.slideshowOverlay.enable();
  7147. }
  7148. overlay.enable();
  7149. overlay.hide();
  7150. }
  7151. else {
  7152. if(nav && nav.slideshowOverlay) {
  7153. nav.slideshowOverlay.disable();
  7154. }
  7155. overlay.show();
  7156. overlay.disable();
  7157. }
  7158. if(this.thumbs && navType != 'thumbs' && this.thumbs.slideshowOverlay !== overlay) {
  7159. this.thumbs.slideshowOverlay.enable();
  7160. this.thumbs.slideshowOverlay.hide();
  7161. }
  7162. if(this.caption && this.caption.slideshowOverlay !== overlay) {
  7163. this.caption.slideshowOverlay.enable();
  7164. this.caption.slideshowOverlay.hide();
  7165. }
  7166. if(this.social && this.social.slideshowOverlay !== overlay) {
  7167. this.social.slideshowOverlay.enable();
  7168. this.social.slideshowOverlay.hide();
  7169. }
  7170. },
  7171. /**
  7172. * Called when an overlay's close button is clicked.
  7173. *
  7174. * @method _overlayCloseClick
  7175. * @protected
  7176. */
  7177. _overlayCloseClick: function()
  7178. {
  7179. if(this.nav && this.nav.slideshowOverlay) {
  7180. this.nav.slideshowOverlay.enable();
  7181. }
  7182. if(this.thumbs && this.thumbs.slideshowOverlay) {
  7183. this.thumbs.slideshowOverlay.enable();
  7184. }
  7185. if(this.caption) {
  7186. this.caption.slideshowOverlay.enable();
  7187. }
  7188. if(this.social) {
  7189. this.social.slideshowOverlay.enable();
  7190. }
  7191. if(this.imageNavLeft) {
  7192. this.imageNavLeft.slideshowOverlay.enable();
  7193. this.imageNavRight.slideshowOverlay.enable();
  7194. }
  7195. },
  7196. /**
  7197. * Hides all overlaid widgets.
  7198. *
  7199. * @method _hideAllOverlays
  7200. * @protected
  7201. */
  7202. _hideAllOverlays: function()
  7203. {
  7204. if(this.nav && this.nav.slideshowOverlay && this.nav.slideshowOverlay._visible) {
  7205. this.nav.slideshowOverlay.enable();
  7206. this.nav.slideshowOverlay.hideWithTimer();
  7207. }
  7208. if(this.thumbs && this.thumbs.slideshowOverlay && this.thumbs.slideshowOverlay._visible) {
  7209. this.thumbs.slideshowOverlay.enable();
  7210. this.thumbs.slideshowOverlay.hideWithTimer();
  7211. }
  7212. if(this.caption && this.caption.slideshowOverlay._visible) {
  7213. this.caption.slideshowOverlay.enable();
  7214. this.caption.slideshowOverlay.hideWithTimer();
  7215. }
  7216. if(this.social && this.social.slideshowOverlay._visible) {
  7217. this.social.slideshowOverlay.enable();
  7218. this.social.slideshowOverlay.hideWithTimer();
  7219. }
  7220. if(this.imageNavLeft) {
  7221. this.imageNavLeft.slideshowOverlay.enable();
  7222. this.imageNavLeft.slideshowOverlay.hideWithTimer();
  7223. this.imageNavRight.slideshowOverlay.enable();
  7224. this.imageNavRight.slideshowOverlay.hideWithTimer();
  7225. }
  7226. },
  7227. /**
  7228. * Checks if overlays are still visible when the mouse enters
  7229. * the bounding box. If they are, overlay functionality is disabled
  7230. * until the overlays are closed by a button or the mouse leaves
  7231. * the bounding box. If only the nav overlay is visible, this
  7232. * function does nothing.
  7233. *
  7234. * @method _checkOverlaysOnMouseenter
  7235. * @protected
  7236. */
  7237. _checkOverlaysOnMouseenter: function()
  7238. {
  7239. var navType = this.get('navType'),
  7240. navOverlay = this.get('navOverlay'),
  7241. nav = this._getNav(),
  7242. overlayVisible = false;
  7243. if(this.thumbs && navType != 'thumbs' && this.thumbs.slideshowOverlay._visible) {
  7244. overlayVisible = true;
  7245. this.thumbs.slideshowOverlay.disable();
  7246. }
  7247. else if(this.caption && this.caption.slideshowOverlay._visible) {
  7248. overlayVisible = true;
  7249. this.caption.slideshowOverlay.disable();
  7250. }
  7251. else if(this.social && this.social.slideshowOverlay._visible) {
  7252. overlayVisible = true;
  7253. this.social.slideshowOverlay.disable();
  7254. }
  7255. if(nav && overlayVisible && navOverlay) {
  7256. nav.slideshowOverlay.disable();
  7257. }
  7258. },
  7259. /**
  7260. * Checks whether a nav button is set or not.
  7261. *
  7262. * @method _hasNavButton
  7263. * @protected
  7264. * @param button {String} The button to look for.
  7265. * @returns Boolean
  7266. */
  7267. _hasNavButton: function(button)
  7268. {
  7269. var navType = this.get('navType');
  7270. if(navType == 'buttons' || navType == 'thumbs' || navType == 'custom') {
  7271. if(Y.Array.indexOf(this.get('navButtons'), button) > -1) {
  7272. return true;
  7273. }
  7274. else if(Y.Array.indexOf(this.get('navButtonsLeft'), button) > -1) {
  7275. return true;
  7276. }
  7277. else if(Y.Array.indexOf(this.get('navButtonsRight'), button) > -1) {
  7278. return true;
  7279. }
  7280. else {
  7281. return false;
  7282. }
  7283. }
  7284. else {
  7285. return false;
  7286. }
  7287. },
  7288. /**
  7289. * @method _removeNavButton
  7290. * @param button {String} The name of the button to remove.
  7291. * @protected
  7292. */
  7293. _removeNavButton: function(button)
  7294. {
  7295. var buttons = this.get('navButtons'),
  7296. buttonsLeft = this.get('navButtonsLeft'),
  7297. buttonsRight = this.get('navButtonsRight'),
  7298. vtTopNavButtons = this.get('verticalThumbsTopNavButtons'),
  7299. vtBottomNavButtons = this.get('verticalThumbsBottomNavButtons');
  7300. if(Y.Array.indexOf(buttons, button) > -1) {
  7301. buttons.splice(Y.Array.indexOf(buttons, button), 1);
  7302. }
  7303. if(Y.Array.indexOf(buttonsLeft, button) > -1) {
  7304. buttonsLeft.splice(Y.Array.indexOf(buttonsLeft, button), 1);
  7305. }
  7306. if(Y.Array.indexOf(buttonsRight, button) > -1) {
  7307. buttonsRight.splice(Y.Array.indexOf(buttonsRight, button), 1);
  7308. }
  7309. if(Y.Array.indexOf(vtTopNavButtons, button) > -1) {
  7310. vtTopNavButtons.splice(Y.Array.indexOf(vtTopNavButtons, button), 1);
  7311. }
  7312. if(Y.Array.indexOf(vtBottomNavButtons, button) > -1) {
  7313. vtBottomNavButtons.splice(Y.Array.indexOf(vtBottomNavButtons, button), 1);
  7314. }
  7315. this._set('navButtons', buttons);
  7316. this._set('navButtonsLeft', buttonsLeft);
  7317. this._set('navButtonsRight', buttonsRight);
  7318. this._set('verticalThumbsTopNavButtons', vtTopNavButtons);
  7319. this._set('verticalThumbsBottomNavButtons', vtBottomNavButtons);
  7320. }
  7321. }, {
  7322. /**
  7323. * Custom CSS class name for the widget.
  7324. *
  7325. * @property CSS_PREFIX
  7326. * @type String
  7327. * @protected
  7328. * @static
  7329. */
  7330. CSS_PREFIX: 'fl-slideshow',
  7331. /**
  7332. * Static property used to define the default attribute configuration of
  7333. * the Widget.
  7334. *
  7335. * @property ATTRS
  7336. * @type Object
  7337. * @protected
  7338. * @static
  7339. */
  7340. ATTRS: {
  7341. /**
  7342. * What should happen when the main image is clicked.
  7343. * Options are none, gallery and url. If url is chosen,
  7344. * clickActionUrl must be set.
  7345. *
  7346. * @attribute clickAction
  7347. * @type String
  7348. * @default none
  7349. */
  7350. clickAction: {
  7351. value: 'none'
  7352. },
  7353. /**
  7354. * The redirect url to use when clickAction is set to url.
  7355. *
  7356. * @attribute clickActionUrl
  7357. * @type String
  7358. * @default none
  7359. */
  7360. clickActionUrl: {
  7361. value: ''
  7362. },
  7363. /**
  7364. * Whether to crop the main image.
  7365. *
  7366. * @attribute crop
  7367. * @type Boolean
  7368. * @default false
  7369. */
  7370. crop: {
  7371. value: false
  7372. },
  7373. /**
  7374. * Whether to only crop horizontal images or not.
  7375. *
  7376. * @attribute cropHorizontalsOnly
  7377. * @type Boolean
  7378. * @default false
  7379. */
  7380. cropHorizontalsOnly: {
  7381. value: false
  7382. },
  7383. /**
  7384. * Whether to always use the loading image between images
  7385. * or to only use it between albums.
  7386. *
  7387. * @attribute loadingImageAlwaysEnabled
  7388. * @type Boolean
  7389. * @default true
  7390. */
  7391. loadingImageAlwaysEnabled: {
  7392. value: true
  7393. },
  7394. /**
  7395. * The x and y position of the main image
  7396. * within the bounding box.
  7397. *
  7398. * @attribute position
  7399. * @type String
  7400. * @default center center
  7401. */
  7402. position: {
  7403. value: 'center center'
  7404. },
  7405. /**
  7406. * Whether to right click protect the main image.
  7407. *
  7408. * @attribute protect
  7409. * @type Boolean
  7410. * @default true
  7411. */
  7412. protect: {
  7413. value: true
  7414. },
  7415. /**
  7416. * Whether to resize the main image past
  7417. * its original width and height.
  7418. *
  7419. * @attribute upsize
  7420. * @type Boolean
  7421. * @default true
  7422. */
  7423. upsize: {
  7424. value: true
  7425. },
  7426. /**
  7427. * The type of transition to use. Possible values are
  7428. * none, fade, slideHorizontal and slideVertical. The
  7429. * value can also be a common seperated string of transitions
  7430. * that will be randomly chosen for each image.
  7431. *
  7432. * @attribute transition
  7433. * @type String
  7434. * @default fade
  7435. */
  7436. transition: {
  7437. value: 'fade'
  7438. },
  7439. /**
  7440. * The duration of the transition, measured in seconds.
  7441. *
  7442. * @attribute transitionDuration
  7443. * @type Number
  7444. * @default 1
  7445. */
  7446. transitionDuration: {
  7447. value: 1
  7448. },
  7449. /**
  7450. * The type of transition easing to use.
  7451. *
  7452. * @attribute transitionEasing
  7453. * @type String
  7454. * @default ease-out
  7455. */
  7456. transitionEasing: {
  7457. value: 'ease-out'
  7458. },
  7459. /**
  7460. * The amount of zoom to use for the Ken Burns effect.
  7461. *
  7462. * @attribute kenBurnsZoom
  7463. * @type Number
  7464. * @default 1.2
  7465. */
  7466. kenBurnsZoom: {
  7467. value: 1.2
  7468. },
  7469. /**
  7470. * The type of navigation to use. Possible values are
  7471. * buttons, thumbs, custon and none.
  7472. *
  7473. * @attribute navType
  7474. * @type String
  7475. * @default none
  7476. */
  7477. navType: {
  7478. value: 'none'
  7479. },
  7480. /**
  7481. * The position of the main nav. Possible values are top and bottom.
  7482. *
  7483. * @attribute navPosition
  7484. * @type String
  7485. * @default bottom
  7486. */
  7487. navPosition: {
  7488. value: 'bottom'
  7489. },
  7490. /**
  7491. * Whether to overlay the nav on top of the main image.
  7492. *
  7493. * @attribute navOverlay
  7494. * @type Boolean
  7495. * @default false
  7496. */
  7497. navOverlay: {
  7498. value: false
  7499. },
  7500. /**
  7501. * An array of button names used to render the main nav's buttons.
  7502. *
  7503. * @attribute navButtons
  7504. * @type Array
  7505. * @default []
  7506. */
  7507. navButtons: {
  7508. value: []
  7509. },
  7510. /**
  7511. * An array of button names used to render the main nav's left buttons.
  7512. *
  7513. * @attribute navButtonsLeft
  7514. * @type Array
  7515. * @default []
  7516. */
  7517. navButtonsLeft: {
  7518. value: []
  7519. },
  7520. /**
  7521. * An array of button names used to render the main nav's right buttons.
  7522. *
  7523. * @attribute navButtonsRight
  7524. * @type Array
  7525. * @default []
  7526. */
  7527. navButtonsRight: {
  7528. value: []
  7529. },
  7530. /**
  7531. * Whether to hide the overlays when the mouse moves or not.
  7532. *
  7533. * @attribute overlayHideOnMousemove
  7534. * @type String
  7535. * @default mouseover
  7536. */
  7537. overlayHideOnMousemove: {
  7538. value: true
  7539. },
  7540. /**
  7541. * How long to wait before hiding the overlays.
  7542. * Measured in milliseconds.
  7543. *
  7544. * @attribute overlayHideDelay
  7545. * @type Number
  7546. * @default false
  7547. */
  7548. overlayHideDelay: {
  7549. value: 3000
  7550. },
  7551. /**
  7552. * Whether to use the image nav or not. If true, a prev
  7553. * and next button will be overlaid on the main image.
  7554. *
  7555. * @attribute imageNavEnabled
  7556. * @type Boolean
  7557. * @default false
  7558. */
  7559. imageNavEnabled: {
  7560. value: false
  7561. },
  7562. /**
  7563. * Whether to use the mouse nav or not. If true, the cursor
  7564. * will turn into a prev or next button when over the slideshow.
  7565. *
  7566. * @attribute mouseNavEnabled
  7567. * @type Boolean
  7568. * @default false
  7569. */
  7570. mouseNavEnabled: {
  7571. value: false
  7572. },
  7573. /**
  7574. * Whether to hide the thumbs when clicking on a thumbnail
  7575. * image or not. Thumbs always hide navType is set to buttons.
  7576. *
  7577. * @attribute thumbsHideOnClick
  7578. * @type Boolean
  7579. * @default false
  7580. */
  7581. thumbsHideOnClick: {
  7582. value: true
  7583. },
  7584. /**
  7585. * The horizontal spacing between thumbs.
  7586. *
  7587. * @attribute thumbsHorizontalSpacing
  7588. * @type Number
  7589. * @default 15
  7590. */
  7591. thumbsHorizontalSpacing: {
  7592. value: 15
  7593. },
  7594. /**
  7595. * The vertical spacing between thumbs.
  7596. *
  7597. * @attribute thumbsVerticalSpacing
  7598. * @type Number
  7599. * @default 15
  7600. */
  7601. thumbsVerticalSpacing: {
  7602. value: 15
  7603. },
  7604. /**
  7605. * Whether to space the thumbs evenly within a page.
  7606. *
  7607. * @attribute thumbsSpaceEvenly
  7608. * @type Boolean
  7609. * @default true
  7610. */
  7611. thumbsSpaceEvenly: {
  7612. value: true
  7613. },
  7614. /**
  7615. * Whether to center single pages of thumbs.
  7616. *
  7617. * @attribute thumbsCenterSinglePage
  7618. * @type Boolean
  7619. * @default false
  7620. */
  7621. thumbsCenterSinglePage: {
  7622. value: true
  7623. },
  7624. /**
  7625. * Whether to pause the slideshow when a thumb is clicked.
  7626. *
  7627. * @attribute thumbsPauseOnClick
  7628. * @type Boolean
  7629. * @default false
  7630. */
  7631. thumbsPauseOnClick: {
  7632. value: false
  7633. },
  7634. /**
  7635. * The type of transition to use between pages of thumbs.
  7636. *
  7637. * @attribute thumbsTransition
  7638. * @type String
  7639. * @default slideHorizontal
  7640. */
  7641. thumbsTransition: {
  7642. value: 'slideHorizontal'
  7643. },
  7644. /**
  7645. * The duration of the transition between pages of thumbs.
  7646. *
  7647. * @attribute thumbsTransitionDuration
  7648. * @type Number
  7649. * @default 0.8
  7650. */
  7651. thumbsTransitionDuration: {
  7652. value: 0.8
  7653. },
  7654. /**
  7655. * The type of transition easing to use between pages of thumbs.
  7656. *
  7657. * @attribute thumbsTransitionEasing
  7658. * @type String
  7659. * @default ease-out
  7660. */
  7661. thumbsTransitionEasing: {
  7662. value: 'ease-out'
  7663. },
  7664. /**
  7665. * Whether to crop the thumbnails.
  7666. *
  7667. * @attribute thumbsImageCrop
  7668. * @type Boolean
  7669. * @default true
  7670. */
  7671. thumbsImageCrop: {
  7672. value: true
  7673. },
  7674. /**
  7675. * The width of each thumbnail.
  7676. *
  7677. * @attribute thumbsImageWidth
  7678. * @type Number
  7679. * @default 50
  7680. */
  7681. thumbsImageWidth: {
  7682. value: 50
  7683. },
  7684. /**
  7685. * The height of each thumbnail.
  7686. *
  7687. * @attribute thumbsImageHeight
  7688. * @type Number
  7689. * @default 50
  7690. */
  7691. thumbsImageHeight: {
  7692. value: 50
  7693. },
  7694. /**
  7695. * The text to use for the "read less" toggle link.
  7696. *
  7697. * @attribute captionLessLinkText
  7698. * @type String
  7699. * @default Read Less
  7700. */
  7701. captionLessLinkText: {
  7702. value: 'Read Less'
  7703. },
  7704. /**
  7705. * The text to use for the "read more" toggle link.
  7706. *
  7707. * @attribute captionMoreLinkText
  7708. * @type String
  7709. * @default Read More
  7710. */
  7711. captionMoreLinkText: {
  7712. value: 'Read More'
  7713. },
  7714. /**
  7715. * The length of the caption to show. If greater than -1,
  7716. * the text will be truncated and a read more link will
  7717. * be displayed. If set to -1, the entire caption will be shown.
  7718. *
  7719. * @attribute captionTextLength
  7720. * @type Number
  7721. * @default 200
  7722. */
  7723. captionTextLength: {
  7724. value: 200
  7725. },
  7726. /**
  7727. * Whether to strip out HTML tags in the caption
  7728. * text or not.
  7729. *
  7730. * @attribute captionStripTags
  7731. * @type Boolean
  7732. * @default false
  7733. */
  7734. captionStripTags: {
  7735. value: false
  7736. },
  7737. /**
  7738. * Whether to use the vertical thumbs or not.
  7739. *
  7740. * @attribute verticalThumbsEnabled
  7741. * @type Boolean
  7742. * @default false
  7743. */
  7744. verticalThumbsEnabled: {
  7745. value: false
  7746. },
  7747. /**
  7748. * Position of the vertical thumbs. Possible values
  7749. * are either left or right.
  7750. *
  7751. * @attribute verticalThumbsPosition
  7752. * @type String
  7753. * @default left
  7754. */
  7755. verticalThumbsPosition: {
  7756. value: 'left'
  7757. },
  7758. /**
  7759. * Whether to overlay the vertical thumbs
  7760. * on the main image or not.
  7761. *
  7762. * @attribute verticalThumbsOverlay
  7763. * @type Boolean
  7764. * @default false
  7765. */
  7766. verticalThumbsOverlay: {
  7767. value: false
  7768. },
  7769. /**
  7770. * The number of columns for the vertical thumbs.
  7771. *
  7772. * @attribute verticalThumbsColumns
  7773. * @type Number
  7774. * @default 1
  7775. */
  7776. verticalThumbsColumns: {
  7777. value: 1
  7778. },
  7779. /**
  7780. * Whether to use the vertical thumbs top nav or not.
  7781. *
  7782. * @attribute verticalThumbsTopNavEnabled
  7783. * @type Boolean
  7784. * @default false
  7785. */
  7786. verticalThumbsTopNavEnabled: {
  7787. value: false
  7788. },
  7789. /**
  7790. * An array of button names used to render
  7791. * the vertical thumbs top nav buttons.
  7792. *
  7793. * @attribute verticalThumbsTopNavButtons
  7794. * @type Array
  7795. * @default prevPage, nextPage
  7796. */
  7797. verticalThumbsTopNavButtons: {
  7798. value: ['prevPage', 'nextPage']
  7799. },
  7800. /**
  7801. * Whether to use the vertical thumbs bottom nav or not.
  7802. *
  7803. * @attribute verticalThumbsBottomNavEnabled
  7804. * @type Boolean
  7805. * @default false
  7806. */
  7807. verticalThumbsBottomNavEnabled: {
  7808. value: true
  7809. },
  7810. /**
  7811. * An array of button names used to render
  7812. * the vertical thumbs top nav buttons.
  7813. *
  7814. * @attribute verticalThumbsBottomNavButtons
  7815. * @type Array
  7816. * @default prevPage, nextPage
  7817. */
  7818. verticalThumbsBottomNavButtons: {
  7819. value: ['prevPage', 'nextPage']
  7820. },
  7821. /**
  7822. * The horizontal spacing between vertical thumbs.
  7823. *
  7824. * @attribute verticalThumbsHorizontalSpacing
  7825. * @type Number
  7826. * @default 15
  7827. */
  7828. verticalThumbsHorizontalSpacing: {
  7829. value: 15
  7830. },
  7831. /**
  7832. * The vertical spacing between vertical thumbs.
  7833. *
  7834. * @attribute verticalThumbsVerticalSpacing
  7835. * @type Number
  7836. * @default 15
  7837. */
  7838. verticalThumbsVerticalSpacing: {
  7839. value: 15
  7840. },
  7841. /**
  7842. * Whether to space the vertical thumbs evenly within a page.
  7843. *
  7844. * @attribute verticalThumbsSpaceEvenly
  7845. * @type Boolean
  7846. * @default false
  7847. */
  7848. verticalThumbsSpaceEvenly: {
  7849. value: false
  7850. },
  7851. /**
  7852. * Whether to pause the slideshow when a vertical thumb is clicked.
  7853. *
  7854. * @attribute verticalThumbsPauseOnClick
  7855. * @type Boolean
  7856. * @default false
  7857. */
  7858. verticalThumbsPauseOnClick: {
  7859. value: false
  7860. },
  7861. /**
  7862. * Whether to crop the vertical thumbs or not.
  7863. *
  7864. * @attribute verticalThumbsImageCrop
  7865. * @type Boolean
  7866. * @default true
  7867. */
  7868. verticalThumbsImageCrop: {
  7869. value: true
  7870. },
  7871. /**
  7872. * The width of each vertical thumbnail.
  7873. *
  7874. * @attribute verticalThumbsImageWidth
  7875. * @type Number
  7876. * @default 75
  7877. */
  7878. verticalThumbsImageWidth: {
  7879. value: 75
  7880. },
  7881. /**
  7882. * The height of each vertical thumbnail.
  7883. *
  7884. * @attribute verticalThumbsImageHeight
  7885. * @type Number
  7886. * @default 75
  7887. */
  7888. verticalThumbsImageHeight: {
  7889. value: 75
  7890. },
  7891. /**
  7892. * The type of transition to use between pages of vertical thumbs.
  7893. *
  7894. * @attribute verticalThumbsTransition
  7895. * @type String
  7896. * @default slideVertical
  7897. */
  7898. verticalThumbsTransition: {
  7899. value: 'slideVertical'
  7900. },
  7901. /**
  7902. * The duration of the transition between pages of vertical thumbs.
  7903. *
  7904. * @attribute verticalThumbsTransitionDuration
  7905. * @type Number
  7906. * @default 0.8
  7907. */
  7908. verticalThumbsTransitionDuration: {
  7909. value: 0.8
  7910. },
  7911. /**
  7912. * The type of transition easing to use between pages of vertical thumbs.
  7913. *
  7914. * @attribute verticalThumbsTransitionEasing
  7915. * @type String
  7916. * @default ease-out
  7917. */
  7918. verticalThumbsTransitionEasing: {
  7919. value: 'ease-out'
  7920. },
  7921. /**
  7922. * Whether to use the Google Plus button or not.
  7923. *
  7924. * @attribute googlePlusButtonEnabled
  7925. * @type Boolean
  7926. * @default true
  7927. */
  7928. googlePlusButtonEnabled: {
  7929. value: true
  7930. },
  7931. /**
  7932. * Whether to use the Facebook like button or not.
  7933. *
  7934. * @attribute likeButtonEnabled
  7935. * @type Boolean
  7936. * @default true
  7937. */
  7938. likeButtonEnabled: {
  7939. value: true
  7940. },
  7941. /**
  7942. * Whether to use the Pinterest button or not.
  7943. *
  7944. * @attribute pinterestButtonEnabled
  7945. * @type Boolean
  7946. * @default true
  7947. */
  7948. pinterestButtonEnabled: {
  7949. value: true
  7950. },
  7951. /**
  7952. * Whether to use the Tweet button or not.
  7953. *
  7954. * @attribute tweetButtonEnabled
  7955. * @type Boolean
  7956. * @default true
  7957. */
  7958. tweetButtonEnabled: {
  7959. value: true
  7960. },
  7961. /**
  7962. * Whether to use touch gestures, when available,
  7963. * to transition between images or not.
  7964. *
  7965. * @attribute touchSupport
  7966. * @type Boolean
  7967. * @default true
  7968. */
  7969. touchSupport: {
  7970. value: true
  7971. }
  7972. }
  7973. });
  7974. }, '2.0.0' ,{requires:['anim', 'event-mouseenter', 'plugin', 'transition', 'fl-event-move', 'fl-slideshow-css', 'fl-slideshow-base', 'fl-utils', 'sm-fonticon']});
  7975. YUI.add('fl-slideshow-album-loader', function(Y) {
  7976. /**
  7977. * @module fl-slideshow-album-loader
  7978. */
  7979. /**
  7980. * Loads slideshow albums using a provided source object.
  7981. *
  7982. * @namespace FL
  7983. * @class SlideshowAlbumLoader
  7984. * @constructor
  7985. * @param config {Object} Configuration object
  7986. * @extends Base
  7987. */
  7988. Y.namespace('FL').SlideshowAlbumLoader = Y.Base.create('fl-slideshow-album-loader', Y.Base, [], {
  7989. /**
  7990. * The source object used for loading.
  7991. *
  7992. * @property _source
  7993. * @type Object
  7994. * @default null
  7995. * @protected
  7996. */
  7997. _source: null,
  7998. /**
  7999. * Loads slideshow album data using the provided source object.
  8000. *
  8001. * @method load
  8002. * @param source {Object} The source object to use for loading.
  8003. */
  8004. load: function(source)
  8005. {
  8006. this._source = source;
  8007. /**
  8008. * Fires before a new load request is made.
  8009. *
  8010. * @event start
  8011. */
  8012. this.fire('start');
  8013. this[Y.FL.SlideshowAlbumLoader.TYPES[source.type]].call(this);
  8014. },
  8015. /**
  8016. * Called when a source type completes loading
  8017. * and fires the complete event.
  8018. *
  8019. * @method _loadComplete
  8020. * @param o {Object} Passed to complete event subscribers.
  8021. * @protected
  8022. */
  8023. _loadComplete: function(o)
  8024. {
  8025. o = this._randomize(o);
  8026. /**
  8027. * Fires after a new load request is made.
  8028. *
  8029. * @event complete
  8030. */
  8031. this.fire('complete', o);
  8032. },
  8033. /**
  8034. * Randomizes images in an album.
  8035. *
  8036. * @method _randomize
  8037. * @param album {Object} The album to randomize.
  8038. * @protected
  8039. */
  8040. _randomize: function(o)
  8041. {
  8042. var i;
  8043. if(this.get('randomize')) {
  8044. o.albumInfo.images.sort(function() { return 0.5 - Math.random(); });
  8045. for(i = 0; i < o.albumInfo.images.length; i++) {
  8046. o.albumInfo.images[i].index = i;
  8047. }
  8048. }
  8049. return o;
  8050. },
  8051. /**
  8052. * Loads slideshow album data from SmugMug.
  8053. *
  8054. * @method _loadSmugMug
  8055. * @protected
  8056. */
  8057. _loadSmugMug: function()
  8058. {
  8059. var sm = new Y.FL.SmugMugAPI();
  8060. sm.on('complete', this._loadSmugMugSuccess, this);
  8061. sm.addParam('method', 'smugmug.images.get');
  8062. sm.addParam('AlbumID', this._source.id);
  8063. sm.addParam('AlbumKey', this._source.key);
  8064. sm.addParam('Extras', 'Caption,Format,FileName');
  8065. // Gallery password
  8066. if(this._source.password) {
  8067. sm.addParam('Password', this._source.password);
  8068. }
  8069. // Site-wide password
  8070. if(this._source.sp) {
  8071. sm.addParam('SitePassword', this._source.sp);
  8072. }
  8073. sm.request();
  8074. },
  8075. /**
  8076. * Processes slideshow album data loaded from SmugMug.
  8077. *
  8078. * @method _loadSmugMugSuccess
  8079. * @param e {Object} The custom event object passed to this function.
  8080. * @protected
  8081. */
  8082. _loadSmugMugSuccess: function(e)
  8083. {
  8084. var images = e.Album.Images,
  8085. album = {},
  8086. proxy = typeof this._source.proxy !== 'undefined' ? this._source.proxy : '',
  8087. buyBase = '',
  8088. baseURL = '',
  8089. ext = '',
  8090. format = '',
  8091. i = 0,
  8092. temp = null,
  8093. iframe = null;
  8094. album.index = this._source.index;
  8095. album.id = e.Album.id;
  8096. album.key = e.Album.Key;
  8097. album.link = e.Album.URL;
  8098. album.title = this._source.title ? this._source.title : '';
  8099. album.images = [];
  8100. buyBase = album.link.replace('https://', '').split('/').shift();
  8101. buyBase = 'https://' + buyBase + '/buy/' + e.Album.id + '_' + e.Album.Key + '/';
  8102. for(i = 0; i < images.length; i++)
  8103. {
  8104. baseURL = proxy + e.Album.URL + '/' + images[i].id + '_' + images[i].Key;
  8105. format = images[i].Format.toLowerCase();
  8106. ext = format == 'mp4' ? '.jpg' : '.' + format;
  8107. album.images[i] = {};
  8108. album.images[i].index = i;
  8109. album.images[i].sourceType = 'smugmug';
  8110. album.images[i].albumId = e.Album.id;
  8111. album.images[i].albumKey = e.Album.Key;
  8112. album.images[i].id = images[i].id;
  8113. album.images[i].key = images[i].Key;
  8114. album.images[i].filename = images[i].FileName;
  8115. album.images[i].format = format;
  8116. album.images[i].caption = images[i].Caption || '';
  8117. album.images[i].link = e.Album.URL + '#' + images[i].id + '_' + images[i].Key;
  8118. album.images[i].tinyURL = baseURL + '-Ti' + ext;
  8119. album.images[i].thumbURL = baseURL + '-Th' + ext;
  8120. album.images[i].smallURL = baseURL + '-S' + ext;
  8121. album.images[i].mediumURL = baseURL + '-M' + ext;
  8122. album.images[i].largeURL = baseURL + '-L' + ext;
  8123. album.images[i].xlargeURL = baseURL + '-XL' + ext;
  8124. album.images[i].x2largeURL = baseURL + '-X2' + ext;
  8125. album.images[i].x3largeURL = baseURL + '-X3' + ext;
  8126. album.images[i].buyURL = buyBase + images[i].id + '_' + images[i].Key;
  8127. album.images[i].iframe = '';
  8128. if(album.images[i].caption.indexOf('iframe')) {
  8129. temp = Y.Node.create('<div>'+ album.images[i].caption +'</div>');
  8130. iframe = temp.one('iframe');
  8131. if(iframe) {
  8132. album.images[i].iframe = iframe.getAttribute('src');
  8133. album.images[i].caption = album.images[i].caption.replace(/<iframe.*>.*<\/iframe>/gi, '');
  8134. }
  8135. }
  8136. }
  8137. this._loadComplete({ 'albumInfo': album });
  8138. },
  8139. /**
  8140. * Loads slideshow album data from an array of urls.
  8141. *
  8142. * NOTE: You must have a large URL.
  8143. *
  8144. * @method _loadUrls
  8145. * @protected
  8146. */
  8147. _loadUrls: function()
  8148. {
  8149. var album = {},
  8150. i = 0;
  8151. album.index = this._source.index;
  8152. album.title = this._source.title ? this._source.title : '';
  8153. album.images = [];
  8154. for( ; i < this._source.urls.length; i++)
  8155. {
  8156. album.images[i] = {};
  8157. album.images[i].index = i;
  8158. album.images[i].sourceType = 'urls';
  8159. album.images[i].filename = this._source.urls[i].largeURL.split('/').pop();
  8160. album.images[i].format = '';
  8161. album.images[i].caption = this._source.urls[i].caption || '';
  8162. album.images[i].link = this._source.urls[i].largeURL;
  8163. album.images[i].thumbURL = this._source.urls[i].thumbURL || this._source.urls[i].largeURL;
  8164. album.images[i].smallURL = this._source.urls[i].smallURL || this._source.urls[i].largeURL;
  8165. album.images[i].mediumURL = this._source.urls[i].mediumURL || this._source.urls[i].largeURL;
  8166. album.images[i].largeURL = this._source.urls[i].largeURL; // Must have a large URL
  8167. album.images[i].xlargeURL = this._source.urls[i].xlargeURL || this._source.urls[i].largeURL;
  8168. album.images[i].x2largeURL = this._source.urls[i].x2largeURL || this._source.urls[i].largeURL;
  8169. album.images[i].x3largeURL = this._source.urls[i].x3largeURL || this._source.urls[i].largeURL;
  8170. album.images[i].buyURL = this._source.urls[i].buyURL || '';
  8171. album.images[i].iframe = this._source.urls[i].iframe || '';
  8172. }
  8173. this._loadComplete({ 'albumInfo': album });
  8174. }
  8175. }, {
  8176. /**
  8177. * Static property used to define the default attribute configuration of
  8178. * the Widget.
  8179. *
  8180. * @property ATTRS
  8181. * @type Object
  8182. * @protected
  8183. * @static
  8184. */
  8185. ATTRS: {
  8186. /**
  8187. * If true, the images will be randomized after loading.
  8188. *
  8189. * @attribute randomize
  8190. * @type Boolean
  8191. * @default false
  8192. */
  8193. randomize: {
  8194. value: false
  8195. }
  8196. },
  8197. /**
  8198. * The types of source data that can be loaded
  8199. * and associated functions.
  8200. *
  8201. * @property TYPES
  8202. * @type Object
  8203. * @readOnly
  8204. * @protected
  8205. * @static
  8206. */
  8207. TYPES: {
  8208. 'smugmug': '_loadSmugMug',
  8209. 'flickr': '_loadFlickr',
  8210. 'picasa': '_loadPicasa',
  8211. 'urls': '_loadUrls',
  8212. 'html': '_loadHtml'
  8213. }
  8214. });
  8215. }, '2.0.0' ,{requires:['base', 'fl-smugmug-api']});
  8216. YUI.add('fl-slideshow-base', function(Y) {
  8217. /**
  8218. * @module fl-slideshow-base
  8219. */
  8220. /**
  8221. * The base class that gets extended when creating new
  8222. * slideshow widgets. Manages loading, playing, and resizing.
  8223. * <p>
  8224. * While SlideshowBase can be instantiated, it is only meant to
  8225. * be extended and does not display any images.
  8226. *
  8227. * @namespace FL
  8228. * @class SlideshowBase
  8229. * @constructor
  8230. * @param config {Object} Configuration object
  8231. * @extends Widget
  8232. */
  8233. Y.namespace('FL').SlideshowBase = Y.Base.create('fl-slideshow-base', Y.Widget, [Y.WidgetParent], {
  8234. /**
  8235. * FL.SlideshowAlbumLoader instance used to load albums.
  8236. *
  8237. * @property _loader
  8238. * @type FL.SlideshowAlbumLoader
  8239. * @default null
  8240. * @protected
  8241. */
  8242. _albumLoader: null,
  8243. /**
  8244. * An array of albums loaded from the source attribute.
  8245. * Each album is an array of objects containing image info.
  8246. *
  8247. * @property albums
  8248. * @type Array
  8249. * @default []
  8250. */
  8251. albums: [],
  8252. /**
  8253. * Info for the active album.
  8254. *
  8255. * @property albumInfo
  8256. * @type Object
  8257. * @default null
  8258. */
  8259. albumInfo: null,
  8260. /**
  8261. * A number that represents the index of the active
  8262. * album in the albums array.
  8263. *
  8264. * @property albumIndex
  8265. * @type Number
  8266. * @default null
  8267. */
  8268. albumIndex: null,
  8269. /**
  8270. * Info for the active image.
  8271. *
  8272. * @property imageInfo
  8273. * @type Object
  8274. * @default null
  8275. */
  8276. imageInfo: null,
  8277. /**
  8278. * A number that represents the index of the active
  8279. * image in the albumInfo array.
  8280. *
  8281. * @property imageIndex
  8282. * @type Number
  8283. * @default null
  8284. */
  8285. imageIndex: null,
  8286. /**
  8287. * A number that represents the index of the last
  8288. * image that was loaded in the albumInfo array.
  8289. *
  8290. * @property lastImageIndex
  8291. * @type Number
  8292. * @default null
  8293. */
  8294. lastImageIndex: null,
  8295. /**
  8296. * Timer for the delay before resizing if one is set.
  8297. *
  8298. * @property _resizeTimer
  8299. * @type Object
  8300. * @default null
  8301. * @protected
  8302. */
  8303. _resizeTimer: null,
  8304. /**
  8305. * Flag for whether the slideshow is currently playing or not.
  8306. *
  8307. * @property playing
  8308. * @type Boolean
  8309. * @default false
  8310. * @protected
  8311. */
  8312. _playing: false,
  8313. /**
  8314. * Timer for the break in between images when
  8315. * the slideshow is playing.
  8316. *
  8317. * @property _playingTimer
  8318. * @type Object
  8319. * @default null
  8320. * @protected
  8321. */
  8322. _playingTimer: null,
  8323. /**
  8324. * If set, the slideshow will only auto start when
  8325. * this event is fired.
  8326. *
  8327. * @property _playingTimerEvent
  8328. * @type Object
  8329. * @default null
  8330. * @protected
  8331. */
  8332. _playingTimerEvent: null,
  8333. /**
  8334. * An instance of FL.Spinner that is shown and hidden
  8335. * using _showLoadingImage and _hideLoadingImage when
  8336. * a loading activity occurs.
  8337. *
  8338. * @property _loadingImage
  8339. * @type FL.Spinner
  8340. * @default null
  8341. * @protected
  8342. */
  8343. _loadingImage: null,
  8344. /**
  8345. * An div node that wraps the loading image.
  8346. *
  8347. * @property _loadingImageWrap
  8348. * @type Node
  8349. * @default null
  8350. * @protected
  8351. */
  8352. _loadingImageWrap: null,
  8353. /**
  8354. * Whether the loading image is visible or not.
  8355. *
  8356. * @property _loadingImageVisible
  8357. * @type Boolean
  8358. * @default false
  8359. * @protected
  8360. */
  8361. _loadingImageVisible: false,
  8362. /**
  8363. * A timer to delay the display of the loading image.
  8364. *
  8365. * @property _loadingImageTimer
  8366. * @type Object
  8367. * @default null
  8368. * @protected
  8369. */
  8370. _loadingImageTimer: null,
  8371. /**
  8372. * The container to insert the loading image into. If
  8373. * no container is set, the loading image will be inserted
  8374. * into the widget's bounding box.
  8375. *
  8376. * @property _loadingImageContainer
  8377. * @type Object
  8378. * @default null
  8379. * @protected
  8380. */
  8381. _loadingImageContainer: null,
  8382. /**
  8383. * The intial height of the slideshow. Used to resize
  8384. * back to the starting height when exiting stretchy.
  8385. *
  8386. * @property _initialHeight
  8387. * @type Number
  8388. * @default null
  8389. * @protected
  8390. */
  8391. _initialHeight: null,
  8392. /**
  8393. * The intial width of the slideshow. Used to resize
  8394. * back to the starting width when exiting stretchy.
  8395. *
  8396. * @property _initialWidth
  8397. * @type Number
  8398. * @default null
  8399. * @protected
  8400. */
  8401. _initialWidth: null,
  8402. /**
  8403. * @method initializer
  8404. * @protected
  8405. */
  8406. initializer: function()
  8407. {
  8408. // Loader
  8409. this._albumLoader = new Y.FL.SlideshowAlbumLoader({
  8410. randomize: this.get('randomize')
  8411. });
  8412. },
  8413. /**
  8414. * @method renderUI
  8415. * @protected
  8416. */
  8417. renderUI: function()
  8418. {
  8419. this._renderLoadingImage();
  8420. },
  8421. /**
  8422. * @method bindUI
  8423. * @protected
  8424. */
  8425. bindUI: function()
  8426. {
  8427. // Album load complete
  8428. this._albumLoader.on('complete', this._loadAlbumComplete, this);
  8429. // Resize Events
  8430. Y.one(window).on('fl-slideshow-base|resize', this._delayResize, this);
  8431. Y.one(window).on('fl-slideshow-base|orientationchange', this._delayResize, this);
  8432. // Key Events
  8433. Y.Node.one('body').on('keydown', Y.bind(this._onKey, this));
  8434. },
  8435. /**
  8436. * @method syncUI
  8437. * @protected
  8438. */
  8439. syncUI: function()
  8440. {
  8441. this.get('boundingBox').addClass('fl-slideshow-' + this.get('color'));
  8442. this.resize();
  8443. if(this.get('loadOnRender')) {
  8444. this.loadAlbum(this.get('defaultAlbum'), this.get('defaultImage'));
  8445. }
  8446. },
  8447. /**
  8448. * Add album data to the source object.
  8449. *
  8450. * @method addAlbum
  8451. * @protected
  8452. */
  8453. addAlbum: function(data)
  8454. {
  8455. var source = this.get('source'),
  8456. i = source.length;
  8457. source[i] = data;
  8458. source[i].index = i;
  8459. this.set('source', source);
  8460. },
  8461. /**
  8462. * Loads an album from the source array with the provided albumIndex.
  8463. * If no albumIndex is provided, the first album in the array will be loaded.
  8464. * An image to load can also be specified using imageIndex.
  8465. *
  8466. * @method loadAlbum
  8467. * @param albumIndex {Number} The album index to load from the source array.
  8468. * @param imageIndex {Number} The image index to load from the album array.
  8469. */
  8470. loadAlbum: function(albumIndex, imageIndex)
  8471. {
  8472. var source = this.get('source'),
  8473. loadImageIndex = typeof imageIndex == 'undefined' ? 0 : imageIndex;
  8474. // Reset internal image indexes.
  8475. this.imageIndex = null;
  8476. this.lastImageIndex = null;
  8477. /**
  8478. * Fires before a new album request is made.
  8479. *
  8480. * @event albumLoadStart
  8481. */
  8482. this.fire('albumLoadStart');
  8483. // Load an image after the album.
  8484. this.once('albumLoadComplete', Y.bind(this.loadImage, this, loadImageIndex));
  8485. // Load data passed from another slideshow instance.
  8486. if(source[albumIndex] && source[albumIndex].type == 'album-data') {
  8487. this.albums[albumIndex] = source[albumIndex].data;
  8488. this._loadAlbumComplete({albumInfo: this.albums[albumIndex]});
  8489. }
  8490. // Load the album from the albums array.
  8491. else if(source[albumIndex] && this.albums[albumIndex]) {
  8492. this._loadAlbumComplete({albumInfo: this.albums[albumIndex]});
  8493. }
  8494. // Load the album using the album loader.
  8495. else {
  8496. this._albumLoader.load(source[albumIndex] || source[0]);
  8497. }
  8498. },
  8499. /**
  8500. * Processes the loaded album and fires the albumLoadComplete event.
  8501. *
  8502. * @method _loadAlbumComplete
  8503. * @param o {Object} The custom event object passed to this method.
  8504. * @protected
  8505. */
  8506. _loadAlbumComplete: function(o)
  8507. {
  8508. this.albums[o.albumInfo.index] = o.albumInfo;
  8509. this.albumInfo = o.albumInfo;
  8510. this.albumIndex = o.albumInfo.index;
  8511. /**
  8512. * Fires after a new album request is made.
  8513. *
  8514. * @event albumLoadComplete
  8515. */
  8516. this.fire('albumLoadComplete');
  8517. // Auto Play
  8518. if(this.get('autoPlay')) {
  8519. this._playingTimerStart();
  8520. this.fire('played');
  8521. this._playing = true;
  8522. }
  8523. },
  8524. /**
  8525. * Sets the active image index and fires the imageLoadComplete event.
  8526. *
  8527. * @method loadImage
  8528. * @param index {Number} The image index to load.
  8529. */
  8530. loadImage: function(index)
  8531. {
  8532. if(this._playing) {
  8533. this._playingTimerStart();
  8534. }
  8535. index = index < 0 ? this.albumInfo.images.length - 1 : index;
  8536. index = index >= this.albumInfo.images.length ? 0 : index;
  8537. this.lastImageIndex = this.imageIndex;
  8538. this.imageIndex = index;
  8539. this.imageInfo = this.albumInfo.images[index];
  8540. /**
  8541. * Fires after a new image index is set.
  8542. *
  8543. * @event imageLoadComplete
  8544. */
  8545. this.fire('imageLoadComplete', { 'imageInfo': this.imageInfo });
  8546. },
  8547. /**
  8548. * Loads the previous image.
  8549. *
  8550. * @method prevImage
  8551. */
  8552. prevImage: function()
  8553. {
  8554. if(this.get('pauseOnNextOrPrev')) {
  8555. this.pause();
  8556. }
  8557. this.loadImage(this.imageIndex - 1);
  8558. /**
  8559. * Fires when the previous image is loaded.
  8560. *
  8561. * @event prevImage
  8562. */
  8563. this.fire('prevImage');
  8564. },
  8565. /**
  8566. * Loads the next image.
  8567. *
  8568. * @method nextImage
  8569. */
  8570. nextImage: function()
  8571. {
  8572. if(this.get('pauseOnNextOrPrev')) {
  8573. this.pause();
  8574. }
  8575. this.loadImage(this.imageIndex + 1);
  8576. /**
  8577. * Fires when the next image is loaded.
  8578. *
  8579. * @event nextImage
  8580. */
  8581. this.fire('nextImage');
  8582. },
  8583. /**
  8584. * Keyboard navigation for the next and prev images.
  8585. *
  8586. * @method _onKey
  8587. * @protected
  8588. */
  8589. _onKey: function(e)
  8590. {
  8591. switch(e.keyCode) {
  8592. case 37:
  8593. this.prevImage();
  8594. break;
  8595. case 39:
  8596. this.nextImage();
  8597. break;
  8598. }
  8599. },
  8600. /**
  8601. * Resizes the slideshow using either the
  8602. * stretchy or standard functions.
  8603. *
  8604. * @method resize
  8605. */
  8606. resize: function()
  8607. {
  8608. var stretchy = this.get('stretchy'),
  8609. stretchyType = this.get('stretchyType'),
  8610. width = parseInt(Y.one('body').get('winWidth'), 10),
  8611. threshold = this.get('responsiveThreshold');
  8612. // Stretchy resize to the window only if the parent width is greater
  8613. // than the responsive threshold and stretchyType is set to window.
  8614. if(width > threshold && stretchy && stretchyType == 'window') {
  8615. this._stretchyWindowResize();
  8616. }
  8617. // Ratio resize if the parent width is less than the responsive
  8618. // threshold or if stretchyType is set to ratio.
  8619. else if((width <= threshold) || (stretchy && stretchyType == 'ratio')) {
  8620. this._stretchyRatioResize();
  8621. }
  8622. // Do a standard resize based on the height and
  8623. // width passed to the constructor function.
  8624. else {
  8625. this._standardResize();
  8626. }
  8627. /**
  8628. * Fires when the slideshow is resized.
  8629. *
  8630. * @event resize
  8631. */
  8632. this.fire('resize');
  8633. },
  8634. /**
  8635. * @method _standardResize
  8636. * @protected
  8637. */
  8638. _standardResize: function()
  8639. {
  8640. var stretchy = this.get('stretchy'),
  8641. stretchyType = this.get('stretchyType'),
  8642. bb = this.get('boundingBox'),
  8643. parent = bb.get('parentNode'),
  8644. parentHeight = parseInt(parent.getComputedStyle('height'), 10),
  8645. parentWidth = parseInt(parent.getComputedStyle('width'), 10),
  8646. height = this.get('height'),
  8647. width = this.get('width');
  8648. // Window resize if we are in fullscreen.
  8649. if(bb.hasClass('fl-fullscreen-active')) {
  8650. this._stretchyWindowResize();
  8651. return;
  8652. }
  8653. // Resize to the width and height of the parent.
  8654. else if(stretchy && stretchyType == 'contain') {
  8655. bb.setStyle('height', parentHeight + 'px');
  8656. bb.setStyle('width', parentWidth + 'px');
  8657. }
  8658. // Ratio resize if we don't have a height defined.
  8659. else if(!Y.Lang.isNumber(height)) {
  8660. this._stretchyRatioResize();
  8661. return;
  8662. }
  8663. // Resize to the defined width and height.
  8664. else {
  8665. bb.setStyle('height', height + 'px');
  8666. if(width) {
  8667. bb.setStyle('width', width + 'px');
  8668. }
  8669. else {
  8670. bb.setStyle('width', parentWidth + 'px');
  8671. }
  8672. }
  8673. },
  8674. /**
  8675. * Resizes to the height of the window, compensating
  8676. * for any padding.
  8677. *
  8678. * @method _stretchyWindowResize
  8679. * @protected
  8680. */
  8681. _stretchyWindowResize: function()
  8682. {
  8683. var bb = this.get('boundingBox'),
  8684. verticalSpace = this.get('stretchyVerticalSpace'),
  8685. paddingTop = parseInt(bb.getStyle('paddingTop'), 10),
  8686. paddingBottom = parseInt(bb.getStyle('paddingBottom'), 10),
  8687. height = parseInt(Y.one('body').get('winHeight'), 10),
  8688. width = '';
  8689. // Set the vertical space to 0 and width to the
  8690. // window's width if we are in fullscreen mode.
  8691. if(bb.hasClass('fl-fullscreen-active')) {
  8692. verticalSpace = 0;
  8693. width = parseInt(Y.one('body').get('winWidth'), 10) + 'px';
  8694. }
  8695. height = (height - paddingTop - paddingBottom - verticalSpace) + 'px';
  8696. bb.setStyle('height', height);
  8697. bb.setStyle('width', width);
  8698. },
  8699. /**
  8700. * Resizes the height by multiplying the width and stretchyRatio value.
  8701. *
  8702. * @method _stretchyRatioResize
  8703. * @protected
  8704. */
  8705. _stretchyRatioResize: function()
  8706. {
  8707. var bb = this.get('boundingBox'),
  8708. parent = bb.get('parentNode'),
  8709. verticalSpace = 0,
  8710. stretchyRatio = this.get('stretchyRatio'),
  8711. paddingTop = parseInt(bb.getStyle('paddingTop'), 10),
  8712. paddingBottom = parseInt(bb.getStyle('paddingBottom'), 10),
  8713. computedWidth = parseInt(parent.getComputedStyle('width'), 10),
  8714. winHeight = parseInt(Y.one('body').get('winHeight'), 10),
  8715. winWidth = parseInt(Y.one('body').get('winWidth'), 10),
  8716. height = computedWidth * stretchyRatio,
  8717. width = '';
  8718. // Use the window's height and width if we are in fullscreen mode.
  8719. if(bb.hasClass('fl-fullscreen-active')) {
  8720. height = winHeight;
  8721. width = winWidth;
  8722. }
  8723. height = (height - paddingTop - paddingBottom - verticalSpace) + 'px';
  8724. bb.setStyle('height', height);
  8725. bb.setStyle('width', width);
  8726. },
  8727. /**
  8728. * Resizes the slideshow after the resize timer completes.
  8729. *
  8730. * @method _delayResize
  8731. * @protected
  8732. */
  8733. _delayResize: function()
  8734. {
  8735. if(this._resizeTimer) {
  8736. this._resizeTimer.cancel();
  8737. }
  8738. this._resizeTimer = Y.later(300, this, this.resize);
  8739. },
  8740. /**
  8741. * Starts a new playing timer and fires the played event.
  8742. *
  8743. * @method play
  8744. */
  8745. play: function()
  8746. {
  8747. this._playingTimer = Y.later(this.get('speed'), this, this._playingTimerComplete);
  8748. /**
  8749. * Fires when the playing timer starts.
  8750. *
  8751. * @event played
  8752. */
  8753. this.fire('played');
  8754. this._playing = true;
  8755. },
  8756. /**
  8757. * Cancels the current playing timer and fires the paused event.
  8758. *
  8759. * @method pause
  8760. */
  8761. pause: function()
  8762. {
  8763. this._playingTimerCancel();
  8764. /**
  8765. * Fires when the playing timer is canceled.
  8766. *
  8767. * @event paused
  8768. */
  8769. this.fire('paused');
  8770. this._playing = false;
  8771. },
  8772. /**
  8773. * A new playing timer will start when this event is fired.
  8774. *
  8775. * @method _setPlayingTimerEvent
  8776. * @param obj {Object} The event's host object.
  8777. * @param e {String} The event to fire on the host object.
  8778. * @protected
  8779. */
  8780. _setPlayingTimerEvent: function(obj, e)
  8781. {
  8782. this._playingTimerEvent = {
  8783. 'obj': obj,
  8784. 'e': e
  8785. };
  8786. },
  8787. /**
  8788. * Cancels the playing timer if it is running and starts a new one.
  8789. * The next image is loaded when the timer completes.
  8790. *
  8791. * @method _playingTimerStart
  8792. * @protected
  8793. */
  8794. _playingTimerStart: function(e)
  8795. {
  8796. this._playingTimerCancel();
  8797. if(!e && this._playingTimerEvent !== null) {
  8798. this._playingTimerEvent.obj.once('fl-slideshow-base|' + this._playingTimerEvent.e, Y.bind(this._playingTimerStart, this));
  8799. }
  8800. else {
  8801. this._playingTimer = Y.later(this.get('speed'), this, this._playingTimerComplete);
  8802. }
  8803. },
  8804. /**
  8805. * Fires when the playing timer completes, starts a
  8806. * new timer and loads the next image.
  8807. *
  8808. * @method _playingTimerComplete
  8809. * @protected
  8810. */
  8811. _playingTimerComplete: function()
  8812. {
  8813. this.loadImage(this.imageIndex + 1);
  8814. /**
  8815. * Fires when the playing timer completes.
  8816. *
  8817. * @event albumLoadStart
  8818. */
  8819. this.fire('playingTimerComplete');
  8820. },
  8821. /**
  8822. * Cancels the playing timer.
  8823. *
  8824. * @method _playingTimerCancel
  8825. * @protected
  8826. */
  8827. _playingTimerCancel: function()
  8828. {
  8829. if(this._playingTimer) {
  8830. this._playingTimer.cancel();
  8831. }
  8832. if(this._playingTimerEvent) {
  8833. this._playingTimerEvent.obj.detach('fl-slideshow-base|' + this._playingTimerEvent.e);
  8834. }
  8835. },
  8836. /**
  8837. * Creates the loading image.
  8838. *
  8839. * @method _renderLoadingImage
  8840. * @protected
  8841. */
  8842. _renderLoadingImage: function()
  8843. {
  8844. var defaults = {
  8845. lines: 11, // The number of lines to draw
  8846. length: 6, // The length of each line
  8847. width: 2, // The line thickness
  8848. radius: 7, // The radius of the inner circle
  8849. color: '', // #rbg or #rrggbb
  8850. speed: 1, // Rounds per second
  8851. trail: 60, // Afterglow percentage
  8852. shadow: false // Whether to render a shadow
  8853. },
  8854. settings = Y.merge(defaults, this.get('loadingImageSettings'));
  8855. if(this.get('loadingImageEnabled')) {
  8856. // Loading image
  8857. if(settings.color === '') {
  8858. settings.color = this._colorToHex(Y.one('body').getStyle('color'));
  8859. }
  8860. this._loadingImage = new Y.FL.Spinner(settings);
  8861. // Loading image wrap
  8862. this._loadingImageWrap = Y.Node.create('<div class="fl-loading-image"></div>');
  8863. this._loadingImageWrap.setStyles({
  8864. position : 'absolute',
  8865. 'z-index' : '1000'
  8866. });
  8867. }
  8868. },
  8869. /**
  8870. * Inserts the loading image.
  8871. *
  8872. * @method _showLoadingImage
  8873. * @protected
  8874. */
  8875. _showLoadingImage: function()
  8876. {
  8877. if(this._loadingImage && !this._loadingImageVisible) {
  8878. this._loadingImageVisible = true;
  8879. this._loadingImage.spin();
  8880. this._loadingImageWrap.insert(this._loadingImage.el);
  8881. if(this._loadingImageContainer !== null) {
  8882. this._loadingImageContainer.insert(this._loadingImageWrap);
  8883. }
  8884. else {
  8885. this.get('contentBox').insert(this._loadingImageWrap);
  8886. }
  8887. this._positionLoadingImage();
  8888. }
  8889. },
  8890. /**
  8891. * Inserts the loading image div node after
  8892. * a timer completes.
  8893. *
  8894. * @method _showLoadingImageWithDelay
  8895. * @protected
  8896. */
  8897. _showLoadingImageWithDelay: function()
  8898. {
  8899. if(this._loadingImage) {
  8900. this._loadingImageTimer = Y.later(1000, this, this._showLoadingImage);
  8901. }
  8902. },
  8903. /**
  8904. * Removes the loading image div node.
  8905. *
  8906. * @method _hideLoadingImage
  8907. * @protected
  8908. */
  8909. _hideLoadingImage: function()
  8910. {
  8911. if(this._loadingImageTimer) {
  8912. this._loadingImageTimer.cancel();
  8913. this._loadingImageTimer = null;
  8914. }
  8915. if(this._loadingImage && this._loadingImageVisible) {
  8916. this._loadingImageVisible = false;
  8917. this._loadingImage.stop();
  8918. this._loadingImageWrap.remove();
  8919. }
  8920. },
  8921. /**
  8922. * Centers the loading image in the content box.
  8923. *
  8924. * @method _positionLoadingImage
  8925. * @protected
  8926. */
  8927. _positionLoadingImage: function()
  8928. {
  8929. if(this._loadingImage && this._loadingImageVisible) {
  8930. var wrap = this._loadingImageWrap,
  8931. wrapHeight = parseInt(wrap.getComputedStyle('height'), 10),
  8932. wrapWidth = parseInt(wrap.getComputedStyle('width'), 10),
  8933. parent = wrap.get('parentNode'),
  8934. parentHeight = parseInt(parent.getComputedStyle('height'), 10),
  8935. parentWidth = parseInt(parent.getComputedStyle('width'), 10),
  8936. left = (parentWidth - wrapWidth)/2,
  8937. top = (parentHeight - wrapHeight)/2;
  8938. wrap.setStyles({
  8939. left : left + 'px',
  8940. top : top + 'px'
  8941. });
  8942. Y.one(this._loadingImage.el).setStyles({
  8943. left : '50%',
  8944. top : '50%'
  8945. });
  8946. }
  8947. },
  8948. /**
  8949. * Convert RGB color value to a hex value.
  8950. *
  8951. * @method _colorToHex
  8952. * @protected
  8953. */
  8954. _colorToHex: function(color)
  8955. {
  8956. var digits, red, green, blue, rgb;
  8957. if(color.substr(0, 1) === '#') {
  8958. return color;
  8959. }
  8960. digits = /(.*?)rgb\((\d+), (\d+), (\d+)\)/.exec(color);
  8961. if ( null === digits ) {
  8962. return '#000';
  8963. }
  8964. red = parseInt(digits[2], 10);
  8965. green = parseInt(digits[3], 10);
  8966. blue = parseInt(digits[4], 10);
  8967. rgb = blue | (green << 8) | (red << 16);
  8968. rgb = rgb.toString(16);
  8969. if(rgb === '0') {
  8970. rgb = '000';
  8971. }
  8972. return digits[1] + '#' + rgb;
  8973. }
  8974. }, {
  8975. /**
  8976. * Custom CSS class name for the widget.
  8977. *
  8978. * @property CSS_PREFIX
  8979. * @type String
  8980. * @protected
  8981. * @static
  8982. */
  8983. CSS_PREFIX: 'fl-slideshow-base',
  8984. /**
  8985. * Static property used to define the default attribute configuration of
  8986. * the Widget.
  8987. *
  8988. * @property ATTRS
  8989. * @type Object
  8990. * @protected
  8991. * @static
  8992. */
  8993. ATTRS: {
  8994. /**
  8995. * Used to create the color class that gets added to the bounding box
  8996. * when the widget is rendered. The color class is used to create new
  8997. * CSS color themes. The default CSS provided includes dark and light themes.
  8998. *
  8999. * @attribute color
  9000. * @type String
  9001. * @default dark
  9002. * @writeOnce
  9003. */
  9004. color: {
  9005. value: 'dark',
  9006. writeOnce: true
  9007. },
  9008. /**
  9009. * An array of source objects used to load albums. Each object must have
  9010. * a type property and can have a title property as well.
  9011. * <p>
  9012. * In addition to those properties, each object has additional required
  9013. * properties specific to its type. The types currently supported are
  9014. * smugmug and urls with planned support for flickr and picasa.
  9015. * See the user guide for information on loading different types.
  9016. *
  9017. * @attribute source
  9018. * @type Array
  9019. * @default []
  9020. * @writeOnce
  9021. */
  9022. source: {
  9023. value: [],
  9024. setter: function(source) {
  9025. if(source.constructor == Object) {
  9026. source = [source];
  9027. }
  9028. for(var i = 0; i < source.length; i++) {
  9029. source[i].index = i;
  9030. }
  9031. return source;
  9032. }
  9033. },
  9034. /**
  9035. * The default album index to load.
  9036. *
  9037. * @attribute defaultAlbum
  9038. * @type Number
  9039. * @default 0
  9040. */
  9041. defaultAlbum: {
  9042. value: 0
  9043. },
  9044. /**
  9045. * The default image index to load.
  9046. *
  9047. * @attribute defaultImage
  9048. * @type Number
  9049. * @default 0
  9050. */
  9051. defaultImage: {
  9052. value: 0
  9053. },
  9054. /**
  9055. * If true, the slideshow will be loaded after rendering.
  9056. *
  9057. * @attribute loadOnRender
  9058. * @type Boolean
  9059. * @default true
  9060. */
  9061. loadOnRender: {
  9062. value: true
  9063. },
  9064. /**
  9065. * If true, the slideshow will start playing after loading.
  9066. *
  9067. * @attribute autoPlay
  9068. * @type Boolean
  9069. * @default true
  9070. */
  9071. autoPlay: {
  9072. value: true
  9073. },
  9074. /**
  9075. * Whether to pause when the next or previous image is loaded
  9076. * using nextImage or prevImage. The slideshow will not be paused
  9077. * if the next or previous image is loaded using loadImage as is the
  9078. * case when the slideshow is playing.
  9079. *
  9080. * @attribute pauseOnNextOrPrev
  9081. * @type Boolean
  9082. * @default true
  9083. */
  9084. pauseOnNextOrPrev: {
  9085. value: true
  9086. },
  9087. /**
  9088. * If true, the images will be randomized after loading.
  9089. *
  9090. * @attribute randomize
  9091. * @type Boolean
  9092. * @default false
  9093. */
  9094. randomize: {
  9095. value: false
  9096. },
  9097. /**
  9098. * The time between images when playing, measured in milliseconds.
  9099. *
  9100. * @attribute speed
  9101. * @type Number
  9102. * @default 4000
  9103. */
  9104. speed: {
  9105. value: 4000
  9106. },
  9107. /**
  9108. * The minimum width of the parent node at which
  9109. * responsive features are enabled. Set to 0 to
  9110. * disable responsive features as they are enabled
  9111. * whether stretchy is set to true or not.
  9112. *
  9113. * @attribute responsiveThreshold
  9114. * @type Number
  9115. * @default 600
  9116. */
  9117. responsiveThreshold: {
  9118. value: 600
  9119. },
  9120. /**
  9121. * Whether stretchy resizing should be enabled.
  9122. *
  9123. * @attribute stretchy
  9124. * @type Boolean
  9125. * @default false
  9126. */
  9127. stretchy: {
  9128. value: false
  9129. },
  9130. /**
  9131. * The type of stretchy logic to use. Possible values are
  9132. * window and ratio. Both types resize the width of the
  9133. * slideshow to the width of its parent node. With window, the
  9134. * height of the slideshow is resized to the height of the window.
  9135. * With ratio, the height of the slideshow is resized based
  9136. * on the ratio set with stretchyRatio or the height of the window
  9137. * if the ratio height is greater than the window height.
  9138. *
  9139. * @attribute stretchyType
  9140. * @type String
  9141. * @default ratio
  9142. */
  9143. stretchyType: {
  9144. value: 'ratio'
  9145. },
  9146. /**
  9147. * The number of pixels to subtract from the height of
  9148. * the slideshow when stretchy is set to true.
  9149. *
  9150. * @attribute stretchyVerticalSpace
  9151. * @type Number
  9152. * @default 0
  9153. */
  9154. stretchyVerticalSpace: {
  9155. value: 0
  9156. },
  9157. /**
  9158. * Used to calculate the height of the slideshow when stretchyType
  9159. * is set to ratio.
  9160. *
  9161. * @attribute stretchyRatio
  9162. * @type Number
  9163. * @default 0.7
  9164. */
  9165. stretchyRatio: {
  9166. value: 0.7
  9167. },
  9168. /**
  9169. * Whether to use the loading image or not.
  9170. *
  9171. * @attribute loadingImageEnabled
  9172. * @type Boolean
  9173. * @default true
  9174. */
  9175. loadingImageEnabled: {
  9176. value: true
  9177. },
  9178. /**
  9179. * Property object for setting up the spin.js loading image.
  9180. * For a complete list of properties see:
  9181. * http://effinroot.eiremedia.netdna-cdn.com/repo/plugins/misc/spin.js/index.html
  9182. *
  9183. * @attribute loadingImageSettings
  9184. * @type Object
  9185. */
  9186. loadingImageSettings: {
  9187. value: {}
  9188. }
  9189. }
  9190. });
  9191. }, '2.0.0' ,{requires:['node', 'base', 'widget', 'widget-parent', 'widget-child', 'fl-slideshow-album-loader', 'fl-spinner']});
  9192. YUI.add('fl-smugmug-api', function(Y) {
  9193. /**
  9194. * @module fl-smugmug-api
  9195. */
  9196. /**
  9197. * SmugMug API wrapper.
  9198. *
  9199. * NOTE: Only anonymous logins are currently supported.
  9200. *
  9201. * @namespace FL
  9202. * @class SmugMugAPI
  9203. * @constructor
  9204. * @param config {Object} Configuration object
  9205. * @extends Base
  9206. */
  9207. Y.namespace('FL').SmugMugAPI = Y.Base.create('fl-smugmug-api', Y.Base, [], {
  9208. /**
  9209. * ID for the current session.
  9210. *
  9211. * @property _sessionID
  9212. * @type String
  9213. * @default null
  9214. * @protected
  9215. */
  9216. _sessionID: null,
  9217. /**
  9218. * URL with parameters for the next API request.
  9219. * Reset after each request.
  9220. *
  9221. * @property _requestURL
  9222. * @type String
  9223. * @default null
  9224. * @protected
  9225. */
  9226. _requestURL: null,
  9227. /**
  9228. * Lifecycle method. Initializes the request url.
  9229. *
  9230. * @method initializer
  9231. * @protected
  9232. */
  9233. initializer: function()
  9234. {
  9235. this._resetRequestURL();
  9236. },
  9237. /**
  9238. * Adds a key/value pair to the request url.
  9239. *
  9240. * @method addParam
  9241. * @param key {String} The name of the parameter (example: key=val).
  9242. * @param val {String} The value of the parameter (example: key=val).
  9243. */
  9244. addParam: function(key, val)
  9245. {
  9246. this._requestURL = this._requestURL + '&' + key + '=' + val;
  9247. },
  9248. /**
  9249. * Requests an anonymous login session.
  9250. *
  9251. * @method loginAnon
  9252. */
  9253. loginAnon: function()
  9254. {
  9255. this.addParam('method', 'smugmug.login.anonymously');
  9256. this.once('complete', this._loginAnonComplete);
  9257. this.request();
  9258. },
  9259. /**
  9260. * Anonymous login success handler.
  9261. *
  9262. * @method _loginAnonComplete
  9263. * @param data {Object} A jsonp data object.
  9264. * @protected
  9265. */
  9266. _loginAnonComplete: function(data)
  9267. {
  9268. if(data.Login) {
  9269. this._sessionID = data.Login.Session.id;
  9270. }
  9271. },
  9272. /**
  9273. * Sends an API request using the request url.
  9274. *
  9275. * @method request
  9276. */
  9277. request: function()
  9278. {
  9279. this.addParam('Callback', '{callback}');
  9280. Y.jsonp(this._requestURL, {
  9281. on: {
  9282. success: this._requestComplete,
  9283. timeout: function(){} // TODO: Handle timeouts
  9284. },
  9285. context: this,
  9286. timeout: 60000,
  9287. args: []
  9288. });
  9289. },
  9290. /**
  9291. * API request complete handler.
  9292. *
  9293. * @method _requestComplete
  9294. * @param data {Object} A jsonp data object.
  9295. * @protected
  9296. */
  9297. _requestComplete: function(data)
  9298. {
  9299. this._resetRequestURL();
  9300. /**
  9301. * Fires when a request is complete.
  9302. *
  9303. * @event complete
  9304. */
  9305. this.fire('complete', data);
  9306. },
  9307. /**
  9308. * Clears all parameters on the request url except
  9309. * the API key and session ID.
  9310. *
  9311. * @method _resetRequestURL
  9312. * @protected
  9313. */
  9314. _resetRequestURL: function()
  9315. {
  9316. this._requestURL = this.get('apiURL') + '?APIKey=' + this.get('apiKey');
  9317. if(this._sessionID) {
  9318. this.addParam('SessionID', this._sessionID);
  9319. }
  9320. }
  9321. }, {
  9322. /**
  9323. * Static property used to define the default attribute configuration of
  9324. * the Widget.
  9325. *
  9326. * @property ATTRS
  9327. * @type Object
  9328. * @protected
  9329. * @static
  9330. */
  9331. ATTRS: {
  9332. /**
  9333. * SmugMug API url to use for requests.
  9334. *
  9335. * @attribute apiUrl
  9336. * @type String
  9337. * @default https://api.smugmug.com/services/api/json/1.3.0/
  9338. */
  9339. apiURL: {
  9340. value: 'https://api.smugmug.com/services/api/json/1.3.0/'
  9341. },
  9342. /**
  9343. * SmugMug API key.
  9344. *
  9345. * @attribute apiKey
  9346. * @type String
  9347. * @default 7w6kuU5Ee6KSgRRExf2KLgppdkez9JD2
  9348. */
  9349. apiKey: {
  9350. value: '7w6kuU5Ee6KSgRRExf2KLgppdkez9JD2'
  9351. }
  9352. }
  9353. });
  9354. }, '2.0.0' ,{requires:['base', 'jsonp']});
  9355. YUI.add('fl-spinner', function(Y) {
  9356. (function(window,document,undefined){var width="width",length="length",radius="radius",lines="lines",trail="trail",color="color",opacity="opacity",speed="speed",shadow="shadow",style="style",height="height",left="left",top="top",px="px",childNodes="childNodes",firstChild="firstChild",parentNode="parentNode",position="position",relative="relative",absolute="absolute",animation="animation",transform="transform",Origin="Origin",Timeout="Timeout",coord="coord",black="#000",styleSheets=style+"Sheets",prefixes="webkit0Moz0ms0O".split(0),animations={},useCssAnimations;function eachPair(args,it){var end=~~((args[length]-1)/2);for(var i=1;i<=end;i++){it(args[i*2-1],args[i*2])}}function createEl(tag){var el=document.createElement(tag||"div");eachPair(arguments,function(prop,val){el[prop]=val});return el}function ins(parent,child1,child2){if(child2&&!child2[parentNode]){ins(parent,child2)}parent.insertBefore(child1,child2||null);return parent}ins(document.getElementsByTagName("head")[0],createEl(style));var sheet=document[styleSheets][document[styleSheets][length]-1];function addAnimation(to,end){var name=[opacity,end,~~(to*100)].join("-"),dest="{"+opacity+":"+to+"}",i;if(!animations[name]){for(i=0;i<prefixes[length];i++){try{sheet.insertRule("@"+(prefixes[i]&&"-"+prefixes[i].toLowerCase()+"-"||"")+"keyframes "+name+"{0%{"+opacity+":1}"+end+"%"+dest+"to"+dest+"}",sheet.cssRules[length])}catch(err){}}animations[name]=1}return name}function vendor(el,prop){var s=el[style],pp,i;if(s[prop]!==undefined){return prop}prop=prop.charAt(0).toUpperCase()+prop.slice(1);for(i=0;i<prefixes[length];i++){pp=prefixes[i]+prop;if(s[pp]!==undefined){return pp}}}function css(el){eachPair(arguments,function(n,val){el[style][vendor(el,n)||n]=val});return el}function defaults(obj){eachPair(arguments,function(prop,val){if(obj[prop]===undefined){obj[prop]=val}});return obj}var Spinner=function Spinner(o){this.opts=defaults(o||{},lines,12,trail,100,length,7,width,5,radius,10,color,black,opacity,1/4,speed,1)},proto=Spinner.prototype={spin:function(target){var self=this,el=self.el=self[lines](self.opts);if(target){ins(target,css(el,left,~~(target.offsetWidth/2)+px,top,~~(target.offsetHeight/2)+px),target[firstChild])}if(!useCssAnimations){var o=self.opts,i=0,f=20/o[speed],ostep=(1-o[opacity])/(f*o[trail]/100),astep=f/o[lines];(function anim(){i++;for(var s=o[lines];s;s--){var alpha=Math.max(1-(i+s*astep)%f*ostep,o[opacity]);self[opacity](el,o[lines]-s,alpha,o)}self[Timeout]=self.el&&window["set"+Timeout](anim,50)})()}return self},stop:function(){var self=this,el=self.el;window["clear"+Timeout](self[Timeout]);if(el&&el[parentNode]){el[parentNode].removeChild(el)}self.el=undefined;return self}};proto[lines]=function(o){var el=css(createEl(),position,relative),animationName=addAnimation(o[opacity],o[trail]),i=0,seg;function fill(color,shadow){return css(createEl(),position,absolute,width,(o[length]+o[width])+px,height,o[width]+px,"background",color,"boxShadow",shadow,transform+Origin,left,transform,"rotate("+~~(360/o[lines]*i)+"deg) translate("+o[radius]+px+",0)","borderRadius","100em")}for(;i<o[lines];i++){seg=css(createEl(),position,absolute,top,1+~(o[width]/2)+px,transform,"translate3d(0,0,0)",animation,animationName+" "+1/o[speed]+"s linear infinite "+(1/o[lines]/o[speed]*i-1/o[speed])+"s");if(o[shadow]){ins(seg,css(fill(black,"0 0 4px "+black),top,2+px))}ins(el,ins(seg,fill(o[color],"0 0 1px rgba(0,0,0,.1)")))}return el};proto[opacity]=function(el,i,val){el[childNodes][i][style][opacity]=val};var behavior="behavior",URL_VML="url(#default#VML)",tag="group0roundrect0fill0stroke".split(0);(function(){var s=css(createEl(tag[0]),behavior,URL_VML),i;if(!vendor(s,transform)&&s.adj){for(i=0;i<tag[length];i++){sheet.addRule(tag[i],behavior+":"+URL_VML)}proto[lines]=function(){var o=this.opts,r=o[length]+o[width],s=2*r;function grp(){return css(createEl(tag[0],coord+"size",s+" "+s,coord+Origin,-r+" "+-r),width,s,height,s)}var g=grp(),margin=~(o[length]+o[radius]+o[width])+px,i;function seg(i,dx,filter){ins(g,ins(css(grp(),"rotation",360/o[lines]*i+"deg",left,~~dx),ins(css(createEl(tag[1],"arcsize",1),width,r,height,o[width],left,o[radius],top,-o[width]/2,"filter",filter),createEl(tag[2],color,o[color],opacity,o[opacity]),createEl(tag[3],opacity,0))))}if(o[shadow]){for(i=1;i<=o[lines];i++){seg(i,-2,"progid:DXImage"+transform+".Microsoft.Blur(pixel"+radius+"=2,make"+shadow+"=1,"+shadow+opacity+"=.3)")}}for(i=1;i<=o[lines];i++){seg(i)}return ins(css(createEl(),"margin",margin+" 0 0 "+margin,position,relative),g)};proto[opacity]=function(el,i,val,o){o=o[shadow]&&o[lines]||0;el[firstChild][childNodes][i+o][firstChild][firstChild][opacity]=val}}else{useCssAnimations=vendor(s,animation)}})();Y.namespace('FL').Spinner=Spinner})(window,document);
  9357. }, '2.0.0' );
  9358. YUI.add('fl-utils', function(Y) {
  9359. /**
  9360. * @module fl-utils
  9361. */
  9362. /**
  9363. * General helper functions for all FastLine modules.
  9364. *
  9365. * @namespace FL
  9366. * @class Utils
  9367. * @constructor
  9368. * @static
  9369. */
  9370. Y.namespace('FL').Utils = {
  9371. /**
  9372. * Checks for support of the provided CSS property.
  9373. * Method adapted from: https://gist.github.com/556448
  9374. *
  9375. * @method cssSupport
  9376. * @param p {String} The property to check.
  9377. * @returns Boolean
  9378. */
  9379. cssSupport: function(p)
  9380. {
  9381. var b = document.body || document.documentElement,
  9382. s = b.style,
  9383. v = ['Moz', 'Webkit', 'Khtml', 'O', 'ms', 'Icab'],
  9384. i = 0;
  9385. // Transform not working well in these browsers
  9386. if(p == 'transform' && Y.UA.gecko && Y.UA.gecko < 4) { return false; }
  9387. if(p == 'transform' && Y.UA.opera > 0) { return false; }
  9388. if(p == 'transform' && Y.UA.ie > 0 && Y.UA.ie < 10) { return false; }
  9389. if(p == 'transform' && navigator.userAgent.match(/Trident/)) { return false; }
  9390. // No css support detected
  9391. if(typeof s == 'undefined') { return false; }
  9392. // Tests for standard prop
  9393. if(typeof s[p] == 'string') { return true; }
  9394. // Tests for vendor specific prop
  9395. p = p.charAt(0).toUpperCase() + p.substr(1);
  9396. for( ; i < v.length; i++) {
  9397. if(typeof s[v[i] + p] == 'string') { return true; }
  9398. }
  9399. }
  9400. };
  9401. }, '2.0.0' );