| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641 |
- /**
- * Slideshow JS Bundle
- */
- YUI.add('fl-event-move', function(Y) {
- /**
- * Adds gesturemovevertical, gesturemoveverticalend, gesturemovehorizontal
- * and gesturemovehorizontalend events.
- *
- * @module fl-event-move
- */
- var _eventBase = {
- _isEndEvent: false,
- on: function(node, subscriber, ce)
- {
- if(this.type.indexOf('end') > -1) {
- this._isEndEvent = true;
- }
- subscriber._direction = this.type.replace('gesturemove', '').replace('end', '');
- if(window.navigator.msPointerEnabled) {
- subscriber._startHandle = node.on('MSPointerDown', this._onStart, this, node, subscriber, ce);
- subscriber._moveHandle = node.on('MSPointerMove', this._onMove, this, node, subscriber, ce);
- subscriber._endHandle = node.on('MSPointerUp', this._onEnd, this, node, subscriber, ce);
- }
- else {
- subscriber._startHandle = node.on('gesturemovestart', this._onStart, null, this, node, subscriber, ce);
- subscriber._moveHandle = node.on('gesturemove', this._onMove, null, this, node, subscriber, ce);
- subscriber._endHandle = node.on('gesturemoveend', this._onEnd, { standAlone: true }, this, node, subscriber, ce);
- }
- },
- detach: function(node, subscriber, ce)
- {
- subscriber._startHandle.detach();
- subscriber._startHandle = null;
- subscriber._moveHandle.detach();
- subscriber._moveHandle = null;
- subscriber._endHandle.detach();
- subscriber._endHandle = null;
- },
- _onStart: function(e, node, subscriber, ce)
- {
- subscriber._doMove = null;
- subscriber._startX = e.pageX;
- subscriber._startY = e.pageY;
- },
- _onMove: function(e, node, subscriber, ce)
- {
- if(this._checkDirection(e, subscriber)) {
- subscriber._doMove = true;
- }
- else {
- subscriber._doMove = false;
- }
- if(subscriber._doMove && !this._isEndEvent) {
- ce.fire(e);
- }
- },
- _onEnd: function(e, node, subscriber, ce)
- {
- if(subscriber._doMove && this._isEndEvent) {
- e.startPageX = subscriber._startX;
- e.startPageY = subscriber._startY;
- ce.fire(e);
- }
- subscriber._doMove = null;
- },
- _checkDirection: function(e, subscriber)
- {
- var xDelta = Math.abs(subscriber._startX - e.pageX),
- yDelta = Math.abs(subscriber._startY - e.pageY);
- if(yDelta > xDelta && subscriber._startY > e.pageY && subscriber._direction == 'vertical') {
- return true;
- }
- else if(yDelta > xDelta && subscriber._startY < e.pageY && subscriber._direction == 'vertical') {
- return true;
- }
- else if(yDelta < xDelta && subscriber._startX > e.pageX && subscriber._direction == 'horizontal') {
- return true;
- }
- else if(yDelta < xDelta && subscriber._startX < e.pageX && subscriber._direction == 'horizontal') {
- return true;
- }
- return false;
- }
- };
- /**
- * @event gesturemovevertical
- * @param type {String} "gesturemovevertical"
- * @param fn {Function} The method the event invokes.
- * @param ctx {Object} Context for the method the event invokes.
- */
- Y.Event.define('gesturemovevertical', _eventBase);
- /**
- * @event gesturemoveverticalend
- * @param type {String} "gesturemoveverticalend"
- * @param fn {Function} The method the event invokes.
- * @param ctx {Object} Context for the method the event invokes.
- */
- Y.Event.define('gesturemoveverticalend', _eventBase);
- /**
- * @event gesturemovehorizontal
- * @param type {String} "gesturemovehorizontal"
- * @param fn {Function} The method the event invokes.
- * @param ctx {Object} Context for the method the event invokes.
- */
- Y.Event.define('gesturemovehorizontal', _eventBase);
- /**
- * @event gesturemovehorizontalend
- * @param type {String} "gesturemovehorizontalend"
- * @param fn {Function} The method the event invokes.
- * @param ctx {Object} Context for the method the event invokes.
- */
- Y.Event.define('gesturemovehorizontalend', _eventBase);
- }, '2.0.0' ,{requires:['event-move']});
- YUI.add('fl-slideshow', function(Y) {
- /**
- * @module fl-slideshow
- */
- /**
- * Caption widget used in slideshows.
- *
- * @namespace FL
- * @class SlideshowCaption
- * @constructor
- * @param config {Object} Configuration object
- * @extends Widget
- */
- Y.namespace('FL').SlideshowCaption = Y.Base.create('fl-slideshow-caption', Y.Widget, [Y.WidgetChild], {
- /**
- * Flag for whether the text has been
- * toggled or not.
- *
- * @property _textToggled
- * @type Boolean
- * @default false
- * @protected
- */
- _textToggled: false,
- /**
- * An anchor node used for the toggle link.
- *
- * @property _textToggleLink
- * @type Object
- * @default null
- * @protected
- */
- _textToggleLink: null,
- /**
- * @method renderUI
- * @protected
- */
- renderUI: function()
- {
- var root = this.get('root'),
- bb = this.get('boundingBox');
- this._textToggleLink = Y.Node.create('<a href="javascript:void(0);"></a>');
- this._textToggleLink.addClass('fl-slideshow-caption-toggle');
- this._textToggleLink.set('innerHTML', root.get('captionMoreLinkText'));
- bb.appendChild(this._textToggleLink);
- },
- /**
- * @method bindUI
- * @protected
- */
- bindUI: function()
- {
- this.get('root').on('imageLoadComplete', Y.bind(this._setText, this));
- this._textToggleLink.on('click', Y.bind(this._toggleText, this));
- },
- /**
- * Sets the caption text and displays the
- * toggle link if necessary.
- *
- * @method _setText
- * @protected
- */
- _setText: function()
- {
- var root = this.get('root'),
- text = root.imageInfo.caption,
- textLength = root.get('captionTextLength'),
- cb = this.get('contentBox');
- if(!root.imageInfo.caption || root.imageInfo.caption === '') {
- cb.set('innerHTML', '');
- this._textToggleLink.setStyle('display', 'none');
- return;
- }
- else if(textLength > -1) {
- if(!this._textToggled && textLength < text.length) {
- text = this._shortenText(text);
- this._textToggleLink.setStyle('display', 'inline-block');
- }
- else if(this._textToggled && textLength < text.length) {
- text = this._stripTags(text);
- this._textToggleLink.setStyle('display', 'inline-block');
- }
- else {
- text = this._stripTags(text);
- this._textToggleLink.setStyle('display', 'none');
- }
- }
- else {
- text = this._stripTags(text);
- }
- cb.set('innerHTML', text);
- },
- /**
- * Shows or hides the full text when the
- * toggle link is clicked.
- *
- * @method _toggleText
- * @protected
- */
- _toggleText: function()
- {
- var root = this.get('root'),
- text = root.imageInfo.caption,
- cb = this.get('contentBox');
- if(this._textToggled) {
- text = this._shortenText(text);
- this._textToggleLink.set('innerHTML', root.get('captionMoreLinkText'));
- this._textToggled = false;
- }
- else {
- text = this._stripTags(text);
- this._textToggleLink.set('innerHTML', root.get('captionLessLinkText'));
- this._textToggled = true;
- }
- cb.set('innerHTML', text);
- },
- /**
- * Strips out HTML tags from the caption text.
- *
- * @method _stripTags
- * @param text {String} The text to strip HTML tags from.
- * @param ignoreSettings {Boolean} If true, will strip tags even if
- * the stripTags attribute is set to false.
- * @protected
- */
- _stripTags: function(text, ignoreSettings)
- {
- var root = this.get('root'), textDiv;
- if(ignoreSettings || root.get('captionStripTags')) {
- textDiv = document.createElement('div');
- textDiv.innerHTML = text;
- text = textDiv.textContent || textDiv.innerText;
- }
- return text;
- },
- /**
- * Shortens the caption text to the length of
- * the textLength attribute.
- *
- * @method _shortenText
- * @protected
- */
- _shortenText: function(text)
- {
- var root = this.get('root');
- text = this._stripTags(text, true).substring(0, root.get('captionTextLength'));
- return Y.Lang.trim(text.substring(0, text.lastIndexOf(' '))) + ' ...';
- }
- }, {
- /**
- * Custom CSS class name for the widget.
- *
- * @property CSS_PREFIX
- * @type String
- * @protected
- * @static
- */
- CSS_PREFIX: 'fl-slideshow-caption',
- /**
- * Static property used to define the default attribute configuration of
- * the Widget.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- }
- });
- /**
- * A widget for loading and transitioning between SlideshowImage
- * instances. Each SlideshowImage instance is a child widget of
- * SlideshowFrame. SlideshowFrame is a child widget of the main
- * slideshow widget.
- *
- * @namespace FL
- * @class SlideshowFrame
- * @constructor
- * @param config {Object} Configuration object
- * @extends Widget
- */
- Y.namespace('FL').SlideshowFrame = Y.Base.create('fl-slideshow-frame', Y.Widget, [Y.WidgetParent, Y.WidgetChild], {
- /**
- * The imageInfo object used to load the active image.
- *
- * @property info
- * @type Object
- * @default null
- * @protected
- */
- _imageInfo: null,
- /**
- * The active FL.SlideshowImage instance in the frame.
- *
- * @property _activeImage
- * @type FL.SlideshowImage
- * @default null
- * @protected
- */
- _activeImage: null,
- /**
- * A FL.SlideshowImage instance used to load the
- * next image and transition it into the frame.
- *
- * @property _nextImage
- * @type FL.SlideshowImage
- * @default null
- * @protected
- */
- _nextImage: null,
- /**
- * Used to store imageInfo if a load request is
- * made while the frame is transitioning. If not null
- * when the transition completes, a new image will
- * be loaded using the imageInfo.
- *
- * @property _loadQueue
- * @type Object
- * @default false
- * @protected
- */
- _loadQueue: null,
- /**
- * An instance of FL.SlideshowTransition used for
- * the current transition in progress.
- *
- * @property _transition
- * @type FL.SlideshowTransition
- * @default null
- * @protected
- */
- _transition: null,
- /**
- * A flag for whether the frame is currently transitioning or not.
- *
- * @property _transitioning
- * @type Boolean
- * @default false
- * @protected
- */
- _transitioning: false,
- /**
- * Flag for whether to resize when the current transition
- * completes. Set to true when a resize request is made
- * during a transition.
- *
- * @property _resizeAfterTransition
- * @type Boolean
- * @default false
- * @protected
- */
- _resizeAfterTransition: false,
- /**
- * Provides functionality for gesture based transitions
- * between the active and next images.
- *
- * @property _gestures
- * @type FL.SlideshowGestures
- * @default null
- * @protected
- */
- _gestures: null,
- /**
- * Creates new instances of FL.SlideshowImage used in the frame.
- *
- * @method initializer
- * @protected
- */
- initializer: function()
- {
- var imageConfig = this.get('imageConfig');
- this._activeImage = new Y.FL.SlideshowImage(imageConfig);
- this._nextImage = new Y.FL.SlideshowImage(imageConfig);
- },
- /**
- * Renders the FL.SlideshowImage instances used in the frame.
- *
- * @method renderUI
- * @protected
- */
- renderUI: function()
- {
- this.add(this._activeImage);
- this.add(this._nextImage);
- },
- /**
- * @method bindUI
- * @protected
- */
- bindUI: function()
- {
- var activeBB = this._activeImage.get('boundingBox'),
- nextBB = this._nextImage.get('boundingBox'),
- transition = this.get('transition');
- if(('ontouchstart' in window || window.navigator.msPointerEnabled) && this.get('touchSupport')) {
- this._gestures = new Y.FL.SlideshowGestures({
- direction: transition == 'slideVertical' ? 'vertical' : 'horizontal',
- activeItem: activeBB,
- nextItem: nextBB
- });
- this._gestures.on('moveStart', this._gesturesMoveStart, this);
- this._gestures.on('endComplete', this._gesturesEndComplete, this);
- }
- },
- /**
- * Functional styles for the UI.
- *
- * @method syncUI
- * @protected
- */
- syncUI: function()
- {
- var activeBB = this._activeImage.get('boundingBox'),
- nextBB = this._nextImage.get('boundingBox'),
- cb = this.get('contentBox');
- activeBB.setStyle('position', 'absolute');
- activeBB.setStyle('top', '0px');
- activeBB.setStyle('left', '-9999px');
- nextBB.setStyle('position', 'absolute');
- nextBB.setStyle('top', '0px');
- nextBB.setStyle('left', '-9999px');
- cb.setStyle('position', 'relative');
- cb.setStyle('overflow', 'hidden');
- },
- /**
- * Checks whether the imageInfo should be loaded or queued.
- * Initializes a new transition if loading is ok.
- *
- * @method load
- * @param imageInfo {Object} The image info to load.
- */
- load: function(imageInfo)
- {
- var activeInfo = this._activeImage._imageInfo;
- if(this._transitioning) {
- this._loadQueue = imageInfo;
- return;
- }
- else if(activeInfo && activeInfo.largeURL == imageInfo.largeURL) {
- return;
- }
- this._imageInfo = imageInfo;
- this._transitionInit(imageInfo);
- },
- /**
- * Preloads the next image using the provided imageInfo.
- *
- * @method preload
- * @param imageInfo {Object} The imageInfo to preload.
- * @param width {Number} The width to preload.
- * @param height {Number} The height to preload.
- */
- preload: function(imageInfo, width, height)
- {
- this._imageInfo = imageInfo;
- this._nextImage.preload(imageInfo, width, height);
- },
- /**
- * Unloads the active and next image instances.
- *
- * @method unload
- */
- unload: function()
- {
- this._imageInfo = null;
- this._loadQueue = null;
- this._transitioning = false;
- this._transition = null;
- this._activeImage.detachAll();
- this._activeImage.unload();
- this._activeImage.get('boundingBox').setStyle('left', '-9999px');
- this._nextImage.detachAll();
- this._nextImage.unload();
- this._nextImage.get('boundingBox').setStyle('left', '-9999px');
- },
- /**
- * Resizes the bounding box and active image.
- *
- * @method resize
- * @param width {Number} The width value.
- * @param height {Number} The height value.
- */
- resize: function(width, height)
- {
- if(!width || !height) {
- return;
- }
- var bb = this.get('boundingBox'),
- padding = [
- parseInt(bb.getComputedStyle('paddingTop'), 10),
- parseInt(bb.getComputedStyle('paddingRight'), 10),
- parseInt(bb.getComputedStyle('paddingBottom'), 10),
- parseInt(bb.getComputedStyle('paddingLeft'), 10)
- ];
- width = width - padding[1] - padding[3];
- height = height - padding[0] - padding[2];
- this.set('width', width);
- this.set('height', height);
- if(this._transitioning) {
- this._resizeAfterTransition = true;
- }
- else {
- this._activeImage.resize(width, height);
- this._nextImage.resize(width, height);
- }
- },
- /**
- * Gets the current transition to use.
- *
- * @method _getTransition
- * @protected
- */
- _getTransition: function()
- {
- var root = this.get('root'),
- lastIndex = root.albumInfo.images.length - 1,
- direction = 'next',
- transition = root.get('transition');
- if(root.lastImageIndex === null) {
- direction = '';
- }
- else if(root.imageIndex == lastIndex && root.lastImageIndex === 0) {
- direction = 'prev';
- }
- else if(root.imageIndex === 0 && root.lastImageIndex == lastIndex) {
- direction = 'next';
- }
- else if(root.lastImageIndex > root.imageIndex) {
- direction = 'prev';
- }
- else if(root.lastImageIndex < root.imageIndex) {
- direction = 'next';
- }
- if(direction == 'next') {
- transition = transition.replace('slideHorizontal', 'slideLeft');
- transition = transition.replace('slideVertical', 'slideUp');
- }
- else if(direction == 'prev') {
- transition = transition.replace('slideHorizontal', 'slideRight');
- transition = transition.replace('slideVertical', 'slideDown');
- }
- return transition;
- },
- /**
- * Fires the transitionInit event and loads the next image.
- * The transition starts when the image's loadComplete
- * event is fired.
- *
- * @method _transitionInit
- * @param imageInfo {Object} The imageInfo to load before transitioning.
- * @protected
- */
- _transitionInit: function(imageInfo)
- {
- this._transitioning = true;
- // Disable gestures if set.
- if(this._gestures) {
- this._gestures.disable();
- }
- /**
- * Fires when the next image is loading before a new transition.
- *
- * @event transitionInit
- */
- this.fire('transitionInit');
- if(imageInfo) {
- this._nextImage.once('loadComplete', this._transitionStart, this);
- this._nextImage.load(imageInfo);
- }
- else {
- this._transitionStart();
- }
- },
- /**
- * Fires the transitionStart event and starts the transition
- * using a new instance of FL.SlideshowTransition.
- *
- * @method _transitionStart
- * @protected
- */
- _transitionStart: function()
- {
- var root = this.get('root');
- /**
- * Fires when the next image has finished loading
- * and a new transition starts.
- *
- * @event transitionStart
- */
- this.fire('transitionStart');
- this._transition = new Y.FL.SlideshowTransition({
- itemIn: this._nextImage._imageInfo ? this._nextImage.get('boundingBox') : null,
- itemOut: this._activeImage._imageInfo ? this._activeImage.get('boundingBox') : null,
- type: this._getTransition(),
- duration: root.get('transitionDuration'),
- easing: root.get('transitionEasing'),
- kenBurnsDuration: root.get('speed')/1000,
- kenBurnsZoom: root.get('kenBurnsZoom')
- });
- if(this._nextImage._imageInfo) {
- this._nextImage.get('boundingBox').setStyle('left', '0px');
- }
- this._transition.once('complete', this._transitionComplete, this);
- this._transition.run();
- },
- /**
- * Switches the next and active image variables, unloads the
- * last image, fires the transitionComplete event and loads
- * or resizes if appropriate.
- *
- * @method _transitionComplete
- * @protected
- */
- _transitionComplete: function()
- {
- var root = this.get('root');
- // Swap image container references.
- this._swapImageRefs();
- /**
- * Fired when the current transition completes.
- *
- * @event transitionComplete
- */
- this.fire('transitionComplete');
- this._transition = null;
- this._transitioning = false;
- // Enable gestures if set.
- if(this._gestures) {
- if(root && root.albumInfo.images.length <= 1) {
- this._gestures.disable();
- }
- else {
- this._gestures.enable();
- }
- }
- // Load from the queue?
- if(this._loadQueue) {
- this.load(this._loadQueue);
- this._loadQueue = null;
- }
- // Resize the active image?
- else if(this._resizeAfterTransition) {
- this._resizeAfterTransition = false;
- this._activeImage.resize(this.get('width'), this.get('height'));
- this._nextImage.resize(this.get('width'), this.get('height'));
- }
- },
- /**
- * @method _gesturesMoveStart
- * @param e {Object} The event object.
- * @protected
- */
- _gesturesMoveStart: function(e)
- {
- var index = 0,
- root = this.get('root');
- index = e.direction == 'next' ? root.imageIndex + 1 : root.imageIndex - 1;
- index = index < 0 ? root.albumInfo.images.length - 1 : index;
- index = index >= root.albumInfo.images.length ? 0 : index;
- root.pause();
- root._hideLoadingImage();
- root._showLoadingImageWithDelay();
- Y.FL.SlideshowImageLoader.removeGroup(this._nextImage.get('loadGroup'));
- this._nextImage.once('loadComplete', root._hideLoadingImage, root);
- this._nextImage.load(root.albumInfo.images[index]);
- },
- /**
- * @method _gesturesEndComplete
- * @protected
- */
- _gesturesEndComplete: function()
- {
- var root = this.get('root'),
- index = 0;
- if(this._nextImage._imageInfo){
- index = this._nextImage._imageInfo.index;
- this._swapImageRefs();
- this._imageInfo = root.albumInfo.images[index];
- root.loadImage(index);
- }
- },
- /**
- * @method _swapImageRefs
- * @protected
- */
- _swapImageRefs: function()
- {
- var active = this._activeImage;
- this._activeImage = this._nextImage;
- this._nextImage = active;
- if(this._nextImage._imageInfo) {
- this._nextImage.unload();
- this._nextImage.get('boundingBox').setStyle('left', '-9999px');
- }
- if(this._gestures) {
- this._gestures.set('activeItem', this._activeImage.get('boundingBox'));
- this._gestures.set('nextItem', this._nextImage.get('boundingBox'));
- }
- }
- }, {
- /**
- * Custom CSS class name for the widget.
- * @property CSS_PREFIX
- * @type String
- * @protected
- * @static
- */
- CSS_PREFIX: 'fl-slideshow-frame',
- /**
- * Static property used to define the default attribute configuration of
- * the Widget.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- /**
- * The configuration object used to create new instances of
- * FL.SlideshowImage. See the API docs for {@link FL.SlideshowImage}
- * for a complete list of configuration attributes.
- *
- * @attribute imageConfig
- * @type Object
- * @default null
- */
- imageConfig: {
- value: null
- },
- /**
- * Whether to use touch gestures, when available,
- * to transition between images or not.
- *
- * @attribute touchSupport
- * @type Boolean
- * @default false
- */
- touchSupport: {
- value: false
- }
- }
- });
- /**
- * A plugin for fullscreen slideshow functionality.
- *
- * @namespace FL
- * @class SlideshowFullscreen
- * @constructor
- * @param config {Object} Configuration object
- * @extends Plugin.Base
- */
- Y.namespace('FL').SlideshowFullscreen = Y.Base.create('fl-slideshow-fullscreen', Y.Plugin.Base, [], {
- /**
- * Flag for whether the slideshow is in
- * fullscreen mode.
- *
- * @property active
- * @type Boolean
- * @default false
- */
- active: false,
- /**
- * A div containing the close message.
- *
- * @property _closeMessage
- * @type Node
- * @default null
- * @protected
- */
- _closeMessage: null,
- /**
- * A timer for hiding the close message.
- *
- * @property _closeMessageTimer
- * @type Object
- * @default null
- * @protected
- */
- _closeMessageTimer: null,
- /**
- * The initial styles of the host's bounding box
- * before entering fullscreen mode.
- *
- * @property _initialStyles
- * @type Object
- * @protected
- */
- _initialStyles: {
- position: 'static',
- top: '0px',
- left: '0px'
- },
- /**
- * @method initializer
- * @protected
- */
- initializer: function()
- {
- var host = this.get('host'),
- bb = host.get('boundingBox'),
- self = this;
- bb.addClass('fl-fullscreen-enabled');
- if(Y.FL.SlideshowFullscreen.OS_SUPPORT) {
- document.addEventListener('fullscreenchange', function(){ self._osChange(); }, false);
- document.addEventListener('mozfullscreenchange', function(){ self._osChange(); }, false);
- document.addEventListener('webkitfullscreenchange', function(){ self._osChange(); }, false);
- }
- else {
- this._renderCloseMessage();
- }
- },
- /**
- * Exits fullscreen if it is currently active
- * otherwise it enters fullscreen.
- *
- * @method toggle
- */
- toggle: function()
- {
- if(this.active) {
- this.exit();
- }
- else {
- this.enter();
- }
- },
- /**
- * Enters OS fullscreen mode if supported, otherwise
- * the slideshow takes over the browser window.
- *
- * @method enter
- */
- enter: function()
- {
- if(Y.FL.SlideshowFullscreen.OS_SUPPORT) {
- this._osEnter();
- }
- else {
- this._browserEnter();
- }
- },
- /**
- * Exits fullscreen mode.
- *
- * @method exit
- */
- exit: function()
- {
- if(Y.FL.SlideshowFullscreen.OS_SUPPORT) {
- this._osExit();
- }
- else {
- this._browserExit();
- }
- },
- /**
- * Enters OS fullscreen mode.
- *
- * @method _osEnter
- * @protected
- */
- _osEnter: function()
- {
- var bbNode = this.get('host').get('boundingBox')._node;
- if(bbNode.webkitRequestFullScreen) {
- bbNode.webkitRequestFullScreen();
- }
- else if(bbNode.mozRequestFullScreen) {
- bbNode.mozRequestFullScreen();
- }
- else if(bbNode.requestFullScreen) {
- bbNode.requestFullScreen();
- }
- },
- /**
- * Exits OS fullscreen mode.
- *
- * @method _osExit
- * @protected
- */
- _osExit: function()
- {
- if(document.exitFullscreen) {
- document.exitFullscreen();
- }
- else if(document.mozCancelFullScreen) {
- document.mozCancelFullScreen();
- }
- else if(document.webkitCancelFullScreen) {
- document.webkitCancelFullScreen();
- }
- },
- /**
- * Called when the OS fullscreenchange event fires and enters
- * or exits standard fullscreen mode which positions and
- * resizes the slideshow.
- *
- * @method _osChange
- * @protected
- */
- _osChange: function()
- {
- var host = this.get('host');
- // Transitions break on Safari while entering and
- // exiting fullscreen. This fixes them!
- if(host.frame && host.frame._transitioning) {
- host.frame._transitionComplete();
- }
- if(this.active) {
- this._exit();
- }
- else {
- this._enter();
- }
- },
- /**
- * Enter browser fullscreen mode.
- *
- * @method _browserEnter
- * @protected
- */
- _browserEnter: function()
- {
- var bb = this.get('host').get('boundingBox');
- this._initialStyles = {
- position: bb.getStyle('position'),
- top: bb.getStyle('top'),
- left: bb.getStyle('left'),
- zIndex: bb.getStyle('zIndex')
- };
- bb.setStyles({
- position: 'fixed',
- top: '0px',
- left: '0px',
- zIndex: 10000
- });
- Y.Node.one('body').on('fl-fullscreen|keydown', Y.bind(this._onKey, this));
- this._showCloseMessage();
- this._enter();
- },
- /**
- * Exit browser fullscreen mode.
- *
- * @method _browserExit
- * @protected
- */
- _browserExit: function()
- {
- var bb = this.get('host').get('boundingBox');
- bb.setStyles({
- position: this._initialStyles.position,
- top: this._initialStyles.top,
- left: this._initialStyles.left,
- zIndex: this._initialStyles.zIndex
- });
- Y.Node.one('body').detach('fl-fullscreen|keydown');
- this._hideCloseMessage();
- this._exit();
- },
- /**
- * Enters fullscreen mode.
- *
- * @method _enter
- * @protected
- */
- _enter: function()
- {
- var host = this.get('host'),
- bb = host.get('boundingBox');
- bb.addClass('fl-fullscreen-active');
- this.active = true;
- host.resize();
- },
- /**
- * Exits fullscreen mode.
- *
- * @method _exit
- * @protected
- */
- _exit: function()
- {
- var host = this.get('host'),
- bb = host.get('boundingBox');
- bb.removeClass('fl-fullscreen-active');
- this.active = false;
- host.resize();
- },
- /**
- * Keyboard input for the esc button.
- *
- * @method _onKey
- * @protected
- */
- _onKey: function(e)
- {
- if(e.keyCode == 27) {
- this.exit();
- return false;
- }
- },
- /**
- * Creates the close message if one is
- * not already available in the document.
- *
- * @method _initCloseMessage
- * @protected
- */
- _renderCloseMessage: function()
- {
- this._closeMessage = Y.Node.create('<div class="fl-fullscreen-close-message"></div>');
- this._closeMessage.set('innerHTML', '<span>Press the "esc" button to exit fullscreen mode.</span>');
- this._closeMessage.setStyle('display', 'none');
- this.get('host').get('boundingBox').insert(this._closeMessage);
- },
- /**
- * Shows the close message.
- *
- * @method _showCloseMessage
- * @protected
- */
- _showCloseMessage: function()
- {
- if(this._closeMessageTimer) {
- this._closeMessageTimer.cancel();
- this._closeMessageTimer = null;
- }
- this._closeMessage.show(true);
- this._closeMessageTimer = Y.later(4000, this, this._hideCloseMessage);
- },
- /**
- * Hides the close message.
- *
- * @method _hideCloseMessage
- * @protected
- */
- _hideCloseMessage: function()
- {
- if(this._closeMessageTimer) {
- this._closeMessageTimer.cancel();
- this._closeMessageTimer = null;
- }
- this._closeMessage.hide(true);
- }
- }, {
- /**
- * Namespace for the plugin.
- *
- * @property NS
- * @type String
- * @protected
- * @static
- */
- NS: 'fullscreen',
- OS_SUPPORT: (function(){
- var doc = document.documentElement;
- return doc.webkitRequestFullScreen || doc.mozRequestFullScreen || doc.requestFullScreen;
- })()
- });
- /**
- * Provides functionality for gesture based transitions
- * between two slideshow components.
- *
- * @namespace FL
- * @class SlideshowGestures
- * @constructor
- * @param config {Object} Configuration object
- * @extends Base
- */
- Y.namespace('FL').SlideshowGestures = Y.Base.create('fl-slideshow-gestures', Y.Base, [], {
- /**
- * The x coordinate for where a gesture event starts.
- *
- * @property _startX
- * @type Number
- * @default null
- * @protected
- */
- _startX: null,
- /**
- * The y coordinate for where a gesture event starts.
- *
- * @property _startY
- * @type Number
- * @default null
- * @protected
- */
- _startY: null,
- /**
- * A flag for whether a gesture is moving or not.
- *
- * @property _moving
- * @type Boolean
- * @default false
- * @protected
- */
- _touchMoving: false,
- /**
- * Whether the gesture is moving or not.
- *
- * @property _moving
- * @type Boolean
- * @default false
- * @protected
- */
- _moving: false,
- /**
- * The direction the current gesture event
- * is moving in (either next or prev).
- *
- * @property _movingDirection
- * @type String
- * @default null
- * @protected
- */
- _movingDirection: null,
- /**
- * A flag for whether a gesture gesture is currently
- * transitioning or not.
- *
- * @property _transitioning
- * @type Boolean
- * @default false
- * @protected
- */
- _transitioning: false,
- /**
- * @method initializer
- * @protected
- */
- initializer: function()
- {
- this.enable();
- },
- /**
- * @method enable
- */
- enable: function()
- {
- var id = this.get('id'),
- direction = this.get('direction'),
- active = this.get('activeItem'),
- next = this.get('nextItem');
- active.on(id + '|gesturemovestart', Y.bind(this._onStart, this));
- next.on(id + '|gesturemovestart', Y.bind(this._onStart, this));
- next.on(id + '|transitionend', Y.bind(this._onEndComplete, this) );
- next.on(id + '|oTransitionEnd', Y.bind(this._onEndComplete, this) );
- next.on(id + '|webkitTransitionEnd', Y.bind(this._onEndComplete, this) );
- if(direction == 'horizontal') {
- active.on(id + '|gesturemovehorizontal', Y.bind(this._onMoveHorizontal, this));
- active.on(id + '|gesturemovehorizontalend', Y.bind(this._onEndHorizontal, this));
- next.on(id + '|gesturemovehorizontal', Y.bind(this._onMoveHorizontal, this));
- next.on(id + '|gesturemovehorizontalend', Y.bind(this._onEndHorizontal, this));
- }
- else {
- active.on(id + '|gesturemovevertical', Y.bind(this._onMoveVertical, this));
- active.on(id + '|gesturemoveverticalend', Y.bind(this._onEndVertical, this));
- next.on(id + '|gesturemovevertical', Y.bind(this._onMoveVertical, this));
- next.on(id + '|gesturemoveverticalend', Y.bind(this._onEndVertical, this));
- }
- },
- /**
- * @method disable
- */
- disable: function()
- {
- var id = this.get('id'),
- active = this.get('activeItem'),
- next = this.get('nextItem');
- active.detach(id + '|*');
- next.detach(id + '|*');
- },
- /**
- * @method _onStart
- * @param e {Object} The event object.
- * @protected
- */
- _onStart: function(e)
- {
- var direction = this.get('direction');
- if(this._transitioning) {
- this._onEndComplete();
- }
- if(direction == 'horizontal') {
- this._startX = e.pageX;
- }
- else {
- this._startY = e.pageY;
- }
- /**
- * @event start
- */
- this.fire('start');
- },
- /**
- * @method _onMoveHorizontal
- * @param e {Object} The event object.
- * @protected
- */
- _onMoveHorizontal: function(e)
- {
- var x = this._startX - e.pageX,
- active = this.get('activeItem'),
- next = this.get('nextItem'),
- width = parseInt(active.getComputedStyle('width'), 10),
- translate = x < 0 ? Math.abs(x) : -x,
- direction = x < 0 ? 'prev' : 'next';
- e.preventDefault();
- if(!this._moving || this._movingDirection != direction) {
- active.setStyle('left', 0);
- next.setStyles({
- 'opacity': 1,
- 'left': x < 0 ? -width : width
- });
- this._moving = true;
- this._movingDirection = direction;
- /**
- * @event moveStart
- */
- this.fire('moveStart', { direction: direction });
- }
- active.setStyle('-webkit-transform', 'translate('+ translate +'px, 0px) translateZ(0px)');
- active.setStyle('-ms-transform', 'translate('+ translate +'px, 0px) translateZ(0px)');
- next.setStyle('-webkit-transform', 'translate('+ translate +'px, 0px) translateZ(0px)');
- next.setStyle('-ms-transform', 'translate('+ translate +'px, 0px) translateZ(0px)');
- /**
- * @event move
- */
- this.fire('move');
- },
- /**
- * @method _onMoveVertical
- * @param e {Object} The event object.
- * @protected
- */
- _onMoveVertical: function(e)
- {
- var y = this._startY - e.pageY,
- active = this.get('activeItem'),
- next = this.get('nextItem'),
- height = parseInt(active.getComputedStyle('height'), 10),
- translate = y < 0 ? Math.abs(y) : -y,
- direction = y < 0 ? 'prev' : 'next';
- e.preventDefault();
- if(!this._moving || this._movingDirection != direction) {
- active.setStyle('top', 0);
- next.setStyles({
- 'opacity': 1,
- 'left' : 'auto',
- 'top': y < 0 ? -height : height
- });
- this._moving = true;
- this._movingDirection = direction;
- /**
- * @event moveStart
- */
- this.fire('moveStart', { direction: direction });
- }
- active.setStyle('-webkit-transform', 'translate(0px, '+ translate +'px) translateZ(0px)');
- active.setStyle('-ms-transform', 'translate(0px, '+ translate +'px) translateZ(0px)');
- next.setStyle('-webkit-transform', 'translate(0px, '+ translate +'px) translateZ(0px)');
- next.setStyle('-ms-transform', 'translate(0px, '+ translate +'px) translateZ(0px)');
- /**
- * @event move
- */
- this.fire('move');
- },
- /**
- * @method _onEndHorizontal
- * @param e {Object} The event object.
- * @protected
- */
- _onEndHorizontal: function(e)
- {
- if(!this._moving) {
- return;
- }
- var x = this._startX - e.pageX,
- active = this.get('activeItem'),
- next = this.get('nextItem'),
- width = parseInt(next.getComputedStyle('width'), 10),
- translate = x < 0 ? width : -width;
- active.transition({
- 'transform': 'translate('+ translate +'px, 0px)'
- });
- next.transition({
- 'transform': 'translate('+ translate +'px, 0px)'
- });
- this._transitioning = true;
- /**
- * @event end
- */
- this.fire('end');
- },
- /**
- * @method _onEndVertical
- * @param e {Object} The event object.
- * @protected
- */
- _onEndVertical: function(e)
- {
- if(!this._moving) {
- return;
- }
- var y = this._startY - e.pageY,
- active = this.get('activeItem'),
- next = this.get('nextItem'),
- height = parseInt(next.getComputedStyle('height'), 10),
- translate = y < 0 ? height : -height;
- active.transition({
- 'transform': 'translate(0px, '+ translate +'px)'
- });
- next.transition({
- 'transform': 'translate(0px, '+ translate +'px)'
- });
- this._transitioning = true;
- /**
- * @event end
- */
- this.fire('end');
- },
- /**
- * @method _onEndComplete
- * @protected
- */
- _onEndComplete: function()
- {
- var direction = this.get('direction'),
- active = this.get('activeItem'),
- next = this.get('nextItem');
- active.setStyles({
- 'opacity': 0,
- '-webkit-transform': '',
- '-webkit-transition': '',
- '-ms-transform': '',
- '-ms-transition': ''
- });
- next.setStyles({
- '-webkit-transform': '',
- '-webkit-transition': '',
- '-ms-transform': '',
- '-ms-transition': ''
- });
- if(direction == 'horizontal') {
- active.setStyle('left', '-9999px');
- next.setStyle('left', '0px');
- }
- else {
- active.setStyle('top', '-9999px');
- next.setStyle('top', '0px');
- }
- this.set('activeItem', next);
- this.set('nextItem', active);
- this._moving = false;
- this._movingDirection = null;
- this._transitioning = false;
- /**
- * @event endComplete
- */
- this.fire('endComplete');
- }
- }, {
- /**
- * Static property used to define the default attribute configuration of
- * the Widget.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- /**
- * The gesture direction to use. Possible values are
- * horizontal and vertical.
- *
- * @attribute direction
- * @type String
- * @default horizontal
- */
- direction: {
- value: 'horizontal'
- },
- /**
- * The Node that is currently visible.
- *
- * @attribute activeItem
- * @type Node
- * @default null
- */
- activeItem: {
- value: null
- },
- /**
- * The Node that will be transitioned in.
- *
- * @attribute nextItem
- * @type Node
- * @default null
- */
- nextItem: {
- value: null
- }
- }
- });
- /**
- * A load queue for slideshow images.
- *
- * @namespace FL
- * @class SlideshowImageLoader
- * @static
- */
- Y.namespace('FL').SlideshowImageLoader = {
- /**
- * Whether an image is being loaded or not.
- *
- * @property _loading
- * @type Boolean
- * @default false
- * @protected
- */
- _loading: false,
- /**
- * An node for loading the next image.
- *
- * @property _currentImage
- * @type Node
- * @default null
- * @protected
- */
- _currentImage: null,
- /**
- * An object containing the group, src and callback
- * for the current image that is being loaded.
- *
- * @property _currentImageData
- * @type Object
- * @default null
- * @protected
- */
- _currentImageData: null,
- /**
- * An array of image data objects that contain the group,
- * src and callback for each image that will be loaded.
- *
- * @property _queue
- * @type Array
- * @default []
- * @protected
- */
- _queue: [],
- /**
- * Adds an image to the queue.
- *
- * @method add
- * @param group {String} The group this image is associated with.
- * Used to remove images in bulk.
- * @param src {String} The image url to load.
- * @param callback {Function} A function to call when the image
- * has finished loading.
- * @param bump {Boolean} If true, the image will be added to
- * the first position in the queue.
- */
- add: function(group, src, callback, bump)
- {
- var imgData = {
- group : group,
- src : src,
- callback : callback
- };
- if(bump) {
- this._queue.unshift(imgData);
- }
- else {
- this._queue.push(imgData);
- }
- if(!this._loading) {
- this._load();
- }
- },
- /**
- * Removes a group of images from the queue.
- *
- * @method removeGroup
- * @param group {String} The group to remove.
- */
- removeGroup: function(group)
- {
- var i = this._queue.length - 1;
- for( ; i > -1 ; i--) {
- if(this._queue[i].group == group) {
- this._queue.splice(i, 1);
- }
- }
- if(this._currentImageData && this._currentImageData.group == group) {
- this._currentImage.detachAll();
- this._currentImage = null;
- this._currentImageData = null;
- if(this._queue.length > 0) {
- this._load();
- }
- else {
- this._loading = false;
- }
- }
- },
- /**
- * Loads the next image in the queue.
- *
- * @method _load
- * @protected
- */
- _load: function()
- {
- this._loading = true;
- this._currentImageData = this._queue.shift();
- this._currentImage = Y.Node.create('<img />');
- this._currentImage.on('error', Y.bind(this._loadComplete, this));
- this._currentImage.on('load', Y.bind(this._loadComplete, this));
- this._currentImage.set('src', this._currentImageData.src);
- },
- /**
- * Calls the current image's callback function if set
- * and loads the next image if the queue is not empty.
- *
- * @method _loadComplete
- * @protected
- */
- _loadComplete: function()
- {
- if(this._currentImageData.callback) {
- this._currentImageData.callback(this._currentImage);
- }
- if(this._queue.length > 0) {
- this._load();
- }
- else {
- this._loading = false;
- this._currentImage = null;
- this._currentImageData = null;
- }
- }
- };
- /**
- * Loads an image or video using the provided imageInfo object.
- *
- * @namespace FL
- * @class SlideshowImage
- * @constructor
- * @param config {Object} Configuration object
- * @extends Widget
- */
- Y.namespace('FL').SlideshowImage = Y.Base.create('fl-slideshow-image', Y.Widget, [Y.WidgetChild], {
- /**
- * The imageInfo object used to load the image and
- * its various sizes.
- *
- * @property info
- * @type Object
- * @default null
- * @protected
- */
- _imageInfo: null,
- /**
- * A reference to the current image node in the bounding box.
- *
- * @property _image
- * @type Node
- * @default null
- * @protected
- */
- _image: null,
- /**
- * Whether or not new imageInfo is loading.
- *
- * @property _loading
- * @type Boolean
- * @default false
- * @protected
- */
- _loading: false,
- /**
- * The URL that is currently being loaded.
- *
- * @property _loadingURL
- * @type Boolean
- * @default null
- * @protected
- */
- _loadingURL: null,
- /**
- * An anchor node used for the video play button.
- *
- * @property _videoButton
- * @type Node
- * @default null
- * @protected
- */
- _videoButton: null,
- /**
- * A div node used to hold the video iframe.
- *
- * @property _videoBox
- * @type Node
- * @default null
- * @protected
- */
- _videoBox: null,
- /**
- * An iframe node used to render the video.
- *
- * @property _video
- * @type Node
- * @default null
- * @protected
- */
- _video: null,
- /**
- * The default content template for the image
- * inherited from Y.Widget. Set to null since
- * only the bounding box is needed.
- *
- * @property CONTENT_TEMPLATE
- * @type String
- * @default null
- * @protected
- */
- CONTENT_TEMPLATE: null,
- /**
- * Initial styling for the bounding box.
- *
- * @method syncUI
- * @protected
- */
- syncUI: function()
- {
- var bb = this.get('boundingBox');
- if(this.get('crop')) {
- bb.setStyle('overflow', 'hidden');
- bb.addClass('fl-slideshow-image-cropped');
- }
- },
- /**
- * Sets the imageInfo object and
- * loads the appropriate image size.
- *
- * @method load
- * @param imageInfo {Object} The imageInfo object.
- */
- load: function(imageInfo)
- {
- this._imageInfo = imageInfo;
- this._loading = true;
- this._load();
- },
- /**
- * Sets the width and height of the bounding box and
- * preloads an image using the provided imageInfo object.
- *
- * @method preload
- * @param imageInfo {Object} The imageInfo to preload.
- * @param width {Number} The width to preload.
- * @param height {Number} The height to preload.
- */
- preload: function(imageInfo, width, height)
- {
- var isVideo = this._isVideo(),
- loadVideos = this.get('loadVideos'),
- showVideoButton = this.get('showVideoButton');
- this.unload();
- this.set('width', width);
- this.set('height', height);
- this._imageInfo = imageInfo;
- if(!isVideo || !loadVideos || (isVideo && loadVideos && showVideoButton)) {
- Y.FL.SlideshowImageLoader.add(
- this.get('loadGroup'),
- this._getImageURL(),
- Y.bind(this._imagePreloaded, this),
- this.get('loadPriority')
- );
- }
- },
- /**
- * Called when preloading completes.
- *
- * @method _imagePreloaded
- * @param img {Object} The image that was preloaded.
- * @protected
- */
- _imagePreloaded: function(img)
- {
- this._image = img;
- },
- /**
- * Unloads the image if there is one loaded
- * and sets the imageInfo object to null.
- *
- * @method unload
- */
- unload: function()
- {
- if(this._image) {
- this._image.remove();
- this._image.detachAll();
- this._image.set('src', '');
- this._image = null;
- }
- if(this._video) {
- this._video.remove();
- this._video = null;
- }
- if(this._videoButton) {
- this._videoButton.remove();
- this._videoButton = null;
- }
- if(this._videoBox) {
- this._removeVideoBox();
- }
- this._imageInfo = null;
- this._loading = false;
- this._loadingURL = null;
- },
- /**
- * Resizes the bounding box and loads the
- * appropriate image size if necessary.
- *
- * @method resize
- * @param width {Number} The width value.
- * @param height {Number} The height value.
- */
- resize: function(width, height)
- {
- var borderWidth = parseInt(this.get('boundingBox').getComputedStyle('borderTopWidth'), 10) * 2,
- bb = this.get('boundingBox');
- this.set('width', width - borderWidth);
- this.set('height', height - borderWidth);
- bb.setStyle('width', width - borderWidth + 'px');
- bb.setStyle('height', height - borderWidth + 'px');
- if(this._videoButton) {
- this._positionVideoButton();
- }
- if(this._videoBox) {
- this._loadVideo();
- }
- if(!this._loading) {
- if(this._imageInfo) {
- this._load();
- }
- if(this._image) {
- this._positionImage();
- }
- }
- },
- /**
- * Loads (or reloads) the image or video.
- *
- * @method _load
- * @protected
- */
- _load: function()
- {
- var loadVideos = this.get('loadVideos'),
- showVideoButton = this.get('showVideoButton');
- if(this._isVideo() && loadVideos && !showVideoButton && !('ontouchstart' in window)) {
- this._loadVideo();
- }
- else {
- this._loadImage();
- }
- },
- /**
- * Loads the appropriate image size if
- * it is not already loading.
- *
- * @method _loadImage
- * @protected
- */
- _loadImage: function()
- {
- var url = this._getImageURL(),
- loadVideos = this.get('loadVideos');
- // Already loading.
- if(url == this._loadingURL) {
- return;
- }
- // New URL to load.
- this._loadingURL = url;
- // Load the new image.
- Y.FL.SlideshowImageLoader.add(
- this.get('loadGroup'),
- this._loadingURL,
- Y.bind(this._loadImageComplete, this),
- this.get('loadPriority')
- );
- // Initial load?
- if(this._loading) {
- if(this._isVideo() && loadVideos) {
- this._insertVideoButton();
- }
- /**
- * Only fires when a new image is being
- * loaded, not a different size.
- *
- * @event loadStart
- */
- this.fire('loadStart');
- }
- },
- /**
- * Fires when the image has finished loading.
- *
- * @method _loadImageComplete
- * @protected
- */
- _loadImageComplete: function(img)
- {
- var bb = this.get('boundingBox'),
- showVideoButton = this.get('showVideoButton');
- this._image = img;
- this._image.setStyle('visibility', 'hidden');
- this._image.addClass('fl-slideshow-image-img');
- // Remove load events.
- this._image.detachAll();
- // Remove previous videos.
- if(this._video && !showVideoButton) {
- this._video.remove();
- this._video = null;
- }
- // Remove the old image.
- bb.all('img').remove();
- // Append the new image.
- bb.append(this._image);
- // Setup, scale and position the new image.
- this._setupImage();
- this._resizeImage();
- this._positionImage();
- this._image.setStyle('visibility', 'visible');
- // Clear the loading url.
- this._loadingURL = null;
- // Finish an initial load?
- if(this._loading) {
- this._loading = false;
- /**
- * Only fires when a new image is being
- * loaded, not a different size.
- *
- * @event loadComplete
- */
- this.fire('loadComplete');
- }
- },
- /**
- * UI setup for the new image.
- *
- * @method _setupImage
- * @protected
- */
- _setupImage: function()
- {
- var bb = this.get('boundingBox');
- // IE interpolation
- if(typeof this._image._node.style.msInterpolationMode != 'undefined') {
- this._image._node.style.msInterpolationMode = 'bicubic';
- }
- // Protection
- if(this.get('protect')) {
- bb.delegate('contextmenu', this._protectImage, 'img');
- bb.delegate('mousedown', this._protectImage, 'img');
- }
- },
- /**
- * Fires on contextmenu or mousedown in attempt
- * to keep the image from being copied.
- *
- * @method _protectImage
- * @return {Boolean} Returns false to prevent the default event.
- * @protected
- */
- _protectImage: function(e)
- {
- e.preventDefault();
- return false;
- },
- /**
- * Resizes the image node.
- *
- * @method _resizeImage
- * @protected
- */
- _resizeImage: function()
- {
- var borderWidth = parseInt(this._image.getComputedStyle('borderTopWidth'), 10) * 2,
- imageWidth = this._image.get('width'),
- imageHeight = this._image.get('height'),
- targetWidth = parseInt(this.get('boundingBox').getComputedStyle('width'), 10),
- targetHeight = parseInt(this.get('boundingBox').getComputedStyle('height'), 10),
- newWidth = 0,
- newHeight = 0,
- xScale = 0,
- yScale = 0,
- cropHorizontalsOnly = this.get('cropHorizontalsOnly'),
- isHorizontal = imageHeight > imageWidth,
- noCrop = false;
- if(this._imageInfo && this.get('checkFilenamesForNoCrop')) {
- noCrop = this._imageInfo.filename.indexOf('nocrop') > -1;
- }
- if(this.get('crop') && !(cropHorizontalsOnly && isHorizontal) && !noCrop) {
- newWidth = targetWidth;
- newHeight = Math.round(imageHeight * targetWidth/imageWidth);
- if(newHeight < targetHeight) {
- newHeight = targetHeight;
- newWidth = Math.round(imageWidth * targetHeight/imageHeight);
- }
- }
- else {
- xScale = imageWidth/targetWidth;
- yScale = imageHeight/targetHeight;
- if (yScale > xScale){
- newWidth = Math.round(imageWidth * (1/yScale));
- newHeight = Math.round(imageHeight * (1/yScale));
- }
- else {
- newWidth = Math.round(imageWidth * (1/xScale));
- newHeight = Math.round(imageHeight * (1/xScale));
- }
- }
- // Don't resize past the original size?
- if(!this.get('crop') && !this.get('upsize') && (newWidth > imageWidth || newHeight > imageHeight)) {
- newWidth = imageWidth;
- newHeight = imageHeight;
- }
- // Compensate for borders.
- newWidth -= borderWidth;
- newHeight -= borderWidth;
- // Resize the image.
- this._image.setStyle('width', newWidth + 'px');
- this._image.setStyle('height', newHeight + 'px');
- // Constrain bounding box to image size.
- if(!this.get('crop') && this.get('constrainWidth')) {
- this.set('width', newWidth + 'px');
- }
- if(!this.get('crop') && this.get('constrainHeight')) {
- this.set('height', newHeight + 'px');
- }
- },
- /**
- * Positions the image within the bounding box.
- *
- * @method _positionImage
- * @protected
- */
- _positionImage: function()
- {
- var pos = this.get('position').split(' '),
- x = pos[0] === '' ? 'center' : pos[0],
- y = pos[1] === '' ? 'center' : pos[1],
- newX = 0,
- newY = 0,
- bbWidth = parseInt(this.get('boundingBox').getComputedStyle('width'), 10),
- bbHeight = parseInt(this.get('boundingBox').getComputedStyle('height'), 10),
- borderWidth = parseInt(this._image.getComputedStyle('borderTopWidth'), 10) * 2,
- imageWidth = parseInt(this._image.getComputedStyle('width'), 10) + borderWidth,
- imageHeight = parseInt(this._image.getComputedStyle('height'), 10) + borderWidth;
- if(isNaN(imageWidth) && isNaN(imageHeight)) {
- return;
- }
- if(x == 'left') {
- newX = 0;
- }
- if(x == 'center') {
- newX = (bbWidth - imageWidth)/2;
- }
- if(x == 'right') {
- newX = bbWidth - imageWidth;
- }
- if(y == 'top') {
- newY = 0;
- }
- if(y == 'center') {
- newY = (bbHeight - imageHeight)/2;
- }
- if(y == 'bottom') {
- newY = bbHeight - imageHeight;
- }
- this._image.setStyles({
- 'left': newX,
- 'top': newY
- });
- },
- /**
- * Gets the appropriate image url based
- * on the size of the bounding box.
- *
- * @method _getImageURL
- * @return {String} The url to load.
- * @protected
- */
- _getImageURL: function()
- {
- var imageWidth = 0,
- imageHeight = 0,
- size = 0,
- targetWidth = this.get('width'),
- targetHeight = this.get('height'),
- useThumbSizes = this.get('useThumbSizes'),
- i = this._imageInfo,
- sizes = [
- i.tinyURL || i.thumbURL || i.largeURL,
- i.thumbURL || i.largeURL,
- i.smallURL || i.largeURL,
- i.mediumURL || i.largeURL || i.smallURL,
- i.largeURL || i.mediumURL || i.smallURL,
- i.xlargeURL || i.largeURL || i.mediumURL || i.smallURL,
- i.x2largeURL || i.largeURL || i.mediumURL || i.smallURL,
- i.x3largeURL || i.x2largeURL || i.largeURL || i.mediumURL || i.smallURL
- ];
- // Width
- if(useThumbSizes && targetWidth <= 100) {
- imageWidth = 0;
- }
- else if(useThumbSizes && targetWidth <= 150) {
- imageWidth = 1;
- }
- else if(targetWidth <= 400) {
- imageWidth = 2;
- }
- else if(targetWidth >= 400 && targetWidth <= 600) {
- imageWidth = 3;
- }
- else if(targetWidth >= 600 && targetWidth <= 800) {
- imageWidth = 4;
- }
- else if(targetWidth >= 800 && targetWidth <= 1024) {
- imageWidth = 5;
- }
- else if(targetWidth >= 1024 && targetWidth <= 1280) {
- imageWidth = 6;
- }
- else {
- imageWidth = 7;
- }
- // Height
- if(useThumbSizes && targetHeight <= 100) {
- imageHeight = 0;
- }
- else if(useThumbSizes && targetHeight <= 150) {
- imageHeight = 1;
- }
- else if(targetHeight <= 300) {
- imageHeight = 2;
- }
- else if(targetHeight >= 300 && targetHeight <= 450) {
- imageHeight = 3;
- }
- else if(targetHeight >= 450 && targetHeight <= 600) {
- imageHeight = 4;
- }
- else if(targetHeight >= 600 && targetHeight <= 768) {
- imageHeight = 5;
- }
- else if(targetHeight >= 768 && targetHeight <= 960) {
- imageHeight = 6;
- }
- else {
- imageHeight = 7;
- }
- // Get the size number.
- size = Math.max(imageWidth, imageHeight);
- return sizes[size];
- },
- /**
- * Checks whether this is a video or not.
- *
- * @method _isVideo
- * @protected
- */
- _isVideo: function()
- {
- if(!this._imageInfo) {
- return false;
- }
- else if(this._imageInfo.format == 'mp4' && this._imageInfo.sourceType == 'smugmug') {
- return true;
- }
- else if(this._imageInfo.iframe !== '') {
- return true;
- }
- return false;
- },
- /**
- * @method _loadVideo
- * @protected
- */
- _loadVideo: function()
- {
- var bb = this.get('boundingBox'),
- showVideoButton = this.get('showVideoButton'),
- autoPlay = showVideoButton ? true : false;
- // Remove previous videos
- if(this._video) {
- this._video.remove();
- this._video = null;
- }
- // Get the video code
- if(this._imageInfo.format == 'mp4' && this._imageInfo.sourceType == 'smugmug') {
- this._video = this._getSmugMugVideoEmbed(this._imageInfo, autoPlay);
- }
- else if(this._imageInfo.iframe !== '') {
- this._video = this._getIframeVideoEmbed(this._imageInfo, autoPlay);
- }
- // Insert the video
- if(this._videoBox) {
- this._videoBox.one('.fl-slideshow-video-wrap').insert(this._video);
- }
- else {
- bb.all('img').remove();
- bb.append(this._video);
- }
- // Finish an initial load?
- if(this._loading) {
- this._loading = false;
- this.fire('loadComplete');
- }
- },
- /**
- * @method _insertVideoButton
- * @protected
- */
- _insertVideoButton: function()
- {
- var bb = this.get('boundingBox'),
- event = 'ontouchstart' in window ? 'touchstart' : 'click';
- this._videoButton = Y.Node.create('<a class="fl-slideshow-video-button" href="javascript:void(0);"></a>');
- this._videoButton.on(event, Y.bind(this._showVideoBox, this));
- bb.insert(this._videoButton);
- this._positionVideoButton();
- },
- /**
- * @method _positionVideoButton
- * @protected
- */
- _positionVideoButton: function()
- {
- var bbWidth = this.get('width'),
- bbHeight = this.get('height'),
- buttonWidth = parseInt(this._videoButton.getStyle('width'), 10),
- buttonHeight = parseInt(this._videoButton.getStyle('height'), 10);
- this._videoButton.setStyles({
- left: (bbWidth - buttonWidth)/2,
- top: (bbHeight - buttonHeight)/2
- });
- },
- /**
- * @method _showVideoBox
- * @protected
- */
- _showVideoBox: function()
- {
- var root = this.get('root'),
- wrap = Y.Node.create('<div class="fl-slideshow-video-wrap"></div>'),
- close = Y.Node.create('<a class="fl-slideshow-video-close" href="javascript:void(0);"></a>'),
- event = 'ontouchstart' in window ? 'touchstart' : 'click';
- this._videoBox = Y.Node.create('<div class="fl-slideshow-video"></div>');
- this._videoBox.setStyle('padding', root.get('boundingBox').getStyle('padding'));
- this._videoBox.insert(wrap);
- this._videoBox.insert(close);
- this._videoBox.on(event, Y.bind(this._removeVideoBox, this));
- close.on(event, Y.bind(this._removeVideoBox, this));
- if(typeof YUI.Env.mods['sm-fonticon'] !== 'undefined') {
- close.addClass('sm-fonticon sm-fonticon-XCrossEncircled sm-button-skin-default sm-button-nochrome');
- }
- Y.one('body').insert(this._videoBox);
- this._loadVideo();
- Y.one('body').on('fl-slideshow-image|keydown', this._onKey, this);
- },
- /**
- * Get the embed code for a SmugMug video.
- *
- * @method _getSmugMugVideoEmbed
- * @param imageInfo {Object} The image info for the embed.
- * @param autoPlay {Boolean} Whether to auto play videos or not.
- * @protected
- */
- _getSmugMugVideoEmbed: function(imageInfo, autoPlay)
- {
- var test = document.createElement('video'),
- width = 0,
- mp4 = '',
- vars = '',
- code = '';
- if(Y.UA.mobile !== null && !!test.canPlayType && test.canPlayType('video/mp4')) {
- width = this.get('width');
- mp4 = 'https://www.smugmug.com/photos/' + imageInfo.id + '_' + imageInfo.key + '-' + width + '.mp4';
- code += '<video width="100%" height="100%" poster="'+ this._getImageURL() +'" controls preload="none"';
- if(autoPlay) {
- code += ' autoplay';
- }
- code += '>';
- code += '<source src="'+ mp4 +'" type="video/mp4" />';
- code += '</video>';
- }
- else {
- vars = 'imageId=' + imageInfo.id;
- vars += '&imageKey=' + imageInfo.key;
- vars += '&albumId=' + imageInfo.albumId;
- vars += '&albumKey=' + imageInfo.albumKey;
- vars += '&apiURL=https://api.smugmug.com/&hostLevel=live&isPro=true';
- if(autoPlay) {
- vars += '&autoPlay=true';
- }
- else {
- vars += '&autoPlay=false';
- }
- code += '<object type="application/x-shockwave-flash" width="100%" height="100%" data="https://cdn.smugmug.com/img/ria/SmugPlayer/2012102601.swf">';
- code += '<param name="movie" value="https://cdn.smugmug.com/img/ria/SmugPlayer/2012102601.swf">';
- code += '<param name="allowFullScreen" value="true">';
- code += '<param name="wmode" value="transparent">';
- code += '<param name="flashVars" value="' + vars + '">';
- 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">';
- code += '</object>';
- }
- return Y.Node.create(code);
- },
- /**
- * Get the iframe video embed code.
- *
- * @method _getIframeVideoEmbed
- * @param imageInfo {Object} The image info for the embed.
- * @param autoPlay {Boolean} Whether to auto play videos or not.
- * @protected
- */
- _getIframeVideoEmbed: function(imageInfo, autoPlay)
- {
- var code = '<iframe width="100%" height="100%" frameborder="0" allowfullscreen ',
- url = imageInfo.iframe;
- if(autoPlay) {
- url += url.indexOf('?') > -1 ? '&autoplay=1' : '?autoplay=1';
- }
- code += 'src="'+ url +'"></iframe>';
- return Y.Node.create(code);
- },
- /**
- * @method _removeVideoBox
- * @protected
- */
- _removeVideoBox: function(e)
- {
- if(typeof e !== 'undefined' && e.target) {
- if(e.target.get('className').indexOf('fl-slideshow-video') < 0) {
- return;
- }
- }
- if(this._videoBox !== null) {
- this._videoBox.remove();
- this._videoBox = null;
- this._video = null;
- }
- Y.one('body').detach('fl-slideshow-image|keydown', this._onKey);
- },
- /**
- * Keyboard input for the esc button.
- *
- * @method _onKey
- * @protected
- */
- _onKey: function(e)
- {
- if(e.keyCode == 27) {
- this._removeVideoBox();
- return false;
- }
- }
- }, {
- /**
- * Custom CSS class name for the widget.
- * @property CSS_PREFIX
- * @type String
- * @protected
- * @static
- */
- CSS_PREFIX: 'fl-slideshow-image',
- /**
- * Static property used to define the default attribute configuration of
- * the Widget.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- /**
- * @attribute loadGroup
- * @type String
- * @default none
- */
- loadGroup: {
- value: 'none'
- },
- /**
- * @attribute loadPriority
- * @type Boolean
- * @default false
- */
- loadPriority: {
- value: false
- },
- /**
- * Whether to crop the image.
- *
- * @attribute crop
- * @type Boolean
- * @default false
- */
- crop: {
- value: false
- },
- /**
- * Checks whether the filename has nocrop in it or not.
- * If it does, the image will not be cropped.
- *
- * @attribute checkFilenamesForNoCrop
- * @type Boolean
- * @default true
- */
- checkFilenamesForNoCrop: {
- value: true
- },
- /**
- * Whether to only crop horizontal images or not.
- *
- * @attribute cropHorizontalsOnly
- * @type Boolean
- * @default false
- */
- cropHorizontalsOnly: {
- value: false
- },
- /**
- * The x and y position of the image
- * within the bounding box.
- *
- * @attribute position
- * @type String
- * @default center center
- */
- position: {
- value: 'center center'
- },
- /**
- * Whether to right click protect the image.
- *
- * @attribute protect
- * @type Boolean
- * @default true
- */
- protect: {
- value: true
- },
- /**
- * Whether to resize the image past
- * its original width and height.
- *
- * @attribute upsize
- * @type Boolean
- * @default true
- */
- upsize: {
- value: true
- },
- /**
- * Whether to load thumb sizes. Defaults
- * to false since thumb sizes are square.
- *
- * @attribute useThumbSizes
- * @type Boolean
- * @default false
- */
- useThumbSizes: {
- value: false
- },
- /**
- * Whether to constrain the width of the
- * bounding box to the width of the image.
- *
- * @attribute constrainWidth
- * @type Boolean
- * @default false
- */
- constrainWidth: {
- value: false
- },
- /**
- * Whether to constrain the height of the
- * bounding box to the height of the image.
- *
- * @attribute constrainHeight
- * @type Boolean
- * @default false
- */
- constrainHeight: {
- value: false
- },
- /**
- * Whether to load videos or not. The poster
- * image will be loaded if set to false.
- *
- * @attribute loadVideos
- * @type Boolean
- * @default true
- */
- loadVideos: {
- value: true
- },
- /**
- * Whether to show the video play button or not.
- * When clicked, videos will be displayed in a
- * lightbox instead of the slideshow itself.
- *
- * @attribute showVideoButton
- * @type Boolean
- * @default true
- */
- showVideoButton: {
- value: true
- }
- }
- });
- /**
- * A plugin that turns the cursor into a prev or next arrow when
- * it is over the left or right side of the slideshow.
- *
- * @namespace FL
- * @class SlideshowMouseNav
- * @constructor
- * @param config {Object} Configuration object
- * @extends Plugin.Base
- */
- Y.namespace('FL').SlideshowMouseNav = Y.Base.create('fl-slideshow-mouse-nav', Y.Plugin.Base, [], {
- /**
- * @method initializer
- * @protected
- */
- initializer: function()
- {
- var trigger = this.get('trigger');
- trigger.on('click', this._triggerClick, this);
- trigger.on('mousemove', this._showArrow, this);
- trigger.on('mouseleave', this._hideArrow, this);
- },
- /**
- * @method _triggerClick
- * @protected
- */
- _triggerClick: function(e)
- {
- var host = this.get('host'),
- trigger = this.get('trigger'),
- triggerWidth = parseInt(trigger.getStyle('width'), 10),
- triggerRegion = trigger.get('region'),
- layerX = e.pageX - triggerRegion.left + 5;
- if(layerX >= triggerWidth/2) {
- host.nextImage();
- }
- else {
- host.prevImage();
- }
- },
- /**
- * @method _showArrow
- * @protected
- */
- _showArrow: function(e)
- {
- var host = this.get('host'),
- trigger = this.get('trigger'),
- triggerWidth = parseInt(trigger.getStyle('width'), 10),
- triggerRegion = trigger.get('region'),
- layerX = e.pageX - triggerRegion.left + 5;
- if(host.albumInfo !== null && host.albumInfo.images.length > 1) {
- if(layerX >= triggerWidth/2) {
- trigger.removeClass('fl-slideshow-mouse-nav-prev');
- trigger.addClass('fl-slideshow-mouse-nav-next');
- }
- else {
- trigger.removeClass('fl-slideshow-mouse-nav-next');
- trigger.addClass('fl-slideshow-mouse-nav-prev');
- }
- }
- },
- /**
- * @method _hideArrow
- * @protected
- */
- _hideArrow: function()
- {
- var trigger = this.get('trigger');
- trigger.removeClass('fl-slideshow-mouse-nav-next');
- trigger.removeClass('fl-slideshow-mouse-nav-prev');
- }
- }, {
- /**
- * Namespace for the plugin.
- *
- * @property NS
- * @type String
- * @protected
- * @static
- */
- NS: 'mouseNav',
- /**
- * Static property used to define the default attribute configuration of
- * the Plugin.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- /**
- * A Node that triggers the arrows.
- *
- * @attribute trigger
- * @type Node
- * @default null
- */
- trigger: {
- value: null
- }
- }
- });
- /**
- * Ken Burns effect for slideshow images.
- *
- * @namespace FL
- * @class SlideshowKenBurns
- * @constructor
- * @param config {Object} Configuration object
- * @extends Base
- */
- Y.namespace('FL').SlideshowKenBurns = Y.Base.create('fl-slideshow-ken-burns', Y.Base, [], {
- /**
- * Runs the Ken Burns effect.
- *
- * @method run
- */
- run: function()
- {
- var imageNode = null,
- transform = null;
- if(Y.FL.Utils.cssSupport('transform')) {
- // Image node
- imageNode = this.get('image').one('img');
- // Transform object
- transform = this._getTransform();
- // Apply the start transform
- imageNode.setStyles({
- '-webkit-transform-origin': transform.origin,
- '-moz-transform-origin': transform.origin,
- '-ms-transform-origin': transform.origin,
- 'transform-origin': transform.origin,
- 'transform': transform.start
- });
- // Transition to the end transform
- imageNode.transition({
- easing: 'ease-out',
- duration : this.get('duration'),
- 'transform' : transform.end
- });
- }
- },
- /**
- * @method _getTransform
- * @protected
- */
- _getTransform: function()
- {
- var zoom = this.get('zoom'),
- image = this.get('image'),
- i = 0,
- zoomDirection = null,
- transform = null;
- // Random zoom direction
- i = Math.floor(Math.random() * Y.FL.SlideshowKenBurns.ZOOM_DIRECTIONS.length);
- zoomDirection = Y.FL.SlideshowKenBurns.ZOOM_DIRECTIONS[i];
- // Random transform
- i = Math.floor(Math.random() * Y.FL.SlideshowKenBurns.TRANSFORMS.length);
- transform = Y.FL.SlideshowKenBurns.TRANSFORMS[i];
- // Get the start and end transforms
- if(!image.hasClass('fl-slideshow-image-cropped') && zoomDirection == 'in') {
- i = Math.floor(Math.random() * 2);
- transform.start = i === 0 ? 'scale(1) translate(100px, 0)' : 'scale(1) translate(-100px, 0)';
- transform.end = 'scale(' + zoom + ') translate(0, 0)';
- transform.origin = 'center center';
- }
- else if(zoomDirection == 'out') {
- transform.start = 'scale(' + zoom + ') ' + transform.translate;
- transform.end = 'scale(1) translate(0, 0)';
- }
- else {
- transform.start = 'scale(1) translate(0, 0)';
- transform.end = 'scale(' + zoom + ') ' + transform.translate;
- }
- return transform;
- }
- }, {
- /**
- * Static property used to define the default attribute configuration of
- * the Widget.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- /**
- * An instance of FL.Slideshow image to apply the
- * Ken Burns effect on.
- *
- * @attribute image
- * @type FL.Slideshow
- * @default null
- */
- image: {
- value: null
- },
- /**
- * The amount to zoom the image. Zooming
- * in our out is done randomly by this class.
- *
- * @attribute scale
- * @type Number
- * @default 1.2
- */
- zoom: {
- value: 1.2
- },
- /**
- * The duration of the effect in seconds.
- *
- * @attribute duration
- * @type Number
- * @default 2
- */
- duration: {
- value: 2
- }
- },
- /**
- * The zoom directions that can be applied to an image.
- *
- * @property ZOOM_DIRECTIONS
- * @type Object
- * @readOnly
- * @protected
- * @static
- */
- ZOOM_DIRECTIONS: [
- 'in',
- 'out'
- ],
- /**
- * The types of transforms that can be applied to an image.
- *
- * @property TRANSFORMS
- * @type Object
- * @readOnly
- * @protected
- * @static
- */
- TRANSFORMS: [
- {
- origin : 'left top',
- translate : 'translate(-30px, -15px)'
- },{
- origin : 'left center',
- translate : 'translate(-30px, 0)'
- },{
- origin : 'left bottom',
- translate : 'translate(-30px, 15px)'
- },{
- origin : 'right top',
- translate : 'translate(30px, -15px)'
- },{
- origin : 'right center',
- translate : 'translate(30px, 0)'
- },{
- origin : 'right bottom',
- translate : 'translate(30px, 15px)'
- }
- ]
- });
- /**
- * Navigation buttons widget for controlling a slideshow instance
- * and its child widgets.
- *
- * @namespace FL
- * @class SlideshowNav
- * @constructor
- * @param config {Object} Configuration object
- * @extends Widget
- */
- Y.namespace('FL').SlideshowNav = Y.Base.create('fl-slideshow-nav', Y.Widget, [Y.WidgetChild], {
- /**
- * An object containing the anchor nodes for all buttons.
- *
- * @property _buttons
- * @type Object
- * @default null
- * @protected
- */
- _buttons: null,
- /**
- * An div node containing the anchor nodes for the main buttons.
- *
- * @property _buttonsContainer
- * @type Object
- * @default null
- * @protected
- */
- _buttonsContainer: null,
- /**
- * An div node containing the anchor nodes for the left buttons.
- *
- * @property _buttonsLeftContainer
- * @type Object
- * @default null
- * @protected
- */
- _buttonsLeftContainer: null,
- /**
- * An div node containing the anchor nodes for the right buttons.
- *
- * @property _buttonsRightContainer
- * @type Object
- * @default null
- * @protected
- */
- _buttonsRightContainer: null,
- /**
- * Property map for rendering SmugMug font icons.
- *
- * @property _fontIcons
- * @type Object
- * @protected
- */
- _fontIcons: {
- buy: 'Cart',
- caption: 'InfoEncircled',
- close: 'XCrossEncircled',
- fullscreen: 'ScreenExpand',
- next: 'ArrowRight',
- nextPage: 'ArrowRight',
- pause: 'PlayerPause',
- play: 'PlayerPlay',
- prev: 'ArrowLeft',
- prevPage: 'ArrowLeft',
- social: 'Heart',
- thumbs: 'ViewThumbGrid'
- },
- /**
- * The default content template for the nav
- * inherited from Y.Widget. Set to null since
- * only the bounding box is needed.
- *
- * @property CONTENT_TEMPLATE
- * @type String
- * @default null
- * @protected
- */
- CONTENT_TEMPLATE: null,
- /**
- * Renders the buttons.
- *
- * @method renderUI
- * @protected
- */
- renderUI: function()
- {
- this._renderContainers();
- this._renderButtons();
- this._renderFontIcons();
- },
- /**
- * Binds events to the root slideshow for each button.
- *
- * @method bindUI
- * @protected
- */
- bindUI: function()
- {
- var root = this.get('root'),
- id = this.get('id');
- if(this._buttons.prev) {
- this._buttons.prev.on('click', root.prevImage, root);
- }
- if(this._buttons.next) {
- this._buttons.next.on('click', root.nextImage, root);
- }
- if(this._buttons.play) {
- this._buttons.play.on('click', this._playClicked, this);
- root.on(id + '|played', this._showPauseButton, this);
- root.on(id + '|paused', this._showPlayButton, this);
- if(root._playing) {
- this._showPauseButton();
- }
- else {
- this._showPlayButton();
- }
- }
- if(this._buttons.buy) {
- root.on(id + '|albumLoadComplete', this._updateBuy, this);
- if(root.albumInfo !== null) {
- this._updateBuy();
- }
- }
- if(this._buttons.count) {
- root.on(id + '|imageLoadComplete', this._updateCount, this);
- }
- if(this._buttons.thumbs) {
- this._buttons.thumbs.on('click', root._toggleThumbs, root);
- }
- if(this._buttons.caption) {
- root.on(id + '|imageLoadComplete', this._updateCaption, this);
- this._updateCaption();
- }
- if(this._buttons.social) {
- this._buttons.social.on('click', root._toggleSocial, root);
- }
- if(this._buttons.fullscreen && root.fullscreen) {
- this._buttons.fullscreen.on('click', root.fullscreen.toggle, root.fullscreen);
- }
- if(this._buttons.close) {
- this._buttons.close.on('click', root.hide, root);
- }
- },
- /**
- * @method destructor
- * @protected
- */
- destructor: function()
- {
- var root = this.get('root'),
- id = this.get('id');
- root.detach(id + '|*');
- },
- /**
- * Renders the button left, right and main button containers.
- *
- * @method _renderContainers
- * @protected
- */
- _renderContainers: function()
- {
- var cb = this.get('contentBox'),
- buttonsLeft = this.get('buttonsLeft'),
- buttonsRight = this.get('buttonsRight');
- this._buttonsContainer = Y.Node.create('<div></div>');
- this._buttonsContainer.addClass('fl-slideshow-nav-buttons');
- cb.appendChild(this._buttonsContainer);
- if(buttonsLeft.length > 0) {
- this._buttonsLeftContainer = Y.Node.create('<div></div>');
- this._buttonsLeftContainer.addClass('fl-slideshow-nav-buttons-left');
- cb.appendChild(this._buttonsLeftContainer);
- }
- if(buttonsRight.length > 0) {
- this._buttonsRightContainer = Y.Node.create('<div></div>');
- this._buttonsRightContainer.addClass('fl-slideshow-nav-buttons-right');
- cb.appendChild(this._buttonsRightContainer);
- }
- },
- /**
- * Renders the buttons based on the buttons array
- * passed in the configuration object.
- *
- * @method _renderButtons
- * @protected
- */
- _renderButtons: function()
- {
- var name = '',
- i = 0,
- k = 0,
- b = [
- {
- names: this.get('buttons'),
- container: this._buttonsContainer
- },
- {
- names: this.get('buttonsLeft'),
- container: this._buttonsLeftContainer
- },
- {
- names: this.get('buttonsRight'),
- container: this._buttonsRightContainer
- }
- ];
- this._buttons = {};
- for( ; i < b.length; i++) {
- for(k = 0; k < b[i].names.length; k++) {
- name = b[i].names[k];
- if(name.indexOf('count') > -1) {
- this._buttons[name] = Y.Node.create('<span></span>');
- this._updateCount();
- }
- else {
- this._buttons[name] = Y.Node.create('<a href="javascript:void(0);"></a>');
- }
- if(name.indexOf('buy') > -1) {
- this._buttons[name].setStyle('display', 'none');
- }
- this._buttons[name].set('name', name);
- this._buttons[name].addClass('fl-slideshow-nav-' + name);
- b[i].container.appendChild(this._buttons[name]);
- }
- }
- },
- /**
- * Renders SmugMug font icons for each button.
- *
- * @method _renderFontIcons
- * @protected
- */
- _renderFontIcons: function()
- {
- var name = null;
- if(this.get('useFontIcons') && typeof YUI.Env.mods['sm-fonticon'] !== 'undefined') {
- for(name in this._buttons) {
- if(typeof this._buttons[name] !== 'undefined' && typeof this._fontIcons[name] !== 'undefined') {
- this._buttons[name].addClass('sm-fonticon-' + this._fontIcons[name]);
- this._buttons[name].addClass('sm-fonticon sm-button-skin-default sm-button-nochrome');
- }
- else if(name.indexOf('count') > -1) {
- this._buttons[name].addClass('fonticons-enabled');
- }
- }
- }
- },
- /**
- * Updates the image count.
- *
- * @method _updateCount
- * @protected
- */
- _updateCount: function()
- {
- var html = '',
- countText = Y.FL.SlideshowNav.COUNT_TEXT,
- current = 1,
- total = 1;
- if(this.get('root').albumInfo) {
- current = this.get('root').imageInfo.index + 1;
- total = this.get('root').albumInfo.images.length;
- }
- html = countText.replace('{current}', current).replace('{total}', total);
- this._buttons.count.set('innerHTML', html);
- },
- /**
- * Shows the caption button if the current image
- * has a caption, hides it if the image does not
- * have a caption.
- *
- * @method _updateCaption
- * @protected
- */
- _updateCaption: function()
- {
- var root = this.get('root'),
- imageInfo = root.imageInfo;
- if(imageInfo && imageInfo.caption === '') {
- root.caption.slideshowOverlay.enable();
- root.caption.slideshowOverlay.hide();
- this._buttons.caption.detach('click');
- this._buttons.caption.addClass('fl-slideshow-nav-caption-disabled');
- }
- else {
- this._buttons.caption.on('click', root._toggleCaption, root);
- this._buttons.caption.removeClass('fl-slideshow-nav-caption-disabled');
- }
- },
- /**
- * Checks if buying has been enabled for the current album.
- *
- * @method _updateBuy
- * @protected
- */
- _updateBuy: function()
- {
- var sm = null,
- root = this.get('root'),
- rootSource = root.get('source')[root.albumIndex],
- albumIndex = root.albumIndex,
- source = root.get('source')[albumIndex];
- if(rootSource && rootSource.type == 'smugmug') {
- if(typeof root.albumInfo.printable !== 'undefined') {
- this._updateBuyComplete();
- }
- else {
- sm = new Y.FL.SmugMugAPI();
- sm.addParam('method', 'smugmug.albums.getInfo');
- sm.addParam('AlbumID', source.id);
- sm.addParam('AlbumKey', source.key);
- sm.on('complete', this._updateBuyComplete, this);
- sm.request();
- }
- }
- },
- /**
- * Shows the buy button and updates the buy url
- * if buying has been enabled.
- *
- * @method _updateBuyComplete
- * @param e {Object} The custom event object passed to this function.
- * @protected
- */
- _updateBuyComplete: function(e)
- {
- var root = this.get('root'),
- printable = typeof e == 'undefined' ? root.albumInfo.printable : e.Album.Printable,
- link = root.albumInfo.link;
- if(printable) {
- root.albumInfo.printable = true;
- this._buttons.buy.set('href', 'https://secure.smugmug.com/cart/batchadd/?url=' + encodeURIComponent(link));
- this._buttons.buy.setStyle('display', 'inline-block');
- }
- else {
- root.albumInfo.printable = false;
- this._buttons.buy.setStyle('display', 'none');
- }
- this.fire('resize');
- },
- /**
- * Pauses the slideshow if it is playing and
- * plays the slideshow if it is paused.
- *
- * @method _playClicked
- * @protected
- */
- _playClicked: function()
- {
- var root = this.get('root');
- if(root._playing) {
- root.pause();
- }
- else {
- root.play();
- }
- },
- /**
- * Toggles the button class for the play button
- * so pause is hidden and play is shown.
- *
- * @method _showPlayButton
- * @protected
- */
- _showPlayButton: function()
- {
- this._buttons.play.removeClass('fl-slideshow-nav-pause');
- this._buttons.play.addClass('fl-slideshow-nav-play');
- if(this.get('useFontIcons') && typeof YUI.Env.mods['sm-fonticon'] !== 'undefined') {
- this._buttons.play.removeClass('sm-fonticon-PlayerPause');
- this._buttons.play.addClass('sm-fonticon-PlayerPlay');
- }
- },
- /**
- * Toggles the button class for the play button
- * so pause is shown and play is hidden.
- *
- * @method _showPauseButton
- * @protected
- */
- _showPauseButton: function()
- {
- this._buttons.play.removeClass('fl-slideshow-nav-play');
- this._buttons.play.addClass('fl-slideshow-nav-pause');
- if(this.get('useFontIcons') && typeof YUI.Env.mods['sm-fonticon'] !== 'undefined') {
- this._buttons.play.removeClass('sm-fonticon-PlayerPlay');
- this._buttons.play.addClass('sm-fonticon-PlayerPause');
- }
- }
- }, {
- /**
- * Custom CSS class name for the widget.
- *
- * @property CSS_PREFIX
- * @type String
- * @protected
- * @static
- */
- CSS_PREFIX: 'fl-slideshow-nav',
- /**
- * Static string used for displaying the image count. Use {current}
- * for the current image and {total} for the total number of images.
- * Those placeholders will be replaced when the count node is created.
- *
- * @property COUNT_TEXT
- * @type String
- * @protected
- * @static
- */
- COUNT_TEXT: '{current} of {total}',
- /**
- * Static property used to define the default attribute configuration of
- * the Widget.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- /**
- * An array of button names that is used to render the main buttons.
- *
- * @attribute buttons
- * @type Array
- * @default []
- * @writeOnce
- */
- buttons: {
- value: [],
- writeOnce: true
- },
- /**
- * An array of button names that is used to render the left buttons.
- *
- * @attribute buttonsLeft
- * @type Array
- * @default []
- * @writeOnce
- */
- buttonsLeft: {
- value: [],
- writeOnce: true
- },
- /**
- * An array of button names that is used to render the right buttons.
- *
- * @attribute buttonsRight
- * @type Array
- * @default []
- * @writeOnce
- */
- buttonsRight: {
- value: [],
- writeOnce: true
- },
- /**
- * Whether to use font icons when available.
- *
- * @attribute useFontIcons
- * @type Boolean
- * @default true
- * @writeOnce
- */
- useFontIcons: {
- value: true,
- writeOnce: true
- }
- }
- });
- /**
- * A plugin for overlaying widgets in a slideshow
- * with specialized show and hide functionality.
- *
- * @namespace FL
- * @class SlideshowOverlay
- * @constructor
- * @param config {Object} Configuration object
- * @extends Plugin.Base
- */
- Y.namespace('FL').SlideshowOverlay = Y.Base.create('fl-slideshow-overlay', Y.Plugin.Base, [], {
- /**
- * Flag for whether the mouse has entered
- * the host's bounding box.
- *
- * @property _focus
- * @type Boolean
- * @default false
- * @protected
- */
- _focus: false,
- /**
- * Flag for whether the host's bounding box is visible.
- *
- * @property _visible
- * @type Boolean
- * @default true
- * @protected
- */
- _visible: true,
- /**
- * Flag for whether show and hide functionality
- * has been disabled.
- *
- * @property _disabled
- * @type Boolean
- * @default false
- * @protected
- */
- _disabled: false,
- /**
- * An object containing properties for the show transition.
- *
- * @property _showProps
- * @type Object
- * @protected
- */
- _showProps: {
- duration: 0.5,
- easing: 'ease-out',
- opacity: 1
- },
- /**
- * An object containing properties for the hide transition.
- *
- * @property _hideProps
- * @type Object
- * @protected
- */
- _hideProps: {
- duration: 0.5,
- easing: 'ease-out',
- opacity: 0
- },
- /**
- * A timer object for delaying the hide transition.
- *
- * @property _hideTimer
- * @type Object
- * @default null
- * @protected
- */
- _hideTimer: null,
- /**
- * @method initializer
- * @protected
- */
- initializer: function()
- {
- var bb = this.get('host').get('boundingBox');
- this.afterHostEvent('render', this._initFocus);
- this.afterHostEvent('render', this._initVisibility);
- if(this.get('closeButton')) {
- this._initCloseButton();
- }
- bb.addClass('fl-slideshow-overlay');
- },
- /**
- * @method destructor
- * @protected
- */
- destructor: function()
- {
- this._hideTimerCancel();
- },
- /**
- * Binds the mouseenter and mouseleave events for setting focus.
- *
- * @method _initFocus
- * @protected
- */
- _initFocus: function()
- {
- var bb = this.get('host').get('boundingBox');
- bb.on('mouseenter', Y.bind(this._setFocusOnMouseenter, this));
- bb.on('mouseleave', Y.bind(this._setFocusOnMouseleave, this));
- },
- /**
- * Sets the initial visibility of the host's bounding box.
- *
- * @method _initVisibility
- * @protected
- */
- _initVisibility: function()
- {
- var bb = this.get('host').get('boundingBox'),
- hideStyle = this.get('hideStyle');
- if(!this.get('visible')) {
- if(hideStyle == 'display') {
- bb.setStyle('display', 'none');
- }
- else if(hideStyle == 'left') {
- bb.setStyle('left', '-99999px');
- }
- bb.setStyle('opacity', '0');
- this._visible = false;
- }
- },
- /**
- * Creates and inserts the close button.
- *
- * @method _initCloseButton
- * @protected
- */
- _initCloseButton: function()
- {
- var bb = this.get('host').get('boundingBox'),
- closeButton = null;
- closeButton = Y.Node.create('<a class="fl-slideshow-overlay-close" href="javascript:void(0);"></a>');
- closeButton.on('click', Y.bind(this._closeButtonClick, this));
- if(typeof YUI.Env.mods['sm-fonticon'] !== 'undefined') {
- closeButton.addClass('sm-fonticon sm-fonticon-XCrossEncircled sm-button-skin-default sm-button-nochrome');
- }
- bb.insert(closeButton);
- },
- /**
- * Hides the overlay when the close button is clicked.
- *
- * @method _closeButtonClick
- * @protected
- */
- _closeButtonClick: function()
- {
- var bb = this.get('host').get('boundingBox');
- bb.transition(this._hideProps, Y.bind(this._hideComplete, this));
- },
- /**
- * Sets the focus flag to true.
- *
- * @method _setFocusOnMouseenter
- * @protected
- */
- _setFocusOnMouseenter: function()
- {
- this._focus = true;
- },
- /**
- * Sets the focus flag to false.
- *
- * @method _setFocusOnMouseleave
- * @protected
- */
- _setFocusOnMouseleave: function()
- {
- this._focus = false;
- },
- /**
- * Disables show and hide functionality.
- *
- * @method disable
- * @public
- */
- disable: function()
- {
- this._disabled = true;
- },
- /**
- * Enables show and hide functionality.
- *
- * @method enable
- * @public
- */
- enable: function()
- {
- this._disabled = false;
- },
- /**
- * Shows the host's bounding box with a fade in transition.
- *
- * @method show
- * @public
- */
- show: function()
- {
- var bb = this.get('host').get('boundingBox'),
- hideStyle = this.get('hideStyle');
- if(this._disabled) {
- return;
- }
- if(hideStyle == 'display') {
- bb.setStyle('display', 'block');
- }
- else if(hideStyle == 'left') {
- bb.setStyle('left', 'auto');
- }
- bb.transition(this._showProps, Y.bind(this._showComplete, this));
- /**
- * @event hideStart
- */
- this.fire('showStart');
- },
- /**
- * @method _showComplete
- * @protected
- */
- _showComplete: function()
- {
- this._visible = true;
- this.hideWithTimer();
- /**
- * @event showComplete
- */
- this.fire('showComplete');
- },
- /**
- * Hides the host's bounding box with a fade out transition.
- *
- * @method hide
- * @public
- */
- hide: function()
- {
- if(this._focus || this._disabled) {
- return;
- }
- var bb = this.get('host').get('boundingBox');
- bb.transition(this._hideProps, Y.bind(this._hideComplete, this));
- /**
- * @event hideStart
- */
- this.fire('hideStart');
- },
- /**
- * Hides the host's bounding box with a fade out transition
- * after a timer completes.
- *
- * @method hideWithTimer
- * @public
- */
- hideWithTimer: function()
- {
- this._hideTimerCancel();
- this._hideTimer = Y.later(this.get('hideDelay'), this, this.hide);
- },
- /**
- * Cancels the hide timer.
- *
- * @method _hideTimerCancel
- * @protected
- */
- _hideTimerCancel: function()
- {
- if(this._hideTimer) {
- this._hideTimer.cancel();
- this._hideTimer = null;
- }
- },
- /**
- * @method _hideComplete
- * @protected
- */
- _hideComplete: function()
- {
- var bb = this.get('host').get('boundingBox'),
- hideStyle = this.get('hideStyle');
- if(hideStyle == 'display') {
- bb.setStyle('display', 'none');
- }
- else if(hideStyle == 'left') {
- bb.setStyle('left', '-99999px');
- }
- this._visible = false;
- /**
- * @event hideComplete
- */
- this.fire('hideComplete');
- }
- }, {
- /**
- * Namespace for the plugin.
- *
- * @property NS
- * @type String
- * @protected
- * @static
- */
- NS: 'slideshowOverlay',
- /**
- * Static property used to define the default attribute configuration of
- * the plugin.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- /**
- * Whether to use the close button or not.
- *
- * @attribute closeButton
- * @type Boolean
- * @default false
- * @writeOnce
- */
- closeButton: {
- value: false,
- writeOnce: true
- },
- /**
- * The time to wait before hiding the host's bounding box.
- * Measured in milliseconds.
- *
- * @attribute hideDelay
- * @type Number
- * @default 3000
- * @writeOnce
- */
- hideDelay: {
- value: 3000,
- writeOnce: true
- },
- /**
- * The style to use for hiding the image. Possible
- * values are display and left.
- *
- * @attribute hideStyle
- * @type String
- * @default display
- * @writeOnce
- */
- hideStyle: {
- value: 'display',
- writeOnce: true
- },
- /**
- * Sets the initial visibility of the host's boudning box.
- *
- * @attribute visible
- * @type Boolean
- * @default true
- * @writeOnce
- */
- visible: {
- value: true,
- writeOnce: true
- }
- }
- });
- /**
- * Social buttons widget used in slideshows.
- *
- * @namespace FL
- * @class SlideshowSocial
- * @constructor
- * @param config {Object} Configuration object
- * @extends Widget
- */
- Y.namespace('FL').SlideshowSocial = Y.Base.create('fl-slideshow-social', Y.Widget, [Y.WidgetChild], {
- /**
- * An object containing the social button nodes.
- *
- * @property _buttons
- * @type Object
- * @default null
- * @protected
- */
- _buttons: null,
- /**
- * @method renderUI
- * @protected
- */
- renderUI: function()
- {
- this._buttons = {};
- if(this.get('root').get('googlePlusButtonEnabled')) {
- this._renderGooglePlusButton();
- }
- },
- /**
- * @method bindUI
- * @protected
- */
- bindUI: function()
- {
- var root = this.get('root');
- if(root.get('likeButtonEnabled')) {
- root.on('imageLoadComplete', Y.bind(this._updateLikeButton, this));
- }
- if(root.get('tweetButtonEnabled')) {
- root.on('imageLoadComplete', Y.bind(this._updateTweetButton, this));
- }
- if(root.get('googlePlusButtonEnabled')) {
- root.on('imageLoadComplete', Y.bind(this._updateGooglePlusButton, this));
- }
- if(root.get('pinterestButtonEnabled')) {
- root.on('imageLoadComplete', Y.bind(this._updatePinterestButton, this));
- }
- },
- /**
- * @method _updateLikeButton
- * @protected
- */
- _updateLikeButton: function()
- {
- var src = null,
- cb = this.get('contentBox'),
- root = this.get('root'),
- albumIndex = root.albumIndex,
- rootSource = root.get('source')[albumIndex],
- imageInfo = root.imageInfo;
- if(this._buttons.like) {
- this._buttons.like.remove();
- this._buttons.like = null;
- }
- if(rootSource.type == 'smugmug') {
- src = 'https://www.facebook.com/plugins/like.php?';
- src += 'href=' + 'https://www.smugmug.com/services/graph/gallery/';
- src += rootSource.id + '_' + rootSource.key +'/' + imageInfo.id + '_' + imageInfo.key;
- }
- else {
- src = 'https://www.facebook.com/plugins/like.php?';
- src += 'href=' + encodeURIComponent(imageInfo.largeURL);
- }
- src += '&send=false';
- src += '&layout=button_count';
- src += '&width=90';
- src += '&show_faces=false';
- src += '&action=like';
- src += '&colorscheme=light';
- src += '&height=21';
- this._buttons.like = Y.Node.create('<iframe src="'+ src +'" scrolling="no" frameborder="0" allowTransparency="true"></iframe>');
- this._buttons.like.setStyles({
- overflow: 'hidden',
- width: '90px',
- height: '21px'
- });
- cb.appendChild(this._buttons.like);
- },
- /**
- * @method _updateTweetButton
- * @protected
- */
- _updateTweetButton: function()
- {
- var src = null,
- imageInfo = this.get('root').imageInfo,
- cb = this.get('contentBox');
- if(this._buttons.tweet) {
- this._buttons.tweet.remove();
- this._buttons.tweet = null;
- }
- src = 'https://platform.twitter.com/widgets/tweet_button.html?';
- src += 'url=' + encodeURIComponent(imageInfo.largeURL);
- src += '&count=none';
- this._buttons.tweet = Y.Node.create('<iframe src="'+ src +'" scrolling="no" frameborder="0" allowTransparency="true"></iframe>');
- this._buttons.tweet.setStyles({
- overflow: 'hidden',
- width: '90px',
- height: '21px'
- });
- cb.appendChild(this._buttons.tweet);
- },
- /**
- * @method _renderGooglePlusButton
- * @protected
- */
- _renderGooglePlusButton: function()
- {
- var po, head;
- po = document.createElement('script');
- po.type = 'text/javascript';
- po.src = 'https://apis.google.com/js/plusone.js';
- head = document.getElementsByTagName('head')[0];
- head.parentNode.appendChild(po);
- },
- /**
- * @method _updateGooglePlusButton
- * @protected
- */
- _updateGooglePlusButton: function()
- {
- if(typeof gapi == 'undefined') {
- setTimeout(Y.bind(this._updateGooglePlusButtonCallback, this), 500);
- }
- else {
- this._updateGooglePlusButtonCallback();
- }
- },
- /**
- * @method _updateGooglePlusButtonCallback
- * @protected
- */
- _updateGooglePlusButtonCallback: function()
- {
- var imageInfo = this.get('root').imageInfo,
- cb = this.get('contentBox');
- if(this._buttons.plus) {
- this._buttons.plus.remove();
- this._buttons.plus = null;
- }
- if(typeof gapi != 'undefined') {
- this._buttons.plus = Y.Node.create('<div></div>');
- cb.appendChild(this._buttons.plus);
- gapi.plusone.render(this._buttons.plus._node, {
- href: encodeURIComponent(imageInfo.largeURL),
- annotation: 'bubble',
- size: 'medium'
- });
- }
- },
- /**
- * @method _updatePinterestButton
- * @protected
- */
- _updatePinterestButton: function()
- {
- var href = 'https://pinterest.com/pin/create/button/',
- imageInfo = this.get('root').imageInfo,
- cb = this.get('contentBox');
- if(this._buttons.pin) {
- this._buttons.pin.remove();
- this._buttons.pin = null;
- }
- href += '?url=' + encodeURIComponent(window.location.href);
- href += '&media='+ encodeURIComponent(imageInfo.mediumURL);
- href += '&description='+ encodeURIComponent(imageInfo.caption);
- this._buttons.pin = Y.Node.create('<a></a>');
- this._buttons.pin.setAttribute('data-pin-config', 'none');
- this._buttons.pin.setAttribute('data-pin-do', 'buttonPin');
- this._buttons.pin.setAttribute('href', href);
- this._buttons.pin.setAttribute('target', '_blank');
- this._buttons.pin.set('innerHTML', '<img src="https://assets.pinterest.com/images/pidgets/pin_it_button.png" border="0" />');
- cb.appendChild(this._buttons.pin);
- }
- }, {
- /**
- * Custom CSS class name for the widget.
- *
- * @property CSS_PREFIX
- * @type String
- * @protected
- * @static
- */
- CSS_PREFIX: 'fl-slideshow-social',
- /**
- * Static property used to define the default attribute configuration of
- * the Widget.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- }
- });
- /**
- * Creates a grid of FL.SlideshowImage instances.
- *
- * @namespace FL
- * @class SlideshowThumbs
- * @constructor
- * @param config {Object} Configuration object
- * @extends Widget
- */
- Y.namespace('FL').SlideshowThumbs = Y.Base.create('fl-slideshow-thumbs', Y.Widget, [Y.WidgetParent, Y.WidgetChild], {
- /**
- * A div node used to hide the overflow when
- * transitioning between pages.
- *
- * @property _clipBox
- * @type Object
- * @default null
- * @protected
- */
- _clipBox: null,
- /**
- * A div node used to hold the pages.
- *
- * @property _pagesBox
- * @type Object
- * @default null
- * @protected
- */
- _pagesBox: null,
- /**
- * A reference to the active page div node. Holds a grid
- * of FL.SlideshowImage instances.
- *
- * @property _activePageBox
- * @type Object
- * @default null
- * @protected
- */
- _activePageBox: null,
- /**
- * The index of the active page of thumbs.
- *
- * @property _activePageIndex
- * @type Number
- * @default 0
- * @protected
- */
- _activePageIndex: 0,
- /**
- * A reference to the next page div node. Holds a grid
- * of FL.SlideshowImage instances.
- *
- * @property _nextPageBox
- * @type Object
- * @default null
- * @protected
- */
- _nextPageBox: null,
- /**
- * An array of FL.SlideshowImage instances in the active page.
- *
- * @property _activeImages
- * @type Array
- * @default null
- * @protected
- */
- _activeImages: null,
- /**
- * An array of FL.SlideshowImage instances used to
- * preload the next page of images.
- *
- * @property _nextImages
- * @type Array
- * @default null
- * @protected
- */
- _nextImages: null,
- /**
- * An array of FL.SlideshowImage instances used to
- * preload the previous page of images.
- *
- * @property _prevImages
- * @type Array
- * @default null
- * @protected
- */
- _prevImages: null,
- /**
- * An instance of FL.SlideshowNav used for the left nav.
- *
- * @property _leftNav
- * @type Object
- * @default null
- * @protected
- */
- _leftNav: null,
- /**
- * An instance of FL.SlideshowNav used for the right nav.
- *
- * @property _rightNav
- * @type Object
- * @default null
- * @protected
- */
- _rightNav: null,
- /**
- * An instance of FL.SlideshowNav used for the top nav.
- *
- * @property _topNav
- * @type Object
- * @default null
- * @protected
- */
- _topNav: null,
- /**
- * An instance of FL.SlideshowNav used for the bottom nav.
- *
- * @property _bottomNav
- * @type Object
- * @default null
- * @protected
- */
- _bottomNav: null,
- /**
- * Height of the bounding box.
- *
- * @property _bbHeight
- * @type Number
- * @default 0
- * @protected
- */
- _bbHeight: 0,
- /**
- * Width of the bounding box.
- *
- * @property _bbWidth
- * @type Number
- * @default 0
- * @protected
- */
- _bbWidth: 0,
- /**
- * Width of the content box.
- *
- * @property _cbWidth
- * @type Number
- * @default 0
- * @protected
- */
- _cbWidth: 0,
- /**
- * Left margin of the clip box.
- *
- * @property _clipBoxMarginLeft
- * @type Number
- * @default 0
- * @protected
- */
- _clipBoxMarginLeft: 0,
- /**
- * Top position of the clip box.
- *
- * @property _clipBoxTop
- * @type Number
- * @default 0
- * @protected
- */
- _clipBoxTop: 0,
- /**
- * The number of columns per page.
- *
- * @property _colsPerPage
- * @type Number
- * @default 0
- * @protected
- */
- _colsPerPage: 0,
- /**
- * The number of rows per page.
- *
- * @property _rowsPerPage
- * @type Number
- * @default 0
- * @protected
- */
- _rowsPerPage: 0,
- /**
- * The number of images per page.
- *
- * @property _imagesPerPage
- * @type Number
- * @default 0
- * @protected
- */
- _imagesPerPage: 0,
- /**
- * The number of pages.
- *
- * @property _numPages
- * @type Number
- * @default 0
- * @protected
- */
- _numPages: 0,
- /**
- * Height of the pages.
- *
- * @property _pageHeight
- * @type Number
- * @default 0
- * @protected
- */
- _pageHeight: 0,
- /**
- * Width of the pages.
- *
- * @property _pageWidth
- * @type Number
- * @default 0
- * @protected
- */
- _pageWidth: 0,
- /**
- * The horizontal spacing between thumbs.
- *
- * @property _horizontalSpacing
- * @type Number
- * @default 0
- * @protected
- */
- _horizontalSpacing: 0,
- /**
- * The vertical spacing between thumbs.
- *
- * @property _verticalSpacing
- * @type Number
- * @default 0
- * @protected
- */
- _verticalSpacing: 0,
- /**
- * Width of the left nav.
- *
- * @property _leftNavWidth
- * @type Number
- * @default 0
- * @protected
- */
- _leftNavWidth: 0,
- /**
- * Width of the right nav.
- *
- * @property _rightNavWidth
- * @type Number
- * @default 0
- * @protected
- */
- _rightNavWidth: 0,
- /**
- * An instance of FL.SlideshowTransition for the current transition.
- *
- * @property _transition
- * @type FL.SlideshowTransition
- * @default null
- * @protected
- */
- _transition: null,
- /**
- * Whether the pages are currently transitioning or not.
- *
- * @property _verticalSpacing
- * @type Boolean
- * @default false
- * @protected
- */
- _transitioning: false,
- /**
- * Direction of the current transition.
- *
- * @property _transitionDirection
- * @type String
- * @default next
- * @protected
- */
- _transitionDirection: 'next',
- /**
- * Provides functionality for gesture based transitions
- * between the active and next pages.
- *
- * @property _gestures
- * @type FL.SlideshowGestures
- * @default null
- * @protected
- */
- _gestures: null,
- /**
- * Initialize image vars.
- *
- * @method initializer
- * @protected
- */
- initializer: function()
- {
- this._activeImages = [];
- this._nextImages = [];
- this._prevImages = [];
- },
- /**
- * Renders the UI boxes.
- *
- * @method renderUI
- * @protected
- */
- renderUI: function()
- {
- this._renderBoxes();
- this._renderNavs();
- },
- /**
- * Binds the UI events.
- *
- * @method bindUI
- * @protected
- */
- bindUI: function()
- {
- var root = this.get('root'),
- id = this.get('id'),
- transition = this.get('transition');
- root.on(id + '|albumLoadComplete', this._albumLoadComplete, this);
- if('ontouchstart' in window && this.get('touchSupport')) {
- this._gestures = new Y.FL.SlideshowGestures({
- direction: transition == 'slideVertical' ? 'vertical' : 'horizontal',
- activeItem: this._activePageBox,
- nextItem: this._nextPageBox
- });
- this._gestures.on('moveStart', this._gesturesMoveStart, this);
- this._gestures.on('endComplete', this._gesturesEndComplete, this);
- }
- },
- /**
- * Syncs the UI boxes.
- *
- * @method syncUI
- * @protected
- */
- syncUI: function()
- {
- this._syncBoxes();
- this._syncNavs();
- },
- /**
- * @method destructor
- * @protected
- */
- destructor: function()
- {
- var root = this.get('root'),
- id = this.get('id');
- root.detach(id + '|*');
- Y.FL.SlideshowImageLoader.removeGroup('thumbs');
- },
- /**
- * Unload all images.
- *
- * @method unload
- */
- unload: function()
- {
- var root = this.get('root'),
- id = this.get('id'),
- i = 0;
- root.detach(id + '|imageLoadComplete');
- Y.FL.SlideshowImageLoader.removeGroup('thumbs');
- for( ; i < this._activeImages.length; i++) {
- this._activeImages[i].unload();
- }
- },
- /**
- * Resizes the UI boxes.
- *
- * @method resize
- */
- resize: function()
- {
- this._setSizeInfo();
- this._togglePageButtons();
- this._resizeBoxes();
- this._resizeNavs();
- if(this.get('root').albumInfo) {
- Y.FL.SlideshowImageLoader.removeGroup('thumbs');
- this._renderActivePage();
- this._preloadNextPage();
- this._preloadPrevPage();
- }
- // Enable or disable gestures.
- if(this._gestures && this._numPages < 2) {
- this._gestures.disable();
- }
- else if(this._gestures) {
- this._gestures.enable();
- }
- },
- /**
- * Transitions to the previous page.
- *
- * @method prevPage
- * @protected
- */
- prevPage: function()
- {
- if(this._transitioning) {
- return;
- }
- this._transitionStart('prev');
- },
- /**
- * Transitions to the next page.
- *
- * @method nextPage
- * @protected
- */
- nextPage: function()
- {
- if(this._transitioning) {
- return;
- }
- this._transitionStart('next');
- },
- /**
- * Called when an album is loaded into the root slideshow widget.
- *
- * @method _albumLoadComplete
- * @protected
- */
- _albumLoadComplete: function()
- {
- var root = this.get('root'),
- id = this.get('id');
- root.once(id + '|imageLoadComplete', this.resize, this);
- root.on(id + '|imageLoadComplete', this._imageLoadComplete, this);
- },
- /**
- * Called when an image is loaded into the root slideshow widget.
- *
- * @method _imageLoadComplete
- * @protected
- */
- _imageLoadComplete: function()
- {
- var albumInfo = this.get('root').albumInfo,
- lastActive = Y.one('.fl-slideshow-image-active'),
- lastInfo = lastActive ? lastActive._imageInfo : null,
- nextActive = null,
- nextInfo = this.get('root').imageInfo;
- this._setActiveImage(this._activeImages);
- nextActive = Y.one('.fl-slideshow-image-active');
- if(lastActive && !nextActive) {
- if(nextInfo.index === 0 && lastInfo.index === albumInfo.images.length - 1) {
- this.nextPage();
- }
- else if(lastInfo.index === 0 && nextInfo.index === albumInfo.images.length - 1) {
- this.prevPage();
- }
- else if(lastInfo.index < nextInfo.index) {
- this.nextPage();
- }
- else if(lastInfo.index > nextInfo.index) {
- this.prevPage();
- }
- }
- },
- /**
- * Renders the boxes.
- *
- * @method _renderBoxes
- * @protected
- */
- _renderBoxes: function()
- {
- // Clip box
- this._clipBox = Y.Node.create('<div></div>');
- this._clipBox.addClass('fl-slideshow-thumbs-clip');
- this.get('contentBox').insert(this._clipBox);
- // Pages box
- this._pagesBox = Y.Node.create('<div></div>');
- this._pagesBox.addClass('fl-slideshow-thumbs-pages');
- this._clipBox.insert(this._pagesBox);
- // Active page box
- this._activePageBox = Y.Node.create('<div></div>');
- this._activePageBox.addClass('fl-slideshow-thumbs-page');
- this._pagesBox.insert(this._activePageBox);
- // Next page box
- this._nextPageBox = Y.Node.create('<div></div>');
- this._nextPageBox.addClass('fl-slideshow-thumbs-page');
- this._pagesBox.insert(this._nextPageBox);
- },
- /**
- * Syncs the boxes.
- *
- * @method _syncBoxes
- * @protected
- */
- _syncBoxes: function()
- {
- // Active page box
- this._activePageBox.setStyle('left', '0');
- // Next page box
- this._nextPageBox.setStyle('left', '-9999px');
- },
- /**
- * Resizes the boxes.
- *
- * @method _resizeBoxes
- * @protected
- */
- _resizeBoxes: function()
- {
- this.set('width', this._bbWidth);
- this.set('height', this._bbHeight);
- this.get('contentBox').setStyle('width', this._cbWidth + 'px');
- this._clipBox.setStyle('width', this._pageWidth + 'px');
- this._clipBox.setStyle('height', this._pageHeight + 'px');
- this._clipBox.setStyle('padding', this._verticalSpacing + 'px 0 0 ' + this._horizontalSpacing + 'px ');
- this._clipBox.setStyle('margin', '0 0 0 ' + this._clipBoxMarginLeft + 'px');
- this._clipBox.setStyle('top', this._clipBoxTop);
- this._pagesBox.setStyle('width', this._pageWidth + 'px');
- this._pagesBox.setStyle('height', this._pageHeight + 'px');
- this._activePageBox.setStyle('width', this._pageWidth + 'px');
- this._activePageBox.setStyle('height', this._pageHeight + 'px');
- this._nextPageBox.setStyle('width', this._pageWidth + 'px');
- this._nextPageBox.setStyle('height', this._pageHeight + 'px');
- },
- /**
- * Renders the active page of images.
- *
- * @method _renderActivePage
- * @protected
- */
- _renderActivePage: function()
- {
- var i = 0,
- root = this.get('root'),
- imageIndex = this._imagesPerPage * this._activePageIndex,
- endIndex = imageIndex + this._imagesPerPage,
- images = root.albumInfo.images;
- this._clearActiveImage();
- // Remove current images
- for( ; i < this._activeImages.length; i++) {
- this._activeImages[i].remove();
- this._activeImages[i].unload();
- this._activeImages[i].get('boundingBox')._imageInfo = null;
- this._activeImages[i].get('boundingBox').remove();
- }
- // Draw images
- for(i = 0; imageIndex < endIndex; imageIndex++) {
- if(!images[imageIndex]) {
- break;
- }
- this._renderImage(this._activeImages, i, this._activePageBox, images[imageIndex]);
- i++;
- }
- this._setActiveImage(this._activeImages);
- },
- /**
- * Renders the next page of images.
- *
- * @method _renderNextPage
- * @protected
- */
- _renderNextPage: function()
- {
- var i = 0,
- imageArray = this._transitionDirection == 'next' ? this._nextImages : this._prevImages;
- this._nextPageBox.get('children').remove();
- for( ; i < imageArray.length; i++) {
- if(imageArray[i]._imageInfo) {
- this._renderImage(imageArray, i, this._nextPageBox, imageArray[i]._imageInfo);
- }
- else {
- break;
- }
- }
- this._setActiveImage(imageArray);
- },
- /**
- * Preloads the next page of images.
- *
- * @method _preloadNextPage
- * @protected
- */
- _preloadNextPage: function()
- {
- var pageIndex = this._activePageIndex + 1 >= this._numPages ? 0 : this._activePageIndex + 1;
- this._preloadPage(pageIndex, this._nextImages);
- },
- /**
- * Preloads the previous page of images.
- *
- * @method _preloadPrevPage
- * @protected
- */
- _preloadPrevPage: function()
- {
- var pageIndex = this._activePageIndex - 1 < 0 ? this._numPages - 1 : this._activePageIndex - 1;
- this._preloadPage(pageIndex, this._prevImages);
- },
- /**
- * Preloads a page of images.
- *
- * @method _preloadPage
- * @param imageIndex {Number} The image index to start preloading from.
- * @param imageArray {Array} The array to store the preloaded images.
- * @protected
- */
- _preloadPage: function(pageIndex, imageArray)
- {
- var i = 0,
- root = this.get('root'),
- images = root.albumInfo.images,
- imageIndex = pageIndex * this._imagesPerPage,
- endIndex = imageIndex + this._imagesPerPage,
- imageConfig = this.get('imageConfig'),
- width = imageConfig.width,
- height = imageConfig.height;
- if(this._numPages > 1) {
- // Unload existing images
- for( ; i < imageArray.length; i++) {
- imageArray[i].remove();
- imageArray[i].unload();
- }
- // Preload the images
- for(i = 0; imageIndex < endIndex; imageIndex++) {
- if(!images[imageIndex]) {
- continue;
- }
- this._renderImage(imageArray, i);
- imageArray[i].preload(images[imageIndex], width, height);
- i++;
- }
- }
- },
- /**
- * Renders an image.
- *
- * @method _renderImage
- * @protected
- */
- _renderImage: function(imageArray, i, page, imageInfo)
- {
- var imageBB = null,
- imageConfig = this.get('imageConfig');
- // Create the image?
- if(typeof imageArray[i] == 'undefined') {
- imageConfig.loadGroup = 'thumbs';
- imageConfig.useThumbSizes = true;
- imageConfig.loadVideos = false;
- imageArray[i] = new Y.FL.SlideshowImage(imageConfig);
- imageBB = imageArray[i].get('boundingBox');
- imageBB.on('click', this._imageClick, this);
- imageBB.on('mouseover', this._imageMouseover, this);
- imageBB.on('mouseout', this._imageMouseout, this);
- }
- // Image bounding box
- imageBB = imageArray[i].get('boundingBox');
- imageBB.setStyle('margin', '0 ' + this._horizontalSpacing + 'px ' + this._verticalSpacing + 'px 0');
- // Add the image to a page?
- if(page) {
- this._childrenContainer = page;
- this.add(imageArray[i]);
- imageArray[i].resize(imageConfig.width, imageConfig.height);
- }
- // Load the image?
- if(imageInfo) {
- imageArray[i].load(imageInfo);
- imageBB._imageInfo = imageInfo;
- }
- },
- /**
- * Overrides the WidgetParent _uiAddChild method so _renderImage
- * will render to the appropriate page.
- *
- * @method _uiAddChild
- * @protected
- * @param child {Widget} The child Widget instance to render.
- * @param parentNode {Object} The Node under which the
- * child Widget is to be rendered. Set to the appropriate page
- * in the _renderImage method by setting _childrenContainer.
- */
- _uiAddChild: function (child, parentNode)
- {
- child.render(parentNode);
- parentNode.appendChild(child.get('boundingBox'));
- },
- /**
- * Called when an image is clicked.
- *
- * @method _imageClick
- * @protected
- */
- _imageClick: function(e)
- {
- var root = this.get('root');
- if(this.get('pauseOnClick')) {
- root.pause();
- }
- root.loadImage(e.currentTarget._imageInfo.index);
- /**
- * Fires when an image is clicked.
- *
- * @event imageClick
- */
- this.fire('imageClick');
- },
- /**
- * Sets the active image.
- *
- * @method _setActiveImage
- * @param imageArray {Array} The image array to check for the active image.
- * @protected
- */
- _setActiveImage: function(imageArray)
- {
- var i = 0;
- this._clearActiveImage();
- for( ; i < imageArray.length; i++) {
- if(imageArray[i]._imageInfo) {
- if(imageArray[i]._imageInfo.index == this.get('root').imageInfo.index) {
- imageArray[i].get('boundingBox').addClass('fl-slideshow-image-active');
- break;
- }
- }
- }
- },
- /**
- * Removes the class name 'fl-slideshow-image-active'
- * from the active image.
- *
- * @method _clearActiveImage
- * @protected
- */
- _clearActiveImage: function()
- {
- var active = Y.one('.fl-slideshow-image-active');
- if(active) {
- active.removeClass('fl-slideshow-image-active');
- }
- },
- /**
- * Gets the transition type.
- *
- * @method _getTransition
- * @protected
- */
- _getTransition: function()
- {
- var transition = this.get('transition');
- if(transition == 'slideHorizontal' && this._transitionDirection == 'next') {
- return 'slideLeft';
- }
- else if(transition == 'slideHorizontal' && this._transitionDirection == 'prev') {
- return 'slideRight';
- }
- else if(transition == 'slideVertical' && this._transitionDirection == 'next') {
- return 'slideUp';
- }
- else if(transition == 'slideVertical' && this._transitionDirection == 'prev') {
- return 'slideDown';
- }
- return transition;
- },
- /**
- * Starts the transition, moving in the provided direction.
- *
- * @method _transitionStart
- * @param direction {String} The direction to transition.
- * @protected
- */
- _transitionStart: function(direction)
- {
- if(this._numPages > 1) {
- Y.FL.SlideshowImageLoader.removeGroup('thumbs');
- this._transitionDirection = direction;
- this._transitioning = true;
- this._nextPageBox.setStyle('left', '0px');
- this._renderNextPage();
- this._transition = new Y.FL.SlideshowTransition({
- itemIn: this._nextPageBox,
- itemOut: this._activePageBox,
- type: this._getTransition(),
- duration: this.get('transitionDuration'),
- easing: this.get('transitionEasing')
- });
- this._transition.once('complete', this._transitionComplete, this);
- this._transition.run();
- // Disable gestures if set.
- if(this._gestures) {
- this._gestures.disable();
- }
- }
- },
- /**
- * Transition cleanup called when the current transition ends.
- *
- * @method _transitionComplete
- * @protected
- */
- _transitionComplete: function()
- {
- this._swapPageRefs();
- this._transitioning = false;
- this._transitionDirection = '';
- this._transition = null;
- // Enable gestures if set.
- if(this._gestures) {
- this._gestures.enable();
- }
- /**
- * Fires when a page transition completes.
- *
- * @event transitionComplete
- */
- this.fire('transitionComplete');
- },
- /**
- * @method _gesturesMoveStart
- * @param e {Object} The event object.
- * @protected
- */
- _gesturesMoveStart: function(e)
- {
- Y.FL.SlideshowImageLoader.removeGroup('thumbs');
- this._transitionDirection = e.direction;
- this._renderNextPage();
- },
- /**
- * @method _gesturesEndComplete
- * @protected
- */
- _gesturesEndComplete: function()
- {
- this._swapPageRefs();
- this._transitionDirection = '';
- this.fire('transitionComplete');
- },
- /**
- * Swaps the active page and next page references when
- * a transition completes and sets the active page index.
- *
- * @method _swapPageRefs
- * @protected
- */
- _swapPageRefs: function()
- {
- var lastBox = this._activePageBox,
- lastImages = this._activeImages;
- this._activePageBox = this._nextPageBox;
- this._nextPageBox = lastBox;
- this._nextPageBox.setStyle('left', '-9999px');
- if(this._transitionDirection == 'next') {
- this._activeImages = this._nextImages;
- this._nextImages = lastImages;
- }
- else {
- this._activeImages = this._prevImages;
- this._prevImages = lastImages;
- }
- // Active page index
- if(this._transitionDirection == 'next' && this._activePageIndex + 1 < this._numPages) {
- this._activePageIndex++;
- }
- else if(this._transitionDirection == 'next') {
- this._activePageIndex = 0;
- }
- else if(this._transitionDirection == 'prev' && this._activePageIndex - 1 > -1) {
- this._activePageIndex--;
- }
- else if(this._transitionDirection == 'prev') {
- this._activePageIndex = this._numPages - 1;
- }
- // Swap gesture refs
- if(this._gestures) {
- this._gestures.set('activeItem', this._activePageBox);
- this._gestures.set('nextItem', this._nextPageBox);
- }
- this._preloadNextPage();
- this._preloadPrevPage();
- },
- /**
- * Renders the enabled navs.
- *
- * @method _renderNavs
- * @protected
- */
- _renderNavs: function()
- {
- var topNavButtons = this.get('topNavButtons'),
- rightNavButtons = this.get('rightNavButtons'),
- bottomNavButtons = this.get('bottomNavButtons'),
- leftNavButtons = this.get('leftNavButtons');
- if(this.get('topNavEnabled') && topNavButtons.length > 0) {
- this._topNav = new Y.FL.SlideshowNav({ buttons: topNavButtons });
- this._topNav.get('boundingBox').addClass('fl-slideshow-thumbs-top-nav');
- this.add(this._topNav);
- this._topNav.render(this.get('contentBox'));
- this._clipBox.insert(this._topNav.get('boundingBox'), 'before');
- this._bindNavEvents(this._topNav);
- }
- if(this.get('rightNavEnabled') && rightNavButtons.length > 0) {
- this._rightNav = new Y.FL.SlideshowNav({ buttons: rightNavButtons });
- this._rightNav.get('boundingBox').addClass('fl-slideshow-thumbs-right-nav');
- this.add(this._rightNav);
- this._rightNav.render(this.get('contentBox'));
- this._bindNavEvents(this._rightNav);
- }
- if(this.get('bottomNavEnabled') && bottomNavButtons.length > 0) {
- this._bottomNav = new Y.FL.SlideshowNav({ buttons: bottomNavButtons });
- this._bottomNav.get('boundingBox').addClass('fl-slideshow-thumbs-bottom-nav');
- this.add(this._bottomNav);
- this._bottomNav.render(this.get('contentBox'));
- this._bindNavEvents(this._bottomNav);
- }
- if(this.get('leftNavEnabled') && leftNavButtons.length > 0) {
- this._leftNav = new Y.FL.SlideshowNav({ buttons: leftNavButtons });
- this._leftNav.get('boundingBox').addClass('fl-slideshow-thumbs-left-nav');
- this.add(this._leftNav);
- this._leftNav.render(this.get('contentBox'));
- this._bindNavEvents(this._leftNav);
- }
- },
- /**
- * Syncs the navs.
- *
- * @method _syncNavs
- * @protected
- */
- _syncNavs: function()
- {
- var rightNavBB, bottomNavBB, leftNavBB;
- if(this._rightNav) {
- rightNavBB = this._rightNav.get('boundingBox');
- rightNavBB.setStyle('position', 'absolute');
- rightNavBB.setStyle('top', '0px');
- rightNavBB.setStyle('right', '0px');
- }
- if(this._bottomNav) {
- bottomNavBB = this._bottomNav.get('boundingBox');
- bottomNavBB.setStyle('position', 'absolute');
- bottomNavBB.setStyle('bottom', '0px');
- bottomNavBB.setStyle('width', '100%');
- }
- if(this._leftNav) {
- leftNavBB = this._leftNav.get('boundingBox');
- leftNavBB.setStyle('position', 'absolute');
- leftNavBB.setStyle('top', '0px');
- leftNavBB.setStyle('left', '0px');
- }
- },
- /**
- * Resizes the navs.
- *
- * @method _resizeNavs
- * @protected
- */
- _resizeNavs: function()
- {
- var rightNavBB,
- leftNavBB,
- marginTop;
- if(this._rightNav) {
- rightNavBB = this._rightNav.get('boundingBox');
- marginTop = this._bbHeight/2 - parseInt(rightNavBB.getComputedStyle('height'), 10)/2;
- rightNavBB.setStyle('marginTop', marginTop + 'px');
- }
- if(this._leftNav) {
- leftNavBB = this._leftNav.get('boundingBox');
- marginTop = this._bbHeight/2 - parseInt(leftNavBB.getComputedStyle('height'), 10)/2;
- leftNavBB.setStyle('marginTop', marginTop + 'px');
- }
- },
- /**
- * Binds events to the provided nav.
- *
- * @method _bindNavEvents
- * @param nav {Object} The nav to bind to.
- * @protected
- */
- _bindNavEvents: function(nav)
- {
- if(nav._buttons.prevPage) {
- nav._buttons.prevPage.on('click', this.prevPage, this);
- }
- if(nav._buttons.nextPage) {
- nav._buttons.nextPage.on('click', this.nextPage, this);
- }
- nav.on('resize', this.resize, this);
- },
- /**
- * Hides the prev page and next page buttons
- * if there is only one page of thumbs.
- *
- * @method _togglePageButtons
- * @protected
- */
- _togglePageButtons: function()
- {
- var buttons = this.get('boundingBox').all('.fl-slideshow-nav-prevPage, .fl-slideshow-nav-nextPage'),
- display = buttons.getStyle('display')[0];
- if(this._numPages == 1 && display == 'inline-block') {
- buttons.setStyle('display', 'none');
- this._setSizeInfo();
- }
- else if(this._numPages > 1 && display == 'none') {
- buttons.setStyle('display', 'inline-block');
- this._setSizeInfo();
- }
- },
- /**
- * Sets the size info used when resizing and loading pages.
- *
- * @method _setSizeInfo
- * @protected
- */
- _setSizeInfo: function()
- {
- var root = this.get('root'),
- bb = this.get('boundingBox'),
- bbPosition = bb.getStyle('position'),
- bbLeftMargin = parseInt(bb.getStyle('marginLeft'), 10),
- bbRightMargin = parseInt(bb.getStyle('marginRight'), 10),
- bbTopMargin = parseInt(bb.getStyle('marginTop'), 10),
- bbBottomMargin = parseInt(bb.getStyle('marginBottom'), 10),
- bbLeftPadding = parseInt(bb.getStyle('paddingLeft'), 10),
- bbRightPadding = parseInt(bb.getStyle('paddingRight'), 10),
- bbTopPadding = parseInt(bb.getStyle('paddingTop'), 10),
- bbBottomPadding = parseInt(bb.getStyle('paddingBottom'), 10),
- parent = bb.get('parentNode'),
- parentWidth = parseInt(parent.getComputedStyle('width'), 10),
- parentHeight = parseInt(parent.getComputedStyle('height'), 10),
- bbWidth = parentWidth - bbLeftPadding - bbRightPadding - bbLeftMargin - bbRightMargin,
- bbHeight = parentHeight - bbTopPadding - bbBottomPadding - bbTopMargin - bbBottomMargin,
- cbWidth = bbWidth,
- pageWidth = bbWidth,
- pageHeight = bbHeight,
- columns = this.get('columns'),
- rows = this.get('rows'),
- imageConfig = this.get('imageConfig'),
- horizontalSpacing = this.get('horizontalSpacing'),
- verticalSpacing = this.get('verticalSpacing'),
- spaceEvenly = this.get('spaceEvenly'),
- centerSinglePage = this.get('centerSinglePage'),
- leftNavWidth = 0,
- rightNavWidth = 0,
- topNavHeight = 0,
- bottomNavHeight = 0,
- colsPerPage = columns,
- rowsPerPage = rows,
- imagesPerPage = 0,
- numPages = 1,
- clipBoxMarginLeft = 0,
- clipBoxTop = 0,
- availHorizSpace = 0,
- availVerticalSpace = 0;
- // Position absolute causes some resizing bugs.
- bb.setStyle('position', 'relative');
- // Bounding box width
- if(!isNaN(columns)) {
- bbWidth = pageWidth = columns * (imageConfig.width + horizontalSpacing) + horizontalSpacing;
- }
- // Bounding box height
- if(!isNaN(rows)) {
- bbHeight = pageHeight = rows * (imageConfig.height + verticalSpacing) + verticalSpacing;
- }
- // Compensate for the navs
- if(this._leftNav) {
- leftNavWidth = parseInt(this._leftNav.get('boundingBox').getComputedStyle('width'), 10);
- if(isNaN(columns)) {
- pageWidth -= leftNavWidth;
- }
- else {
- bbWidth += leftNavWidth;
- }
- }
- if(this._rightNav) {
- rightNavWidth = parseInt(this._rightNav.get('boundingBox').getComputedStyle('width'), 10);
- if(isNaN(columns)) {
- pageWidth -= rightNavWidth;
- }
- else {
- bbWidth += rightNavWidth;
- }
- }
- if(this._topNav) {
- topNavHeight = parseInt(this._topNav.get('boundingBox').getComputedStyle('height'), 10);
- if(isNaN(rows)) {
- pageHeight -= topNavHeight;
- }
- else {
- bbHeight += topNavHeight;
- }
- }
- if(this._bottomNav) {
- bottomNavHeight = parseInt(this._bottomNav.get('boundingBox').getComputedStyle('height'), 10);
- if(isNaN(rows)) {
- pageHeight -= bottomNavHeight;
- }
- else {
- bbHeight += bottomNavHeight;
- }
- }
- // Columns per page
- if(isNaN(columns)) {
- colsPerPage = Math.floor(pageWidth/(imageConfig.width + horizontalSpacing));
- colsPerPage = colsPerPage < 1 ? 1 : colsPerPage;
- }
- // Rows per page
- if(isNaN(rows)) {
- rowsPerPage = Math.floor(pageHeight/(imageConfig.height + verticalSpacing));
- rowsPerPage = rowsPerPage < 1 ? 1 : rowsPerPage;
- }
- // Images per page
- imagesPerPage = colsPerPage * rowsPerPage;
- // Number of pages
- if(root.albumInfo) {
- numPages = Math.ceil(root.albumInfo.images.length/imagesPerPage);
- }
- // Horizontal spacing
- if(isNaN(columns) && spaceEvenly) {
- horizontalSpacing = Math.floor((pageWidth - (imageConfig.width * colsPerPage))/(colsPerPage + 1));
- }
- // Vertical spacing
- if(isNaN(rows) && spaceEvenly) {
- verticalSpacing = Math.floor((pageHeight - (imageConfig.height * rowsPerPage))/(rowsPerPage + 1));
- }
- // Content container width
- if(root.albumInfo && centerSinglePage && numPages == 1 && rowsPerPage == 1) {
- cbWidth = root.albumInfo.images.length * imageConfig.width;
- cbWidth += horizontalSpacing * (root.albumInfo.images.length + 1);
- if(this._leftNav) {
- cbWidth += leftNavWidth;
- }
- if(this._rightNav) {
- cbWidth += rightNavWidth;
- }
- }
- else {
- cbWidth = bbWidth;
- }
- // Final page width and height
- if(root.albumInfo && centerSinglePage && numPages == 1 && rowsPerPage == 1) {
- pageWidth = root.albumInfo.images.length * imageConfig.width;
- pageWidth += horizontalSpacing * root.albumInfo.images.length;
- }
- else {
- pageWidth = colsPerPage * (imageConfig.width + horizontalSpacing);
- }
- pageHeight = rowsPerPage * (imageConfig.height + verticalSpacing);
- // Clip box margin left
- if(numPages < 2) {
- clipBoxMarginLeft = leftNavWidth;
- }
- else {
- availHorizSpace = bbWidth;
- if(this._rightNav) {
- availHorizSpace -= rightNavWidth;
- }
- if(this._leftNav) {
- availHorizSpace -= leftNavWidth;
- clipBoxMarginLeft = leftNavWidth + (availHorizSpace - pageWidth - horizontalSpacing)/2;
- }
- else {
- clipBoxMarginLeft = (availHorizSpace - pageWidth - horizontalSpacing)/2;
- }
- }
- // Clip box margin top
- if(numPages > 1 && !spaceEvenly) {
- availVerticalSpace = bbHeight;
- if(this._topNav) {
- availVerticalSpace -= topNavHeight;
- }
- if(this._bottomNav) {
- availVerticalSpace -= bottomNavHeight;
- }
- clipBoxTop = (availVerticalSpace - (verticalSpacing + pageHeight))/2;
- }
- // Set the info
- this._bbHeight = bbHeight;
- this._bbWidth = bbWidth;
- this._cbWidth = cbWidth;
- this._clipBoxMarginLeft = clipBoxMarginLeft;
- this._clipBoxTop = clipBoxTop;
- this._colsPerPage = colsPerPage;
- this._rowsPerPage = rowsPerPage;
- this._imagesPerPage = imagesPerPage;
- this._numPages = numPages;
- this._pageHeight = pageHeight;
- this._pageWidth = pageWidth;
- this._leftNavWidth = leftNavWidth;
- this._rightNavWidth = rightNavWidth;
- this._horizontalSpacing = horizontalSpacing;
- this._verticalSpacing = verticalSpacing;
- this._activePageIndex = Math.floor(root.imageIndex/this._imagesPerPage);
- // Set back to the initial position.
- bb.setStyle('position', bbPosition);
- }
- }, {
- /**
- * Custom CSS class name for the widget.
- *
- * @property CSS_PREFIX
- * @type String
- * @protected
- * @static
- */
- CSS_PREFIX: 'fl-slideshow-thumbs',
- /**
- * Static property used to define the default attribute configuration of
- * the Widget.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- /**
- * The number of thumbnail columns. If set to auto, the number of
- * columns will be calculated based on the width of the parent node.
- *
- * @attribute columns
- * @type String or Number
- * @default auto
- */
- columns: {
- value: 'auto'
- },
- /**
- * The number of thumbnail rows. If set to auto, the number of
- * rows will be calculated based on the height of the parent node.
- *
- * @attribute rows
- * @type String or Number
- * @default auto
- */
- rows: {
- value: 'auto'
- },
- /**
- * The horizontal spacing between thumbs.
- *
- * @attribute horizontalSpacing
- * @type Number
- * @default 15
- */
- horizontalSpacing: {
- value: 15
- },
- /**
- * The vertical spacing between thumbs.
- *
- * @attribute verticalSpacing
- * @type Number
- * @default 15
- */
- verticalSpacing: {
- value: 15
- },
- /**
- * Whether to space the thumbs evenly within a page.
- *
- * @attribute spaceEvenly
- * @type Boolean
- * @default true
- */
- spaceEvenly: {
- value: true
- },
- /**
- * Whether to center single pages of thumbs.
- *
- * @attribute centerSinglePage
- * @type Boolean
- * @default false
- */
- centerSinglePage: {
- value: true
- },
- /**
- * Whether to pause the parent slideshow when a thumb is clicked.
- *
- * @attribute pauseOnClick
- * @type Boolean
- * @default false
- */
- pauseOnClick: {
- value: false
- },
- /**
- * The type of transition to use between pages.
- *
- * @attribute transition
- * @type String
- * @default slideHorizontal
- */
- transition: {
- value: 'slideHorizontal'
- },
- /**
- * The duration of the transition between pages.
- *
- * @attribute transitionDuration
- * @type Number
- * @default 0.8
- */
- transitionDuration: {
- value: 0.8
- },
- /**
- * The type of transition easing to use between pages.
- *
- * @attribute transitionEasing
- * @type String
- * @default ease-out
- */
- transitionEasing: {
- value: 'ease-out'
- },
- /**
- * The configuration object used to create new instances of
- * FL.SlideshowImage. See the API docs for {@link FL.SlideshowImage}
- * for a complete list of configuration attributes.
- *
- * @attribute imageConfig
- * @type Object
- * @default {}
- */
- imageConfig: {
- value: {
- crop: true,
- width: 50,
- height: 50
- }
- },
- /**
- * Whether to use the top nav or not.
- *
- * @attribute topNavEnabled
- * @type Boolean
- * @default false
- */
- topNavEnabled: {
- value: false
- },
- /**
- * An array of button names used to render the top nav buttons.
- *
- * @attribute topNavButtons
- * @type Array
- * @default prevPage, nextPage
- */
- topNavButtons: {
- value: ['prevPage', 'nextPage']
- },
- /**
- * Whether to use the right nav or not.
- *
- * @attribute rightNavEnabled
- * @type Boolean
- * @default true
- */
- rightNavEnabled: {
- value: true
- },
- /**
- * An array of button names used to render the right nav buttons.
- *
- * @attribute rightNavButtons
- * @type Array
- * @default nextPage
- */
- rightNavButtons: {
- value: ['nextPage']
- },
- /**
- * Whether to use the bottom nav or not.
- *
- * @attribute bottomNavEnabled
- * @type Boolean
- * @default false
- */
- bottomNavEnabled: {
- value: false
- },
- /**
- * An array of button names used to render the bottom nav buttons.
- *
- * @attribute bottomNavButtons
- * @type Array
- * @default prevPage, nextPage
- */
- bottomNavButtons:{
- value: ['prevPage', 'nextPage']
- },
- /**
- * Whether to use the left nav or not.
- *
- * @attribute leftNavEnabled
- * @type Boolean
- * @default true
- */
- leftNavEnabled: {
- value: true
- },
- /**
- * An array of button names used to render the left nav buttons.
- *
- * @attribute leftNavButtons
- * @type Array
- * @default prevPage
- */
- leftNavButtons:{
- value: ['prevPage']
- },
- /**
- * Whether to use touch gestures, when available,
- * to transition between pages or not.
- *
- * @attribute touchSupport
- * @type Boolean
- * @default false
- */
- touchSupport: {
- value: false
- }
- }
- });
- /**
- * Provides functionality for transitions between slideshow components.
- *
- * @namespace FL
- * @class SlideshowTransition
- * @constructor
- * @param config {Object} Configuration object
- * @extends Base
- */
- Y.namespace('FL').SlideshowTransition = Y.Base.create('fl-slideshow-transition', Y.Base, [], {
- /**
- * The transition function to use when run is called.
- *
- * @property _transitionFunction
- * @type String
- * @default _transitionFade
- * @protected
- */
- _transitionFunction: '_transitionFade',
- /**
- * The current transition type.
- *
- * @property _type
- * @type String
- * @default fade
- * @protected
- */
- _type: 'fade',
- /**
- * Parses the transition type and sets the _transitionFunction
- * used when run is called.
- *
- * @method initializer
- * @protected
- */
- initializer: function()
- {
- var type = this.get('type'),
- typeArray = [],
- types = Y.FL.SlideshowTransition.TYPES,
- slideshowImageTypes = Y.FL.SlideshowTransition.SLIDESHOW_IMAGE_TYPES,
- isSlideshowImageTransition = Y.Array.indexOf(slideshowImageTypes, type) > -1,
- isSlideshowImage = this._isSlideshowImage(),
- itemIn = this.get('itemIn'),
- itemOut = this.get('itemOut');
- // Check for random transitions.
- if(type.indexOf(',') > -1) {
- typeArray = type.split(',');
- typeArray.sort(function() { return 0.5 - Math.random(); });
- type = typeArray[0];
- }
- // Make sure we can run this transition, otherwise set a fallback.
- if(!isSlideshowImage && isSlideshowImageTransition) {
- type = 'fade';
- }
- else if(isSlideshowImage) {
- if((itemIn && itemIn.one('img') === null) || (itemOut && itemOut.one('img') === null)) {
- type = 'none';
- }
- else if(isSlideshowImageTransition) {
- if((Y.UA.gecko && Y.UA.gecko < 5) || Y.UA.opera > 0 || (Y.UA.ie > 0 && Y.UA.ie < 9)) {
- type = 'fade';
- }
- }
- }
- // Set the transition function and type.
- if(Y.FL.SlideshowTransition.TYPES[type]) {
- this._transitionFunction = types[type];
- this._type = type;
- }
- // Setup the items.
- this._setupItems();
- },
- /**
- * Fires the start event and calls the transition function.
- *
- * @method run
- */
- run: function()
- {
- /**
- * Fires when the transition starts.
- *
- * @event start
- */
- this.fire('start');
- this[this._transitionFunction].call(this);
- },
- /**
- * Set initial styles for the items.
- *
- * @method _setupItems
- * @protected
- */
- _setupItems: function()
- {
- var itemIn = this.get('itemIn'),
- itemOut = this.get('itemOut');
- if(itemIn) {
- itemIn.setStyle('zIndex', 2);
- itemIn.setStyle('opacity', 1);
- if(Y.FL.Utils.cssSupport('transform')) {
- itemIn.setStyle('transform', 'translate(0, 0)');
- }
- else {
- itemIn.setStyle('top', '0');
- itemIn.setStyle('left', '0');
- }
- }
- if(itemOut) {
- itemOut.setStyle('zIndex', 1);
- }
- },
- /**
- * Checks if the transition is being run
- * on an instance of FL.SlideshowImage or not.
- *
- * @method _isSlideshowImage
- * @protected
- */
- _isSlideshowImage: function()
- {
- var itemIn = this.get('itemIn'),
- itemOut = this.get('itemOut');
- if(itemIn && itemIn.hasClass('fl-slideshow-image')) {
- return true;
- }
- else if(itemOut && itemOut.hasClass('fl-slideshow-image')) {
- return true;
- }
- return false;
- },
- /**
- * Starts the transtion using the provided property objects.
- *
- * @method _transitionStart
- * @param propsIn {Object} The properties to animate in.
- * @param propsOut {Object} The properties to animate out.
- * @protected
- */
- _transitionStart: function(propsIn, propsOut)
- {
- var itemIn = this.get('itemIn'),
- itemOut = this.get('itemOut'),
- itemInCallback = Y.bind(this._transitionComplete, this),
- itemOutCallback = !itemIn ? itemInCallback : null,
- duration = this.get('duration'),
- easing = this.get('easing');
- if(itemIn) {
- propsIn.duration = propsIn.duration || duration;
- propsIn.easing = propsIn.easing || easing;
- itemIn.transition(propsIn);
- }
- if(itemOut) {
- propsOut.duration = propsOut.duration || duration;
- propsOut.easing = propsOut.easing || easing;
- itemOut.transition(propsOut);
- }
- if(itemInCallback) {
- Y.later(propsIn.duration * 1000 + 100, null, itemInCallback);
- }
- else if(itemOutCallback) {
- Y.later(propsOut.duration * 1000 + 100, null, itemOutCallback);
- }
- },
- /**
- * Clean up method called when the transition completes.
- *
- * @method _transitionComplete
- * @protected
- */
- _transitionComplete: function()
- {
- this._set('itemIn', null);
- this._set('itemOut', null);
- /**
- * Fires when the transition completes.
- *
- * @event complete
- */
- this.fire('complete');
- },
- /**
- * No transition.
- *
- * @method _transitionNone
- * @protected
- */
- _transitionNone: function()
- {
- var itemIn = this.get('itemIn'),
- itemOut = this.get('itemOut');
- if(itemIn) {
- itemIn.setStyle('opacity', 1);
- }
- if(itemOut) {
- itemOut.setStyle('opacity', 0);
- }
- this._transitionComplete();
- },
- /**
- * Fade transition.
- *
- * @method _transitionFade
- * @protected
- */
- _transitionFade: function()
- {
- var itemIn = this.get('itemIn');
- if(itemIn) {
- itemIn.setStyle('opacity', 0);
- }
- this._transitionStart({ opacity: 1 },{ opacity: 0 });
- },
- /**
- * Slide left transition.
- *
- * @method _transitionSlideLeft
- * @protected
- */
- _transitionSlideLeft: function()
- {
- if(Y.FL.Utils.cssSupport('transform')) {
- this._cssTransitionSlide({
- inStart: 'translate(100%, 0)',
- inEnd: 'translate(0, 0)',
- outStart: 'translate(0, 0)',
- outEnd: 'translate(-100%, 0)'
- });
- }
- else {
- this._jsTransitionSlide('left');
- }
- },
- /**
- * Slide right transition.
- *
- * @method _transitionSlideRight
- * @protected
- */
- _transitionSlideRight: function()
- {
- if(Y.FL.Utils.cssSupport('transform')) {
- this._cssTransitionSlide({
- inStart: 'translate(-100%, 0)',
- inEnd: 'translate(0, 0)',
- outStart: 'translate(0, 0)',
- outEnd: 'translate(100%, 0)'
- });
- }
- else {
- this._jsTransitionSlide('right');
- }
- },
- /**
- * Slide up transition.
- *
- * @method _transitionSlideUp
- * @protected
- */
- _transitionSlideUp: function()
- {
- if(Y.FL.Utils.cssSupport('transform')) {
- this._cssTransitionSlide({
- inStart: 'translate(0, 100%)',
- inEnd: 'translate(0, 0)',
- outStart: 'translate(0, 0)',
- outEnd: 'translate(0, -100%)'
- });
- }
- else {
- this._jsTransitionSlide('up');
- }
- },
- /**
- * Slide down transition.
- *
- * @method _transitionSlideDown
- * @protected
- */
- _transitionSlideDown: function()
- {
- if(Y.FL.Utils.cssSupport('transform')) {
- this._cssTransitionSlide({
- inStart: 'translate(0, -100%)',
- inEnd: 'translate(0, 0)',
- outStart: 'translate(0, 0)',
- outEnd: 'translate(0, 100%)'
- });
- }
- else {
- this._jsTransitionSlide('down');
- }
- },
- /**
- * JavaScript slide transition.
- *
- * @method _jsTransitionSlide
- * @protected
- */
- _jsTransitionSlide: function(direction)
- {
- var itemIn = this.get('itemIn'),
- itemOut = this.get('itemOut'),
- itemOutEnd = 0;
- // Item Out
- if(itemOut && direction == 'left') {
- itemOutEnd = -parseInt(itemOut.getStyle('width'), 10);
- }
- if(itemOut && direction == 'right') {
- itemOutEnd = parseInt(itemOut.getStyle('width'), 10);
- }
- if(itemOut && direction == 'up') {
- itemOutEnd = -parseInt(itemOut.getStyle('height'), 10);
- }
- if(itemOut && direction == 'down') {
- itemOutEnd = parseInt(itemOut.getStyle('height'), 10);
- }
- // Item In
- if(itemIn) {
- itemIn.setStyle('opacity', 1);
- }
- if(itemIn && direction == 'left') {
- itemIn.setStyle('left', itemIn.getStyle('width'));
- }
- if(itemIn && direction == 'right') {
- itemIn.setStyle('left', '-' + itemIn.getStyle('width'));
- }
- if(itemIn && direction == 'up') {
- itemIn.setStyle('top', itemIn.getStyle('height'));
- }
- if(itemIn && direction == 'down') {
- itemIn.setStyle('top', '-' + itemIn.getStyle('height'));
- }
- // Transition Start
- if(direction == 'left' || direction == 'right') {
- this._transitionStart({ left: 0 },{ left: itemOutEnd });
- }
- else {
- this._transitionStart({ top: 0 },{ top: itemOutEnd });
- }
- },
- /**
- * CSS slide transition.
- *
- * @method _cssTransitionSlide
- * @protected
- */
- _cssTransitionSlide: function(props)
- {
- var itemIn = this.get('itemIn'),
- itemOut = this.get('itemOut'),
- transformProp = Y.UA.chrome < 36 ? 'transform' : '-webkit-transform',
- inProps = {},
- outProps = {};
- inProps[transformProp] = props.inEnd;
- outProps[transformProp] = props.outEnd;
- if(itemIn) {
- itemIn.setStyle('transition', '');
- itemIn.setStyle('opacity', 1);
- itemIn.setStyle(transformProp, props.inStart);
- }
- if(itemOut) {
- itemOut.setStyle('transition', '');
- itemOut.setStyle(transformProp, props.outStart);
- }
- this._transitionStart(inProps, outProps);
- },
- /**
- * Bars and blinds transition.
- *
- * @method _transitionBars
- * @protected
- */
- _transitionBars: function()
- {
- // Hide the image until the slices have transitioned in.
- this.get('itemIn').one('.fl-slideshow-image-img').setStyle('opacity', 0);
- var numBars = this.get('bars'),
- slices = this._renderSlices(1, numBars),
- duration = this.get('duration'),
- delay = 0,
- increment = 100,
- last = false,
- i = 0,
- clone = null,
- props = {
- duration: duration,
- opacity: 1
- };
- // barsRandom
- if(this._type == 'barsRandom') {
- slices = this._randomizeSlices(slices);
- }
- // Transition the slices.
- for( ; i < slices.length; i++) {
- // Make a clone of our transition properties.
- clone = Y.clone(props);
- // blinds
- if(this._type == 'blinds') {
- clone.width = parseFloat(slices[i].getComputedStyle('width'), 10) + 'px';
- slices[i].setStyle('width', '0px');
- increment = 50;
- }
- // Run the transition.
- last = i == slices.length - 1 ? true : false;
- Y.later(delay, this, this._transitionSlice, [slices[i], clone, last]);
- delay += increment;
- }
- this._transitionSlicesFadeLast(delay);
- },
- /**
- * Boxes transition.
- *
- * @method _transitionBoxes
- * @protected
- */
- _transitionBoxes: function()
- {
- // Hide the image until the slices have transitioned in.
- this.get('itemIn').one('.fl-slideshow-image-img').setStyle('opacity', 0);
- var numCols = this.get('boxCols'),
- numRows = this.get('boxRows'),
- numSlices = numCols * numRows,
- multi = this._type != 'boxesRandom',
- slices = this._renderSlices(numRows, numCols, multi),
- duration = this.get('duration'),
- delay = 0,
- increment = 150,
- last = false,
- i = 0,
- row = 0,
- col = 0,
- startCol = -1,
- clone = null,
- props = {
- duration: duration,
- opacity: 1
- };
- // boxesRandom
- if(!multi) {
- slices = this._randomizeSlices(slices);
- increment = 30;
- for( ; i < slices.length; i++) {
- clone = Y.clone(props);
- last = i == slices.length - 1 ? true : false;
- Y.later(delay, this, this._transitionSlice, [slices[i], clone, last]);
- delay += increment;
- }
- }
- // boxes
- else {
- while(i < numSlices) {
- for(row = 0; row < numRows; row++) {
- if(row === 0) {
- startCol++;
- col = startCol;
- }
- if(col > -1 && col < numCols) {
- i++;
- clone = Y.clone(props);
- // boxesGrow
- if(this._type == 'boxesGrow') {
- clone.height = parseFloat(slices[row][col].getComputedStyle('height'), 10) + 'px';
- clone.width = parseFloat(slices[row][col].getComputedStyle('width'), 10) + 'px';
- slices[row][col].setStyle('height', '0px');
- slices[row][col].setStyle('width', '0px');
- increment = 50;
- }
- last = i == numSlices - 1 ? true : false;
- Y.later(delay, this, this._transitionSlice, [slices[row][col], clone, last]);
- }
- col--;
- }
- delay += increment;
- }
- }
- this._transitionSlicesFadeLast(delay);
- },
- /**
- * Renders the divs for slice based transitions.
- *
- * @method _renderSlices
- * @protected
- */
- _renderSlices: function(numRows, numCols, multidimensional)
- {
- var itemIn = this.get('itemIn'),
- itemHeight = parseFloat(itemIn.getComputedStyle('height'), 10),
- itemWidth = parseFloat(itemIn.getComputedStyle('width'), 10),
- img = itemIn.one('img'),
- imgSrc = img.get('src'),
- imgHeight = parseFloat(img.getComputedStyle('height'), 10),
- imgWidth = parseFloat(img.getComputedStyle('width'), 10),
- imgLeft = parseFloat(img.getComputedStyle('left'), 10),
- imgTop = parseFloat(img.getComputedStyle('top'), 10),
- col = 0,
- row = 0,
- sliceHeight = Math.round(itemHeight/numRows),
- sliceWidth = Math.round(itemWidth/numCols),
- slice = null,
- sliceImg = null,
- slices = [];
- for( ; row < numRows; row++) {
- if(typeof multidimensional !== 'undefined' && multidimensional) {
- slices[row] = [];
- }
- for(col = 0; col < numCols; col++) {
- slice = Y.Node.create('<div class="fl-slideshow-transition-slice"></div>');
- sliceImg = Y.Node.create('<img src="'+ imgSrc +'" />');
- slice.setStyles({
- left: (sliceWidth * col) + 'px',
- top: (sliceHeight * row) + 'px',
- width: col == numCols - 1 ? (itemWidth - (sliceWidth * col)) + 'px' : sliceWidth + 'px',
- height: row == numRows - 1 ? (itemHeight - (sliceHeight * row)) + 'px' : sliceHeight + 'px',
- opacity: 0
- });
- sliceImg.setStyles({
- height: imgHeight + 'px',
- width: imgWidth + 'px',
- top: imgTop - ((sliceHeight + (row * sliceHeight)) - sliceHeight) + 'px',
- left: imgLeft - ((sliceWidth + (col * sliceWidth)) - sliceWidth) + 'px'
- });
- slice.append(sliceImg);
- itemIn.append(slice);
- if(typeof multidimensional !== 'undefined' && multidimensional) {
- slices[row].push(slice);
- }
- else {
- slices.push(slice);
- }
- }
- }
- return slices;
- },
- /**
- * Fade the itemOut node.
- *
- * @method _transitionSlicesFadeLast
- * @protected
- */
- _transitionSlicesFadeLast: function(delay)
- {
- var itemOut = this.get('itemOut');
- if(itemOut && !itemOut.hasClass('fl-slideshow-image-cropped')) {
- itemOut.transition({
- duration: delay/1000 + this.get('duration'),
- opacity: 0
- });
- }
- },
- /**
- * Transitions a single slice.
- *
- * @method _transitionSlice
- * @protected
- */
- _transitionSlice: function(slice, props, last)
- {
- var callback = last ? Y.bind(this._transitionSlicesComplete, this) : null;
- slice.transition(props, callback);
- },
- /**
- * Complete callback for slice based transitions.
- *
- * @method _transitionSlicesComplete
- * @protected
- */
- _transitionSlicesComplete: function()
- {
- var itemIn = this.get('itemIn');
- itemIn.all('.fl-slideshow-transition-slice').remove();
- itemIn.one('.fl-slideshow-image-img').setStyle('opacity', 1);
- this._transitionComplete();
- },
- /**
- * Randomizes a slices array.
- *
- * @method _radomizeSlices
- * @protected
- */
- _randomizeSlices: function(slices)
- {
- var i = slices.length, j, temp;
- if(i === 0) {
- return;
- }
- while(--i) {
- j = Math.floor( Math.random() * ( i + 1 ) );
- temp = slices[i];
- slices[i] = slices[j];
- slices[j] = temp;
- }
- return slices;
- },
- _transitionKenBurns: function()
- {
- var kbDuration = this.get('kenBurnsDuration'),
- duration = this.get('duration'),
- itemIn = this.get('itemIn'),
- zoom = this.get('kenBurnsZoom');
- this._transitionFade();
- (new Y.FL.SlideshowKenBurns({
- duration: kbDuration + duration + 4,
- image: itemIn,
- zoom: zoom
- })).run();
- }
- }, {
- /**
- * Static property used to define the default attribute configuration of
- * the Widget.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- /**
- * The Node to transition in.
- *
- * @attribute itemIn
- * @type Node
- * @default null
- */
- itemIn: {
- value: null
- },
- /**
- * The Node to transition out.
- *
- * @attribute itemOut
- * @type Node
- * @default null
- */
- itemOut: {
- value: null
- },
- /**
- * The duration of the transition in seconds.
- *
- * @attribute duration
- * @type Number
- * @default 0.5
- */
- duration: {
- value: 0.5
- },
- /**
- * The type of easing to use.
- *
- * @attribute easing
- * @type String
- * @default ease-out
- */
- easing: {
- value: 'ease-out'
- },
- /**
- * The type of transition to use.
- *
- * @attribute type
- * @type String
- * @default fade
- */
- type: {
- value: 'fade'
- },
- /**
- * The number of bars to use for
- * transitions such as blinds.
- *
- * @attribute bars
- * @type Number
- * @default 15
- */
- bars: {
- value: 15
- },
- /**
- * The number of columns to use for
- * transitions such as boxes.
- *
- * @attribute boxCols
- * @type Number
- * @default 8
- */
- boxCols: {
- value: 8
- },
- /**
- * The number of rows to use for
- * transitions such as boxes.
- *
- * @attribute boxRows
- * @type Number
- * @default 4
- */
- boxRows: {
- value: 4
- },
- /**
- * The duration the ken burns effect will
- * last, measured in seconds.
- *
- * @attribute kenBurnsDuration
- * @type Number
- * @default 4
- */
- kenBurnsDuration: {
- value: 4
- },
- /**
- * The amount of zoom to use for the Ken Burns effect.
- *
- * @attribute kenBurnsZoom
- * @type Number
- * @default 1.2
- */
- kenBurnsZoom: {
- value: 1.2
- }
- },
- /**
- * The types of transitions and associated functions.
- *
- * @property TYPES
- * @type Object
- * @readOnly
- * @protected
- * @static
- */
- TYPES: {
- fade: '_transitionFade',
- none: '_transitionNone',
- slideLeft: '_transitionSlideLeft',
- slideRight: '_transitionSlideRight',
- slideUp: '_transitionSlideUp',
- slideDown: '_transitionSlideDown',
- blinds: '_transitionBars',
- bars: '_transitionBars',
- barsRandom: '_transitionBars',
- boxes: '_transitionBoxes',
- boxesRandom: '_transitionBoxes',
- boxesGrow: '_transitionBoxes',
- kenBurns: '_transitionKenBurns'
- },
- /**
- * The types of transitions that can only be
- * run on FL.SlideshowImage widgets.
- *
- * @property SLIDESHOW_IMAGE_TYPES
- * @type Object
- * @readOnly
- * @protected
- * @static
- */
- SLIDESHOW_IMAGE_TYPES: [
- 'blinds',
- 'bars',
- 'barsRandom',
- 'boxes',
- 'boxesRandom',
- 'boxesGrow',
- 'kenBurns'
- ]
- });
- /**
- * A highly configurable slideshow widget.
- *
- * @namespace FL
- * @class Slideshow
- * @constructor
- * @param config {Object} Configuration object
- * @extends FL.SlideshowBase
- */
- Y.namespace('FL').Slideshow = Y.Base.create('fl-slideshow', Y.FL.SlideshowBase, [], {
- /**
- * A FL.SlideshowFrame instance used for the main image.
- *
- * @property frame
- * @type FL.SlideshowFrame
- * @default null
- */
- frame: null,
- /**
- * A FL.SlideshowNav instance used for the main nav.
- *
- * @property nav
- * @type FL.SlideshowNav
- * @default null
- */
- nav: null,
- /**
- * A FL.SlideshowNav instance used for the image nav's left button.
- *
- * @property imageNavLeft
- * @type FL.SlideshowNav
- * @default null
- */
- imageNavLeft: null,
- /**
- * A FL.SlideshowNav instance used for the image nav's right button.
- *
- * @property imageNavRight
- * @type FL.SlideshowNav
- * @default null
- */
- imageNavRight: null,
- /**
- * A FL.SlideshowThumbs instance used for the thumbnail grid.
- *
- * @property thumbs
- * @type FL.SlideshowThumbs
- * @default null
- */
- thumbs: null,
- /**
- * A FL.SlideshowThumbs instance used for the vertical thumbnail grid.
- *
- * @property verticalThumbs
- * @type FL.SlideshowThumbs
- * @default null
- */
- verticalThumbs: null,
- /**
- * A FL.SlideshowCaption instance.
- *
- * @property caption
- * @type FL.SlideshowCaption
- * @default null
- */
- caption: null,
- /**
- * A FL.SlideshowSocial instance.
- *
- * @property social
- * @type FL.SlideshowSocial
- * @default null
- */
- social: null,
- /**
- * A FL.SlideshowImage instance used to preload
- * the next image.
- *
- * @property _nextImagePreloader
- * @type FL.SlideshowImage
- * @default null
- * @protected
- */
- _nextImagePreloader: null,
- /**
- * An object that holds the initial nav settings
- * when the mini nav has been enabled for a responsive layout.
- *
- * @property _initialNavSettings
- * @type Object
- * @default null
- * @protected
- */
- _initialNavSettings: null,
- /**
- * Initializes the preloaders, nav buttons, fullscreen and captions.
- *
- * @method initializer
- * @protected
- */
- initializer: function()
- {
- // Preloader config
- var imageConfig = {
- loadGroup: 'main-preload',
- crop: this.get('crop'),
- position: this.get('position'),
- protect: this.get('protect'),
- upsize: this.get('upsize')
- };
- // Preloader
- this._nextImagePreloader = new Y.FL.SlideshowImage(imageConfig);
- // Nav buttons not needed for touch
- if(this._isMobile()) {
- this._removeNavButton('prevPage');
- this._removeNavButton('nextPage');
- this._removeNavButton('fullscreen');
- }
- // Fullscreen
- if(this._hasNavButton('fullscreen')) {
- if(Y.FL.SlideshowFullscreen.OS_SUPPORT) {
- this.plug(Y.FL.SlideshowFullscreen);
- }
- else {
- this._removeNavButton('fullscreen');
- }
- }
- },
- /**
- * Calls the FL.SlideshowBase superclass renderUI method
- * and renders the child widgets.
- *
- * @method renderUI
- * @protected
- */
- renderUI: function()
- {
- Y.FL.Slideshow.superclass.renderUI.apply(this, arguments);
- this._renderFrame();
- this._renderVerticalThumbs();
- this._renderNavAndThumbs();
- this._renderImageNav();
- this._renderMouseNav();
- this._renderCaption();
- this._renderSocial();
- },
- /**
- * Calls the FL.SlideshowBase superclass bindUI method, binds
- * _resizeChildWidgets to fire after the resize method inherited
- * from FL.SlideshowBase, shows the loading image, binds overlay events
- * and binds an event to load an image into the frame.
- *
- * @method bindUI
- * @protected
- */
- bindUI: function()
- {
- var ssBB = this.get('boundingBox'),
- frameBB = this.frame.get('boundingBox'),
- navOverlay = this.get('navOverlay'),
- navType = this.get('navType'),
- nav = this._getNav(),
- clickAction = this.get('clickAction');
- // Call superclass bindUI
- Y.FL.Slideshow.superclass.bindUI.apply(this, arguments);
- // Resize child widgets after the superclass resize method.
- Y.Do.after(this._resizeChildWidgets, this, 'resize');
- // Loading events
- this.on('albumLoadStart', this._albumLoadStart, this);
- this.on('albumLoadComplete', this._albumLoadComplete, this);
- this.on('imageLoadComplete', this._loadFrame, this);
- // Loading image
- if(this.get('loadingImageAlwaysEnabled')) {
- this.frame.on('transitionInit', Y.bind(this._showLoadingImageWithDelay, this));
- this.frame.on('transitionStart', Y.bind(this._hideLoadingImage, this));
- }
- // Overlay events
- if(this.get('overlayHideOnMousemove')) {
- if(nav && navOverlay) {
- this.frame.once('transitionComplete', nav.slideshowOverlay.hideWithTimer, nav.slideshowOverlay);
- ssBB.on('mousemove', Y.bind(this._toggleNav, this));
- }
- if(navType == 'buttons' || navType == 'thumbs' || navType == 'custom') {
- ssBB.on('mouseenter', Y.bind(this._checkOverlaysOnMouseenter, this));
- ssBB.on('mouseleave', Y.bind(this._hideAllOverlays, this));
- }
- }
- ssBB.delegate('click', Y.bind(this._overlayCloseClick, this), '.fl-slideshow-overlay-close');
- // Click action
- if(clickAction == 'gallery' || clickAction == 'url') {
- frameBB.delegate('click', Y.bind(this._frameClick, this), '.fl-slideshow-image-img');
- }
- },
- /**
- * Calls the FL.SlideshowBase superclass syncUI method
- * and makes the bounding box unselectable.
- *
- * @method syncUI
- * @protected
- */
- syncUI: function()
- {
- var bb = this.get('boundingBox');
- Y.FL.Slideshow.superclass.syncUI.apply(this, arguments);
- bb._node.onselectstart = function() { return false; };
- bb._node.unselectable = "on";
- bb._node.style.MozUserSelect = "none";
- if(this.get('clickAction') != 'none') {
- this.frame.get('boundingBox').addClass('fl-click-action-enabled');
- }
- },
- /**
- * Checks to see if the current device is mobile.
- *
- * @since 1.9.3
- * @access private
- * @method _isMobile
- * @return {Boolean}
- */
- _isMobile: function()
- {
- return /Mobile|Android|Silk\/|Kindle|BlackBerry|Opera Mini|Opera Mobi|webOS/i.test( navigator.userAgent );
- },
- /**
- * Unload all slideshow images and pause
- * the slideshow.
- *
- * @method unload
- */
- unload: function()
- {
- this.pause();
- this.frame.unload();
- if(this.thumbs !== null) {
- this.thumbs.unload();
- }
- },
- /**
- * @method _albumLoadStart
- * @protected
- */
- _albumLoadStart: function()
- {
- this._showLoadingImage();
- },
- /**
- * @method _albumLoadComplete
- * @protected
- */
- _albumLoadComplete: function()
- {
- this.frame.once('transitionStart', Y.bind(this._hideLoadingImage, this));
- },
- /**
- * Resizes all enabled child widgets.
- *
- * @method _resizeChildWidgets
- * @protected
- */
- _resizeChildWidgets: function()
- {
- var bb = this.get('boundingBox'),
- cb = this.get('contentBox'),
- imageNavEnabled = this.get('imageNavEnabled');
- this._renderNavAndThumbs();
- if(this.get('verticalThumbsOverlay')) {
- this._resizeFrame(cb.get('offsetWidth'), bb.get('offsetHeight'));
- this._resizeVerticalThumbs();
- }
- else {
- this._resizeVerticalThumbs();
- this._resizeFrame(cb.get('offsetWidth'), bb.get('offsetHeight'));
- }
- if(imageNavEnabled) {
- this._positionImageNav();
- }
- this._positionLoadingImage();
- },
- /**
- * @method _renderVerticalThumbs
- * @protected
- */
- _renderVerticalThumbs: function()
- {
- var threshold = this.get('responsiveThreshold'),
- ssBB = this.get('boundingBox'),
- bbWidth = ssBB.get('offsetWidth'),
- vtBB;
- if(this.get('verticalThumbsEnabled') && bbWidth > threshold) {
- this.verticalThumbs = new Y.FL.SlideshowThumbs(this._getVerticalThumbsConfig());
- this.add(this.verticalThumbs);
- this.verticalThumbs.render(ssBB);
- vtBB = this.verticalThumbs.get('boundingBox');
- vtBB.addClass('fl-slideshow-vertical-thumbs');
- vtBB.setStyle(this.get('verticalThumbsPosition'), 0);
- ssBB.append(vtBB);
- if(this.get('verticalThumbsOverlay')) {
- this.verticalThumbs.plug(Y.FL.SlideshowOverlay, {
- hideDelay: this.get('overlayHideDelay'),
- hideStyle: 'left'
- });
- this.frame.get('boundingBox').append(vtBB);
- this.verticalThumbs.resize();
- }
- else {
- this.verticalThumbs.resize();
- this._adjustContentForVerticalThumbs();
- }
- this._bindVerticalThumbs();
- }
- },
- /**
- * Prepares and returns the vertical thumbs config object.
- *
- * @method _getVerticalThumbsConfig
- * @protected
- * @returns Object
- */
- _getVerticalThumbsConfig: function()
- {
- var attrs = this.getAttrs(),
- config = {
- columns: attrs.verticalThumbsColumns,
- rows: 'auto',
- centerSinglePage: false,
- horizontalSpacing: attrs.verticalThumbsHorizontalSpacing,
- verticalSpacing: attrs.verticalThumbsVerticalSpacing,
- spaceEvenly: attrs.verticalThumbsSpaceEvenly,
- rightNavEnabled: false,
- leftNavEnabled: false,
- topNavEnabled: attrs.verticalThumbsTopNavEnabled,
- topNavButtons: attrs.verticalThumbsTopNavButtons,
- bottomNavEnabled: attrs.verticalThumbsBottomNavEnabled,
- bottomNavButtons: attrs.verticalThumbsBottomNavButtons,
- pauseOnClick: attrs.verticalThumbsPauseOnClick,
- transition: attrs.verticalThumbsTransition,
- transitionDirection: attrs.verticalThumbsTransitionDirection,
- transitionEasing: attrs.verticalThumbsTransitionEasing,
- touchSupport: true,
- imageConfig: {
- crop: attrs.verticalThumbsImageCrop,
- width: attrs.verticalThumbsImageWidth,
- height: attrs.verticalThumbsImageHeight
- }
- };
- return config;
- },
- _bindVerticalThumbs: function()
- {
- var ssBB = this.get('boundingBox'),
- hideOnMouse = this.get('overlayHideOnMousemove'),
- vtOverlay = this.get('verticalThumbsOverlay'),
- vt = this.verticalThumbs;
- if(vt && hideOnMouse && vtOverlay) {
- this.frame.once('transitionComplete', vt.slideshowOverlay.hideWithTimer, vt.slideshowOverlay);
- ssBB.on('mousemove', Y.bind(this._toggleVerticalThumbs, this));
- ssBB.on('mouseenter', Y.bind(this._toggleVerticalThumbs, this));
- }
- },
- /**
- * Resizes the vertical thumbs.
- *
- * @method _resizeVerticalThumbs
- * @protected
- */
- _resizeVerticalThumbs: function()
- {
- var vtEnabled = this.get('verticalThumbsEnabled'),
- vtOverlay,
- threshold,
- ssBB,
- bbWidth,
- navOverlay,
- navType,
- nav,
- navBB;
- if(vtEnabled) {
- vtOverlay = this.get('verticalThumbsOverlay');
- threshold = this.get('responsiveThreshold');
- ssBB = this.get('boundingBox');
- bbWidth = ssBB.get('offsetWidth');
- navOverlay = this.get('navOverlay');
- navType = this.get('navType');
- nav = this._getNav();
- if(this.verticalThumbs && bbWidth > threshold) {
- this.verticalThumbs.get('boundingBox').setStyle('display', 'block');
- this.verticalThumbs.resize();
- if(!vtOverlay) {
- this._adjustContentForVerticalThumbs();
- }
- else if(nav && navOverlay) {
- navBB = nav.get('boundingBox');
- if(navType == 'thumbs') {
- this._adjustOverlayForVerticalThumbs(navBB, true);
- this.thumbs.resize();
- }
- else {
- this._adjustOverlayForVerticalThumbs(navBB);
- }
- }
- }
- else if(!this.verticalThumbs && bbWidth > threshold) {
- this._renderVerticalThumbs();
- }
- else if(this.verticalThumbs && bbWidth <= threshold) {
- this.verticalThumbs.get('boundingBox').setStyle('display', 'none');
- if(!vtOverlay) {
- this.get('contentBox').setStyles({
- left: 'auto',
- position: 'relative',
- right: 'auto',
- width: 'auto'
- });
- }
- }
- }
- },
- /**
- * Toggles the visibility of the vertical thumbs.
- *
- * @method _toggleVerticalThumbs
- * @protected
- */
- _toggleVerticalThumbs: function()
- {
- if(this.verticalThumbs) {
- if(this.verticalThumbs.slideshowOverlay._visible) {
- this.verticalThumbs.slideshowOverlay.hideWithTimer();
- }
- else {
- this.verticalThumbs.slideshowOverlay.show();
- }
- }
- },
- /**
- * Adjusts the content position and width
- * for the vertical thumbs.
- *
- * @method _adjustContentForVerticalThumbs
- * @protected
- */
- _adjustContentForVerticalThumbs: function()
- {
- var ssBB = this.get('boundingBox'),
- vtBB = this.verticalThumbs.get('boundingBox'),
- vtPos = this.get('verticalThumbsPosition'),
- ssCB = this.get('contentBox'),
- cbPos = vtPos == 'left' ? 'right' : 'left',
- cbWidth = ssBB.get('offsetWidth') - vtBB.get('offsetWidth');
- ssCB.setStyle('position', 'absolute');
- ssCB.setStyle(cbPos, 0);
- ssCB.setStyle('width', cbWidth);
- },
- /**
- * Adjusts an overlay's position for the vertical
- * thumbs when they are overlaid as well.
- *
- * @method _adjustOverlayForVerticalThumbs
- * @protected
- */
- _adjustOverlayForVerticalThumbs: function(node, useMargin)
- {
- var vtEnabled = this.get('verticalThumbsEnabled'),
- vtOverlay = this.get('verticalThumbsOverlay'),
- vtBB = null,
- vtPos = null,
- margin = typeof useMargin === 'undefined' ? '' : 'margin-',
- vtWidth = 0;
- if(this.verticalThumbs && vtEnabled && vtOverlay) {
- vtBB = this.verticalThumbs.get('boundingBox');
- vtWidth = vtBB.get('offsetWidth');
- vtPos = this.get('verticalThumbsPosition');
- if(vtPos == 'left') {
- node.setStyle(margin + 'left', vtWidth + 'px');
- }
- else {
- node.setStyle(margin + 'right', vtWidth + 'px');
- }
- }
- },
- /**
- * Creates and renders a new instance of FL.SlideshowFrame
- * used for the main image.
- *
- * @method _renderFrame
- * @protected
- */
- _renderFrame: function()
- {
- this.frame = new Y.FL.SlideshowFrame({
- imageConfig: {
- loadGroup: 'main',
- loadPriority: true,
- crop: this.get('crop'),
- cropHorizontalsOnly: this.get('cropHorizontalsOnly'),
- position: this.get('position'),
- protect: this.get('protect'),
- upsize: this.get('upsize'),
- showVideoButton: this.get('navOverlay')
- },
- touchSupport: this.get('touchSupport')
- });
- this.add(this.frame);
- this.frame.render(this.get('contentBox'));
- this.frame.get('boundingBox').addClass('fl-slideshow-main-image');
- this._setPlayingTimerEvent(this.frame, 'transitionComplete');
- this._loadingImageContainer = this.frame.get('contentBox');
- },
- /**
- * Resizes the frame used for the main image.
- *
- * @method _resizeMainImage
- * @param width {Number} The width to resize to.
- * @param height {Number} The height to resize to.
- * @protected
- */
- _resizeFrame: function(width, height)
- {
- var navOverlay = this.get('navOverlay'),
- nav = this._getNav();
- if(nav && !navOverlay) {
- height -= parseInt(nav.get('boundingBox').getComputedStyle('height'), 10);
- }
- this.frame.resize(width, height);
- },
- /**
- * Called when the imageLoadComplete event fires.
- * Loads an image into the frame and preloads the next image.
- *
- * @method _loadFrame
- * @param e {Object} Event object containing the image info.
- * @protected
- */
- _loadFrame: function(e)
- {
- var activeIndex = this.imageInfo.index,
- images = this.albumInfo.images,
- nextIndex = activeIndex + 1 >= images.length ? 0 : activeIndex + 1,
- width = this.frame.get('width'),
- height = this.frame.get('height');
- // Load the frame.
- this.frame.load(e.imageInfo);
- // Remove main preload images from the load queue.
- Y.FL.SlideshowImageLoader.removeGroup('main-preload');
- // Preload the next image.
- this._nextImagePreloader.preload(images[nextIndex], width, height);
- },
- /**
- * Fired when the frame img tag is clicked.
- *
- * @method _frameClick
- * @protected
- */
- _frameClick: function()
- {
- var clickAction = this.get('clickAction'),
- clickActionUrl = this.get('clickActionUrl');
- if(clickAction == 'url') {
- window.location.href = clickActionUrl;
- }
- else if(clickAction == 'gallery') {
- window.location.href = this.imageInfo.link;
- }
- },
- /**
- * Sets attributes to display a compact nav
- * for responsive layouts.
- *
- * @method _initMiniNav
- * @protected
- */
- _initMiniNav: function()
- {
- var buttons = [];
- if(this._hasNavButton('prev')) {
- buttons.push('prev');
- }
- if(this._hasNavButton('thumbs') || this.get('navType') == 'thumbs') {
- buttons.push('thumbs');
- }
- if(this._hasNavButton('caption')) {
- buttons.push('caption');
- }
- if(this._hasNavButton('social')) {
- buttons.push('social');
- }
- if(this._hasNavButton('buy')) {
- buttons.push('buy');
- }
- if(this._hasNavButton('play')) {
- buttons.push('play');
- }
- if(this._hasNavButton('fullscreen') && !('ontouchstart' in window)) {
- buttons.push('fullscreen');
- }
- if(this._hasNavButton('next')) {
- buttons.push('next');
- }
- this._initialNavSettings = {
- buttons: this.get('navButtons'),
- buttonsLeft: this.get('navButtonsLeft'),
- buttonsRight: this.get('navButtonsRight'),
- type: this.get('navType')
- };
- this._set('navButtons', buttons);
- this._set('navButtonsLeft', []);
- this._set('navButtonsRight', []);
- this._set('navType', 'buttons');
- },
- /**
- * Renders the nav and thumbs layout based on the
- * current window size.
- *
- * @method _renderNavAndThumbs
- * @protected
- */
- _renderNavAndThumbs: function()
- {
- var navType = this.get('navType'),
- renderNav = false,
- bbWidth,
- threshold;
- if(navType == 'buttons' || navType == 'thumbs') {
- bbWidth = this.get('boundingBox').get('offsetWidth');
- threshold = this.get('responsiveThreshold');
- if(bbWidth <= threshold && this._initialNavSettings === null) {
- this._initMiniNav();
- renderNav = true;
- }
- else if(bbWidth > threshold && this._initialNavSettings !== null) {
- this._set('navButtons', this._initialNavSettings.buttons);
- this._set('navButtonsLeft', this._initialNavSettings.buttonsLeft);
- this._set('navButtonsRight', this._initialNavSettings.buttonsRight);
- this._set('navType', this._initialNavSettings.type);
- this._initialNavSettings = null;
- renderNav = true;
- }
- // Button nav
- if(renderNav || this.nav === null) {
- this._renderNav();
- }
- // Thumbs nav
- if(renderNav || this.thumbs === null) {
- this._renderThumbs();
- }
- else if(this._thumbsEnabled()) {
- this._resizeThumbs();
- }
- // Caption
- if(renderNav && this.caption !== null) {
- this._syncCaption();
- }
- // Social
- if(renderNav && this.social !== null) {
- this._syncSocial();
- }
- }
- },
- /**
- * Creates and renders a new instance of FL.SlideshowNav
- * used for the main nav.
- *
- * @method _renderNav
- * @protected
- */
- _renderNav: function()
- {
- var frameBB = this.frame.get('boundingBox'),
- navBB = null,
- navOverlay = this.get('navOverlay'),
- navPosition = this.get('navPosition');
- // Destroy old instances
- this._destroyNav();
- // Create a new instance
- if(this.get('navType') == 'buttons') {
- // Create the nav
- this.nav = new Y.FL.SlideshowNav({
- buttons: this.get('navButtons'),
- buttonsLeft: this.get('navButtonsLeft'),
- buttonsRight: this.get('navButtonsRight')
- });
- // Add to widget parent and render
- this.add(this.nav);
- this.nav.render(this.get('contentBox'));
- navBB = this.nav.get('boundingBox');
- // Plug overlay?
- if(navOverlay) {
- this.nav.plug(Y.FL.SlideshowOverlay, {
- hideDelay: this.get('overlayHideDelay')
- });
- navBB.setStyle('position', 'absolute');
- navBB.setStyle(navPosition, '0px');
- }
- // Insert
- if(navPosition == 'top') {
- frameBB.insert(navBB, 'before');
- }
- else {
- frameBB.insert(navBB, 'after');
- }
- // CSS class name
- navBB.addClass('fl-slideshow-main-nav');
- }
- },
- /**
- * Destroy the current nav instance.
- *
- * @method _destroyNav
- * @protected
- */
- _destroyNav: function()
- {
- if(this.nav !== null) {
- if(this.nav.slideshowOverlay) {
- this.nav.slideshowOverlay.destroy();
- }
- this.nav.get('boundingBox').remove();
- this.remove(this.nav);
- try { this.nav.destroy(true); } catch(e) {}
- this.nav = null;
- }
- },
- /**
- * Returns the nav object or null if navType is
- * set to none or custom.
- *
- * @method _getNav
- * @protected
- */
- _getNav: function()
- {
- var navType = this.get('navType');
- if(navType == 'buttons') {
- return this.nav;
- }
- else if(navType == 'thumbs') {
- return this.thumbs;
- }
- else {
- return null;
- }
- },
- /**
- * Toggles the visibility of the nav or thumbs nav
- * if navOverlay is set to true.
- *
- * @method _toggleNav
- * @protected
- */
- _toggleNav: function()
- {
- var nav = this._getNav();
- if(nav.slideshowOverlay) {
- if(nav.slideshowOverlay._visible) {
- nav.slideshowOverlay.hideWithTimer();
- }
- else {
- nav.slideshowOverlay.show();
- }
- }
- },
- /**
- * Creates and renders two instances of FL.SlideshowNav for the
- * prev and next button that will be overlaid on the main image.
- *
- * @method _renderImageNav
- * @protected
- */
- _renderImageNav: function()
- {
- var ssBB;
- if(this.get('imageNavEnabled')) {
- if(this._isMobile()) {
- this._set('imageNavEnabled', false);
- }
- else {
- ssBB = this.get('boundingBox');
- this.imageNavLeft = new Y.FL.SlideshowNav({
- buttons: ['prev'],
- useFontIcons: false
- });
- this.imageNavRight = new Y.FL.SlideshowNav({
- buttons: ['next'],
- useFontIcons: false
- });
- this.add(this.imageNavLeft);
- this.add(this.imageNavRight);
- this.imageNavLeft.render(this.frame.get('boundingBox'));
- this.imageNavRight.render(this.frame.get('boundingBox'));
- this.imageNavLeft.plug(Y.FL.SlideshowOverlay, { hideDelay: this.get('overlayHideDelay') });
- this.imageNavRight.plug(Y.FL.SlideshowOverlay, { hideDelay: this.get('overlayHideDelay') });
- if(this.get('overlayHideOnMousemove')) {
- this.frame.once('transitionComplete', this.imageNavLeft.slideshowOverlay.hideWithTimer, this.imageNavLeft.slideshowOverlay);
- this.frame.once('transitionComplete', this.imageNavRight.slideshowOverlay.hideWithTimer, this.imageNavRight.slideshowOverlay);
- ssBB.on('mousemove', Y.bind(this._toggleImageNav, this));
- ssBB.on('mouseenter', Y.bind(this._toggleImageNav, this));
- }
- this.imageNavLeft.get('boundingBox').addClass('fl-slideshow-image-nav-left');
- this.imageNavRight.get('boundingBox').addClass('fl-slideshow-image-nav-right');
- }
- }
- },
- /**
- * @method _positionImageNav
- * @protected
- */
- _positionImageNav: function()
- {
- var leftBB = this.imageNavLeft.get('boundingBox'),
- rightBB = this.imageNavRight.get('boundingBox'),
- imageNavHeight = leftBB.get('offsetHeight'),
- frameHeight = this.frame.get('boundingBox').get('offsetHeight'),
- top = frameHeight/2 - imageNavHeight/2,
- styles = {
- top: top + 'px',
- display: 'block'
- };
- leftBB.setStyles(styles);
- rightBB.setStyles(styles);
- this._adjustOverlayForVerticalThumbs(leftBB);
- this._adjustOverlayForVerticalThumbs(rightBB);
- },
- /**
- * Toggles the visibility of the image nav buttons.
- *
- * @method _toggleImageNav
- * @protected
- */
- _toggleImageNav: function()
- {
- if(this.imageNavLeft.slideshowOverlay._visible) {
- this.imageNavLeft.slideshowOverlay.hideWithTimer();
- }
- else {
- this.imageNavLeft.slideshowOverlay.show();
- }
- if(this.imageNavRight.slideshowOverlay._visible) {
- this.imageNavRight.slideshowOverlay.hideWithTimer();
- }
- else {
- this.imageNavRight.slideshowOverlay.show();
- }
- },
- /**
- * @method _renderMouseNav
- * @protected
- */
- _renderMouseNav: function()
- {
- if(this.get('mouseNavEnabled') && !('ontouchstart' in window) && !window.navigator.msPointerEnabled) {
- this.plug(Y.FL.SlideshowMouseNav, {
- trigger: this.frame.get('boundingBox')
- });
- }
- },
- /**
- * Checks whether the thumbs are enabled.
- *
- * @method _thumbsEnabled
- * @protected
- * @returns Boolean
- */
- _thumbsEnabled: function()
- {
- var navType = this.get('navType');
- if(navType == 'thumbs') {
- return true;
- }
- if((navType == 'buttons' || navType == 'custom') && this._hasNavButton('thumbs')) {
- return true;
- }
- else {
- return false;
- }
- },
- /**
- * Creates and renders a new instance of FL.SlideshowThumbs.
- *
- * @method _renderThumbs
- * @protected
- */
- _renderThumbs: function()
- {
- var frameBB, navOverlay, navPosition, navType;
- // Destroy old instances
- this._destroyThumbs();
- // Create a new instance
- if(this._thumbsEnabled()) {
- frameBB = this.frame.get('boundingBox');
- navOverlay = this.get('navOverlay');
- navPosition = this.get('navPosition');
- navType = this.get('navType');
- // Create the thumbs
- this.thumbs = new Y.FL.SlideshowThumbs(this._getThumbsConfig());
- // This breaks sometimes on SM Next. Try/catch bandaid for now.
- try { this.add(this.thumbs); } catch(e) {}
- // Overlay setup
- if(navType == 'buttons' || navType == 'custom') {
- this.thumbs.plug(Y.FL.SlideshowOverlay, {
- hideDelay: this.get('overlayHideDelay'),
- hideStyle: 'left',
- visible: false
- });
- }
- else if(navType == 'thumbs' && navOverlay) {
- this.thumbs.plug(Y.FL.SlideshowOverlay, {
- hideDelay: this.get('overlayHideDelay'),
- hideStyle: 'left'
- });
- }
- // Insert
- this.thumbs.render(this.get('contentBox'));
- if(navPosition == 'top') {
- frameBB.insert(this.thumbs.get('boundingBox'), 'before');
- }
- else {
- frameBB.insert(this.thumbs.get('boundingBox'), 'after');
- }
- // Hide overlay thumbs on click
- if(this.get('thumbsHideOnClick') && navType != 'thumbs') {
- this.thumbs.on('imageClick', Y.bind(this._hideThumbsOnImageClick, this));
- }
- this._syncThumbs();
- }
- },
- /**
- * Destroy the current thumbs instance.
- *
- * @method _destroyThumbs
- * @protected
- */
- _destroyThumbs: function()
- {
- if(this.thumbs !== null) {
- if(this.thumbs.slideshowOverlay) {
- this.thumbs.slideshowOverlay.destroy();
- }
- this.thumbs.get('boundingBox').remove();
- this.remove(this.thumbs);
- try { this.thumbs.destroy(true); } catch(e) {}
- this.thumbs = null;
- }
- },
- /**
- * Syncs the thumbs UI styles.
- *
- * @method _syncThumbs
- * @protected
- */
- _syncThumbs: function()
- {
- var thumbsBB = this.thumbs.get('boundingBox'),
- navOverlay = this.get('navOverlay'),
- navPosition = this.get('navPosition'),
- navType = this.get('navType'),
- paddingType = 'padding' + navPosition.charAt(0).toUpperCase() + navPosition.slice(1),
- navHeight = 0;
- if(navType == 'buttons') {
- navHeight = parseInt(this.nav.get('boundingBox').getComputedStyle('height'), 10);
- thumbsBB.setStyle('position', 'absolute');
- if(navOverlay) {
- thumbsBB.setStyle(paddingType, navHeight + 'px');
- thumbsBB.setStyle(navPosition, '0px');
- }
- else {
- thumbsBB.setStyle(navPosition, navHeight + 'px');
- }
- }
- if(navType == 'custom' || (navType == 'thumbs' && navOverlay)) {
- thumbsBB.setStyle('position', 'absolute');
- thumbsBB.setStyle(navPosition, '0px');
- }
- this.thumbs.resize();
- },
- /**
- * Prepares and returns the thumbs config object.
- *
- * @method _getThumbsConfig
- * @protected
- * @returns Object
- */
- _getThumbsConfig: function()
- {
- var attrs = this.getAttrs(),
- navType = this.get('navType'),
- imageConfig = {
- crop: attrs.thumbsImageCrop,
- width: attrs.thumbsImageWidth,
- height: attrs.thumbsImageHeight
- },
- config = {
- columns: 'auto',
- rows: 1,
- horizontalSpacing: attrs.thumbsHorizontalSpacing,
- verticalSpacing: attrs.thumbsVerticalSpacing,
- spaceEvenly: attrs.thumbsSpaceEvenly,
- centerSinglePage: attrs.thumbsCenterSinglePage,
- pauseOnClick: attrs.thumbsPauseOnClick,
- transition: attrs.thumbsTransition,
- transitionDirection: attrs.thumbsTransitionDirection,
- transitionEasing: attrs.thumbsTransitionEasing,
- leftNavButtons: attrs.navButtonsLeft,
- rightNavButtons: attrs.navButtonsRight,
- imageConfig: imageConfig,
- touchSupport: true
- };
- if(navType == 'buttons' || navType == 'custom') {
- if('ontouchstart' in window) {
- config.leftNavEnabled = false;
- config.rightNavEnabled = false;
- }
- else {
- config.centerSinglePage = false;
- config.leftNavButtons = ['prevPage'];
- config.rightNavButtons = ['nextPage'];
- }
- }
- return config;
- },
- /**
- * Resizes the thumbs.
- *
- * @method _resizeThumbs
- * @protected
- */
- _resizeThumbs: function()
- {
- if(this.thumbs) {
- this.thumbs.resize();
- }
- },
- /**
- * Shows or hides the thumbs.
- *
- * @method _toggleThumbs
- * @protected
- */
- _toggleThumbs: function()
- {
- this._toggleOverlay(this.thumbs.slideshowOverlay);
- },
- /**
- * Hides the thumbs when a thumb image is clicked.
- *
- * @method _hideThumbsOnImageClick
- * @protected
- */
- _hideThumbsOnImageClick: function()
- {
- if(this.thumbs.slideshowOverlay) {
- this.thumbs.slideshowOverlay._focus = false;
- this.thumbs.slideshowOverlay.enable();
- this.thumbs.slideshowOverlay.hide();
- if(this.nav && this.nav.slideshowOverlay) {
- this.nav.slideshowOverlay.enable();
- }
- }
- },
- /**
- * Creates and renders a new instance of FL.SlideshowCaption.
- *
- * @method _renderCaption
- * @protected
- */
- _renderCaption: function()
- {
- if(this._hasNavButton('caption')) {
- this.caption = new Y.FL.SlideshowCaption({
- lessLinkText: this.get('captionLessLinkText'),
- moreLinkText: this.get('captionMoreLinkText'),
- textLength: this.get('captionTextLength'),
- stripTags: this.get('captionStripTags')
- });
- this.add(this.caption);
- this.caption.plug(Y.FL.SlideshowOverlay, {
- hideDelay: this.get('overlayHideDelay'),
- visible: false,
- closeButton: true
- });
- this._syncCaption();
- }
- },
- /**
- * Syncs the caption UI styles.
- *
- * @method _syncCaption
- * @protected
- */
- _syncCaption: function()
- {
- var captionBB = this.caption.get('boundingBox'),
- navOverlay = this.get('navOverlay'),
- navPosition = this.get('navPosition'),
- nav = this._getNav(),
- paddingType = 'padding' + navPosition.charAt(0).toUpperCase() + navPosition.slice(1),
- navHeight = 0;
- captionBB.setStyle('position', 'absolute');
- if(nav) {
- navHeight = parseInt(nav.get('boundingBox').getComputedStyle('height'), 10);
- }
- if(nav && navOverlay) {
- captionBB.setStyle(paddingType, navHeight + 'px');
- captionBB.setStyle(navPosition, '0px');
- }
- else {
- captionBB.setStyle(navPosition, navHeight + 'px');
- }
- },
- /**
- * Shows or hides the caption.
- *
- * @method _toggleCaption
- * @protected
- */
- _toggleCaption: function()
- {
- this._toggleOverlay(this.caption.slideshowOverlay);
- },
- /**
- * Creates and renders a new instance of FL.SlideshowSocial.
- *
- * @method _renderSocial
- * @protected
- */
- _renderSocial: function()
- {
- if(this._hasNavButton('social')) {
- this.social = new Y.FL.SlideshowSocial();
- this.add(this.social);
- this.social.plug(Y.FL.SlideshowOverlay, {
- hideDelay: this.get('overlayHideDelay'),
- visible: false,
- closeButton: true
- });
- this._syncSocial();
- }
- },
- /**
- * Syncs the social UI styles.
- *
- * @method _syncSocial
- * @protected
- */
- _syncSocial: function()
- {
- var socialBB = this.social.get('boundingBox'),
- navOverlay = this.get('navOverlay'),
- navPosition = this.get('navPosition'),
- nav = this._getNav(),
- paddingType = 'padding' + navPosition.charAt(0).toUpperCase() + navPosition.slice(1),
- navHeight = 0;
- socialBB.setStyle('position', 'absolute');
- if(nav) {
- navHeight = parseInt(nav.get('boundingBox').getComputedStyle('height'), 10);
- }
- if(nav && navOverlay) {
- socialBB.setStyle(paddingType, navHeight + 'px');
- socialBB.setStyle(navPosition, '0px');
- }
- else {
- socialBB.setStyle(navPosition, navHeight + 'px');
- }
- },
- /**
- * Shows or hides the social buttons.
- *
- * @method _toggleSocial
- * @protected
- */
- _toggleSocial: function()
- {
- this._toggleOverlay(this.social.slideshowOverlay);
- },
- /**
- * Shows or hides an overlaid widget based
- * on its current visibility.
- *
- * @method _toggleOverlay
- * @param overlay {Object} The overlay to toggle.
- * @protected
- */
- _toggleOverlay: function(overlay)
- {
- var navType = this.get('navType'),
- nav = this._getNav();
- if(overlay._visible) {
- if(nav && nav.slideshowOverlay) {
- nav.slideshowOverlay.enable();
- }
- overlay.enable();
- overlay.hide();
- }
- else {
- if(nav && nav.slideshowOverlay) {
- nav.slideshowOverlay.disable();
- }
- overlay.show();
- overlay.disable();
- }
- if(this.thumbs && navType != 'thumbs' && this.thumbs.slideshowOverlay !== overlay) {
- this.thumbs.slideshowOverlay.enable();
- this.thumbs.slideshowOverlay.hide();
- }
- if(this.caption && this.caption.slideshowOverlay !== overlay) {
- this.caption.slideshowOverlay.enable();
- this.caption.slideshowOverlay.hide();
- }
- if(this.social && this.social.slideshowOverlay !== overlay) {
- this.social.slideshowOverlay.enable();
- this.social.slideshowOverlay.hide();
- }
- },
- /**
- * Called when an overlay's close button is clicked.
- *
- * @method _overlayCloseClick
- * @protected
- */
- _overlayCloseClick: function()
- {
- if(this.nav && this.nav.slideshowOverlay) {
- this.nav.slideshowOverlay.enable();
- }
- if(this.thumbs && this.thumbs.slideshowOverlay) {
- this.thumbs.slideshowOverlay.enable();
- }
- if(this.caption) {
- this.caption.slideshowOverlay.enable();
- }
- if(this.social) {
- this.social.slideshowOverlay.enable();
- }
- if(this.imageNavLeft) {
- this.imageNavLeft.slideshowOverlay.enable();
- this.imageNavRight.slideshowOverlay.enable();
- }
- },
- /**
- * Hides all overlaid widgets.
- *
- * @method _hideAllOverlays
- * @protected
- */
- _hideAllOverlays: function()
- {
- if(this.nav && this.nav.slideshowOverlay && this.nav.slideshowOverlay._visible) {
- this.nav.slideshowOverlay.enable();
- this.nav.slideshowOverlay.hideWithTimer();
- }
- if(this.thumbs && this.thumbs.slideshowOverlay && this.thumbs.slideshowOverlay._visible) {
- this.thumbs.slideshowOverlay.enable();
- this.thumbs.slideshowOverlay.hideWithTimer();
- }
- if(this.caption && this.caption.slideshowOverlay._visible) {
- this.caption.slideshowOverlay.enable();
- this.caption.slideshowOverlay.hideWithTimer();
- }
- if(this.social && this.social.slideshowOverlay._visible) {
- this.social.slideshowOverlay.enable();
- this.social.slideshowOverlay.hideWithTimer();
- }
- if(this.imageNavLeft) {
- this.imageNavLeft.slideshowOverlay.enable();
- this.imageNavLeft.slideshowOverlay.hideWithTimer();
- this.imageNavRight.slideshowOverlay.enable();
- this.imageNavRight.slideshowOverlay.hideWithTimer();
- }
- },
- /**
- * Checks if overlays are still visible when the mouse enters
- * the bounding box. If they are, overlay functionality is disabled
- * until the overlays are closed by a button or the mouse leaves
- * the bounding box. If only the nav overlay is visible, this
- * function does nothing.
- *
- * @method _checkOverlaysOnMouseenter
- * @protected
- */
- _checkOverlaysOnMouseenter: function()
- {
- var navType = this.get('navType'),
- navOverlay = this.get('navOverlay'),
- nav = this._getNav(),
- overlayVisible = false;
- if(this.thumbs && navType != 'thumbs' && this.thumbs.slideshowOverlay._visible) {
- overlayVisible = true;
- this.thumbs.slideshowOverlay.disable();
- }
- else if(this.caption && this.caption.slideshowOverlay._visible) {
- overlayVisible = true;
- this.caption.slideshowOverlay.disable();
- }
- else if(this.social && this.social.slideshowOverlay._visible) {
- overlayVisible = true;
- this.social.slideshowOverlay.disable();
- }
- if(nav && overlayVisible && navOverlay) {
- nav.slideshowOverlay.disable();
- }
- },
- /**
- * Checks whether a nav button is set or not.
- *
- * @method _hasNavButton
- * @protected
- * @param button {String} The button to look for.
- * @returns Boolean
- */
- _hasNavButton: function(button)
- {
- var navType = this.get('navType');
- if(navType == 'buttons' || navType == 'thumbs' || navType == 'custom') {
- if(Y.Array.indexOf(this.get('navButtons'), button) > -1) {
- return true;
- }
- else if(Y.Array.indexOf(this.get('navButtonsLeft'), button) > -1) {
- return true;
- }
- else if(Y.Array.indexOf(this.get('navButtonsRight'), button) > -1) {
- return true;
- }
- else {
- return false;
- }
- }
- else {
- return false;
- }
- },
- /**
- * @method _removeNavButton
- * @param button {String} The name of the button to remove.
- * @protected
- */
- _removeNavButton: function(button)
- {
- var buttons = this.get('navButtons'),
- buttonsLeft = this.get('navButtonsLeft'),
- buttonsRight = this.get('navButtonsRight'),
- vtTopNavButtons = this.get('verticalThumbsTopNavButtons'),
- vtBottomNavButtons = this.get('verticalThumbsBottomNavButtons');
- if(Y.Array.indexOf(buttons, button) > -1) {
- buttons.splice(Y.Array.indexOf(buttons, button), 1);
- }
- if(Y.Array.indexOf(buttonsLeft, button) > -1) {
- buttonsLeft.splice(Y.Array.indexOf(buttonsLeft, button), 1);
- }
- if(Y.Array.indexOf(buttonsRight, button) > -1) {
- buttonsRight.splice(Y.Array.indexOf(buttonsRight, button), 1);
- }
- if(Y.Array.indexOf(vtTopNavButtons, button) > -1) {
- vtTopNavButtons.splice(Y.Array.indexOf(vtTopNavButtons, button), 1);
- }
- if(Y.Array.indexOf(vtBottomNavButtons, button) > -1) {
- vtBottomNavButtons.splice(Y.Array.indexOf(vtBottomNavButtons, button), 1);
- }
- this._set('navButtons', buttons);
- this._set('navButtonsLeft', buttonsLeft);
- this._set('navButtonsRight', buttonsRight);
- this._set('verticalThumbsTopNavButtons', vtTopNavButtons);
- this._set('verticalThumbsBottomNavButtons', vtBottomNavButtons);
- }
- }, {
- /**
- * Custom CSS class name for the widget.
- *
- * @property CSS_PREFIX
- * @type String
- * @protected
- * @static
- */
- CSS_PREFIX: 'fl-slideshow',
- /**
- * Static property used to define the default attribute configuration of
- * the Widget.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- /**
- * What should happen when the main image is clicked.
- * Options are none, gallery and url. If url is chosen,
- * clickActionUrl must be set.
- *
- * @attribute clickAction
- * @type String
- * @default none
- */
- clickAction: {
- value: 'none'
- },
- /**
- * The redirect url to use when clickAction is set to url.
- *
- * @attribute clickActionUrl
- * @type String
- * @default none
- */
- clickActionUrl: {
- value: ''
- },
- /**
- * Whether to crop the main image.
- *
- * @attribute crop
- * @type Boolean
- * @default false
- */
- crop: {
- value: false
- },
- /**
- * Whether to only crop horizontal images or not.
- *
- * @attribute cropHorizontalsOnly
- * @type Boolean
- * @default false
- */
- cropHorizontalsOnly: {
- value: false
- },
- /**
- * Whether to always use the loading image between images
- * or to only use it between albums.
- *
- * @attribute loadingImageAlwaysEnabled
- * @type Boolean
- * @default true
- */
- loadingImageAlwaysEnabled: {
- value: true
- },
- /**
- * The x and y position of the main image
- * within the bounding box.
- *
- * @attribute position
- * @type String
- * @default center center
- */
- position: {
- value: 'center center'
- },
- /**
- * Whether to right click protect the main image.
- *
- * @attribute protect
- * @type Boolean
- * @default true
- */
- protect: {
- value: true
- },
- /**
- * Whether to resize the main image past
- * its original width and height.
- *
- * @attribute upsize
- * @type Boolean
- * @default true
- */
- upsize: {
- value: true
- },
- /**
- * The type of transition to use. Possible values are
- * none, fade, slideHorizontal and slideVertical. The
- * value can also be a common seperated string of transitions
- * that will be randomly chosen for each image.
- *
- * @attribute transition
- * @type String
- * @default fade
- */
- transition: {
- value: 'fade'
- },
- /**
- * The duration of the transition, measured in seconds.
- *
- * @attribute transitionDuration
- * @type Number
- * @default 1
- */
- transitionDuration: {
- value: 1
- },
- /**
- * The type of transition easing to use.
- *
- * @attribute transitionEasing
- * @type String
- * @default ease-out
- */
- transitionEasing: {
- value: 'ease-out'
- },
- /**
- * The amount of zoom to use for the Ken Burns effect.
- *
- * @attribute kenBurnsZoom
- * @type Number
- * @default 1.2
- */
- kenBurnsZoom: {
- value: 1.2
- },
- /**
- * The type of navigation to use. Possible values are
- * buttons, thumbs, custon and none.
- *
- * @attribute navType
- * @type String
- * @default none
- */
- navType: {
- value: 'none'
- },
- /**
- * The position of the main nav. Possible values are top and bottom.
- *
- * @attribute navPosition
- * @type String
- * @default bottom
- */
- navPosition: {
- value: 'bottom'
- },
- /**
- * Whether to overlay the nav on top of the main image.
- *
- * @attribute navOverlay
- * @type Boolean
- * @default false
- */
- navOverlay: {
- value: false
- },
- /**
- * An array of button names used to render the main nav's buttons.
- *
- * @attribute navButtons
- * @type Array
- * @default []
- */
- navButtons: {
- value: []
- },
- /**
- * An array of button names used to render the main nav's left buttons.
- *
- * @attribute navButtonsLeft
- * @type Array
- * @default []
- */
- navButtonsLeft: {
- value: []
- },
- /**
- * An array of button names used to render the main nav's right buttons.
- *
- * @attribute navButtonsRight
- * @type Array
- * @default []
- */
- navButtonsRight: {
- value: []
- },
- /**
- * Whether to hide the overlays when the mouse moves or not.
- *
- * @attribute overlayHideOnMousemove
- * @type String
- * @default mouseover
- */
- overlayHideOnMousemove: {
- value: true
- },
- /**
- * How long to wait before hiding the overlays.
- * Measured in milliseconds.
- *
- * @attribute overlayHideDelay
- * @type Number
- * @default false
- */
- overlayHideDelay: {
- value: 3000
- },
- /**
- * Whether to use the image nav or not. If true, a prev
- * and next button will be overlaid on the main image.
- *
- * @attribute imageNavEnabled
- * @type Boolean
- * @default false
- */
- imageNavEnabled: {
- value: false
- },
- /**
- * Whether to use the mouse nav or not. If true, the cursor
- * will turn into a prev or next button when over the slideshow.
- *
- * @attribute mouseNavEnabled
- * @type Boolean
- * @default false
- */
- mouseNavEnabled: {
- value: false
- },
- /**
- * Whether to hide the thumbs when clicking on a thumbnail
- * image or not. Thumbs always hide navType is set to buttons.
- *
- * @attribute thumbsHideOnClick
- * @type Boolean
- * @default false
- */
- thumbsHideOnClick: {
- value: true
- },
- /**
- * The horizontal spacing between thumbs.
- *
- * @attribute thumbsHorizontalSpacing
- * @type Number
- * @default 15
- */
- thumbsHorizontalSpacing: {
- value: 15
- },
- /**
- * The vertical spacing between thumbs.
- *
- * @attribute thumbsVerticalSpacing
- * @type Number
- * @default 15
- */
- thumbsVerticalSpacing: {
- value: 15
- },
- /**
- * Whether to space the thumbs evenly within a page.
- *
- * @attribute thumbsSpaceEvenly
- * @type Boolean
- * @default true
- */
- thumbsSpaceEvenly: {
- value: true
- },
- /**
- * Whether to center single pages of thumbs.
- *
- * @attribute thumbsCenterSinglePage
- * @type Boolean
- * @default false
- */
- thumbsCenterSinglePage: {
- value: true
- },
- /**
- * Whether to pause the slideshow when a thumb is clicked.
- *
- * @attribute thumbsPauseOnClick
- * @type Boolean
- * @default false
- */
- thumbsPauseOnClick: {
- value: false
- },
- /**
- * The type of transition to use between pages of thumbs.
- *
- * @attribute thumbsTransition
- * @type String
- * @default slideHorizontal
- */
- thumbsTransition: {
- value: 'slideHorizontal'
- },
- /**
- * The duration of the transition between pages of thumbs.
- *
- * @attribute thumbsTransitionDuration
- * @type Number
- * @default 0.8
- */
- thumbsTransitionDuration: {
- value: 0.8
- },
- /**
- * The type of transition easing to use between pages of thumbs.
- *
- * @attribute thumbsTransitionEasing
- * @type String
- * @default ease-out
- */
- thumbsTransitionEasing: {
- value: 'ease-out'
- },
- /**
- * Whether to crop the thumbnails.
- *
- * @attribute thumbsImageCrop
- * @type Boolean
- * @default true
- */
- thumbsImageCrop: {
- value: true
- },
- /**
- * The width of each thumbnail.
- *
- * @attribute thumbsImageWidth
- * @type Number
- * @default 50
- */
- thumbsImageWidth: {
- value: 50
- },
- /**
- * The height of each thumbnail.
- *
- * @attribute thumbsImageHeight
- * @type Number
- * @default 50
- */
- thumbsImageHeight: {
- value: 50
- },
- /**
- * The text to use for the "read less" toggle link.
- *
- * @attribute captionLessLinkText
- * @type String
- * @default Read Less
- */
- captionLessLinkText: {
- value: 'Read Less'
- },
- /**
- * The text to use for the "read more" toggle link.
- *
- * @attribute captionMoreLinkText
- * @type String
- * @default Read More
- */
- captionMoreLinkText: {
- value: 'Read More'
- },
- /**
- * The length of the caption to show. If greater than -1,
- * the text will be truncated and a read more link will
- * be displayed. If set to -1, the entire caption will be shown.
- *
- * @attribute captionTextLength
- * @type Number
- * @default 200
- */
- captionTextLength: {
- value: 200
- },
- /**
- * Whether to strip out HTML tags in the caption
- * text or not.
- *
- * @attribute captionStripTags
- * @type Boolean
- * @default false
- */
- captionStripTags: {
- value: false
- },
- /**
- * Whether to use the vertical thumbs or not.
- *
- * @attribute verticalThumbsEnabled
- * @type Boolean
- * @default false
- */
- verticalThumbsEnabled: {
- value: false
- },
- /**
- * Position of the vertical thumbs. Possible values
- * are either left or right.
- *
- * @attribute verticalThumbsPosition
- * @type String
- * @default left
- */
- verticalThumbsPosition: {
- value: 'left'
- },
- /**
- * Whether to overlay the vertical thumbs
- * on the main image or not.
- *
- * @attribute verticalThumbsOverlay
- * @type Boolean
- * @default false
- */
- verticalThumbsOverlay: {
- value: false
- },
- /**
- * The number of columns for the vertical thumbs.
- *
- * @attribute verticalThumbsColumns
- * @type Number
- * @default 1
- */
- verticalThumbsColumns: {
- value: 1
- },
- /**
- * Whether to use the vertical thumbs top nav or not.
- *
- * @attribute verticalThumbsTopNavEnabled
- * @type Boolean
- * @default false
- */
- verticalThumbsTopNavEnabled: {
- value: false
- },
- /**
- * An array of button names used to render
- * the vertical thumbs top nav buttons.
- *
- * @attribute verticalThumbsTopNavButtons
- * @type Array
- * @default prevPage, nextPage
- */
- verticalThumbsTopNavButtons: {
- value: ['prevPage', 'nextPage']
- },
- /**
- * Whether to use the vertical thumbs bottom nav or not.
- *
- * @attribute verticalThumbsBottomNavEnabled
- * @type Boolean
- * @default false
- */
- verticalThumbsBottomNavEnabled: {
- value: true
- },
- /**
- * An array of button names used to render
- * the vertical thumbs top nav buttons.
- *
- * @attribute verticalThumbsBottomNavButtons
- * @type Array
- * @default prevPage, nextPage
- */
- verticalThumbsBottomNavButtons: {
- value: ['prevPage', 'nextPage']
- },
- /**
- * The horizontal spacing between vertical thumbs.
- *
- * @attribute verticalThumbsHorizontalSpacing
- * @type Number
- * @default 15
- */
- verticalThumbsHorizontalSpacing: {
- value: 15
- },
- /**
- * The vertical spacing between vertical thumbs.
- *
- * @attribute verticalThumbsVerticalSpacing
- * @type Number
- * @default 15
- */
- verticalThumbsVerticalSpacing: {
- value: 15
- },
- /**
- * Whether to space the vertical thumbs evenly within a page.
- *
- * @attribute verticalThumbsSpaceEvenly
- * @type Boolean
- * @default false
- */
- verticalThumbsSpaceEvenly: {
- value: false
- },
- /**
- * Whether to pause the slideshow when a vertical thumb is clicked.
- *
- * @attribute verticalThumbsPauseOnClick
- * @type Boolean
- * @default false
- */
- verticalThumbsPauseOnClick: {
- value: false
- },
- /**
- * Whether to crop the vertical thumbs or not.
- *
- * @attribute verticalThumbsImageCrop
- * @type Boolean
- * @default true
- */
- verticalThumbsImageCrop: {
- value: true
- },
- /**
- * The width of each vertical thumbnail.
- *
- * @attribute verticalThumbsImageWidth
- * @type Number
- * @default 75
- */
- verticalThumbsImageWidth: {
- value: 75
- },
- /**
- * The height of each vertical thumbnail.
- *
- * @attribute verticalThumbsImageHeight
- * @type Number
- * @default 75
- */
- verticalThumbsImageHeight: {
- value: 75
- },
- /**
- * The type of transition to use between pages of vertical thumbs.
- *
- * @attribute verticalThumbsTransition
- * @type String
- * @default slideVertical
- */
- verticalThumbsTransition: {
- value: 'slideVertical'
- },
- /**
- * The duration of the transition between pages of vertical thumbs.
- *
- * @attribute verticalThumbsTransitionDuration
- * @type Number
- * @default 0.8
- */
- verticalThumbsTransitionDuration: {
- value: 0.8
- },
- /**
- * The type of transition easing to use between pages of vertical thumbs.
- *
- * @attribute verticalThumbsTransitionEasing
- * @type String
- * @default ease-out
- */
- verticalThumbsTransitionEasing: {
- value: 'ease-out'
- },
- /**
- * Whether to use the Google Plus button or not.
- *
- * @attribute googlePlusButtonEnabled
- * @type Boolean
- * @default true
- */
- googlePlusButtonEnabled: {
- value: true
- },
- /**
- * Whether to use the Facebook like button or not.
- *
- * @attribute likeButtonEnabled
- * @type Boolean
- * @default true
- */
- likeButtonEnabled: {
- value: true
- },
- /**
- * Whether to use the Pinterest button or not.
- *
- * @attribute pinterestButtonEnabled
- * @type Boolean
- * @default true
- */
- pinterestButtonEnabled: {
- value: true
- },
- /**
- * Whether to use the Tweet button or not.
- *
- * @attribute tweetButtonEnabled
- * @type Boolean
- * @default true
- */
- tweetButtonEnabled: {
- value: true
- },
- /**
- * Whether to use touch gestures, when available,
- * to transition between images or not.
- *
- * @attribute touchSupport
- * @type Boolean
- * @default true
- */
- touchSupport: {
- value: true
- }
- }
- });
- }, '2.0.0' ,{requires:['anim', 'event-mouseenter', 'plugin', 'transition', 'fl-event-move', 'fl-slideshow-css', 'fl-slideshow-base', 'fl-utils', 'sm-fonticon']});
- YUI.add('fl-slideshow-album-loader', function(Y) {
- /**
- * @module fl-slideshow-album-loader
- */
- /**
- * Loads slideshow albums using a provided source object.
- *
- * @namespace FL
- * @class SlideshowAlbumLoader
- * @constructor
- * @param config {Object} Configuration object
- * @extends Base
- */
- Y.namespace('FL').SlideshowAlbumLoader = Y.Base.create('fl-slideshow-album-loader', Y.Base, [], {
- /**
- * The source object used for loading.
- *
- * @property _source
- * @type Object
- * @default null
- * @protected
- */
- _source: null,
- /**
- * Loads slideshow album data using the provided source object.
- *
- * @method load
- * @param source {Object} The source object to use for loading.
- */
- load: function(source)
- {
- this._source = source;
- /**
- * Fires before a new load request is made.
- *
- * @event start
- */
- this.fire('start');
- this[Y.FL.SlideshowAlbumLoader.TYPES[source.type]].call(this);
- },
- /**
- * Called when a source type completes loading
- * and fires the complete event.
- *
- * @method _loadComplete
- * @param o {Object} Passed to complete event subscribers.
- * @protected
- */
- _loadComplete: function(o)
- {
- o = this._randomize(o);
- /**
- * Fires after a new load request is made.
- *
- * @event complete
- */
- this.fire('complete', o);
- },
- /**
- * Randomizes images in an album.
- *
- * @method _randomize
- * @param album {Object} The album to randomize.
- * @protected
- */
- _randomize: function(o)
- {
- var i;
- if(this.get('randomize')) {
- o.albumInfo.images.sort(function() { return 0.5 - Math.random(); });
- for(i = 0; i < o.albumInfo.images.length; i++) {
- o.albumInfo.images[i].index = i;
- }
- }
- return o;
- },
- /**
- * Loads slideshow album data from SmugMug.
- *
- * @method _loadSmugMug
- * @protected
- */
- _loadSmugMug: function()
- {
- var sm = new Y.FL.SmugMugAPI();
- sm.on('complete', this._loadSmugMugSuccess, this);
- sm.addParam('method', 'smugmug.images.get');
- sm.addParam('AlbumID', this._source.id);
- sm.addParam('AlbumKey', this._source.key);
- sm.addParam('Extras', 'Caption,Format,FileName');
- // Gallery password
- if(this._source.password) {
- sm.addParam('Password', this._source.password);
- }
- // Site-wide password
- if(this._source.sp) {
- sm.addParam('SitePassword', this._source.sp);
- }
- sm.request();
- },
- /**
- * Processes slideshow album data loaded from SmugMug.
- *
- * @method _loadSmugMugSuccess
- * @param e {Object} The custom event object passed to this function.
- * @protected
- */
- _loadSmugMugSuccess: function(e)
- {
- var images = e.Album.Images,
- album = {},
- proxy = typeof this._source.proxy !== 'undefined' ? this._source.proxy : '',
- buyBase = '',
- baseURL = '',
- ext = '',
- format = '',
- i = 0,
- temp = null,
- iframe = null;
- album.index = this._source.index;
- album.id = e.Album.id;
- album.key = e.Album.Key;
- album.link = e.Album.URL;
- album.title = this._source.title ? this._source.title : '';
- album.images = [];
- buyBase = album.link.replace('https://', '').split('/').shift();
- buyBase = 'https://' + buyBase + '/buy/' + e.Album.id + '_' + e.Album.Key + '/';
- for(i = 0; i < images.length; i++)
- {
- baseURL = proxy + e.Album.URL + '/' + images[i].id + '_' + images[i].Key;
- format = images[i].Format.toLowerCase();
- ext = format == 'mp4' ? '.jpg' : '.' + format;
- album.images[i] = {};
- album.images[i].index = i;
- album.images[i].sourceType = 'smugmug';
- album.images[i].albumId = e.Album.id;
- album.images[i].albumKey = e.Album.Key;
- album.images[i].id = images[i].id;
- album.images[i].key = images[i].Key;
- album.images[i].filename = images[i].FileName;
- album.images[i].format = format;
- album.images[i].caption = images[i].Caption || '';
- album.images[i].link = e.Album.URL + '#' + images[i].id + '_' + images[i].Key;
- album.images[i].tinyURL = baseURL + '-Ti' + ext;
- album.images[i].thumbURL = baseURL + '-Th' + ext;
- album.images[i].smallURL = baseURL + '-S' + ext;
- album.images[i].mediumURL = baseURL + '-M' + ext;
- album.images[i].largeURL = baseURL + '-L' + ext;
- album.images[i].xlargeURL = baseURL + '-XL' + ext;
- album.images[i].x2largeURL = baseURL + '-X2' + ext;
- album.images[i].x3largeURL = baseURL + '-X3' + ext;
- album.images[i].buyURL = buyBase + images[i].id + '_' + images[i].Key;
- album.images[i].iframe = '';
- if(album.images[i].caption.indexOf('iframe')) {
- temp = Y.Node.create('<div>'+ album.images[i].caption +'</div>');
- iframe = temp.one('iframe');
- if(iframe) {
- album.images[i].iframe = iframe.getAttribute('src');
- album.images[i].caption = album.images[i].caption.replace(/<iframe.*>.*<\/iframe>/gi, '');
- }
- }
- }
- this._loadComplete({ 'albumInfo': album });
- },
- /**
- * Loads slideshow album data from an array of urls.
- *
- * NOTE: You must have a large URL.
- *
- * @method _loadUrls
- * @protected
- */
- _loadUrls: function()
- {
- var album = {},
- i = 0;
- album.index = this._source.index;
- album.title = this._source.title ? this._source.title : '';
- album.images = [];
- for( ; i < this._source.urls.length; i++)
- {
- album.images[i] = {};
- album.images[i].index = i;
- album.images[i].sourceType = 'urls';
- album.images[i].filename = this._source.urls[i].largeURL.split('/').pop();
- album.images[i].format = '';
- album.images[i].caption = this._source.urls[i].caption || '';
- album.images[i].link = this._source.urls[i].largeURL;
- album.images[i].thumbURL = this._source.urls[i].thumbURL || this._source.urls[i].largeURL;
- album.images[i].smallURL = this._source.urls[i].smallURL || this._source.urls[i].largeURL;
- album.images[i].mediumURL = this._source.urls[i].mediumURL || this._source.urls[i].largeURL;
- album.images[i].largeURL = this._source.urls[i].largeURL; // Must have a large URL
- album.images[i].xlargeURL = this._source.urls[i].xlargeURL || this._source.urls[i].largeURL;
- album.images[i].x2largeURL = this._source.urls[i].x2largeURL || this._source.urls[i].largeURL;
- album.images[i].x3largeURL = this._source.urls[i].x3largeURL || this._source.urls[i].largeURL;
- album.images[i].buyURL = this._source.urls[i].buyURL || '';
- album.images[i].iframe = this._source.urls[i].iframe || '';
- }
- this._loadComplete({ 'albumInfo': album });
- }
- }, {
- /**
- * Static property used to define the default attribute configuration of
- * the Widget.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- /**
- * If true, the images will be randomized after loading.
- *
- * @attribute randomize
- * @type Boolean
- * @default false
- */
- randomize: {
- value: false
- }
- },
- /**
- * The types of source data that can be loaded
- * and associated functions.
- *
- * @property TYPES
- * @type Object
- * @readOnly
- * @protected
- * @static
- */
- TYPES: {
- 'smugmug': '_loadSmugMug',
- 'flickr': '_loadFlickr',
- 'picasa': '_loadPicasa',
- 'urls': '_loadUrls',
- 'html': '_loadHtml'
- }
- });
- }, '2.0.0' ,{requires:['base', 'fl-smugmug-api']});
- YUI.add('fl-slideshow-base', function(Y) {
- /**
- * @module fl-slideshow-base
- */
- /**
- * The base class that gets extended when creating new
- * slideshow widgets. Manages loading, playing, and resizing.
- * <p>
- * While SlideshowBase can be instantiated, it is only meant to
- * be extended and does not display any images.
- *
- * @namespace FL
- * @class SlideshowBase
- * @constructor
- * @param config {Object} Configuration object
- * @extends Widget
- */
- Y.namespace('FL').SlideshowBase = Y.Base.create('fl-slideshow-base', Y.Widget, [Y.WidgetParent], {
- /**
- * FL.SlideshowAlbumLoader instance used to load albums.
- *
- * @property _loader
- * @type FL.SlideshowAlbumLoader
- * @default null
- * @protected
- */
- _albumLoader: null,
- /**
- * An array of albums loaded from the source attribute.
- * Each album is an array of objects containing image info.
- *
- * @property albums
- * @type Array
- * @default []
- */
- albums: [],
- /**
- * Info for the active album.
- *
- * @property albumInfo
- * @type Object
- * @default null
- */
- albumInfo: null,
- /**
- * A number that represents the index of the active
- * album in the albums array.
- *
- * @property albumIndex
- * @type Number
- * @default null
- */
- albumIndex: null,
- /**
- * Info for the active image.
- *
- * @property imageInfo
- * @type Object
- * @default null
- */
- imageInfo: null,
- /**
- * A number that represents the index of the active
- * image in the albumInfo array.
- *
- * @property imageIndex
- * @type Number
- * @default null
- */
- imageIndex: null,
- /**
- * A number that represents the index of the last
- * image that was loaded in the albumInfo array.
- *
- * @property lastImageIndex
- * @type Number
- * @default null
- */
- lastImageIndex: null,
- /**
- * Timer for the delay before resizing if one is set.
- *
- * @property _resizeTimer
- * @type Object
- * @default null
- * @protected
- */
- _resizeTimer: null,
- /**
- * Flag for whether the slideshow is currently playing or not.
- *
- * @property playing
- * @type Boolean
- * @default false
- * @protected
- */
- _playing: false,
- /**
- * Timer for the break in between images when
- * the slideshow is playing.
- *
- * @property _playingTimer
- * @type Object
- * @default null
- * @protected
- */
- _playingTimer: null,
- /**
- * If set, the slideshow will only auto start when
- * this event is fired.
- *
- * @property _playingTimerEvent
- * @type Object
- * @default null
- * @protected
- */
- _playingTimerEvent: null,
- /**
- * An instance of FL.Spinner that is shown and hidden
- * using _showLoadingImage and _hideLoadingImage when
- * a loading activity occurs.
- *
- * @property _loadingImage
- * @type FL.Spinner
- * @default null
- * @protected
- */
- _loadingImage: null,
- /**
- * An div node that wraps the loading image.
- *
- * @property _loadingImageWrap
- * @type Node
- * @default null
- * @protected
- */
- _loadingImageWrap: null,
- /**
- * Whether the loading image is visible or not.
- *
- * @property _loadingImageVisible
- * @type Boolean
- * @default false
- * @protected
- */
- _loadingImageVisible: false,
- /**
- * A timer to delay the display of the loading image.
- *
- * @property _loadingImageTimer
- * @type Object
- * @default null
- * @protected
- */
- _loadingImageTimer: null,
- /**
- * The container to insert the loading image into. If
- * no container is set, the loading image will be inserted
- * into the widget's bounding box.
- *
- * @property _loadingImageContainer
- * @type Object
- * @default null
- * @protected
- */
- _loadingImageContainer: null,
- /**
- * The intial height of the slideshow. Used to resize
- * back to the starting height when exiting stretchy.
- *
- * @property _initialHeight
- * @type Number
- * @default null
- * @protected
- */
- _initialHeight: null,
- /**
- * The intial width of the slideshow. Used to resize
- * back to the starting width when exiting stretchy.
- *
- * @property _initialWidth
- * @type Number
- * @default null
- * @protected
- */
- _initialWidth: null,
- /**
- * @method initializer
- * @protected
- */
- initializer: function()
- {
- // Loader
- this._albumLoader = new Y.FL.SlideshowAlbumLoader({
- randomize: this.get('randomize')
- });
- },
- /**
- * @method renderUI
- * @protected
- */
- renderUI: function()
- {
- this._renderLoadingImage();
- },
- /**
- * @method bindUI
- * @protected
- */
- bindUI: function()
- {
- // Album load complete
- this._albumLoader.on('complete', this._loadAlbumComplete, this);
- // Resize Events
- Y.one(window).on('fl-slideshow-base|resize', this._delayResize, this);
- Y.one(window).on('fl-slideshow-base|orientationchange', this._delayResize, this);
- // Key Events
- Y.Node.one('body').on('keydown', Y.bind(this._onKey, this));
- },
- /**
- * @method syncUI
- * @protected
- */
- syncUI: function()
- {
- this.get('boundingBox').addClass('fl-slideshow-' + this.get('color'));
- this.resize();
- if(this.get('loadOnRender')) {
- this.loadAlbum(this.get('defaultAlbum'), this.get('defaultImage'));
- }
- },
- /**
- * Add album data to the source object.
- *
- * @method addAlbum
- * @protected
- */
- addAlbum: function(data)
- {
- var source = this.get('source'),
- i = source.length;
- source[i] = data;
- source[i].index = i;
- this.set('source', source);
- },
- /**
- * Loads an album from the source array with the provided albumIndex.
- * If no albumIndex is provided, the first album in the array will be loaded.
- * An image to load can also be specified using imageIndex.
- *
- * @method loadAlbum
- * @param albumIndex {Number} The album index to load from the source array.
- * @param imageIndex {Number} The image index to load from the album array.
- */
- loadAlbum: function(albumIndex, imageIndex)
- {
- var source = this.get('source'),
- loadImageIndex = typeof imageIndex == 'undefined' ? 0 : imageIndex;
- // Reset internal image indexes.
- this.imageIndex = null;
- this.lastImageIndex = null;
- /**
- * Fires before a new album request is made.
- *
- * @event albumLoadStart
- */
- this.fire('albumLoadStart');
- // Load an image after the album.
- this.once('albumLoadComplete', Y.bind(this.loadImage, this, loadImageIndex));
- // Load data passed from another slideshow instance.
- if(source[albumIndex] && source[albumIndex].type == 'album-data') {
- this.albums[albumIndex] = source[albumIndex].data;
- this._loadAlbumComplete({albumInfo: this.albums[albumIndex]});
- }
- // Load the album from the albums array.
- else if(source[albumIndex] && this.albums[albumIndex]) {
- this._loadAlbumComplete({albumInfo: this.albums[albumIndex]});
- }
- // Load the album using the album loader.
- else {
- this._albumLoader.load(source[albumIndex] || source[0]);
- }
- },
- /**
- * Processes the loaded album and fires the albumLoadComplete event.
- *
- * @method _loadAlbumComplete
- * @param o {Object} The custom event object passed to this method.
- * @protected
- */
- _loadAlbumComplete: function(o)
- {
- this.albums[o.albumInfo.index] = o.albumInfo;
- this.albumInfo = o.albumInfo;
- this.albumIndex = o.albumInfo.index;
- /**
- * Fires after a new album request is made.
- *
- * @event albumLoadComplete
- */
- this.fire('albumLoadComplete');
- // Auto Play
- if(this.get('autoPlay')) {
- this._playingTimerStart();
- this.fire('played');
- this._playing = true;
- }
- },
- /**
- * Sets the active image index and fires the imageLoadComplete event.
- *
- * @method loadImage
- * @param index {Number} The image index to load.
- */
- loadImage: function(index)
- {
- if(this._playing) {
- this._playingTimerStart();
- }
- index = index < 0 ? this.albumInfo.images.length - 1 : index;
- index = index >= this.albumInfo.images.length ? 0 : index;
- this.lastImageIndex = this.imageIndex;
- this.imageIndex = index;
- this.imageInfo = this.albumInfo.images[index];
- /**
- * Fires after a new image index is set.
- *
- * @event imageLoadComplete
- */
- this.fire('imageLoadComplete', { 'imageInfo': this.imageInfo });
- },
- /**
- * Loads the previous image.
- *
- * @method prevImage
- */
- prevImage: function()
- {
- if(this.get('pauseOnNextOrPrev')) {
- this.pause();
- }
- this.loadImage(this.imageIndex - 1);
- /**
- * Fires when the previous image is loaded.
- *
- * @event prevImage
- */
- this.fire('prevImage');
- },
- /**
- * Loads the next image.
- *
- * @method nextImage
- */
- nextImage: function()
- {
- if(this.get('pauseOnNextOrPrev')) {
- this.pause();
- }
- this.loadImage(this.imageIndex + 1);
- /**
- * Fires when the next image is loaded.
- *
- * @event nextImage
- */
- this.fire('nextImage');
- },
- /**
- * Keyboard navigation for the next and prev images.
- *
- * @method _onKey
- * @protected
- */
- _onKey: function(e)
- {
- switch(e.keyCode) {
- case 37:
- this.prevImage();
- break;
- case 39:
- this.nextImage();
- break;
- }
- },
- /**
- * Resizes the slideshow using either the
- * stretchy or standard functions.
- *
- * @method resize
- */
- resize: function()
- {
- var stretchy = this.get('stretchy'),
- stretchyType = this.get('stretchyType'),
- width = parseInt(Y.one('body').get('winWidth'), 10),
- threshold = this.get('responsiveThreshold');
- // Stretchy resize to the window only if the parent width is greater
- // than the responsive threshold and stretchyType is set to window.
- if(width > threshold && stretchy && stretchyType == 'window') {
- this._stretchyWindowResize();
- }
- // Ratio resize if the parent width is less than the responsive
- // threshold or if stretchyType is set to ratio.
- else if((width <= threshold) || (stretchy && stretchyType == 'ratio')) {
- this._stretchyRatioResize();
- }
- // Do a standard resize based on the height and
- // width passed to the constructor function.
- else {
- this._standardResize();
- }
- /**
- * Fires when the slideshow is resized.
- *
- * @event resize
- */
- this.fire('resize');
- },
- /**
- * @method _standardResize
- * @protected
- */
- _standardResize: function()
- {
- var stretchy = this.get('stretchy'),
- stretchyType = this.get('stretchyType'),
- bb = this.get('boundingBox'),
- parent = bb.get('parentNode'),
- parentHeight = parseInt(parent.getComputedStyle('height'), 10),
- parentWidth = parseInt(parent.getComputedStyle('width'), 10),
- height = this.get('height'),
- width = this.get('width');
- // Window resize if we are in fullscreen.
- if(bb.hasClass('fl-fullscreen-active')) {
- this._stretchyWindowResize();
- return;
- }
- // Resize to the width and height of the parent.
- else if(stretchy && stretchyType == 'contain') {
- bb.setStyle('height', parentHeight + 'px');
- bb.setStyle('width', parentWidth + 'px');
- }
- // Ratio resize if we don't have a height defined.
- else if(!Y.Lang.isNumber(height)) {
- this._stretchyRatioResize();
- return;
- }
- // Resize to the defined width and height.
- else {
- bb.setStyle('height', height + 'px');
- if(width) {
- bb.setStyle('width', width + 'px');
- }
- else {
- bb.setStyle('width', parentWidth + 'px');
- }
- }
- },
- /**
- * Resizes to the height of the window, compensating
- * for any padding.
- *
- * @method _stretchyWindowResize
- * @protected
- */
- _stretchyWindowResize: function()
- {
- var bb = this.get('boundingBox'),
- verticalSpace = this.get('stretchyVerticalSpace'),
- paddingTop = parseInt(bb.getStyle('paddingTop'), 10),
- paddingBottom = parseInt(bb.getStyle('paddingBottom'), 10),
- height = parseInt(Y.one('body').get('winHeight'), 10),
- width = '';
- // Set the vertical space to 0 and width to the
- // window's width if we are in fullscreen mode.
- if(bb.hasClass('fl-fullscreen-active')) {
- verticalSpace = 0;
- width = parseInt(Y.one('body').get('winWidth'), 10) + 'px';
- }
- height = (height - paddingTop - paddingBottom - verticalSpace) + 'px';
- bb.setStyle('height', height);
- bb.setStyle('width', width);
- },
- /**
- * Resizes the height by multiplying the width and stretchyRatio value.
- *
- * @method _stretchyRatioResize
- * @protected
- */
- _stretchyRatioResize: function()
- {
- var bb = this.get('boundingBox'),
- parent = bb.get('parentNode'),
- verticalSpace = 0,
- stretchyRatio = this.get('stretchyRatio'),
- paddingTop = parseInt(bb.getStyle('paddingTop'), 10),
- paddingBottom = parseInt(bb.getStyle('paddingBottom'), 10),
- computedWidth = parseInt(parent.getComputedStyle('width'), 10),
- winHeight = parseInt(Y.one('body').get('winHeight'), 10),
- winWidth = parseInt(Y.one('body').get('winWidth'), 10),
- height = computedWidth * stretchyRatio,
- width = '';
- // Use the window's height and width if we are in fullscreen mode.
- if(bb.hasClass('fl-fullscreen-active')) {
- height = winHeight;
- width = winWidth;
- }
- height = (height - paddingTop - paddingBottom - verticalSpace) + 'px';
- bb.setStyle('height', height);
- bb.setStyle('width', width);
- },
- /**
- * Resizes the slideshow after the resize timer completes.
- *
- * @method _delayResize
- * @protected
- */
- _delayResize: function()
- {
- if(this._resizeTimer) {
- this._resizeTimer.cancel();
- }
- this._resizeTimer = Y.later(300, this, this.resize);
- },
- /**
- * Starts a new playing timer and fires the played event.
- *
- * @method play
- */
- play: function()
- {
- this._playingTimer = Y.later(this.get('speed'), this, this._playingTimerComplete);
- /**
- * Fires when the playing timer starts.
- *
- * @event played
- */
- this.fire('played');
- this._playing = true;
- },
- /**
- * Cancels the current playing timer and fires the paused event.
- *
- * @method pause
- */
- pause: function()
- {
- this._playingTimerCancel();
- /**
- * Fires when the playing timer is canceled.
- *
- * @event paused
- */
- this.fire('paused');
- this._playing = false;
- },
- /**
- * A new playing timer will start when this event is fired.
- *
- * @method _setPlayingTimerEvent
- * @param obj {Object} The event's host object.
- * @param e {String} The event to fire on the host object.
- * @protected
- */
- _setPlayingTimerEvent: function(obj, e)
- {
- this._playingTimerEvent = {
- 'obj': obj,
- 'e': e
- };
- },
- /**
- * Cancels the playing timer if it is running and starts a new one.
- * The next image is loaded when the timer completes.
- *
- * @method _playingTimerStart
- * @protected
- */
- _playingTimerStart: function(e)
- {
- this._playingTimerCancel();
- if(!e && this._playingTimerEvent !== null) {
- this._playingTimerEvent.obj.once('fl-slideshow-base|' + this._playingTimerEvent.e, Y.bind(this._playingTimerStart, this));
- }
- else {
- this._playingTimer = Y.later(this.get('speed'), this, this._playingTimerComplete);
- }
- },
- /**
- * Fires when the playing timer completes, starts a
- * new timer and loads the next image.
- *
- * @method _playingTimerComplete
- * @protected
- */
- _playingTimerComplete: function()
- {
- this.loadImage(this.imageIndex + 1);
- /**
- * Fires when the playing timer completes.
- *
- * @event albumLoadStart
- */
- this.fire('playingTimerComplete');
- },
- /**
- * Cancels the playing timer.
- *
- * @method _playingTimerCancel
- * @protected
- */
- _playingTimerCancel: function()
- {
- if(this._playingTimer) {
- this._playingTimer.cancel();
- }
- if(this._playingTimerEvent) {
- this._playingTimerEvent.obj.detach('fl-slideshow-base|' + this._playingTimerEvent.e);
- }
- },
- /**
- * Creates the loading image.
- *
- * @method _renderLoadingImage
- * @protected
- */
- _renderLoadingImage: function()
- {
- var defaults = {
- lines: 11, // The number of lines to draw
- length: 6, // The length of each line
- width: 2, // The line thickness
- radius: 7, // The radius of the inner circle
- color: '', // #rbg or #rrggbb
- speed: 1, // Rounds per second
- trail: 60, // Afterglow percentage
- shadow: false // Whether to render a shadow
- },
- settings = Y.merge(defaults, this.get('loadingImageSettings'));
- if(this.get('loadingImageEnabled')) {
- // Loading image
- if(settings.color === '') {
- settings.color = this._colorToHex(Y.one('body').getStyle('color'));
- }
- this._loadingImage = new Y.FL.Spinner(settings);
- // Loading image wrap
- this._loadingImageWrap = Y.Node.create('<div class="fl-loading-image"></div>');
- this._loadingImageWrap.setStyles({
- position : 'absolute',
- 'z-index' : '1000'
- });
- }
- },
- /**
- * Inserts the loading image.
- *
- * @method _showLoadingImage
- * @protected
- */
- _showLoadingImage: function()
- {
- if(this._loadingImage && !this._loadingImageVisible) {
- this._loadingImageVisible = true;
- this._loadingImage.spin();
- this._loadingImageWrap.insert(this._loadingImage.el);
- if(this._loadingImageContainer !== null) {
- this._loadingImageContainer.insert(this._loadingImageWrap);
- }
- else {
- this.get('contentBox').insert(this._loadingImageWrap);
- }
- this._positionLoadingImage();
- }
- },
- /**
- * Inserts the loading image div node after
- * a timer completes.
- *
- * @method _showLoadingImageWithDelay
- * @protected
- */
- _showLoadingImageWithDelay: function()
- {
- if(this._loadingImage) {
- this._loadingImageTimer = Y.later(1000, this, this._showLoadingImage);
- }
- },
- /**
- * Removes the loading image div node.
- *
- * @method _hideLoadingImage
- * @protected
- */
- _hideLoadingImage: function()
- {
- if(this._loadingImageTimer) {
- this._loadingImageTimer.cancel();
- this._loadingImageTimer = null;
- }
- if(this._loadingImage && this._loadingImageVisible) {
- this._loadingImageVisible = false;
- this._loadingImage.stop();
- this._loadingImageWrap.remove();
- }
- },
- /**
- * Centers the loading image in the content box.
- *
- * @method _positionLoadingImage
- * @protected
- */
- _positionLoadingImage: function()
- {
- if(this._loadingImage && this._loadingImageVisible) {
- var wrap = this._loadingImageWrap,
- wrapHeight = parseInt(wrap.getComputedStyle('height'), 10),
- wrapWidth = parseInt(wrap.getComputedStyle('width'), 10),
- parent = wrap.get('parentNode'),
- parentHeight = parseInt(parent.getComputedStyle('height'), 10),
- parentWidth = parseInt(parent.getComputedStyle('width'), 10),
- left = (parentWidth - wrapWidth)/2,
- top = (parentHeight - wrapHeight)/2;
- wrap.setStyles({
- left : left + 'px',
- top : top + 'px'
- });
- Y.one(this._loadingImage.el).setStyles({
- left : '50%',
- top : '50%'
- });
- }
- },
- /**
- * Convert RGB color value to a hex value.
- *
- * @method _colorToHex
- * @protected
- */
- _colorToHex: function(color)
- {
- var digits, red, green, blue, rgb;
- if(color.substr(0, 1) === '#') {
- return color;
- }
- digits = /(.*?)rgb\((\d+), (\d+), (\d+)\)/.exec(color);
- if ( null === digits ) {
- return '#000';
- }
- red = parseInt(digits[2], 10);
- green = parseInt(digits[3], 10);
- blue = parseInt(digits[4], 10);
- rgb = blue | (green << 8) | (red << 16);
- rgb = rgb.toString(16);
- if(rgb === '0') {
- rgb = '000';
- }
- return digits[1] + '#' + rgb;
- }
- }, {
- /**
- * Custom CSS class name for the widget.
- *
- * @property CSS_PREFIX
- * @type String
- * @protected
- * @static
- */
- CSS_PREFIX: 'fl-slideshow-base',
- /**
- * Static property used to define the default attribute configuration of
- * the Widget.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- /**
- * Used to create the color class that gets added to the bounding box
- * when the widget is rendered. The color class is used to create new
- * CSS color themes. The default CSS provided includes dark and light themes.
- *
- * @attribute color
- * @type String
- * @default dark
- * @writeOnce
- */
- color: {
- value: 'dark',
- writeOnce: true
- },
- /**
- * An array of source objects used to load albums. Each object must have
- * a type property and can have a title property as well.
- * <p>
- * In addition to those properties, each object has additional required
- * properties specific to its type. The types currently supported are
- * smugmug and urls with planned support for flickr and picasa.
- * See the user guide for information on loading different types.
- *
- * @attribute source
- * @type Array
- * @default []
- * @writeOnce
- */
- source: {
- value: [],
- setter: function(source) {
- if(source.constructor == Object) {
- source = [source];
- }
- for(var i = 0; i < source.length; i++) {
- source[i].index = i;
- }
- return source;
- }
- },
- /**
- * The default album index to load.
- *
- * @attribute defaultAlbum
- * @type Number
- * @default 0
- */
- defaultAlbum: {
- value: 0
- },
- /**
- * The default image index to load.
- *
- * @attribute defaultImage
- * @type Number
- * @default 0
- */
- defaultImage: {
- value: 0
- },
- /**
- * If true, the slideshow will be loaded after rendering.
- *
- * @attribute loadOnRender
- * @type Boolean
- * @default true
- */
- loadOnRender: {
- value: true
- },
- /**
- * If true, the slideshow will start playing after loading.
- *
- * @attribute autoPlay
- * @type Boolean
- * @default true
- */
- autoPlay: {
- value: true
- },
- /**
- * Whether to pause when the next or previous image is loaded
- * using nextImage or prevImage. The slideshow will not be paused
- * if the next or previous image is loaded using loadImage as is the
- * case when the slideshow is playing.
- *
- * @attribute pauseOnNextOrPrev
- * @type Boolean
- * @default true
- */
- pauseOnNextOrPrev: {
- value: true
- },
- /**
- * If true, the images will be randomized after loading.
- *
- * @attribute randomize
- * @type Boolean
- * @default false
- */
- randomize: {
- value: false
- },
- /**
- * The time between images when playing, measured in milliseconds.
- *
- * @attribute speed
- * @type Number
- * @default 4000
- */
- speed: {
- value: 4000
- },
- /**
- * The minimum width of the parent node at which
- * responsive features are enabled. Set to 0 to
- * disable responsive features as they are enabled
- * whether stretchy is set to true or not.
- *
- * @attribute responsiveThreshold
- * @type Number
- * @default 600
- */
- responsiveThreshold: {
- value: 600
- },
- /**
- * Whether stretchy resizing should be enabled.
- *
- * @attribute stretchy
- * @type Boolean
- * @default false
- */
- stretchy: {
- value: false
- },
- /**
- * The type of stretchy logic to use. Possible values are
- * window and ratio. Both types resize the width of the
- * slideshow to the width of its parent node. With window, the
- * height of the slideshow is resized to the height of the window.
- * With ratio, the height of the slideshow is resized based
- * on the ratio set with stretchyRatio or the height of the window
- * if the ratio height is greater than the window height.
- *
- * @attribute stretchyType
- * @type String
- * @default ratio
- */
- stretchyType: {
- value: 'ratio'
- },
- /**
- * The number of pixels to subtract from the height of
- * the slideshow when stretchy is set to true.
- *
- * @attribute stretchyVerticalSpace
- * @type Number
- * @default 0
- */
- stretchyVerticalSpace: {
- value: 0
- },
- /**
- * Used to calculate the height of the slideshow when stretchyType
- * is set to ratio.
- *
- * @attribute stretchyRatio
- * @type Number
- * @default 0.7
- */
- stretchyRatio: {
- value: 0.7
- },
- /**
- * Whether to use the loading image or not.
- *
- * @attribute loadingImageEnabled
- * @type Boolean
- * @default true
- */
- loadingImageEnabled: {
- value: true
- },
- /**
- * Property object for setting up the spin.js loading image.
- * For a complete list of properties see:
- * http://effinroot.eiremedia.netdna-cdn.com/repo/plugins/misc/spin.js/index.html
- *
- * @attribute loadingImageSettings
- * @type Object
- */
- loadingImageSettings: {
- value: {}
- }
- }
- });
- }, '2.0.0' ,{requires:['node', 'base', 'widget', 'widget-parent', 'widget-child', 'fl-slideshow-album-loader', 'fl-spinner']});
- YUI.add('fl-smugmug-api', function(Y) {
- /**
- * @module fl-smugmug-api
- */
- /**
- * SmugMug API wrapper.
- *
- * NOTE: Only anonymous logins are currently supported.
- *
- * @namespace FL
- * @class SmugMugAPI
- * @constructor
- * @param config {Object} Configuration object
- * @extends Base
- */
- Y.namespace('FL').SmugMugAPI = Y.Base.create('fl-smugmug-api', Y.Base, [], {
- /**
- * ID for the current session.
- *
- * @property _sessionID
- * @type String
- * @default null
- * @protected
- */
- _sessionID: null,
- /**
- * URL with parameters for the next API request.
- * Reset after each request.
- *
- * @property _requestURL
- * @type String
- * @default null
- * @protected
- */
- _requestURL: null,
- /**
- * Lifecycle method. Initializes the request url.
- *
- * @method initializer
- * @protected
- */
- initializer: function()
- {
- this._resetRequestURL();
- },
- /**
- * Adds a key/value pair to the request url.
- *
- * @method addParam
- * @param key {String} The name of the parameter (example: key=val).
- * @param val {String} The value of the parameter (example: key=val).
- */
- addParam: function(key, val)
- {
- this._requestURL = this._requestURL + '&' + key + '=' + val;
- },
- /**
- * Requests an anonymous login session.
- *
- * @method loginAnon
- */
- loginAnon: function()
- {
- this.addParam('method', 'smugmug.login.anonymously');
- this.once('complete', this._loginAnonComplete);
- this.request();
- },
- /**
- * Anonymous login success handler.
- *
- * @method _loginAnonComplete
- * @param data {Object} A jsonp data object.
- * @protected
- */
- _loginAnonComplete: function(data)
- {
- if(data.Login) {
- this._sessionID = data.Login.Session.id;
- }
- },
- /**
- * Sends an API request using the request url.
- *
- * @method request
- */
- request: function()
- {
- this.addParam('Callback', '{callback}');
- Y.jsonp(this._requestURL, {
- on: {
- success: this._requestComplete,
- timeout: function(){} // TODO: Handle timeouts
- },
- context: this,
- timeout: 60000,
- args: []
- });
- },
- /**
- * API request complete handler.
- *
- * @method _requestComplete
- * @param data {Object} A jsonp data object.
- * @protected
- */
- _requestComplete: function(data)
- {
- this._resetRequestURL();
- /**
- * Fires when a request is complete.
- *
- * @event complete
- */
- this.fire('complete', data);
- },
- /**
- * Clears all parameters on the request url except
- * the API key and session ID.
- *
- * @method _resetRequestURL
- * @protected
- */
- _resetRequestURL: function()
- {
- this._requestURL = this.get('apiURL') + '?APIKey=' + this.get('apiKey');
- if(this._sessionID) {
- this.addParam('SessionID', this._sessionID);
- }
- }
- }, {
- /**
- * Static property used to define the default attribute configuration of
- * the Widget.
- *
- * @property ATTRS
- * @type Object
- * @protected
- * @static
- */
- ATTRS: {
- /**
- * SmugMug API url to use for requests.
- *
- * @attribute apiUrl
- * @type String
- * @default https://api.smugmug.com/services/api/json/1.3.0/
- */
- apiURL: {
- value: 'https://api.smugmug.com/services/api/json/1.3.0/'
- },
- /**
- * SmugMug API key.
- *
- * @attribute apiKey
- * @type String
- * @default 7w6kuU5Ee6KSgRRExf2KLgppdkez9JD2
- */
- apiKey: {
- value: '7w6kuU5Ee6KSgRRExf2KLgppdkez9JD2'
- }
- }
- });
- }, '2.0.0' ,{requires:['base', 'jsonp']});
- YUI.add('fl-spinner', function(Y) {
- (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);
- }, '2.0.0' );
- YUI.add('fl-utils', function(Y) {
- /**
- * @module fl-utils
- */
- /**
- * General helper functions for all FastLine modules.
- *
- * @namespace FL
- * @class Utils
- * @constructor
- * @static
- */
- Y.namespace('FL').Utils = {
- /**
- * Checks for support of the provided CSS property.
- * Method adapted from: https://gist.github.com/556448
- *
- * @method cssSupport
- * @param p {String} The property to check.
- * @returns Boolean
- */
- cssSupport: function(p)
- {
- var b = document.body || document.documentElement,
- s = b.style,
- v = ['Moz', 'Webkit', 'Khtml', 'O', 'ms', 'Icab'],
- i = 0;
- // Transform not working well in these browsers
- if(p == 'transform' && Y.UA.gecko && Y.UA.gecko < 4) { return false; }
- if(p == 'transform' && Y.UA.opera > 0) { return false; }
- if(p == 'transform' && Y.UA.ie > 0 && Y.UA.ie < 10) { return false; }
- if(p == 'transform' && navigator.userAgent.match(/Trident/)) { return false; }
- // No css support detected
- if(typeof s == 'undefined') { return false; }
- // Tests for standard prop
- if(typeof s[p] == 'string') { return true; }
- // Tests for vendor specific prop
- p = p.charAt(0).toUpperCase() + p.substr(1);
- for( ; i < v.length; i++) {
- if(typeof s[v[i] + p] == 'string') { return true; }
- }
- }
- };
- }, '2.0.0' );
|