foundation.cjs.js 342 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
  4. var $ = _interopDefault(require('jquery'));
  5. function _typeof(obj) {
  6. if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
  7. _typeof = function (obj) {
  8. return typeof obj;
  9. };
  10. } else {
  11. _typeof = function (obj) {
  12. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  13. };
  14. }
  15. return _typeof(obj);
  16. }
  17. function _classCallCheck(instance, Constructor) {
  18. if (!(instance instanceof Constructor)) {
  19. throw new TypeError("Cannot call a class as a function");
  20. }
  21. }
  22. function _defineProperties(target, props) {
  23. for (var i = 0; i < props.length; i++) {
  24. var descriptor = props[i];
  25. descriptor.enumerable = descriptor.enumerable || false;
  26. descriptor.configurable = true;
  27. if ("value" in descriptor) descriptor.writable = true;
  28. Object.defineProperty(target, descriptor.key, descriptor);
  29. }
  30. }
  31. function _createClass(Constructor, protoProps, staticProps) {
  32. if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  33. if (staticProps) _defineProperties(Constructor, staticProps);
  34. return Constructor;
  35. }
  36. function _inherits(subClass, superClass) {
  37. if (typeof superClass !== "function" && superClass !== null) {
  38. throw new TypeError("Super expression must either be null or a function");
  39. }
  40. subClass.prototype = Object.create(superClass && superClass.prototype, {
  41. constructor: {
  42. value: subClass,
  43. writable: true,
  44. configurable: true
  45. }
  46. });
  47. if (superClass) _setPrototypeOf(subClass, superClass);
  48. }
  49. function _getPrototypeOf(o) {
  50. _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
  51. return o.__proto__ || Object.getPrototypeOf(o);
  52. };
  53. return _getPrototypeOf(o);
  54. }
  55. function _setPrototypeOf(o, p) {
  56. _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
  57. o.__proto__ = p;
  58. return o;
  59. };
  60. return _setPrototypeOf(o, p);
  61. }
  62. function _assertThisInitialized(self) {
  63. if (self === void 0) {
  64. throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  65. }
  66. return self;
  67. }
  68. function _possibleConstructorReturn(self, call) {
  69. if (call && (typeof call === "object" || typeof call === "function")) {
  70. return call;
  71. }
  72. return _assertThisInitialized(self);
  73. }
  74. function _superPropBase(object, property) {
  75. while (!Object.prototype.hasOwnProperty.call(object, property)) {
  76. object = _getPrototypeOf(object);
  77. if (object === null) break;
  78. }
  79. return object;
  80. }
  81. function _get(target, property, receiver) {
  82. if (typeof Reflect !== "undefined" && Reflect.get) {
  83. _get = Reflect.get;
  84. } else {
  85. _get = function _get(target, property, receiver) {
  86. var base = _superPropBase(target, property);
  87. if (!base) return;
  88. var desc = Object.getOwnPropertyDescriptor(base, property);
  89. if (desc.get) {
  90. return desc.get.call(receiver);
  91. }
  92. return desc.value;
  93. };
  94. }
  95. return _get(target, property, receiver || target);
  96. }
  97. /**
  98. * Returns a boolean for RTL support
  99. */
  100. function rtl() {
  101. return $('html').attr('dir') === 'rtl';
  102. }
  103. /**
  104. * returns a random base-36 uid with namespacing
  105. * @function
  106. * @param {Number} length - number of random base-36 digits desired. Increase for more random strings.
  107. * @param {String} namespace - name of plugin to be incorporated in uid, optional.
  108. * @default {String} '' - if no plugin name is provided, nothing is appended to the uid.
  109. * @returns {String} - unique id
  110. */
  111. function GetYoDigits(length, namespace) {
  112. length = length || 6;
  113. return Math.round(Math.pow(36, length + 1) - Math.random() * Math.pow(36, length)).toString(36).slice(1) + (namespace ? "-".concat(namespace) : '');
  114. }
  115. /**
  116. * Escape a string so it can be used as a regexp pattern
  117. * @function
  118. * @see https://stackoverflow.com/a/9310752/4317384
  119. *
  120. * @param {String} str - string to escape.
  121. * @returns {String} - escaped string
  122. */
  123. function RegExpEscape(str) {
  124. return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
  125. }
  126. function transitionend($elem) {
  127. var transitions = {
  128. 'transition': 'transitionend',
  129. 'WebkitTransition': 'webkitTransitionEnd',
  130. 'MozTransition': 'transitionend',
  131. 'OTransition': 'otransitionend'
  132. };
  133. var elem = document.createElement('div'),
  134. end;
  135. for (var t in transitions) {
  136. if (typeof elem.style[t] !== 'undefined') {
  137. end = transitions[t];
  138. }
  139. }
  140. if (end) {
  141. return end;
  142. } else {
  143. end = setTimeout(function () {
  144. $elem.triggerHandler('transitionend', [$elem]);
  145. }, 1);
  146. return 'transitionend';
  147. }
  148. }
  149. /**
  150. * Return an event type to listen for window load.
  151. *
  152. * If `$elem` is passed, an event will be triggered on `$elem`. If window is already loaded, the event will still be triggered.
  153. * If `handler` is passed, attach it to the event on `$elem`.
  154. * Calling `onLoad` without handler allows you to get the event type that will be triggered before attaching the handler by yourself.
  155. * @function
  156. *
  157. * @param {Object} [] $elem - jQuery element on which the event will be triggered if passed.
  158. * @param {Function} [] handler - function to attach to the event.
  159. * @returns {String} - event type that should or will be triggered.
  160. */
  161. function onLoad($elem, handler) {
  162. var didLoad = document.readyState === 'complete';
  163. var eventType = (didLoad ? '_didLoad' : 'load') + '.zf.util.onLoad';
  164. var cb = function cb() {
  165. return $elem.triggerHandler(eventType);
  166. };
  167. if ($elem) {
  168. if (handler) $elem.one(eventType, handler);
  169. if (didLoad) setTimeout(cb);else $(window).one('load', cb);
  170. }
  171. return eventType;
  172. }
  173. /**
  174. * Retuns an handler for the `mouseleave` that ignore disappeared mouses.
  175. *
  176. * If the mouse "disappeared" from the document (like when going on a browser UI element, See https://git.io/zf-11410),
  177. * the event is ignored.
  178. * - If the `ignoreLeaveWindow` is `true`, the event is ignored when the user actually left the window
  179. * (like by switching to an other window with [Alt]+[Tab]).
  180. * - If the `ignoreReappear` is `true`, the event will be ignored when the mouse will reappear later on the document
  181. * outside of the element it left.
  182. *
  183. * @function
  184. *
  185. * @param {Function} [] handler - handler for the filtered `mouseleave` event to watch.
  186. * @param {Object} [] options - object of options:
  187. * - {Boolean} [false] ignoreLeaveWindow - also ignore when the user switched windows.
  188. * - {Boolean} [false] ignoreReappear - also ignore when the mouse reappeared outside of the element it left.
  189. * @returns {Function} - filtered handler to use to listen on the `mouseleave` event.
  190. */
  191. function ignoreMousedisappear(handler) {
  192. var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
  193. _ref$ignoreLeaveWindo = _ref.ignoreLeaveWindow,
  194. ignoreLeaveWindow = _ref$ignoreLeaveWindo === void 0 ? false : _ref$ignoreLeaveWindo,
  195. _ref$ignoreReappear = _ref.ignoreReappear,
  196. ignoreReappear = _ref$ignoreReappear === void 0 ? false : _ref$ignoreReappear;
  197. return function leaveEventHandler(eLeave) {
  198. for (var _len = arguments.length, rest = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  199. rest[_key - 1] = arguments[_key];
  200. }
  201. var callback = handler.bind.apply(handler, [this, eLeave].concat(rest)); // The mouse left: call the given callback if the mouse entered elsewhere
  202. if (eLeave.relatedTarget !== null) {
  203. return callback();
  204. } // Otherwise, check if the mouse actually left the window.
  205. // In firefox if the user switched between windows, the window sill have the focus by the time
  206. // the event is triggered. We have to debounce the event to test this case.
  207. setTimeout(function leaveEventDebouncer() {
  208. if (!ignoreLeaveWindow && document.hasFocus && !document.hasFocus()) {
  209. return callback();
  210. } // Otherwise, wait for the mouse to reeapear outside of the element,
  211. if (!ignoreReappear) {
  212. $(document).one('mouseenter', function reenterEventHandler(eReenter) {
  213. if (!$(eLeave.currentTarget).has(eReenter.target).length) {
  214. // Fill where the mouse finally entered.
  215. eLeave.relatedTarget = eReenter.target;
  216. callback();
  217. }
  218. });
  219. }
  220. }, 0);
  221. };
  222. }
  223. var foundation_core_utils = /*#__PURE__*/Object.freeze({
  224. rtl: rtl,
  225. GetYoDigits: GetYoDigits,
  226. RegExpEscape: RegExpEscape,
  227. transitionend: transitionend,
  228. onLoad: onLoad,
  229. ignoreMousedisappear: ignoreMousedisappear
  230. });
  231. // Authors & copyright(c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas, David Knight. MIT license
  232. /* eslint-disable */
  233. window.matchMedia || (window.matchMedia = function () {
  234. var styleMedia = window.styleMedia || window.media; // For those that don't support matchMedium
  235. if (!styleMedia) {
  236. var style = document.createElement('style'),
  237. script = document.getElementsByTagName('script')[0],
  238. info = null;
  239. style.type = 'text/css';
  240. style.id = 'matchmediajs-test';
  241. if (!script) {
  242. document.head.appendChild(style);
  243. } else {
  244. script.parentNode.insertBefore(style, script);
  245. } // 'style.currentStyle' is used by IE <= 8 and 'window.getComputedStyle' for all other browsers
  246. info = 'getComputedStyle' in window && window.getComputedStyle(style, null) || style.currentStyle;
  247. styleMedia = {
  248. matchMedium: function matchMedium(media) {
  249. var text = '@media ' + media + '{ #matchmediajs-test { width: 1px; } }'; // 'style.styleSheet' is used by IE <= 8 and 'style.textContent' for all other browsers
  250. if (style.styleSheet) {
  251. style.styleSheet.cssText = text;
  252. } else {
  253. style.textContent = text;
  254. } // Test if media query is true or false
  255. return info.width === '1px';
  256. }
  257. };
  258. }
  259. return function (media) {
  260. return {
  261. matches: styleMedia.matchMedium(media || 'all'),
  262. media: media || 'all'
  263. };
  264. };
  265. }());
  266. /* eslint-enable */
  267. var MediaQuery = {
  268. queries: [],
  269. current: '',
  270. /**
  271. * Initializes the media query helper, by extracting the breakpoint list from the CSS and activating the breakpoint watcher.
  272. * @function
  273. * @private
  274. */
  275. _init: function _init() {
  276. var self = this;
  277. var $meta = $('meta.foundation-mq');
  278. if (!$meta.length) {
  279. $('<meta class="foundation-mq">').appendTo(document.head);
  280. }
  281. var extractedStyles = $('.foundation-mq').css('font-family');
  282. var namedQueries;
  283. namedQueries = parseStyleToObject(extractedStyles);
  284. for (var key in namedQueries) {
  285. if (namedQueries.hasOwnProperty(key)) {
  286. self.queries.push({
  287. name: key,
  288. value: "only screen and (min-width: ".concat(namedQueries[key], ")")
  289. });
  290. }
  291. }
  292. this.current = this._getCurrentSize();
  293. this._watcher();
  294. },
  295. /**
  296. * Checks if the screen is at least as wide as a breakpoint.
  297. * @function
  298. * @param {String} size - Name of the breakpoint to check.
  299. * @returns {Boolean} `true` if the breakpoint matches, `false` if it's smaller.
  300. */
  301. atLeast: function atLeast(size) {
  302. var query = this.get(size);
  303. if (query) {
  304. return window.matchMedia(query).matches;
  305. }
  306. return false;
  307. },
  308. /**
  309. * Checks if the screen matches to a breakpoint.
  310. * @function
  311. * @param {String} size - Name of the breakpoint to check, either 'small only' or 'small'. Omitting 'only' falls back to using atLeast() method.
  312. * @returns {Boolean} `true` if the breakpoint matches, `false` if it does not.
  313. */
  314. is: function is(size) {
  315. size = size.trim().split(' ');
  316. if (size.length > 1 && size[1] === 'only') {
  317. if (size[0] === this._getCurrentSize()) return true;
  318. } else {
  319. return this.atLeast(size[0]);
  320. }
  321. return false;
  322. },
  323. /**
  324. * Gets the media query of a breakpoint.
  325. * @function
  326. * @param {String} size - Name of the breakpoint to get.
  327. * @returns {String|null} - The media query of the breakpoint, or `null` if the breakpoint doesn't exist.
  328. */
  329. get: function get(size) {
  330. for (var i in this.queries) {
  331. if (this.queries.hasOwnProperty(i)) {
  332. var query = this.queries[i];
  333. if (size === query.name) return query.value;
  334. }
  335. }
  336. return null;
  337. },
  338. /**
  339. * Gets the current breakpoint name by testing every breakpoint and returning the last one to match (the biggest one).
  340. * @function
  341. * @private
  342. * @returns {String} Name of the current breakpoint.
  343. */
  344. _getCurrentSize: function _getCurrentSize() {
  345. var matched;
  346. for (var i = 0; i < this.queries.length; i++) {
  347. var query = this.queries[i];
  348. if (window.matchMedia(query.value).matches) {
  349. matched = query;
  350. }
  351. }
  352. if (_typeof(matched) === 'object') {
  353. return matched.name;
  354. } else {
  355. return matched;
  356. }
  357. },
  358. /**
  359. * Activates the breakpoint watcher, which fires an event on the window whenever the breakpoint changes.
  360. * @function
  361. * @private
  362. */
  363. _watcher: function _watcher() {
  364. var _this = this;
  365. $(window).off('resize.zf.mediaquery').on('resize.zf.mediaquery', function () {
  366. var newSize = _this._getCurrentSize(),
  367. currentSize = _this.current;
  368. if (newSize !== currentSize) {
  369. // Change the current media query
  370. _this.current = newSize; // Broadcast the media query change on the window
  371. $(window).trigger('changed.zf.mediaquery', [newSize, currentSize]);
  372. }
  373. });
  374. }
  375. }; // Thank you: https://github.com/sindresorhus/query-string
  376. function parseStyleToObject(str) {
  377. var styleObject = {};
  378. if (typeof str !== 'string') {
  379. return styleObject;
  380. }
  381. str = str.trim().slice(1, -1); // browsers re-quote string style values
  382. if (!str) {
  383. return styleObject;
  384. }
  385. styleObject = str.split('&').reduce(function (ret, param) {
  386. var parts = param.replace(/\+/g, ' ').split('=');
  387. var key = parts[0];
  388. var val = parts[1];
  389. key = decodeURIComponent(key); // missing `=` should be `null`:
  390. // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
  391. val = typeof val === 'undefined' ? null : decodeURIComponent(val);
  392. if (!ret.hasOwnProperty(key)) {
  393. ret[key] = val;
  394. } else if (Array.isArray(ret[key])) {
  395. ret[key].push(val);
  396. } else {
  397. ret[key] = [ret[key], val];
  398. }
  399. return ret;
  400. }, {});
  401. return styleObject;
  402. }
  403. var FOUNDATION_VERSION = '6.5.3'; // Global Foundation object
  404. // This is attached to the window, or used as a module for AMD/Browserify
  405. var Foundation = {
  406. version: FOUNDATION_VERSION,
  407. /**
  408. * Stores initialized plugins.
  409. */
  410. _plugins: {},
  411. /**
  412. * Stores generated unique ids for plugin instances
  413. */
  414. _uuids: [],
  415. /**
  416. * Defines a Foundation plugin, adding it to the `Foundation` namespace and the list of plugins to initialize when reflowing.
  417. * @param {Object} plugin - The constructor of the plugin.
  418. */
  419. plugin: function plugin(_plugin, name) {
  420. // Object key to use when adding to global Foundation object
  421. // Examples: Foundation.Reveal, Foundation.OffCanvas
  422. var className = name || functionName(_plugin); // Object key to use when storing the plugin, also used to create the identifying data attribute for the plugin
  423. // Examples: data-reveal, data-off-canvas
  424. var attrName = hyphenate(className); // Add to the Foundation object and the plugins list (for reflowing)
  425. this._plugins[attrName] = this[className] = _plugin;
  426. },
  427. /**
  428. * @function
  429. * Populates the _uuids array with pointers to each individual plugin instance.
  430. * Adds the `zfPlugin` data-attribute to programmatically created plugins to allow use of $(selector).foundation(method) calls.
  431. * Also fires the initialization event for each plugin, consolidating repetitive code.
  432. * @param {Object} plugin - an instance of a plugin, usually `this` in context.
  433. * @param {String} name - the name of the plugin, passed as a camelCased string.
  434. * @fires Plugin#init
  435. */
  436. registerPlugin: function registerPlugin(plugin, name) {
  437. var pluginName = name ? hyphenate(name) : functionName(plugin.constructor).toLowerCase();
  438. plugin.uuid = GetYoDigits(6, pluginName);
  439. if (!plugin.$element.attr("data-".concat(pluginName))) {
  440. plugin.$element.attr("data-".concat(pluginName), plugin.uuid);
  441. }
  442. if (!plugin.$element.data('zfPlugin')) {
  443. plugin.$element.data('zfPlugin', plugin);
  444. }
  445. /**
  446. * Fires when the plugin has initialized.
  447. * @event Plugin#init
  448. */
  449. plugin.$element.trigger("init.zf.".concat(pluginName));
  450. this._uuids.push(plugin.uuid);
  451. return;
  452. },
  453. /**
  454. * @function
  455. * Removes the plugins uuid from the _uuids array.
  456. * Removes the zfPlugin data attribute, as well as the data-plugin-name attribute.
  457. * Also fires the destroyed event for the plugin, consolidating repetitive code.
  458. * @param {Object} plugin - an instance of a plugin, usually `this` in context.
  459. * @fires Plugin#destroyed
  460. */
  461. unregisterPlugin: function unregisterPlugin(plugin) {
  462. var pluginName = hyphenate(functionName(plugin.$element.data('zfPlugin').constructor));
  463. this._uuids.splice(this._uuids.indexOf(plugin.uuid), 1);
  464. plugin.$element.removeAttr("data-".concat(pluginName)).removeData('zfPlugin')
  465. /**
  466. * Fires when the plugin has been destroyed.
  467. * @event Plugin#destroyed
  468. */
  469. .trigger("destroyed.zf.".concat(pluginName));
  470. for (var prop in plugin) {
  471. plugin[prop] = null; //clean up script to prep for garbage collection.
  472. }
  473. return;
  474. },
  475. /**
  476. * @function
  477. * Causes one or more active plugins to re-initialize, resetting event listeners, recalculating positions, etc.
  478. * @param {String} plugins - optional string of an individual plugin key, attained by calling `$(element).data('pluginName')`, or string of a plugin class i.e. `'dropdown'`
  479. * @default If no argument is passed, reflow all currently active plugins.
  480. */
  481. reInit: function reInit(plugins) {
  482. var isJQ = plugins instanceof $;
  483. try {
  484. if (isJQ) {
  485. plugins.each(function () {
  486. $(this).data('zfPlugin')._init();
  487. });
  488. } else {
  489. var type = _typeof(plugins),
  490. _this = this,
  491. fns = {
  492. 'object': function object(plgs) {
  493. plgs.forEach(function (p) {
  494. p = hyphenate(p);
  495. $('[data-' + p + ']').foundation('_init');
  496. });
  497. },
  498. 'string': function string() {
  499. plugins = hyphenate(plugins);
  500. $('[data-' + plugins + ']').foundation('_init');
  501. },
  502. 'undefined': function undefined() {
  503. this['object'](Object.keys(_this._plugins));
  504. }
  505. };
  506. fns[type](plugins);
  507. }
  508. } catch (err) {
  509. console.error(err);
  510. } finally {
  511. return plugins;
  512. }
  513. },
  514. /**
  515. * Initialize plugins on any elements within `elem` (and `elem` itself) that aren't already initialized.
  516. * @param {Object} elem - jQuery object containing the element to check inside. Also checks the element itself, unless it's the `document` object.
  517. * @param {String|Array} plugins - A list of plugins to initialize. Leave this out to initialize everything.
  518. */
  519. reflow: function reflow(elem, plugins) {
  520. // If plugins is undefined, just grab everything
  521. if (typeof plugins === 'undefined') {
  522. plugins = Object.keys(this._plugins);
  523. } // If plugins is a string, convert it to an array with one item
  524. else if (typeof plugins === 'string') {
  525. plugins = [plugins];
  526. }
  527. var _this = this; // Iterate through each plugin
  528. $.each(plugins, function (i, name) {
  529. // Get the current plugin
  530. var plugin = _this._plugins[name]; // Localize the search to all elements inside elem, as well as elem itself, unless elem === document
  531. var $elem = $(elem).find('[data-' + name + ']').addBack('[data-' + name + ']'); // For each plugin found, initialize it
  532. $elem.each(function () {
  533. var $el = $(this),
  534. opts = {}; // Don't double-dip on plugins
  535. if ($el.data('zfPlugin')) {
  536. console.warn("Tried to initialize " + name + " on an element that already has a Foundation plugin.");
  537. return;
  538. }
  539. if ($el.attr('data-options')) {
  540. var thing = $el.attr('data-options').split(';').forEach(function (e, i) {
  541. var opt = e.split(':').map(function (el) {
  542. return el.trim();
  543. });
  544. if (opt[0]) opts[opt[0]] = parseValue(opt[1]);
  545. });
  546. }
  547. try {
  548. $el.data('zfPlugin', new plugin($(this), opts));
  549. } catch (er) {
  550. console.error(er);
  551. } finally {
  552. return;
  553. }
  554. });
  555. });
  556. },
  557. getFnName: functionName,
  558. addToJquery: function addToJquery($$$1) {
  559. // TODO: consider not making this a jQuery function
  560. // TODO: need way to reflow vs. re-initialize
  561. /**
  562. * The Foundation jQuery method.
  563. * @param {String|Array} method - An action to perform on the current jQuery object.
  564. */
  565. var foundation = function foundation(method) {
  566. var type = _typeof(method),
  567. $noJS = $$$1('.no-js');
  568. if ($noJS.length) {
  569. $noJS.removeClass('no-js');
  570. }
  571. if (type === 'undefined') {
  572. //needs to initialize the Foundation object, or an individual plugin.
  573. MediaQuery._init();
  574. Foundation.reflow(this);
  575. } else if (type === 'string') {
  576. //an individual method to invoke on a plugin or group of plugins
  577. var args = Array.prototype.slice.call(arguments, 1); //collect all the arguments, if necessary
  578. var plugClass = this.data('zfPlugin'); //determine the class of plugin
  579. if (typeof plugClass !== 'undefined' && typeof plugClass[method] !== 'undefined') {
  580. //make sure both the class and method exist
  581. if (this.length === 1) {
  582. //if there's only one, call it directly.
  583. plugClass[method].apply(plugClass, args);
  584. } else {
  585. this.each(function (i, el) {
  586. //otherwise loop through the jQuery collection and invoke the method on each
  587. plugClass[method].apply($$$1(el).data('zfPlugin'), args);
  588. });
  589. }
  590. } else {
  591. //error for no class or no method
  592. throw new ReferenceError("We're sorry, '" + method + "' is not an available method for " + (plugClass ? functionName(plugClass) : 'this element') + '.');
  593. }
  594. } else {
  595. //error for invalid argument type
  596. throw new TypeError("We're sorry, ".concat(type, " is not a valid parameter. You must use a string representing the method you wish to invoke."));
  597. }
  598. return this;
  599. };
  600. $$$1.fn.foundation = foundation;
  601. return $$$1;
  602. }
  603. };
  604. Foundation.util = {
  605. /**
  606. * Function for applying a debounce effect to a function call.
  607. * @function
  608. * @param {Function} func - Function to be called at end of timeout.
  609. * @param {Number} delay - Time in ms to delay the call of `func`.
  610. * @returns function
  611. */
  612. throttle: function throttle(func, delay) {
  613. var timer = null;
  614. return function () {
  615. var context = this,
  616. args = arguments;
  617. if (timer === null) {
  618. timer = setTimeout(function () {
  619. func.apply(context, args);
  620. timer = null;
  621. }, delay);
  622. }
  623. };
  624. }
  625. };
  626. window.Foundation = Foundation; // Polyfill for requestAnimationFrame
  627. (function () {
  628. if (!Date.now || !window.Date.now) window.Date.now = Date.now = function () {
  629. return new Date().getTime();
  630. };
  631. var vendors = ['webkit', 'moz'];
  632. for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
  633. var vp = vendors[i];
  634. window.requestAnimationFrame = window[vp + 'RequestAnimationFrame'];
  635. window.cancelAnimationFrame = window[vp + 'CancelAnimationFrame'] || window[vp + 'CancelRequestAnimationFrame'];
  636. }
  637. if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
  638. var lastTime = 0;
  639. window.requestAnimationFrame = function (callback) {
  640. var now = Date.now();
  641. var nextTime = Math.max(lastTime + 16, now);
  642. return setTimeout(function () {
  643. callback(lastTime = nextTime);
  644. }, nextTime - now);
  645. };
  646. window.cancelAnimationFrame = clearTimeout;
  647. }
  648. /**
  649. * Polyfill for performance.now, required by rAF
  650. */
  651. if (!window.performance || !window.performance.now) {
  652. window.performance = {
  653. start: Date.now(),
  654. now: function now() {
  655. return Date.now() - this.start;
  656. }
  657. };
  658. }
  659. })();
  660. if (!Function.prototype.bind) {
  661. Function.prototype.bind = function (oThis) {
  662. if (typeof this !== 'function') {
  663. // closest thing possible to the ECMAScript 5
  664. // internal IsCallable function
  665. throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
  666. }
  667. var aArgs = Array.prototype.slice.call(arguments, 1),
  668. fToBind = this,
  669. fNOP = function fNOP() {},
  670. fBound = function fBound() {
  671. return fToBind.apply(this instanceof fNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
  672. };
  673. if (this.prototype) {
  674. // native functions don't have a prototype
  675. fNOP.prototype = this.prototype;
  676. }
  677. fBound.prototype = new fNOP();
  678. return fBound;
  679. };
  680. } // Polyfill to get the name of a function in IE9
  681. function functionName(fn) {
  682. if (typeof Function.prototype.name === 'undefined') {
  683. var funcNameRegex = /function\s([^(]{1,})\(/;
  684. var results = funcNameRegex.exec(fn.toString());
  685. return results && results.length > 1 ? results[1].trim() : "";
  686. } else if (typeof fn.prototype === 'undefined') {
  687. return fn.constructor.name;
  688. } else {
  689. return fn.prototype.constructor.name;
  690. }
  691. }
  692. function parseValue(str) {
  693. if ('true' === str) return true;else if ('false' === str) return false;else if (!isNaN(str * 1)) return parseFloat(str);
  694. return str;
  695. } // Convert PascalCase to kebab-case
  696. // Thank you: http://stackoverflow.com/a/8955580
  697. function hyphenate(str) {
  698. return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
  699. }
  700. var Box = {
  701. ImNotTouchingYou: ImNotTouchingYou,
  702. OverlapArea: OverlapArea,
  703. GetDimensions: GetDimensions,
  704. GetOffsets: GetOffsets,
  705. GetExplicitOffsets: GetExplicitOffsets
  706. /**
  707. * Compares the dimensions of an element to a container and determines collision events with container.
  708. * @function
  709. * @param {jQuery} element - jQuery object to test for collisions.
  710. * @param {jQuery} parent - jQuery object to use as bounding container.
  711. * @param {Boolean} lrOnly - set to true to check left and right values only.
  712. * @param {Boolean} tbOnly - set to true to check top and bottom values only.
  713. * @default if no parent object passed, detects collisions with `window`.
  714. * @returns {Boolean} - true if collision free, false if a collision in any direction.
  715. */
  716. };
  717. function ImNotTouchingYou(element, parent, lrOnly, tbOnly, ignoreBottom) {
  718. return OverlapArea(element, parent, lrOnly, tbOnly, ignoreBottom) === 0;
  719. }
  720. function OverlapArea(element, parent, lrOnly, tbOnly, ignoreBottom) {
  721. var eleDims = GetDimensions(element),
  722. topOver,
  723. bottomOver,
  724. leftOver,
  725. rightOver;
  726. if (parent) {
  727. var parDims = GetDimensions(parent);
  728. bottomOver = parDims.height + parDims.offset.top - (eleDims.offset.top + eleDims.height);
  729. topOver = eleDims.offset.top - parDims.offset.top;
  730. leftOver = eleDims.offset.left - parDims.offset.left;
  731. rightOver = parDims.width + parDims.offset.left - (eleDims.offset.left + eleDims.width);
  732. } else {
  733. bottomOver = eleDims.windowDims.height + eleDims.windowDims.offset.top - (eleDims.offset.top + eleDims.height);
  734. topOver = eleDims.offset.top - eleDims.windowDims.offset.top;
  735. leftOver = eleDims.offset.left - eleDims.windowDims.offset.left;
  736. rightOver = eleDims.windowDims.width - (eleDims.offset.left + eleDims.width);
  737. }
  738. bottomOver = ignoreBottom ? 0 : Math.min(bottomOver, 0);
  739. topOver = Math.min(topOver, 0);
  740. leftOver = Math.min(leftOver, 0);
  741. rightOver = Math.min(rightOver, 0);
  742. if (lrOnly) {
  743. return leftOver + rightOver;
  744. }
  745. if (tbOnly) {
  746. return topOver + bottomOver;
  747. } // use sum of squares b/c we care about overlap area.
  748. return Math.sqrt(topOver * topOver + bottomOver * bottomOver + leftOver * leftOver + rightOver * rightOver);
  749. }
  750. /**
  751. * Uses native methods to return an object of dimension values.
  752. * @function
  753. * @param {jQuery || HTML} element - jQuery object or DOM element for which to get the dimensions. Can be any element other that document or window.
  754. * @returns {Object} - nested object of integer pixel values
  755. * TODO - if element is window, return only those values.
  756. */
  757. function GetDimensions(elem) {
  758. elem = elem.length ? elem[0] : elem;
  759. if (elem === window || elem === document) {
  760. throw new Error("I'm sorry, Dave. I'm afraid I can't do that.");
  761. }
  762. var rect = elem.getBoundingClientRect(),
  763. parRect = elem.parentNode.getBoundingClientRect(),
  764. winRect = document.body.getBoundingClientRect(),
  765. winY = window.pageYOffset,
  766. winX = window.pageXOffset;
  767. return {
  768. width: rect.width,
  769. height: rect.height,
  770. offset: {
  771. top: rect.top + winY,
  772. left: rect.left + winX
  773. },
  774. parentDims: {
  775. width: parRect.width,
  776. height: parRect.height,
  777. offset: {
  778. top: parRect.top + winY,
  779. left: parRect.left + winX
  780. }
  781. },
  782. windowDims: {
  783. width: winRect.width,
  784. height: winRect.height,
  785. offset: {
  786. top: winY,
  787. left: winX
  788. }
  789. }
  790. };
  791. }
  792. /**
  793. * Returns an object of top and left integer pixel values for dynamically rendered elements,
  794. * such as: Tooltip, Reveal, and Dropdown. Maintained for backwards compatibility, and where
  795. * you don't know alignment, but generally from
  796. * 6.4 forward you should use GetExplicitOffsets, as GetOffsets conflates position and alignment.
  797. * @function
  798. * @param {jQuery} element - jQuery object for the element being positioned.
  799. * @param {jQuery} anchor - jQuery object for the element's anchor point.
  800. * @param {String} position - a string relating to the desired position of the element, relative to it's anchor
  801. * @param {Number} vOffset - integer pixel value of desired vertical separation between anchor and element.
  802. * @param {Number} hOffset - integer pixel value of desired horizontal separation between anchor and element.
  803. * @param {Boolean} isOverflow - if a collision event is detected, sets to true to default the element to full width - any desired offset.
  804. * TODO alter/rewrite to work with `em` values as well/instead of pixels
  805. */
  806. function GetOffsets(element, anchor, position, vOffset, hOffset, isOverflow) {
  807. console.log("NOTE: GetOffsets is deprecated in favor of GetExplicitOffsets and will be removed in 6.5");
  808. switch (position) {
  809. case 'top':
  810. return rtl() ? GetExplicitOffsets(element, anchor, 'top', 'left', vOffset, hOffset, isOverflow) : GetExplicitOffsets(element, anchor, 'top', 'right', vOffset, hOffset, isOverflow);
  811. case 'bottom':
  812. return rtl() ? GetExplicitOffsets(element, anchor, 'bottom', 'left', vOffset, hOffset, isOverflow) : GetExplicitOffsets(element, anchor, 'bottom', 'right', vOffset, hOffset, isOverflow);
  813. case 'center top':
  814. return GetExplicitOffsets(element, anchor, 'top', 'center', vOffset, hOffset, isOverflow);
  815. case 'center bottom':
  816. return GetExplicitOffsets(element, anchor, 'bottom', 'center', vOffset, hOffset, isOverflow);
  817. case 'center left':
  818. return GetExplicitOffsets(element, anchor, 'left', 'center', vOffset, hOffset, isOverflow);
  819. case 'center right':
  820. return GetExplicitOffsets(element, anchor, 'right', 'center', vOffset, hOffset, isOverflow);
  821. case 'left bottom':
  822. return GetExplicitOffsets(element, anchor, 'bottom', 'left', vOffset, hOffset, isOverflow);
  823. case 'right bottom':
  824. return GetExplicitOffsets(element, anchor, 'bottom', 'right', vOffset, hOffset, isOverflow);
  825. // Backwards compatibility... this along with the reveal and reveal full
  826. // classes are the only ones that didn't reference anchor
  827. case 'center':
  828. return {
  829. left: $eleDims.windowDims.offset.left + $eleDims.windowDims.width / 2 - $eleDims.width / 2 + hOffset,
  830. top: $eleDims.windowDims.offset.top + $eleDims.windowDims.height / 2 - ($eleDims.height / 2 + vOffset)
  831. };
  832. case 'reveal':
  833. return {
  834. left: ($eleDims.windowDims.width - $eleDims.width) / 2 + hOffset,
  835. top: $eleDims.windowDims.offset.top + vOffset
  836. };
  837. case 'reveal full':
  838. return {
  839. left: $eleDims.windowDims.offset.left,
  840. top: $eleDims.windowDims.offset.top
  841. };
  842. break;
  843. default:
  844. return {
  845. left: rtl() ? $anchorDims.offset.left - $eleDims.width + $anchorDims.width - hOffset : $anchorDims.offset.left + hOffset,
  846. top: $anchorDims.offset.top + $anchorDims.height + vOffset
  847. };
  848. }
  849. }
  850. function GetExplicitOffsets(element, anchor, position, alignment, vOffset, hOffset, isOverflow) {
  851. var $eleDims = GetDimensions(element),
  852. $anchorDims = anchor ? GetDimensions(anchor) : null;
  853. var topVal, leftVal; // set position related attribute
  854. switch (position) {
  855. case 'top':
  856. topVal = $anchorDims.offset.top - ($eleDims.height + vOffset);
  857. break;
  858. case 'bottom':
  859. topVal = $anchorDims.offset.top + $anchorDims.height + vOffset;
  860. break;
  861. case 'left':
  862. leftVal = $anchorDims.offset.left - ($eleDims.width + hOffset);
  863. break;
  864. case 'right':
  865. leftVal = $anchorDims.offset.left + $anchorDims.width + hOffset;
  866. break;
  867. } // set alignment related attribute
  868. switch (position) {
  869. case 'top':
  870. case 'bottom':
  871. switch (alignment) {
  872. case 'left':
  873. leftVal = $anchorDims.offset.left + hOffset;
  874. break;
  875. case 'right':
  876. leftVal = $anchorDims.offset.left - $eleDims.width + $anchorDims.width - hOffset;
  877. break;
  878. case 'center':
  879. leftVal = isOverflow ? hOffset : $anchorDims.offset.left + $anchorDims.width / 2 - $eleDims.width / 2 + hOffset;
  880. break;
  881. }
  882. break;
  883. case 'right':
  884. case 'left':
  885. switch (alignment) {
  886. case 'bottom':
  887. topVal = $anchorDims.offset.top - vOffset + $anchorDims.height - $eleDims.height;
  888. break;
  889. case 'top':
  890. topVal = $anchorDims.offset.top + vOffset;
  891. break;
  892. case 'center':
  893. topVal = $anchorDims.offset.top + vOffset + $anchorDims.height / 2 - $eleDims.height / 2;
  894. break;
  895. }
  896. break;
  897. }
  898. return {
  899. top: topVal,
  900. left: leftVal
  901. };
  902. }
  903. /**
  904. * Runs a callback function when images are fully loaded.
  905. * @param {Object} images - Image(s) to check if loaded.
  906. * @param {Func} callback - Function to execute when image is fully loaded.
  907. */
  908. function onImagesLoaded(images, callback) {
  909. var unloaded = images.length;
  910. if (unloaded === 0) {
  911. callback();
  912. }
  913. images.each(function () {
  914. // Check if image is loaded
  915. if (this.complete && typeof this.naturalWidth !== 'undefined') {
  916. singleImageLoaded();
  917. } else {
  918. // If the above check failed, simulate loading on detached element.
  919. var image = new Image(); // Still count image as loaded if it finalizes with an error.
  920. var events = "load.zf.images error.zf.images";
  921. $(image).one(events, function me(event) {
  922. // Unbind the event listeners. We're using 'one' but only one of the two events will have fired.
  923. $(this).off(events, me);
  924. singleImageLoaded();
  925. });
  926. image.src = $(this).attr('src');
  927. }
  928. });
  929. function singleImageLoaded() {
  930. unloaded--;
  931. if (unloaded === 0) {
  932. callback();
  933. }
  934. }
  935. }
  936. /*******************************************
  937. * *
  938. * This util was created by Marius Olbertz *
  939. * Please thank Marius on GitHub /owlbertz *
  940. * or the web http://www.mariusolbertz.de/ *
  941. * *
  942. ******************************************/
  943. var keyCodes = {
  944. 9: 'TAB',
  945. 13: 'ENTER',
  946. 27: 'ESCAPE',
  947. 32: 'SPACE',
  948. 35: 'END',
  949. 36: 'HOME',
  950. 37: 'ARROW_LEFT',
  951. 38: 'ARROW_UP',
  952. 39: 'ARROW_RIGHT',
  953. 40: 'ARROW_DOWN'
  954. };
  955. var commands = {}; // Functions pulled out to be referenceable from internals
  956. function findFocusable($element) {
  957. if (!$element) {
  958. return false;
  959. }
  960. return $element.find('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]').filter(function () {
  961. if (!$(this).is(':visible') || $(this).attr('tabindex') < 0) {
  962. return false;
  963. } //only have visible elements and those that have a tabindex greater or equal 0
  964. return true;
  965. });
  966. }
  967. function parseKey(event) {
  968. var key = keyCodes[event.which || event.keyCode] || String.fromCharCode(event.which).toUpperCase(); // Remove un-printable characters, e.g. for `fromCharCode` calls for CTRL only events
  969. key = key.replace(/\W+/, '');
  970. if (event.shiftKey) key = "SHIFT_".concat(key);
  971. if (event.ctrlKey) key = "CTRL_".concat(key);
  972. if (event.altKey) key = "ALT_".concat(key); // Remove trailing underscore, in case only modifiers were used (e.g. only `CTRL_ALT`)
  973. key = key.replace(/_$/, '');
  974. return key;
  975. }
  976. var Keyboard = {
  977. keys: getKeyCodes(keyCodes),
  978. /**
  979. * Parses the (keyboard) event and returns a String that represents its key
  980. * Can be used like Foundation.parseKey(event) === Foundation.keys.SPACE
  981. * @param {Event} event - the event generated by the event handler
  982. * @return String key - String that represents the key pressed
  983. */
  984. parseKey: parseKey,
  985. /**
  986. * Handles the given (keyboard) event
  987. * @param {Event} event - the event generated by the event handler
  988. * @param {String} component - Foundation component's name, e.g. Slider or Reveal
  989. * @param {Objects} functions - collection of functions that are to be executed
  990. */
  991. handleKey: function handleKey(event, component, functions) {
  992. var commandList = commands[component],
  993. keyCode = this.parseKey(event),
  994. cmds,
  995. command,
  996. fn;
  997. if (!commandList) return console.warn('Component not defined!');
  998. if (typeof commandList.ltr === 'undefined') {
  999. // this component does not differentiate between ltr and rtl
  1000. cmds = commandList; // use plain list
  1001. } else {
  1002. // merge ltr and rtl: if document is rtl, rtl overwrites ltr and vice versa
  1003. if (rtl()) cmds = $.extend({}, commandList.ltr, commandList.rtl);else cmds = $.extend({}, commandList.rtl, commandList.ltr);
  1004. }
  1005. command = cmds[keyCode];
  1006. fn = functions[command];
  1007. if (fn && typeof fn === 'function') {
  1008. // execute function if exists
  1009. var returnValue = fn.apply();
  1010. if (functions.handled || typeof functions.handled === 'function') {
  1011. // execute function when event was handled
  1012. functions.handled(returnValue);
  1013. }
  1014. } else {
  1015. if (functions.unhandled || typeof functions.unhandled === 'function') {
  1016. // execute function when event was not handled
  1017. functions.unhandled();
  1018. }
  1019. }
  1020. },
  1021. /**
  1022. * Finds all focusable elements within the given `$element`
  1023. * @param {jQuery} $element - jQuery object to search within
  1024. * @return {jQuery} $focusable - all focusable elements within `$element`
  1025. */
  1026. findFocusable: findFocusable,
  1027. /**
  1028. * Returns the component name name
  1029. * @param {Object} component - Foundation component, e.g. Slider or Reveal
  1030. * @return String componentName
  1031. */
  1032. register: function register(componentName, cmds) {
  1033. commands[componentName] = cmds;
  1034. },
  1035. // TODO9438: These references to Keyboard need to not require global. Will 'this' work in this context?
  1036. //
  1037. /**
  1038. * Traps the focus in the given element.
  1039. * @param {jQuery} $element jQuery object to trap the foucs into.
  1040. */
  1041. trapFocus: function trapFocus($element) {
  1042. var $focusable = findFocusable($element),
  1043. $firstFocusable = $focusable.eq(0),
  1044. $lastFocusable = $focusable.eq(-1);
  1045. $element.on('keydown.zf.trapfocus', function (event) {
  1046. if (event.target === $lastFocusable[0] && parseKey(event) === 'TAB') {
  1047. event.preventDefault();
  1048. $firstFocusable.focus();
  1049. } else if (event.target === $firstFocusable[0] && parseKey(event) === 'SHIFT_TAB') {
  1050. event.preventDefault();
  1051. $lastFocusable.focus();
  1052. }
  1053. });
  1054. },
  1055. /**
  1056. * Releases the trapped focus from the given element.
  1057. * @param {jQuery} $element jQuery object to release the focus for.
  1058. */
  1059. releaseFocus: function releaseFocus($element) {
  1060. $element.off('keydown.zf.trapfocus');
  1061. }
  1062. };
  1063. /*
  1064. * Constants for easier comparing.
  1065. * Can be used like Foundation.parseKey(event) === Foundation.keys.SPACE
  1066. */
  1067. function getKeyCodes(kcs) {
  1068. var k = {};
  1069. for (var kc in kcs) {
  1070. k[kcs[kc]] = kcs[kc];
  1071. }
  1072. return k;
  1073. }
  1074. /**
  1075. * Motion module.
  1076. * @module foundation.motion
  1077. */
  1078. var initClasses = ['mui-enter', 'mui-leave'];
  1079. var activeClasses = ['mui-enter-active', 'mui-leave-active'];
  1080. var Motion = {
  1081. animateIn: function animateIn(element, animation, cb) {
  1082. animate(true, element, animation, cb);
  1083. },
  1084. animateOut: function animateOut(element, animation, cb) {
  1085. animate(false, element, animation, cb);
  1086. }
  1087. };
  1088. function Move(duration, elem, fn) {
  1089. var anim,
  1090. prog,
  1091. start = null; // console.log('called');
  1092. if (duration === 0) {
  1093. fn.apply(elem);
  1094. elem.trigger('finished.zf.animate', [elem]).triggerHandler('finished.zf.animate', [elem]);
  1095. return;
  1096. }
  1097. function move(ts) {
  1098. if (!start) start = ts; // console.log(start, ts);
  1099. prog = ts - start;
  1100. fn.apply(elem);
  1101. if (prog < duration) {
  1102. anim = window.requestAnimationFrame(move, elem);
  1103. } else {
  1104. window.cancelAnimationFrame(anim);
  1105. elem.trigger('finished.zf.animate', [elem]).triggerHandler('finished.zf.animate', [elem]);
  1106. }
  1107. }
  1108. anim = window.requestAnimationFrame(move);
  1109. }
  1110. /**
  1111. * Animates an element in or out using a CSS transition class.
  1112. * @function
  1113. * @private
  1114. * @param {Boolean} isIn - Defines if the animation is in or out.
  1115. * @param {Object} element - jQuery or HTML object to animate.
  1116. * @param {String} animation - CSS class to use.
  1117. * @param {Function} cb - Callback to run when animation is finished.
  1118. */
  1119. function animate(isIn, element, animation, cb) {
  1120. element = $(element).eq(0);
  1121. if (!element.length) return;
  1122. var initClass = isIn ? initClasses[0] : initClasses[1];
  1123. var activeClass = isIn ? activeClasses[0] : activeClasses[1]; // Set up the animation
  1124. reset();
  1125. element.addClass(animation).css('transition', 'none');
  1126. requestAnimationFrame(function () {
  1127. element.addClass(initClass);
  1128. if (isIn) element.show();
  1129. }); // Start the animation
  1130. requestAnimationFrame(function () {
  1131. element[0].offsetWidth;
  1132. element.css('transition', '').addClass(activeClass);
  1133. }); // Clean up the animation when it finishes
  1134. element.one(transitionend(element), finish); // Hides the element (for out animations), resets the element, and runs a callback
  1135. function finish() {
  1136. if (!isIn) element.hide();
  1137. reset();
  1138. if (cb) cb.apply(element);
  1139. } // Resets transitions and removes motion-specific classes
  1140. function reset() {
  1141. element[0].style.transitionDuration = 0;
  1142. element.removeClass("".concat(initClass, " ").concat(activeClass, " ").concat(animation));
  1143. }
  1144. }
  1145. var Nest = {
  1146. Feather: function Feather(menu) {
  1147. var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'zf';
  1148. menu.attr('role', 'menubar');
  1149. var items = menu.find('li').attr({
  1150. 'role': 'menuitem'
  1151. }),
  1152. subMenuClass = "is-".concat(type, "-submenu"),
  1153. subItemClass = "".concat(subMenuClass, "-item"),
  1154. hasSubClass = "is-".concat(type, "-submenu-parent"),
  1155. applyAria = type !== 'accordion'; // Accordions handle their own ARIA attriutes.
  1156. items.each(function () {
  1157. var $item = $(this),
  1158. $sub = $item.children('ul');
  1159. if ($sub.length) {
  1160. $item.addClass(hasSubClass);
  1161. if (applyAria) {
  1162. $item.attr({
  1163. 'aria-haspopup': true,
  1164. 'aria-label': $item.children('a:first').text()
  1165. }); // Note: Drilldowns behave differently in how they hide, and so need
  1166. // additional attributes. We should look if this possibly over-generalized
  1167. // utility (Nest) is appropriate when we rework menus in 6.4
  1168. if (type === 'drilldown') {
  1169. $item.attr({
  1170. 'aria-expanded': false
  1171. });
  1172. }
  1173. }
  1174. $sub.addClass("submenu ".concat(subMenuClass)).attr({
  1175. 'data-submenu': '',
  1176. 'role': 'menubar'
  1177. });
  1178. if (type === 'drilldown') {
  1179. $sub.attr({
  1180. 'aria-hidden': true
  1181. });
  1182. }
  1183. }
  1184. if ($item.parent('[data-submenu]').length) {
  1185. $item.addClass("is-submenu-item ".concat(subItemClass));
  1186. }
  1187. });
  1188. return;
  1189. },
  1190. Burn: function Burn(menu, type) {
  1191. var //items = menu.find('li'),
  1192. subMenuClass = "is-".concat(type, "-submenu"),
  1193. subItemClass = "".concat(subMenuClass, "-item"),
  1194. hasSubClass = "is-".concat(type, "-submenu-parent");
  1195. menu.find('>li, > li > ul, .menu, .menu > li, [data-submenu] > li').removeClass("".concat(subMenuClass, " ").concat(subItemClass, " ").concat(hasSubClass, " is-submenu-item submenu is-active")).removeAttr('data-submenu').css('display', '');
  1196. }
  1197. };
  1198. function Timer(elem, options, cb) {
  1199. var _this = this,
  1200. duration = options.duration,
  1201. //options is an object for easily adding features later.
  1202. nameSpace = Object.keys(elem.data())[0] || 'timer',
  1203. remain = -1,
  1204. start,
  1205. timer;
  1206. this.isPaused = false;
  1207. this.restart = function () {
  1208. remain = -1;
  1209. clearTimeout(timer);
  1210. this.start();
  1211. };
  1212. this.start = function () {
  1213. this.isPaused = false; // if(!elem.data('paused')){ return false; }//maybe implement this sanity check if used for other things.
  1214. clearTimeout(timer);
  1215. remain = remain <= 0 ? duration : remain;
  1216. elem.data('paused', false);
  1217. start = Date.now();
  1218. timer = setTimeout(function () {
  1219. if (options.infinite) {
  1220. _this.restart(); //rerun the timer.
  1221. }
  1222. if (cb && typeof cb === 'function') {
  1223. cb();
  1224. }
  1225. }, remain);
  1226. elem.trigger("timerstart.zf.".concat(nameSpace));
  1227. };
  1228. this.pause = function () {
  1229. this.isPaused = true; //if(elem.data('paused')){ return false; }//maybe implement this sanity check if used for other things.
  1230. clearTimeout(timer);
  1231. elem.data('paused', true);
  1232. var end = Date.now();
  1233. remain = remain - (end - start);
  1234. elem.trigger("timerpaused.zf.".concat(nameSpace));
  1235. };
  1236. }
  1237. var Touch = {};
  1238. var startPosX,
  1239. startPosY,
  1240. startTime,
  1241. elapsedTime,
  1242. startEvent,
  1243. isMoving = false,
  1244. didMoved = false;
  1245. function onTouchEnd(e) {
  1246. this.removeEventListener('touchmove', onTouchMove);
  1247. this.removeEventListener('touchend', onTouchEnd); // If the touch did not move, consider it as a "tap"
  1248. if (!didMoved) {
  1249. var tapEvent = $.Event('tap', startEvent || e);
  1250. $(this).trigger(tapEvent);
  1251. }
  1252. startEvent = null;
  1253. isMoving = false;
  1254. didMoved = false;
  1255. }
  1256. function onTouchMove(e) {
  1257. if ($.spotSwipe.preventDefault) {
  1258. e.preventDefault();
  1259. }
  1260. if (isMoving) {
  1261. var x = e.touches[0].pageX;
  1262. var y = e.touches[0].pageY;
  1263. var dx = startPosX - x;
  1264. var dir;
  1265. didMoved = true;
  1266. elapsedTime = new Date().getTime() - startTime;
  1267. if (Math.abs(dx) >= $.spotSwipe.moveThreshold && elapsedTime <= $.spotSwipe.timeThreshold) {
  1268. dir = dx > 0 ? 'left' : 'right';
  1269. } // else if(Math.abs(dy) >= $.spotSwipe.moveThreshold && elapsedTime <= $.spotSwipe.timeThreshold) {
  1270. // dir = dy > 0 ? 'down' : 'up';
  1271. // }
  1272. if (dir) {
  1273. e.preventDefault();
  1274. onTouchEnd.apply(this, arguments);
  1275. $(this).trigger($.Event('swipe', e), dir).trigger($.Event("swipe".concat(dir), e));
  1276. }
  1277. }
  1278. }
  1279. function onTouchStart(e) {
  1280. if (e.touches.length == 1) {
  1281. startPosX = e.touches[0].pageX;
  1282. startPosY = e.touches[0].pageY;
  1283. startEvent = e;
  1284. isMoving = true;
  1285. didMoved = false;
  1286. startTime = new Date().getTime();
  1287. this.addEventListener('touchmove', onTouchMove, false);
  1288. this.addEventListener('touchend', onTouchEnd, false);
  1289. }
  1290. }
  1291. function init() {
  1292. this.addEventListener && this.addEventListener('touchstart', onTouchStart, false);
  1293. }
  1294. var SpotSwipe =
  1295. /*#__PURE__*/
  1296. function () {
  1297. function SpotSwipe($$$1) {
  1298. _classCallCheck(this, SpotSwipe);
  1299. this.version = '1.0.0';
  1300. this.enabled = 'ontouchstart' in document.documentElement;
  1301. this.preventDefault = false;
  1302. this.moveThreshold = 75;
  1303. this.timeThreshold = 200;
  1304. this.$ = $$$1;
  1305. this._init();
  1306. }
  1307. _createClass(SpotSwipe, [{
  1308. key: "_init",
  1309. value: function _init() {
  1310. var $$$1 = this.$;
  1311. $$$1.event.special.swipe = {
  1312. setup: init
  1313. };
  1314. $$$1.event.special.tap = {
  1315. setup: init
  1316. };
  1317. $$$1.each(['left', 'up', 'down', 'right'], function () {
  1318. $$$1.event.special["swipe".concat(this)] = {
  1319. setup: function setup() {
  1320. $$$1(this).on('swipe', $$$1.noop);
  1321. }
  1322. };
  1323. });
  1324. }
  1325. }]);
  1326. return SpotSwipe;
  1327. }();
  1328. /****************************************************
  1329. * As far as I can tell, both setupSpotSwipe and *
  1330. * setupTouchHandler should be idempotent, *
  1331. * because they directly replace functions & *
  1332. * values, and do not add event handlers directly. *
  1333. ****************************************************/
  1334. Touch.setupSpotSwipe = function ($$$1) {
  1335. $$$1.spotSwipe = new SpotSwipe($$$1);
  1336. };
  1337. /****************************************************
  1338. * Method for adding pseudo drag events to elements *
  1339. ***************************************************/
  1340. Touch.setupTouchHandler = function ($$$1) {
  1341. $$$1.fn.addTouch = function () {
  1342. this.each(function (i, el) {
  1343. $$$1(el).bind('touchstart touchmove touchend touchcancel', function (event) {
  1344. //we pass the original event object because the jQuery event
  1345. //object is normalized to w3c specs and does not provide the TouchList
  1346. handleTouch(event);
  1347. });
  1348. });
  1349. var handleTouch = function handleTouch(event) {
  1350. var touches = event.changedTouches,
  1351. first = touches[0],
  1352. eventTypes = {
  1353. touchstart: 'mousedown',
  1354. touchmove: 'mousemove',
  1355. touchend: 'mouseup'
  1356. },
  1357. type = eventTypes[event.type],
  1358. simulatedEvent;
  1359. if ('MouseEvent' in window && typeof window.MouseEvent === 'function') {
  1360. simulatedEvent = new window.MouseEvent(type, {
  1361. 'bubbles': true,
  1362. 'cancelable': true,
  1363. 'screenX': first.screenX,
  1364. 'screenY': first.screenY,
  1365. 'clientX': first.clientX,
  1366. 'clientY': first.clientY
  1367. });
  1368. } else {
  1369. simulatedEvent = document.createEvent('MouseEvent');
  1370. simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY, false, false, false, false, 0
  1371. /*left*/
  1372. , null);
  1373. }
  1374. first.target.dispatchEvent(simulatedEvent);
  1375. };
  1376. };
  1377. };
  1378. Touch.init = function ($$$1) {
  1379. if (typeof $$$1.spotSwipe === 'undefined') {
  1380. Touch.setupSpotSwipe($$$1);
  1381. Touch.setupTouchHandler($$$1);
  1382. }
  1383. };
  1384. var MutationObserver = function () {
  1385. var prefixes = ['WebKit', 'Moz', 'O', 'Ms', ''];
  1386. for (var i = 0; i < prefixes.length; i++) {
  1387. if ("".concat(prefixes[i], "MutationObserver") in window) {
  1388. return window["".concat(prefixes[i], "MutationObserver")];
  1389. }
  1390. }
  1391. return false;
  1392. }();
  1393. var triggers = function triggers(el, type) {
  1394. el.data(type).split(' ').forEach(function (id) {
  1395. $("#".concat(id))[type === 'close' ? 'trigger' : 'triggerHandler']("".concat(type, ".zf.trigger"), [el]);
  1396. });
  1397. };
  1398. var Triggers = {
  1399. Listeners: {
  1400. Basic: {},
  1401. Global: {}
  1402. },
  1403. Initializers: {}
  1404. };
  1405. Triggers.Listeners.Basic = {
  1406. openListener: function openListener() {
  1407. triggers($(this), 'open');
  1408. },
  1409. closeListener: function closeListener() {
  1410. var id = $(this).data('close');
  1411. if (id) {
  1412. triggers($(this), 'close');
  1413. } else {
  1414. $(this).trigger('close.zf.trigger');
  1415. }
  1416. },
  1417. toggleListener: function toggleListener() {
  1418. var id = $(this).data('toggle');
  1419. if (id) {
  1420. triggers($(this), 'toggle');
  1421. } else {
  1422. $(this).trigger('toggle.zf.trigger');
  1423. }
  1424. },
  1425. closeableListener: function closeableListener(e) {
  1426. e.stopPropagation();
  1427. var animation = $(this).data('closable');
  1428. if (animation !== '') {
  1429. Motion.animateOut($(this), animation, function () {
  1430. $(this).trigger('closed.zf');
  1431. });
  1432. } else {
  1433. $(this).fadeOut().trigger('closed.zf');
  1434. }
  1435. },
  1436. toggleFocusListener: function toggleFocusListener() {
  1437. var id = $(this).data('toggle-focus');
  1438. $("#".concat(id)).triggerHandler('toggle.zf.trigger', [$(this)]);
  1439. }
  1440. }; // Elements with [data-open] will reveal a plugin that supports it when clicked.
  1441. Triggers.Initializers.addOpenListener = function ($elem) {
  1442. $elem.off('click.zf.trigger', Triggers.Listeners.Basic.openListener);
  1443. $elem.on('click.zf.trigger', '[data-open]', Triggers.Listeners.Basic.openListener);
  1444. }; // Elements with [data-close] will close a plugin that supports it when clicked.
  1445. // If used without a value on [data-close], the event will bubble, allowing it to close a parent component.
  1446. Triggers.Initializers.addCloseListener = function ($elem) {
  1447. $elem.off('click.zf.trigger', Triggers.Listeners.Basic.closeListener);
  1448. $elem.on('click.zf.trigger', '[data-close]', Triggers.Listeners.Basic.closeListener);
  1449. }; // Elements with [data-toggle] will toggle a plugin that supports it when clicked.
  1450. Triggers.Initializers.addToggleListener = function ($elem) {
  1451. $elem.off('click.zf.trigger', Triggers.Listeners.Basic.toggleListener);
  1452. $elem.on('click.zf.trigger', '[data-toggle]', Triggers.Listeners.Basic.toggleListener);
  1453. }; // Elements with [data-closable] will respond to close.zf.trigger events.
  1454. Triggers.Initializers.addCloseableListener = function ($elem) {
  1455. $elem.off('close.zf.trigger', Triggers.Listeners.Basic.closeableListener);
  1456. $elem.on('close.zf.trigger', '[data-closeable], [data-closable]', Triggers.Listeners.Basic.closeableListener);
  1457. }; // Elements with [data-toggle-focus] will respond to coming in and out of focus
  1458. Triggers.Initializers.addToggleFocusListener = function ($elem) {
  1459. $elem.off('focus.zf.trigger blur.zf.trigger', Triggers.Listeners.Basic.toggleFocusListener);
  1460. $elem.on('focus.zf.trigger blur.zf.trigger', '[data-toggle-focus]', Triggers.Listeners.Basic.toggleFocusListener);
  1461. }; // More Global/complex listeners and triggers
  1462. Triggers.Listeners.Global = {
  1463. resizeListener: function resizeListener($nodes) {
  1464. if (!MutationObserver) {
  1465. //fallback for IE 9
  1466. $nodes.each(function () {
  1467. $(this).triggerHandler('resizeme.zf.trigger');
  1468. });
  1469. } //trigger all listening elements and signal a resize event
  1470. $nodes.attr('data-events', "resize");
  1471. },
  1472. scrollListener: function scrollListener($nodes) {
  1473. if (!MutationObserver) {
  1474. //fallback for IE 9
  1475. $nodes.each(function () {
  1476. $(this).triggerHandler('scrollme.zf.trigger');
  1477. });
  1478. } //trigger all listening elements and signal a scroll event
  1479. $nodes.attr('data-events', "scroll");
  1480. },
  1481. closeMeListener: function closeMeListener(e, pluginId) {
  1482. var plugin = e.namespace.split('.')[0];
  1483. var plugins = $("[data-".concat(plugin, "]")).not("[data-yeti-box=\"".concat(pluginId, "\"]"));
  1484. plugins.each(function () {
  1485. var _this = $(this);
  1486. _this.triggerHandler('close.zf.trigger', [_this]);
  1487. });
  1488. } // Global, parses whole document.
  1489. };
  1490. Triggers.Initializers.addClosemeListener = function (pluginName) {
  1491. var yetiBoxes = $('[data-yeti-box]'),
  1492. plugNames = ['dropdown', 'tooltip', 'reveal'];
  1493. if (pluginName) {
  1494. if (typeof pluginName === 'string') {
  1495. plugNames.push(pluginName);
  1496. } else if (_typeof(pluginName) === 'object' && typeof pluginName[0] === 'string') {
  1497. plugNames = plugNames.concat(pluginName);
  1498. } else {
  1499. console.error('Plugin names must be strings');
  1500. }
  1501. }
  1502. if (yetiBoxes.length) {
  1503. var listeners = plugNames.map(function (name) {
  1504. return "closeme.zf.".concat(name);
  1505. }).join(' ');
  1506. $(window).off(listeners).on(listeners, Triggers.Listeners.Global.closeMeListener);
  1507. }
  1508. };
  1509. function debounceGlobalListener(debounce, trigger, listener) {
  1510. var timer,
  1511. args = Array.prototype.slice.call(arguments, 3);
  1512. $(window).off(trigger).on(trigger, function (e) {
  1513. if (timer) {
  1514. clearTimeout(timer);
  1515. }
  1516. timer = setTimeout(function () {
  1517. listener.apply(null, args);
  1518. }, debounce || 10); //default time to emit scroll event
  1519. });
  1520. }
  1521. Triggers.Initializers.addResizeListener = function (debounce) {
  1522. var $nodes = $('[data-resize]');
  1523. if ($nodes.length) {
  1524. debounceGlobalListener(debounce, 'resize.zf.trigger', Triggers.Listeners.Global.resizeListener, $nodes);
  1525. }
  1526. };
  1527. Triggers.Initializers.addScrollListener = function (debounce) {
  1528. var $nodes = $('[data-scroll]');
  1529. if ($nodes.length) {
  1530. debounceGlobalListener(debounce, 'scroll.zf.trigger', Triggers.Listeners.Global.scrollListener, $nodes);
  1531. }
  1532. };
  1533. Triggers.Initializers.addMutationEventsListener = function ($elem) {
  1534. if (!MutationObserver) {
  1535. return false;
  1536. }
  1537. var $nodes = $elem.find('[data-resize], [data-scroll], [data-mutate]'); //element callback
  1538. var listeningElementsMutation = function listeningElementsMutation(mutationRecordsList) {
  1539. var $target = $(mutationRecordsList[0].target); //trigger the event handler for the element depending on type
  1540. switch (mutationRecordsList[0].type) {
  1541. case "attributes":
  1542. if ($target.attr("data-events") === "scroll" && mutationRecordsList[0].attributeName === "data-events") {
  1543. $target.triggerHandler('scrollme.zf.trigger', [$target, window.pageYOffset]);
  1544. }
  1545. if ($target.attr("data-events") === "resize" && mutationRecordsList[0].attributeName === "data-events") {
  1546. $target.triggerHandler('resizeme.zf.trigger', [$target]);
  1547. }
  1548. if (mutationRecordsList[0].attributeName === "style") {
  1549. $target.closest("[data-mutate]").attr("data-events", "mutate");
  1550. $target.closest("[data-mutate]").triggerHandler('mutateme.zf.trigger', [$target.closest("[data-mutate]")]);
  1551. }
  1552. break;
  1553. case "childList":
  1554. $target.closest("[data-mutate]").attr("data-events", "mutate");
  1555. $target.closest("[data-mutate]").triggerHandler('mutateme.zf.trigger', [$target.closest("[data-mutate]")]);
  1556. break;
  1557. default:
  1558. return false;
  1559. //nothing
  1560. }
  1561. };
  1562. if ($nodes.length) {
  1563. //for each element that needs to listen for resizing, scrolling, or mutation add a single observer
  1564. for (var i = 0; i <= $nodes.length - 1; i++) {
  1565. var elementObserver = new MutationObserver(listeningElementsMutation);
  1566. elementObserver.observe($nodes[i], {
  1567. attributes: true,
  1568. childList: true,
  1569. characterData: false,
  1570. subtree: true,
  1571. attributeFilter: ["data-events", "style"]
  1572. });
  1573. }
  1574. }
  1575. };
  1576. Triggers.Initializers.addSimpleListeners = function () {
  1577. var $document = $(document);
  1578. Triggers.Initializers.addOpenListener($document);
  1579. Triggers.Initializers.addCloseListener($document);
  1580. Triggers.Initializers.addToggleListener($document);
  1581. Triggers.Initializers.addCloseableListener($document);
  1582. Triggers.Initializers.addToggleFocusListener($document);
  1583. };
  1584. Triggers.Initializers.addGlobalListeners = function () {
  1585. var $document = $(document);
  1586. Triggers.Initializers.addMutationEventsListener($document);
  1587. Triggers.Initializers.addResizeListener();
  1588. Triggers.Initializers.addScrollListener();
  1589. Triggers.Initializers.addClosemeListener();
  1590. };
  1591. Triggers.init = function ($$$1, Foundation) {
  1592. onLoad($$$1(window), function () {
  1593. if ($$$1.triggersInitialized !== true) {
  1594. Triggers.Initializers.addSimpleListeners();
  1595. Triggers.Initializers.addGlobalListeners();
  1596. $$$1.triggersInitialized = true;
  1597. }
  1598. });
  1599. if (Foundation) {
  1600. Foundation.Triggers = Triggers; // Legacy included to be backwards compatible for now.
  1601. Foundation.IHearYou = Triggers.Initializers.addGlobalListeners;
  1602. }
  1603. };
  1604. // {function} _setup (replaces previous constructor),
  1605. // {function} _destroy (replaces previous destroy)
  1606. var Plugin =
  1607. /*#__PURE__*/
  1608. function () {
  1609. function Plugin(element, options) {
  1610. _classCallCheck(this, Plugin);
  1611. this._setup(element, options);
  1612. var pluginName = getPluginName(this);
  1613. this.uuid = GetYoDigits(6, pluginName);
  1614. if (!this.$element.attr("data-".concat(pluginName))) {
  1615. this.$element.attr("data-".concat(pluginName), this.uuid);
  1616. }
  1617. if (!this.$element.data('zfPlugin')) {
  1618. this.$element.data('zfPlugin', this);
  1619. }
  1620. /**
  1621. * Fires when the plugin has initialized.
  1622. * @event Plugin#init
  1623. */
  1624. this.$element.trigger("init.zf.".concat(pluginName));
  1625. }
  1626. _createClass(Plugin, [{
  1627. key: "destroy",
  1628. value: function destroy() {
  1629. this._destroy();
  1630. var pluginName = getPluginName(this);
  1631. this.$element.removeAttr("data-".concat(pluginName)).removeData('zfPlugin')
  1632. /**
  1633. * Fires when the plugin has been destroyed.
  1634. * @event Plugin#destroyed
  1635. */
  1636. .trigger("destroyed.zf.".concat(pluginName));
  1637. for (var prop in this) {
  1638. this[prop] = null; //clean up script to prep for garbage collection.
  1639. }
  1640. }
  1641. }]);
  1642. return Plugin;
  1643. }(); // Convert PascalCase to kebab-case
  1644. // Thank you: http://stackoverflow.com/a/8955580
  1645. function hyphenate$1(str) {
  1646. return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
  1647. }
  1648. function getPluginName(obj) {
  1649. if (typeof obj.constructor.name !== 'undefined') {
  1650. return hyphenate$1(obj.constructor.name);
  1651. } else {
  1652. return hyphenate$1(obj.className);
  1653. }
  1654. }
  1655. /**
  1656. * Abide module.
  1657. * @module foundation.abide
  1658. */
  1659. var Abide =
  1660. /*#__PURE__*/
  1661. function (_Plugin) {
  1662. _inherits(Abide, _Plugin);
  1663. function Abide() {
  1664. _classCallCheck(this, Abide);
  1665. return _possibleConstructorReturn(this, _getPrototypeOf(Abide).apply(this, arguments));
  1666. }
  1667. _createClass(Abide, [{
  1668. key: "_setup",
  1669. /**
  1670. * Creates a new instance of Abide.
  1671. * @class
  1672. * @name Abide
  1673. * @fires Abide#init
  1674. * @param {Object} element - jQuery object to add the trigger to.
  1675. * @param {Object} options - Overrides to the default plugin settings.
  1676. */
  1677. value: function _setup(element) {
  1678. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  1679. this.$element = element;
  1680. this.options = $.extend(true, {}, Abide.defaults, this.$element.data(), options);
  1681. this.className = 'Abide'; // ie9 back compat
  1682. this._init();
  1683. }
  1684. /**
  1685. * Initializes the Abide plugin and calls functions to get Abide functioning on load.
  1686. * @private
  1687. */
  1688. }, {
  1689. key: "_init",
  1690. value: function _init() {
  1691. var _this2 = this;
  1692. this.$inputs = $.merge( // Consider as input to validate:
  1693. this.$element.find('input').not('[type=submit]'), // * all input fields expect submit
  1694. this.$element.find('textarea, select') // * all textareas and select fields
  1695. );
  1696. var $globalErrors = this.$element.find('[data-abide-error]'); // Add a11y attributes to all fields
  1697. if (this.options.a11yAttributes) {
  1698. this.$inputs.each(function (i, input) {
  1699. return _this2.addA11yAttributes($(input));
  1700. });
  1701. $globalErrors.each(function (i, error) {
  1702. return _this2.addGlobalErrorA11yAttributes($(error));
  1703. });
  1704. }
  1705. this._events();
  1706. }
  1707. /**
  1708. * Initializes events for Abide.
  1709. * @private
  1710. */
  1711. }, {
  1712. key: "_events",
  1713. value: function _events() {
  1714. var _this3 = this;
  1715. this.$element.off('.abide').on('reset.zf.abide', function () {
  1716. _this3.resetForm();
  1717. }).on('submit.zf.abide', function () {
  1718. return _this3.validateForm();
  1719. });
  1720. if (this.options.validateOn === 'fieldChange') {
  1721. this.$inputs.off('change.zf.abide').on('change.zf.abide', function (e) {
  1722. _this3.validateInput($(e.target));
  1723. });
  1724. }
  1725. if (this.options.liveValidate) {
  1726. this.$inputs.off('input.zf.abide').on('input.zf.abide', function (e) {
  1727. _this3.validateInput($(e.target));
  1728. });
  1729. }
  1730. if (this.options.validateOnBlur) {
  1731. this.$inputs.off('blur.zf.abide').on('blur.zf.abide', function (e) {
  1732. _this3.validateInput($(e.target));
  1733. });
  1734. }
  1735. }
  1736. /**
  1737. * Calls necessary functions to update Abide upon DOM change
  1738. * @private
  1739. */
  1740. }, {
  1741. key: "_reflow",
  1742. value: function _reflow() {
  1743. this._init();
  1744. }
  1745. /**
  1746. * Checks whether or not a form element has the required attribute and if it's checked or not
  1747. * @param {Object} element - jQuery object to check for required attribute
  1748. * @returns {Boolean} Boolean value depends on whether or not attribute is checked or empty
  1749. */
  1750. }, {
  1751. key: "requiredCheck",
  1752. value: function requiredCheck($el) {
  1753. if (!$el.attr('required')) return true;
  1754. var isGood = true;
  1755. switch ($el[0].type) {
  1756. case 'checkbox':
  1757. isGood = $el[0].checked;
  1758. break;
  1759. case 'select':
  1760. case 'select-one':
  1761. case 'select-multiple':
  1762. var opt = $el.find('option:selected');
  1763. if (!opt.length || !opt.val()) isGood = false;
  1764. break;
  1765. default:
  1766. if (!$el.val() || !$el.val().length) isGood = false;
  1767. }
  1768. return isGood;
  1769. }
  1770. /**
  1771. * Get:
  1772. * - Based on $el, the first element(s) corresponding to `formErrorSelector` in this order:
  1773. * 1. The element's direct sibling('s).
  1774. * 2. The element's parent's children.
  1775. * - Element(s) with the attribute `[data-form-error-for]` set with the element's id.
  1776. *
  1777. * This allows for multiple form errors per input, though if none are found, no form errors will be shown.
  1778. *
  1779. * @param {Object} $el - jQuery object to use as reference to find the form error selector.
  1780. * @returns {Object} jQuery object with the selector.
  1781. */
  1782. }, {
  1783. key: "findFormError",
  1784. value: function findFormError($el) {
  1785. var id = $el[0].id;
  1786. var $error = $el.siblings(this.options.formErrorSelector);
  1787. if (!$error.length) {
  1788. $error = $el.parent().find(this.options.formErrorSelector);
  1789. }
  1790. if (id) {
  1791. $error = $error.add(this.$element.find("[data-form-error-for=\"".concat(id, "\"]")));
  1792. }
  1793. return $error;
  1794. }
  1795. /**
  1796. * Get the first element in this order:
  1797. * 2. The <label> with the attribute `[for="someInputId"]`
  1798. * 3. The `.closest()` <label>
  1799. *
  1800. * @param {Object} $el - jQuery object to check for required attribute
  1801. * @returns {Boolean} Boolean value depends on whether or not attribute is checked or empty
  1802. */
  1803. }, {
  1804. key: "findLabel",
  1805. value: function findLabel($el) {
  1806. var id = $el[0].id;
  1807. var $label = this.$element.find("label[for=\"".concat(id, "\"]"));
  1808. if (!$label.length) {
  1809. return $el.closest('label');
  1810. }
  1811. return $label;
  1812. }
  1813. /**
  1814. * Get the set of labels associated with a set of radio els in this order
  1815. * 2. The <label> with the attribute `[for="someInputId"]`
  1816. * 3. The `.closest()` <label>
  1817. *
  1818. * @param {Object} $el - jQuery object to check for required attribute
  1819. * @returns {Boolean} Boolean value depends on whether or not attribute is checked or empty
  1820. */
  1821. }, {
  1822. key: "findRadioLabels",
  1823. value: function findRadioLabels($els) {
  1824. var _this4 = this;
  1825. var labels = $els.map(function (i, el) {
  1826. var id = el.id;
  1827. var $label = _this4.$element.find("label[for=\"".concat(id, "\"]"));
  1828. if (!$label.length) {
  1829. $label = $(el).closest('label');
  1830. }
  1831. return $label[0];
  1832. });
  1833. return $(labels);
  1834. }
  1835. /**
  1836. * Adds the CSS error class as specified by the Abide settings to the label, input, and the form
  1837. * @param {Object} $el - jQuery object to add the class to
  1838. */
  1839. }, {
  1840. key: "addErrorClasses",
  1841. value: function addErrorClasses($el) {
  1842. var $label = this.findLabel($el);
  1843. var $formError = this.findFormError($el);
  1844. if ($label.length) {
  1845. $label.addClass(this.options.labelErrorClass);
  1846. }
  1847. if ($formError.length) {
  1848. $formError.addClass(this.options.formErrorClass);
  1849. }
  1850. $el.addClass(this.options.inputErrorClass).attr({
  1851. 'data-invalid': '',
  1852. 'aria-invalid': true
  1853. });
  1854. }
  1855. /**
  1856. * Adds [for] and [role=alert] attributes to all form error targetting $el,
  1857. * and [aria-describedby] attribute to $el toward the first form error.
  1858. * @param {Object} $el - jQuery object
  1859. */
  1860. }, {
  1861. key: "addA11yAttributes",
  1862. value: function addA11yAttributes($el) {
  1863. var $errors = this.findFormError($el);
  1864. var $labels = $errors.filter('label');
  1865. var $error = $errors.first();
  1866. if (!$errors.length) return; // Set [aria-describedby] on the input toward the first form error if it is not set
  1867. if (typeof $el.attr('aria-describedby') === 'undefined') {
  1868. // Get the first error ID or create one
  1869. var errorId = $error.attr('id');
  1870. if (typeof errorId === 'undefined') {
  1871. errorId = GetYoDigits(6, 'abide-error');
  1872. $error.attr('id', errorId);
  1873. }
  1874. $el.attr('aria-describedby', errorId);
  1875. }
  1876. if ($labels.filter('[for]').length < $labels.length) {
  1877. // Get the input ID or create one
  1878. var elemId = $el.attr('id');
  1879. if (typeof elemId === 'undefined') {
  1880. elemId = GetYoDigits(6, 'abide-input');
  1881. $el.attr('id', elemId);
  1882. }
  1883. $labels.each(function (i, label) {
  1884. var $label = $(label);
  1885. if (typeof $label.attr('for') === 'undefined') $label.attr('for', elemId);
  1886. });
  1887. } // For each error targeting $el, set [role=alert] if it is not set.
  1888. $errors.each(function (i, label) {
  1889. var $label = $(label);
  1890. if (typeof $label.attr('role') === 'undefined') $label.attr('role', 'alert');
  1891. }).end();
  1892. }
  1893. /**
  1894. * Adds [aria-live] attribute to the given global form error $el.
  1895. * @param {Object} $el - jQuery object to add the attribute to
  1896. */
  1897. }, {
  1898. key: "addGlobalErrorA11yAttributes",
  1899. value: function addGlobalErrorA11yAttributes($el) {
  1900. if (typeof $el.attr('aria-live') === 'undefined') $el.attr('aria-live', this.options.a11yErrorLevel);
  1901. }
  1902. /**
  1903. * Remove CSS error classes etc from an entire radio button group
  1904. * @param {String} groupName - A string that specifies the name of a radio button group
  1905. *
  1906. */
  1907. }, {
  1908. key: "removeRadioErrorClasses",
  1909. value: function removeRadioErrorClasses(groupName) {
  1910. var $els = this.$element.find(":radio[name=\"".concat(groupName, "\"]"));
  1911. var $labels = this.findRadioLabels($els);
  1912. var $formErrors = this.findFormError($els);
  1913. if ($labels.length) {
  1914. $labels.removeClass(this.options.labelErrorClass);
  1915. }
  1916. if ($formErrors.length) {
  1917. $formErrors.removeClass(this.options.formErrorClass);
  1918. }
  1919. $els.removeClass(this.options.inputErrorClass).attr({
  1920. 'data-invalid': null,
  1921. 'aria-invalid': null
  1922. });
  1923. }
  1924. /**
  1925. * Removes CSS error class as specified by the Abide settings from the label, input, and the form
  1926. * @param {Object} $el - jQuery object to remove the class from
  1927. */
  1928. }, {
  1929. key: "removeErrorClasses",
  1930. value: function removeErrorClasses($el) {
  1931. // radios need to clear all of the els
  1932. if ($el[0].type == 'radio') {
  1933. return this.removeRadioErrorClasses($el.attr('name'));
  1934. }
  1935. var $label = this.findLabel($el);
  1936. var $formError = this.findFormError($el);
  1937. if ($label.length) {
  1938. $label.removeClass(this.options.labelErrorClass);
  1939. }
  1940. if ($formError.length) {
  1941. $formError.removeClass(this.options.formErrorClass);
  1942. }
  1943. $el.removeClass(this.options.inputErrorClass).attr({
  1944. 'data-invalid': null,
  1945. 'aria-invalid': null
  1946. });
  1947. }
  1948. /**
  1949. * Goes through a form to find inputs and proceeds to validate them in ways specific to their type.
  1950. * Ignores inputs with data-abide-ignore, type="hidden" or disabled attributes set
  1951. * @fires Abide#invalid
  1952. * @fires Abide#valid
  1953. * @param {Object} element - jQuery object to validate, should be an HTML input
  1954. * @returns {Boolean} goodToGo - If the input is valid or not.
  1955. */
  1956. }, {
  1957. key: "validateInput",
  1958. value: function validateInput($el) {
  1959. var clearRequire = this.requiredCheck($el),
  1960. validated = false,
  1961. customValidator = true,
  1962. validator = $el.attr('data-validator'),
  1963. equalTo = true; // don't validate ignored inputs or hidden inputs or disabled inputs
  1964. if ($el.is('[data-abide-ignore]') || $el.is('[type="hidden"]') || $el.is('[disabled]')) {
  1965. return true;
  1966. }
  1967. switch ($el[0].type) {
  1968. case 'radio':
  1969. validated = this.validateRadio($el.attr('name'));
  1970. break;
  1971. case 'checkbox':
  1972. validated = clearRequire;
  1973. break;
  1974. case 'select':
  1975. case 'select-one':
  1976. case 'select-multiple':
  1977. validated = clearRequire;
  1978. break;
  1979. default:
  1980. validated = this.validateText($el);
  1981. }
  1982. if (validator) {
  1983. customValidator = this.matchValidation($el, validator, $el.attr('required'));
  1984. }
  1985. if ($el.attr('data-equalto')) {
  1986. equalTo = this.options.validators.equalTo($el);
  1987. }
  1988. var goodToGo = [clearRequire, validated, customValidator, equalTo].indexOf(false) === -1;
  1989. var message = (goodToGo ? 'valid' : 'invalid') + '.zf.abide';
  1990. if (goodToGo) {
  1991. // Re-validate inputs that depend on this one with equalto
  1992. var dependentElements = this.$element.find("[data-equalto=\"".concat($el.attr('id'), "\"]"));
  1993. if (dependentElements.length) {
  1994. var _this = this;
  1995. dependentElements.each(function () {
  1996. if ($(this).val()) {
  1997. _this.validateInput($(this));
  1998. }
  1999. });
  2000. }
  2001. }
  2002. this[goodToGo ? 'removeErrorClasses' : 'addErrorClasses']($el);
  2003. /**
  2004. * Fires when the input is done checking for validation. Event trigger is either `valid.zf.abide` or `invalid.zf.abide`
  2005. * Trigger includes the DOM element of the input.
  2006. * @event Abide#valid
  2007. * @event Abide#invalid
  2008. */
  2009. $el.trigger(message, [$el]);
  2010. return goodToGo;
  2011. }
  2012. /**
  2013. * Goes through a form and if there are any invalid inputs, it will display the form error element
  2014. * @returns {Boolean} noError - true if no errors were detected...
  2015. * @fires Abide#formvalid
  2016. * @fires Abide#forminvalid
  2017. */
  2018. }, {
  2019. key: "validateForm",
  2020. value: function validateForm() {
  2021. var _this5 = this;
  2022. var acc = [];
  2023. var _this = this;
  2024. this.$inputs.each(function () {
  2025. acc.push(_this.validateInput($(this)));
  2026. });
  2027. var noError = acc.indexOf(false) === -1;
  2028. this.$element.find('[data-abide-error]').each(function (i, elem) {
  2029. var $elem = $(elem); // Ensure a11y attributes are set
  2030. if (_this5.options.a11yAttributes) _this5.addGlobalErrorA11yAttributes($elem); // Show or hide the error
  2031. $elem.css('display', noError ? 'none' : 'block');
  2032. });
  2033. /**
  2034. * Fires when the form is finished validating. Event trigger is either `formvalid.zf.abide` or `forminvalid.zf.abide`.
  2035. * Trigger includes the element of the form.
  2036. * @event Abide#formvalid
  2037. * @event Abide#forminvalid
  2038. */
  2039. this.$element.trigger((noError ? 'formvalid' : 'forminvalid') + '.zf.abide', [this.$element]);
  2040. return noError;
  2041. }
  2042. /**
  2043. * Determines whether or a not a text input is valid based on the pattern specified in the attribute. If no matching pattern is found, returns true.
  2044. * @param {Object} $el - jQuery object to validate, should be a text input HTML element
  2045. * @param {String} pattern - string value of one of the RegEx patterns in Abide.options.patterns
  2046. * @returns {Boolean} Boolean value depends on whether or not the input value matches the pattern specified
  2047. */
  2048. }, {
  2049. key: "validateText",
  2050. value: function validateText($el, pattern) {
  2051. // A pattern can be passed to this function, or it will be infered from the input's "pattern" attribute, or it's "type" attribute
  2052. pattern = pattern || $el.attr('pattern') || $el.attr('type');
  2053. var inputText = $el.val();
  2054. var valid = false;
  2055. if (inputText.length) {
  2056. // If the pattern attribute on the element is in Abide's list of patterns, then test that regexp
  2057. if (this.options.patterns.hasOwnProperty(pattern)) {
  2058. valid = this.options.patterns[pattern].test(inputText);
  2059. } // If the pattern name isn't also the type attribute of the field, then test it as a regexp
  2060. else if (pattern !== $el.attr('type')) {
  2061. valid = new RegExp(pattern).test(inputText);
  2062. } else {
  2063. valid = true;
  2064. }
  2065. } // An empty field is valid if it's not required
  2066. else if (!$el.prop('required')) {
  2067. valid = true;
  2068. }
  2069. return valid;
  2070. }
  2071. /**
  2072. * Determines whether or a not a radio input is valid based on whether or not it is required and selected. Although the function targets a single `<input>`, it validates by checking the `required` and `checked` properties of all radio buttons in its group.
  2073. * @param {String} groupName - A string that specifies the name of a radio button group
  2074. * @returns {Boolean} Boolean value depends on whether or not at least one radio input has been selected (if it's required)
  2075. */
  2076. }, {
  2077. key: "validateRadio",
  2078. value: function validateRadio(groupName) {
  2079. // If at least one radio in the group has the `required` attribute, the group is considered required
  2080. // Per W3C spec, all radio buttons in a group should have `required`, but we're being nice
  2081. var $group = this.$element.find(":radio[name=\"".concat(groupName, "\"]"));
  2082. var valid = false,
  2083. required = false; // For the group to be required, at least one radio needs to be required
  2084. $group.each(function (i, e) {
  2085. if ($(e).attr('required')) {
  2086. required = true;
  2087. }
  2088. });
  2089. if (!required) valid = true;
  2090. if (!valid) {
  2091. // For the group to be valid, at least one radio needs to be checked
  2092. $group.each(function (i, e) {
  2093. if ($(e).prop('checked')) {
  2094. valid = true;
  2095. }
  2096. });
  2097. }
  2098. return valid;
  2099. }
  2100. /**
  2101. * Determines if a selected input passes a custom validation function. Multiple validations can be used, if passed to the element with `data-validator="foo bar baz"` in a space separated listed.
  2102. * @param {Object} $el - jQuery input element.
  2103. * @param {String} validators - a string of function names matching functions in the Abide.options.validators object.
  2104. * @param {Boolean} required - self explanatory?
  2105. * @returns {Boolean} - true if validations passed.
  2106. */
  2107. }, {
  2108. key: "matchValidation",
  2109. value: function matchValidation($el, validators, required) {
  2110. var _this6 = this;
  2111. required = required ? true : false;
  2112. var clear = validators.split(' ').map(function (v) {
  2113. return _this6.options.validators[v]($el, required, $el.parent());
  2114. });
  2115. return clear.indexOf(false) === -1;
  2116. }
  2117. /**
  2118. * Resets form inputs and styles
  2119. * @fires Abide#formreset
  2120. */
  2121. }, {
  2122. key: "resetForm",
  2123. value: function resetForm() {
  2124. var $form = this.$element,
  2125. opts = this.options;
  2126. $(".".concat(opts.labelErrorClass), $form).not('small').removeClass(opts.labelErrorClass);
  2127. $(".".concat(opts.inputErrorClass), $form).not('small').removeClass(opts.inputErrorClass);
  2128. $("".concat(opts.formErrorSelector, ".").concat(opts.formErrorClass)).removeClass(opts.formErrorClass);
  2129. $form.find('[data-abide-error]').css('display', 'none');
  2130. $(':input', $form).not(':button, :submit, :reset, :hidden, :radio, :checkbox, [data-abide-ignore]').val('').attr({
  2131. 'data-invalid': null,
  2132. 'aria-invalid': null
  2133. });
  2134. $(':input:radio', $form).not('[data-abide-ignore]').prop('checked', false).attr({
  2135. 'data-invalid': null,
  2136. 'aria-invalid': null
  2137. });
  2138. $(':input:checkbox', $form).not('[data-abide-ignore]').prop('checked', false).attr({
  2139. 'data-invalid': null,
  2140. 'aria-invalid': null
  2141. });
  2142. /**
  2143. * Fires when the form has been reset.
  2144. * @event Abide#formreset
  2145. */
  2146. $form.trigger('formreset.zf.abide', [$form]);
  2147. }
  2148. /**
  2149. * Destroys an instance of Abide.
  2150. * Removes error styles and classes from elements, without resetting their values.
  2151. */
  2152. }, {
  2153. key: "_destroy",
  2154. value: function _destroy() {
  2155. var _this = this;
  2156. this.$element.off('.abide').find('[data-abide-error]').css('display', 'none');
  2157. this.$inputs.off('.abide').each(function () {
  2158. _this.removeErrorClasses($(this));
  2159. });
  2160. }
  2161. }]);
  2162. return Abide;
  2163. }(Plugin);
  2164. /**
  2165. * Default settings for plugin
  2166. */
  2167. Abide.defaults = {
  2168. /**
  2169. * The default event to validate inputs. Checkboxes and radios validate immediately.
  2170. * Remove or change this value for manual validation.
  2171. * @option
  2172. * @type {?string}
  2173. * @default 'fieldChange'
  2174. */
  2175. validateOn: 'fieldChange',
  2176. /**
  2177. * Class to be applied to input labels on failed validation.
  2178. * @option
  2179. * @type {string}
  2180. * @default 'is-invalid-label'
  2181. */
  2182. labelErrorClass: 'is-invalid-label',
  2183. /**
  2184. * Class to be applied to inputs on failed validation.
  2185. * @option
  2186. * @type {string}
  2187. * @default 'is-invalid-input'
  2188. */
  2189. inputErrorClass: 'is-invalid-input',
  2190. /**
  2191. * Class selector to use to target Form Errors for show/hide.
  2192. * @option
  2193. * @type {string}
  2194. * @default '.form-error'
  2195. */
  2196. formErrorSelector: '.form-error',
  2197. /**
  2198. * Class added to Form Errors on failed validation.
  2199. * @option
  2200. * @type {string}
  2201. * @default 'is-visible'
  2202. */
  2203. formErrorClass: 'is-visible',
  2204. /**
  2205. * If true, automatically insert when possible:
  2206. * - `[aria-describedby]` on fields
  2207. * - `[role=alert]` on form errors and `[for]` on form error labels
  2208. * - `[aria-live]` on global errors `[data-abide-error]` (see option `a11yErrorLevel`).
  2209. * @option
  2210. * @type {boolean}
  2211. * @default true
  2212. */
  2213. a11yAttributes: true,
  2214. /**
  2215. * [aria-live] attribute value to be applied on global errors `[data-abide-error]`.
  2216. * Options are: 'assertive', 'polite' and 'off'/null
  2217. * @option
  2218. * @see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions
  2219. * @type {string}
  2220. * @default 'assertive'
  2221. */
  2222. a11yErrorLevel: 'assertive',
  2223. /**
  2224. * Set to true to validate text inputs on any value change.
  2225. * @option
  2226. * @type {boolean}
  2227. * @default false
  2228. */
  2229. liveValidate: false,
  2230. /**
  2231. * Set to true to validate inputs on blur.
  2232. * @option
  2233. * @type {boolean}
  2234. * @default false
  2235. */
  2236. validateOnBlur: false,
  2237. patterns: {
  2238. alpha: /^[a-zA-Z]+$/,
  2239. alpha_numeric: /^[a-zA-Z0-9]+$/,
  2240. integer: /^[-+]?\d+$/,
  2241. number: /^[-+]?\d*(?:[\.\,]\d+)?$/,
  2242. // amex, visa, diners
  2243. card: /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(?:222[1-9]|2[3-6][0-9]{2}|27[0-1][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/,
  2244. cvv: /^([0-9]){3,4}$/,
  2245. // http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address
  2246. email: /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/,
  2247. // From CommonRegexJS (@talyssonoc)
  2248. // https://github.com/talyssonoc/CommonRegexJS/blob/e2901b9f57222bc14069dc8f0598d5f412555411/lib/commonregex.js#L76
  2249. // For more restrictive URL Regexs, see https://mathiasbynens.be/demo/url-regex.
  2250. url: /^((?:(https?|ftps?|file|ssh|sftp):\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\((?:[^\s()<>]+|(?:\([^\s()<>]+\)))*\))+(?:\((?:[^\s()<>]+|(?:\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?\xab\xbb\u201c\u201d\u2018\u2019]))$/,
  2251. // abc.de
  2252. domain: /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,8}$/,
  2253. datetime: /^([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])T([0-5][0-9])\:([0-5][0-9])\:([0-5][0-9])(Z|([\-\+]([0-1][0-9])\:00))$/,
  2254. // YYYY-MM-DD
  2255. date: /(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))$/,
  2256. // HH:MM:SS
  2257. time: /^(0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]){2}$/,
  2258. dateISO: /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/,
  2259. // MM/DD/YYYY
  2260. month_day_year: /^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.]\d{4}$/,
  2261. // DD/MM/YYYY
  2262. day_month_year: /^(0[1-9]|[12][0-9]|3[01])[- \/.](0[1-9]|1[012])[- \/.]\d{4}$/,
  2263. // #FFF or #FFFFFF
  2264. color: /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/,
  2265. // Domain || URL
  2266. website: {
  2267. test: function test(text) {
  2268. return Abide.defaults.patterns['domain'].test(text) || Abide.defaults.patterns['url'].test(text);
  2269. }
  2270. }
  2271. },
  2272. /**
  2273. * Optional validation functions to be used. `equalTo` being the only default included function.
  2274. * Functions should return only a boolean if the input is valid or not. Functions are given the following arguments:
  2275. * el : The jQuery element to validate.
  2276. * required : Boolean value of the required attribute be present or not.
  2277. * parent : The direct parent of the input.
  2278. * @option
  2279. */
  2280. validators: {
  2281. equalTo: function equalTo(el, required, parent) {
  2282. return $("#".concat(el.attr('data-equalto'))).val() === el.val();
  2283. }
  2284. }
  2285. };
  2286. /**
  2287. * Accordion module.
  2288. * @module foundation.accordion
  2289. * @requires foundation.util.keyboard
  2290. */
  2291. var Accordion =
  2292. /*#__PURE__*/
  2293. function (_Plugin) {
  2294. _inherits(Accordion, _Plugin);
  2295. function Accordion() {
  2296. _classCallCheck(this, Accordion);
  2297. return _possibleConstructorReturn(this, _getPrototypeOf(Accordion).apply(this, arguments));
  2298. }
  2299. _createClass(Accordion, [{
  2300. key: "_setup",
  2301. /**
  2302. * Creates a new instance of an accordion.
  2303. * @class
  2304. * @name Accordion
  2305. * @fires Accordion#init
  2306. * @param {jQuery} element - jQuery object to make into an accordion.
  2307. * @param {Object} options - a plain object with settings to override the default options.
  2308. */
  2309. value: function _setup(element, options) {
  2310. this.$element = element;
  2311. this.options = $.extend({}, Accordion.defaults, this.$element.data(), options);
  2312. this.className = 'Accordion'; // ie9 back compat
  2313. this._init();
  2314. Keyboard.register('Accordion', {
  2315. 'ENTER': 'toggle',
  2316. 'SPACE': 'toggle',
  2317. 'ARROW_DOWN': 'next',
  2318. 'ARROW_UP': 'previous'
  2319. });
  2320. }
  2321. /**
  2322. * Initializes the accordion by animating the preset active pane(s).
  2323. * @private
  2324. */
  2325. }, {
  2326. key: "_init",
  2327. value: function _init() {
  2328. var _this2 = this;
  2329. this._isInitializing = true;
  2330. this.$element.attr('role', 'tablist');
  2331. this.$tabs = this.$element.children('[data-accordion-item]');
  2332. this.$tabs.each(function (idx, el) {
  2333. var $el = $(el),
  2334. $content = $el.children('[data-tab-content]'),
  2335. id = $content[0].id || GetYoDigits(6, 'accordion'),
  2336. linkId = el.id ? "".concat(el.id, "-label") : "".concat(id, "-label");
  2337. $el.find('a:first').attr({
  2338. 'aria-controls': id,
  2339. 'role': 'tab',
  2340. 'id': linkId,
  2341. 'aria-expanded': false,
  2342. 'aria-selected': false
  2343. });
  2344. $content.attr({
  2345. 'role': 'tabpanel',
  2346. 'aria-labelledby': linkId,
  2347. 'aria-hidden': true,
  2348. 'id': id
  2349. });
  2350. });
  2351. var $initActive = this.$element.find('.is-active').children('[data-tab-content]');
  2352. if ($initActive.length) {
  2353. // Save up the initial hash to return to it later when going back in history
  2354. this._initialAnchor = $initActive.prev('a').attr('href');
  2355. this._openSingleTab($initActive);
  2356. }
  2357. this._checkDeepLink = function () {
  2358. var anchor = window.location.hash;
  2359. if (!anchor.length) {
  2360. // If we are still initializing and there is no anchor, then there is nothing to do
  2361. if (_this2._isInitializing) return; // Otherwise, move to the initial anchor
  2362. if (_this2._initialAnchor) anchor = _this2._initialAnchor;
  2363. }
  2364. var $anchor = anchor && $(anchor);
  2365. var $link = anchor && _this2.$element.find("[href$=\"".concat(anchor, "\"]")); // Whether the anchor element that has been found is part of this element
  2366. var isOwnAnchor = !!($anchor.length && $link.length); // If there is an anchor for the hash, open it (if not already active)
  2367. if ($anchor && $link && $link.length) {
  2368. if (!$link.parent('[data-accordion-item]').hasClass('is-active')) {
  2369. _this2._openSingleTab($anchor);
  2370. }
  2371. } // Otherwise, close everything
  2372. else {
  2373. _this2._closeAllTabs();
  2374. }
  2375. if (isOwnAnchor) {
  2376. // Roll up a little to show the titles
  2377. if (_this2.options.deepLinkSmudge) {
  2378. onLoad($(window), function () {
  2379. var offset = _this2.$element.offset();
  2380. $('html, body').animate({
  2381. scrollTop: offset.top
  2382. }, _this2.options.deepLinkSmudgeDelay);
  2383. });
  2384. }
  2385. /**
  2386. * Fires when the plugin has deeplinked at pageload
  2387. * @event Accordion#deeplink
  2388. */
  2389. _this2.$element.trigger('deeplink.zf.accordion', [$link, $anchor]);
  2390. }
  2391. }; //use browser to open a tab, if it exists in this tabset
  2392. if (this.options.deepLink) {
  2393. this._checkDeepLink();
  2394. }
  2395. this._events();
  2396. this._isInitializing = false;
  2397. }
  2398. /**
  2399. * Adds event handlers for items within the accordion.
  2400. * @private
  2401. */
  2402. }, {
  2403. key: "_events",
  2404. value: function _events() {
  2405. var _this = this;
  2406. this.$tabs.each(function () {
  2407. var $elem = $(this);
  2408. var $tabContent = $elem.children('[data-tab-content]');
  2409. if ($tabContent.length) {
  2410. $elem.children('a').off('click.zf.accordion keydown.zf.accordion').on('click.zf.accordion', function (e) {
  2411. e.preventDefault();
  2412. _this.toggle($tabContent);
  2413. }).on('keydown.zf.accordion', function (e) {
  2414. Keyboard.handleKey(e, 'Accordion', {
  2415. toggle: function toggle() {
  2416. _this.toggle($tabContent);
  2417. },
  2418. next: function next() {
  2419. var $a = $elem.next().find('a').focus();
  2420. if (!_this.options.multiExpand) {
  2421. $a.trigger('click.zf.accordion');
  2422. }
  2423. },
  2424. previous: function previous() {
  2425. var $a = $elem.prev().find('a').focus();
  2426. if (!_this.options.multiExpand) {
  2427. $a.trigger('click.zf.accordion');
  2428. }
  2429. },
  2430. handled: function handled() {
  2431. e.preventDefault();
  2432. e.stopPropagation();
  2433. }
  2434. });
  2435. });
  2436. }
  2437. });
  2438. if (this.options.deepLink) {
  2439. $(window).on('hashchange', this._checkDeepLink);
  2440. }
  2441. }
  2442. /**
  2443. * Toggles the selected content pane's open/close state.
  2444. * @param {jQuery} $target - jQuery object of the pane to toggle (`.accordion-content`).
  2445. * @function
  2446. */
  2447. }, {
  2448. key: "toggle",
  2449. value: function toggle($target) {
  2450. if ($target.closest('[data-accordion]').is('[disabled]')) {
  2451. console.info('Cannot toggle an accordion that is disabled.');
  2452. return;
  2453. }
  2454. if ($target.parent().hasClass('is-active')) {
  2455. this.up($target);
  2456. } else {
  2457. this.down($target);
  2458. } //either replace or update browser history
  2459. if (this.options.deepLink) {
  2460. var anchor = $target.prev('a').attr('href');
  2461. if (this.options.updateHistory) {
  2462. history.pushState({}, '', anchor);
  2463. } else {
  2464. history.replaceState({}, '', anchor);
  2465. }
  2466. }
  2467. }
  2468. /**
  2469. * Opens the accordion tab defined by `$target`.
  2470. * @param {jQuery} $target - Accordion pane to open (`.accordion-content`).
  2471. * @fires Accordion#down
  2472. * @function
  2473. */
  2474. }, {
  2475. key: "down",
  2476. value: function down($target) {
  2477. if ($target.closest('[data-accordion]').is('[disabled]')) {
  2478. console.info('Cannot call down on an accordion that is disabled.');
  2479. return;
  2480. }
  2481. if (this.options.multiExpand) this._openTab($target);else this._openSingleTab($target);
  2482. }
  2483. /**
  2484. * Closes the tab defined by `$target`.
  2485. * It may be ignored if the Accordion options don't allow it.
  2486. *
  2487. * @param {jQuery} $target - Accordion tab to close (`.accordion-content`).
  2488. * @fires Accordion#up
  2489. * @function
  2490. */
  2491. }, {
  2492. key: "up",
  2493. value: function up($target) {
  2494. if (this.$element.is('[disabled]')) {
  2495. console.info('Cannot call up on an accordion that is disabled.');
  2496. return;
  2497. } // Don't close the item if it is already closed
  2498. var $targetItem = $target.parent();
  2499. if (!$targetItem.hasClass('is-active')) return; // Don't close the item if there is no other active item (unless with `allowAllClosed`)
  2500. var $othersItems = $targetItem.siblings();
  2501. if (!this.options.allowAllClosed && !$othersItems.hasClass('is-active')) return;
  2502. this._closeTab($target);
  2503. }
  2504. /**
  2505. * Make the tab defined by `$target` the only opened tab, closing all others tabs.
  2506. * @param {jQuery} $target - Accordion tab to open (`.accordion-content`).
  2507. * @function
  2508. * @private
  2509. */
  2510. }, {
  2511. key: "_openSingleTab",
  2512. value: function _openSingleTab($target) {
  2513. // Close all the others active tabs.
  2514. var $activeContents = this.$element.children('.is-active').children('[data-tab-content]');
  2515. if ($activeContents.length) {
  2516. this._closeTab($activeContents.not($target));
  2517. } // Then open the target.
  2518. this._openTab($target);
  2519. }
  2520. /**
  2521. * Opens the tab defined by `$target`.
  2522. * @param {jQuery} $target - Accordion tab to open (`.accordion-content`).
  2523. * @fires Accordion#down
  2524. * @function
  2525. * @private
  2526. */
  2527. }, {
  2528. key: "_openTab",
  2529. value: function _openTab($target) {
  2530. var _this3 = this;
  2531. var $targetItem = $target.parent();
  2532. var targetContentId = $target.attr('aria-labelledby');
  2533. $target.attr('aria-hidden', false);
  2534. $targetItem.addClass('is-active');
  2535. $("#".concat(targetContentId)).attr({
  2536. 'aria-expanded': true,
  2537. 'aria-selected': true
  2538. });
  2539. $target.slideDown(this.options.slideSpeed, function () {
  2540. /**
  2541. * Fires when the tab is done opening.
  2542. * @event Accordion#down
  2543. */
  2544. _this3.$element.trigger('down.zf.accordion', [$target]);
  2545. });
  2546. }
  2547. /**
  2548. * Closes the tab defined by `$target`.
  2549. * @param {jQuery} $target - Accordion tab to close (`.accordion-content`).
  2550. * @fires Accordion#up
  2551. * @function
  2552. * @private
  2553. */
  2554. }, {
  2555. key: "_closeTab",
  2556. value: function _closeTab($target) {
  2557. var _this4 = this;
  2558. var $targetItem = $target.parent();
  2559. var targetContentId = $target.attr('aria-labelledby');
  2560. $target.attr('aria-hidden', true);
  2561. $targetItem.removeClass('is-active');
  2562. $("#".concat(targetContentId)).attr({
  2563. 'aria-expanded': false,
  2564. 'aria-selected': false
  2565. });
  2566. $target.slideUp(this.options.slideSpeed, function () {
  2567. /**
  2568. * Fires when the tab is done collapsing up.
  2569. * @event Accordion#up
  2570. */
  2571. _this4.$element.trigger('up.zf.accordion', [$target]);
  2572. });
  2573. }
  2574. /**
  2575. * Closes all active tabs
  2576. * @fires Accordion#up
  2577. * @function
  2578. * @private
  2579. */
  2580. }, {
  2581. key: "_closeAllTabs",
  2582. value: function _closeAllTabs() {
  2583. var $activeTabs = this.$element.children('.is-active').children('[data-tab-content]');
  2584. if ($activeTabs.length) {
  2585. this._closeTab($activeTabs);
  2586. }
  2587. }
  2588. /**
  2589. * Destroys an instance of an accordion.
  2590. * @fires Accordion#destroyed
  2591. * @function
  2592. */
  2593. }, {
  2594. key: "_destroy",
  2595. value: function _destroy() {
  2596. this.$element.find('[data-tab-content]').stop(true).slideUp(0).css('display', '');
  2597. this.$element.find('a').off('.zf.accordion');
  2598. if (this.options.deepLink) {
  2599. $(window).off('hashchange', this._checkDeepLink);
  2600. }
  2601. }
  2602. }]);
  2603. return Accordion;
  2604. }(Plugin);
  2605. Accordion.defaults = {
  2606. /**
  2607. * Amount of time to animate the opening of an accordion pane.
  2608. * @option
  2609. * @type {number}
  2610. * @default 250
  2611. */
  2612. slideSpeed: 250,
  2613. /**
  2614. * Allow the accordion to have multiple open panes.
  2615. * @option
  2616. * @type {boolean}
  2617. * @default false
  2618. */
  2619. multiExpand: false,
  2620. /**
  2621. * Allow the accordion to close all panes.
  2622. * @option
  2623. * @type {boolean}
  2624. * @default false
  2625. */
  2626. allowAllClosed: false,
  2627. /**
  2628. * Link the location hash to the open pane.
  2629. * Set the location hash when the opened pane changes, and open and scroll to the corresponding pane when the location changes.
  2630. * @option
  2631. * @type {boolean}
  2632. * @default false
  2633. */
  2634. deepLink: false,
  2635. /**
  2636. * If `deepLink` is enabled, adjust the deep link scroll to make sure the top of the accordion panel is visible
  2637. * @option
  2638. * @type {boolean}
  2639. * @default false
  2640. */
  2641. deepLinkSmudge: false,
  2642. /**
  2643. * If `deepLinkSmudge` is enabled, animation time (ms) for the deep link adjustment
  2644. * @option
  2645. * @type {number}
  2646. * @default 300
  2647. */
  2648. deepLinkSmudgeDelay: 300,
  2649. /**
  2650. * If `deepLink` is enabled, update the browser history with the open accordion
  2651. * @option
  2652. * @type {boolean}
  2653. * @default false
  2654. */
  2655. updateHistory: false
  2656. };
  2657. /**
  2658. * AccordionMenu module.
  2659. * @module foundation.accordionMenu
  2660. * @requires foundation.util.keyboard
  2661. * @requires foundation.util.nest
  2662. */
  2663. var AccordionMenu =
  2664. /*#__PURE__*/
  2665. function (_Plugin) {
  2666. _inherits(AccordionMenu, _Plugin);
  2667. function AccordionMenu() {
  2668. _classCallCheck(this, AccordionMenu);
  2669. return _possibleConstructorReturn(this, _getPrototypeOf(AccordionMenu).apply(this, arguments));
  2670. }
  2671. _createClass(AccordionMenu, [{
  2672. key: "_setup",
  2673. /**
  2674. * Creates a new instance of an accordion menu.
  2675. * @class
  2676. * @name AccordionMenu
  2677. * @fires AccordionMenu#init
  2678. * @param {jQuery} element - jQuery object to make into an accordion menu.
  2679. * @param {Object} options - Overrides to the default plugin settings.
  2680. */
  2681. value: function _setup(element, options) {
  2682. this.$element = element;
  2683. this.options = $.extend({}, AccordionMenu.defaults, this.$element.data(), options);
  2684. this.className = 'AccordionMenu'; // ie9 back compat
  2685. this._init();
  2686. Keyboard.register('AccordionMenu', {
  2687. 'ENTER': 'toggle',
  2688. 'SPACE': 'toggle',
  2689. 'ARROW_RIGHT': 'open',
  2690. 'ARROW_UP': 'up',
  2691. 'ARROW_DOWN': 'down',
  2692. 'ARROW_LEFT': 'close',
  2693. 'ESCAPE': 'closeAll'
  2694. });
  2695. }
  2696. /**
  2697. * Initializes the accordion menu by hiding all nested menus.
  2698. * @private
  2699. */
  2700. }, {
  2701. key: "_init",
  2702. value: function _init() {
  2703. Nest.Feather(this.$element, 'accordion');
  2704. var _this = this;
  2705. this.$element.find('[data-submenu]').not('.is-active').slideUp(0); //.find('a').css('padding-left', '1rem');
  2706. this.$element.attr({
  2707. 'role': 'tree',
  2708. 'aria-multiselectable': this.options.multiOpen
  2709. });
  2710. this.$menuLinks = this.$element.find('.is-accordion-submenu-parent');
  2711. this.$menuLinks.each(function () {
  2712. var linkId = this.id || GetYoDigits(6, 'acc-menu-link'),
  2713. $elem = $(this),
  2714. $sub = $elem.children('[data-submenu]'),
  2715. subId = $sub[0].id || GetYoDigits(6, 'acc-menu'),
  2716. isActive = $sub.hasClass('is-active');
  2717. if (_this.options.parentLink) {
  2718. var $anchor = $elem.children('a');
  2719. $anchor.clone().prependTo($sub).wrap('<li data-is-parent-link class="is-submenu-parent-item is-submenu-item is-accordion-submenu-item"></li>');
  2720. }
  2721. if (_this.options.submenuToggle) {
  2722. $elem.addClass('has-submenu-toggle');
  2723. $elem.children('a').after('<button id="' + linkId + '" class="submenu-toggle" aria-controls="' + subId + '" aria-expanded="' + isActive + '" title="' + _this.options.submenuToggleText + '"><span class="submenu-toggle-text">' + _this.options.submenuToggleText + '</span></button>');
  2724. } else {
  2725. $elem.attr({
  2726. 'aria-controls': subId,
  2727. 'aria-expanded': isActive,
  2728. 'id': linkId
  2729. });
  2730. }
  2731. $sub.attr({
  2732. 'aria-labelledby': linkId,
  2733. 'aria-hidden': !isActive,
  2734. 'role': 'group',
  2735. 'id': subId
  2736. });
  2737. });
  2738. this.$element.find('li').attr({
  2739. 'role': 'treeitem'
  2740. });
  2741. var initPanes = this.$element.find('.is-active');
  2742. if (initPanes.length) {
  2743. var _this = this;
  2744. initPanes.each(function () {
  2745. _this.down($(this));
  2746. });
  2747. }
  2748. this._events();
  2749. }
  2750. /**
  2751. * Adds event handlers for items within the menu.
  2752. * @private
  2753. */
  2754. }, {
  2755. key: "_events",
  2756. value: function _events() {
  2757. var _this = this;
  2758. this.$element.find('li').each(function () {
  2759. var $submenu = $(this).children('[data-submenu]');
  2760. if ($submenu.length) {
  2761. if (_this.options.submenuToggle) {
  2762. $(this).children('.submenu-toggle').off('click.zf.accordionMenu').on('click.zf.accordionMenu', function (e) {
  2763. _this.toggle($submenu);
  2764. });
  2765. } else {
  2766. $(this).children('a').off('click.zf.accordionMenu').on('click.zf.accordionMenu', function (e) {
  2767. e.preventDefault();
  2768. _this.toggle($submenu);
  2769. });
  2770. }
  2771. }
  2772. }).on('keydown.zf.accordionmenu', function (e) {
  2773. var $element = $(this),
  2774. $elements = $element.parent('ul').children('li'),
  2775. $prevElement,
  2776. $nextElement,
  2777. $target = $element.children('[data-submenu]');
  2778. $elements.each(function (i) {
  2779. if ($(this).is($element)) {
  2780. $prevElement = $elements.eq(Math.max(0, i - 1)).find('a').first();
  2781. $nextElement = $elements.eq(Math.min(i + 1, $elements.length - 1)).find('a').first();
  2782. if ($(this).children('[data-submenu]:visible').length) {
  2783. // has open sub menu
  2784. $nextElement = $element.find('li:first-child').find('a').first();
  2785. }
  2786. if ($(this).is(':first-child')) {
  2787. // is first element of sub menu
  2788. $prevElement = $element.parents('li').first().find('a').first();
  2789. } else if ($prevElement.parents('li').first().children('[data-submenu]:visible').length) {
  2790. // if previous element has open sub menu
  2791. $prevElement = $prevElement.parents('li').find('li:last-child').find('a').first();
  2792. }
  2793. if ($(this).is(':last-child')) {
  2794. // is last element of sub menu
  2795. $nextElement = $element.parents('li').first().next('li').find('a').first();
  2796. }
  2797. return;
  2798. }
  2799. });
  2800. Keyboard.handleKey(e, 'AccordionMenu', {
  2801. open: function open() {
  2802. if ($target.is(':hidden')) {
  2803. _this.down($target);
  2804. $target.find('li').first().find('a').first().focus();
  2805. }
  2806. },
  2807. close: function close() {
  2808. if ($target.length && !$target.is(':hidden')) {
  2809. // close active sub of this item
  2810. _this.up($target);
  2811. } else if ($element.parent('[data-submenu]').length) {
  2812. // close currently open sub
  2813. _this.up($element.parent('[data-submenu]'));
  2814. $element.parents('li').first().find('a').first().focus();
  2815. }
  2816. },
  2817. up: function up() {
  2818. $prevElement.focus();
  2819. return true;
  2820. },
  2821. down: function down() {
  2822. $nextElement.focus();
  2823. return true;
  2824. },
  2825. toggle: function toggle() {
  2826. if (_this.options.submenuToggle) {
  2827. return false;
  2828. }
  2829. if ($element.children('[data-submenu]').length) {
  2830. _this.toggle($element.children('[data-submenu]'));
  2831. return true;
  2832. }
  2833. },
  2834. closeAll: function closeAll() {
  2835. _this.hideAll();
  2836. },
  2837. handled: function handled(preventDefault) {
  2838. if (preventDefault) {
  2839. e.preventDefault();
  2840. }
  2841. e.stopImmediatePropagation();
  2842. }
  2843. });
  2844. }); //.attr('tabindex', 0);
  2845. }
  2846. /**
  2847. * Closes all panes of the menu.
  2848. * @function
  2849. */
  2850. }, {
  2851. key: "hideAll",
  2852. value: function hideAll() {
  2853. this.up(this.$element.find('[data-submenu]'));
  2854. }
  2855. /**
  2856. * Opens all panes of the menu.
  2857. * @function
  2858. */
  2859. }, {
  2860. key: "showAll",
  2861. value: function showAll() {
  2862. this.down(this.$element.find('[data-submenu]'));
  2863. }
  2864. /**
  2865. * Toggles the open/close state of a submenu.
  2866. * @function
  2867. * @param {jQuery} $target - the submenu to toggle
  2868. */
  2869. }, {
  2870. key: "toggle",
  2871. value: function toggle($target) {
  2872. if (!$target.is(':animated')) {
  2873. if (!$target.is(':hidden')) {
  2874. this.up($target);
  2875. } else {
  2876. this.down($target);
  2877. }
  2878. }
  2879. }
  2880. /**
  2881. * Opens the sub-menu defined by `$target`.
  2882. * @param {jQuery} $target - Sub-menu to open.
  2883. * @fires AccordionMenu#down
  2884. */
  2885. }, {
  2886. key: "down",
  2887. value: function down($target) {
  2888. var _this2 = this;
  2889. // If having multiple submenus active is disabled, close all the submenus
  2890. // that are not parents or children of the targeted submenu.
  2891. if (!this.options.multiOpen) {
  2892. // The "branch" of the targetted submenu, from the component root to
  2893. // the active submenus nested in it.
  2894. var $targetBranch = $target.parentsUntil(this.$element).add($target).add($target.find('.is-active')); // All the active submenus that are not in the branch.
  2895. var $othersActiveSubmenus = this.$element.find('.is-active').not($targetBranch);
  2896. this.up($othersActiveSubmenus);
  2897. }
  2898. $target.addClass('is-active').attr({
  2899. 'aria-hidden': false
  2900. });
  2901. if (this.options.submenuToggle) {
  2902. $target.prev('.submenu-toggle').attr({
  2903. 'aria-expanded': true
  2904. });
  2905. } else {
  2906. $target.parent('.is-accordion-submenu-parent').attr({
  2907. 'aria-expanded': true
  2908. });
  2909. }
  2910. $target.slideDown(this.options.slideSpeed, function () {
  2911. /**
  2912. * Fires when the menu is done opening.
  2913. * @event AccordionMenu#down
  2914. */
  2915. _this2.$element.trigger('down.zf.accordionMenu', [$target]);
  2916. });
  2917. }
  2918. /**
  2919. * Closes the sub-menu defined by `$target`. All sub-menus inside the target will be closed as well.
  2920. * @param {jQuery} $target - Sub-menu to close.
  2921. * @fires AccordionMenu#up
  2922. */
  2923. }, {
  2924. key: "up",
  2925. value: function up($target) {
  2926. var _this3 = this;
  2927. var $submenus = $target.find('[data-submenu]');
  2928. var $allmenus = $target.add($submenus);
  2929. $submenus.slideUp(0);
  2930. $allmenus.removeClass('is-active').attr('aria-hidden', true);
  2931. if (this.options.submenuToggle) {
  2932. $allmenus.prev('.submenu-toggle').attr('aria-expanded', false);
  2933. } else {
  2934. $allmenus.parent('.is-accordion-submenu-parent').attr('aria-expanded', false);
  2935. }
  2936. $target.slideUp(this.options.slideSpeed, function () {
  2937. /**
  2938. * Fires when the menu is done collapsing up.
  2939. * @event AccordionMenu#up
  2940. */
  2941. _this3.$element.trigger('up.zf.accordionMenu', [$target]);
  2942. });
  2943. }
  2944. /**
  2945. * Destroys an instance of accordion menu.
  2946. * @fires AccordionMenu#destroyed
  2947. */
  2948. }, {
  2949. key: "_destroy",
  2950. value: function _destroy() {
  2951. this.$element.find('[data-submenu]').slideDown(0).css('display', '');
  2952. this.$element.find('a').off('click.zf.accordionMenu');
  2953. this.$element.find('[data-is-parent-link]').detach();
  2954. if (this.options.submenuToggle) {
  2955. this.$element.find('.has-submenu-toggle').removeClass('has-submenu-toggle');
  2956. this.$element.find('.submenu-toggle').remove();
  2957. }
  2958. Nest.Burn(this.$element, 'accordion');
  2959. }
  2960. }]);
  2961. return AccordionMenu;
  2962. }(Plugin);
  2963. AccordionMenu.defaults = {
  2964. /**
  2965. * Adds the parent link to the submenu.
  2966. * @option
  2967. * @type {boolean}
  2968. * @default false
  2969. */
  2970. parentLink: false,
  2971. /**
  2972. * Amount of time to animate the opening of a submenu in ms.
  2973. * @option
  2974. * @type {number}
  2975. * @default 250
  2976. */
  2977. slideSpeed: 250,
  2978. /**
  2979. * Adds a separate submenu toggle button. This allows the parent item to have a link.
  2980. * @option
  2981. * @example true
  2982. */
  2983. submenuToggle: false,
  2984. /**
  2985. * The text used for the submenu toggle if enabled. This is used for screen readers only.
  2986. * @option
  2987. * @example true
  2988. */
  2989. submenuToggleText: 'Toggle menu',
  2990. /**
  2991. * Allow the menu to have multiple open panes.
  2992. * @option
  2993. * @type {boolean}
  2994. * @default true
  2995. */
  2996. multiOpen: true
  2997. };
  2998. /**
  2999. * Drilldown module.
  3000. * @module foundation.drilldown
  3001. * @requires foundation.util.keyboard
  3002. * @requires foundation.util.nest
  3003. * @requires foundation.util.box
  3004. */
  3005. var Drilldown =
  3006. /*#__PURE__*/
  3007. function (_Plugin) {
  3008. _inherits(Drilldown, _Plugin);
  3009. function Drilldown() {
  3010. _classCallCheck(this, Drilldown);
  3011. return _possibleConstructorReturn(this, _getPrototypeOf(Drilldown).apply(this, arguments));
  3012. }
  3013. _createClass(Drilldown, [{
  3014. key: "_setup",
  3015. /**
  3016. * Creates a new instance of a drilldown menu.
  3017. * @class
  3018. * @name Drilldown
  3019. * @param {jQuery} element - jQuery object to make into an accordion menu.
  3020. * @param {Object} options - Overrides to the default plugin settings.
  3021. */
  3022. value: function _setup(element, options) {
  3023. this.$element = element;
  3024. this.options = $.extend({}, Drilldown.defaults, this.$element.data(), options);
  3025. this.className = 'Drilldown'; // ie9 back compat
  3026. this._init();
  3027. Keyboard.register('Drilldown', {
  3028. 'ENTER': 'open',
  3029. 'SPACE': 'open',
  3030. 'ARROW_RIGHT': 'next',
  3031. 'ARROW_UP': 'up',
  3032. 'ARROW_DOWN': 'down',
  3033. 'ARROW_LEFT': 'previous',
  3034. 'ESCAPE': 'close',
  3035. 'TAB': 'down',
  3036. 'SHIFT_TAB': 'up'
  3037. });
  3038. }
  3039. /**
  3040. * Initializes the drilldown by creating jQuery collections of elements
  3041. * @private
  3042. */
  3043. }, {
  3044. key: "_init",
  3045. value: function _init() {
  3046. Nest.Feather(this.$element, 'drilldown');
  3047. if (this.options.autoApplyClass) {
  3048. this.$element.addClass('drilldown');
  3049. }
  3050. this.$element.attr({
  3051. 'role': 'tree',
  3052. 'aria-multiselectable': false
  3053. });
  3054. this.$submenuAnchors = this.$element.find('li.is-drilldown-submenu-parent').children('a');
  3055. this.$submenus = this.$submenuAnchors.parent('li').children('[data-submenu]').attr('role', 'group');
  3056. this.$menuItems = this.$element.find('li').not('.js-drilldown-back').attr('role', 'treeitem').find('a'); // Set the main menu as current by default (unless a submenu is selected)
  3057. // Used to set the wrapper height when the drilldown is closed/reopened from any (sub)menu
  3058. this.$currentMenu = this.$element;
  3059. this.$element.attr('data-mutate', this.$element.attr('data-drilldown') || GetYoDigits(6, 'drilldown'));
  3060. this._prepareMenu();
  3061. this._registerEvents();
  3062. this._keyboardEvents();
  3063. }
  3064. /**
  3065. * prepares drilldown menu by setting attributes to links and elements
  3066. * sets a min height to prevent content jumping
  3067. * wraps the element if not already wrapped
  3068. * @private
  3069. * @function
  3070. */
  3071. }, {
  3072. key: "_prepareMenu",
  3073. value: function _prepareMenu() {
  3074. var _this = this; // if(!this.options.holdOpen){
  3075. // this._menuLinkEvents();
  3076. // }
  3077. this.$submenuAnchors.each(function () {
  3078. var $link = $(this);
  3079. var $sub = $link.parent();
  3080. if (_this.options.parentLink) {
  3081. $link.clone().prependTo($sub.children('[data-submenu]')).wrap('<li data-is-parent-link class="is-submenu-parent-item is-submenu-item is-drilldown-submenu-item" role="menuitem"></li>');
  3082. }
  3083. $link.data('savedHref', $link.attr('href')).removeAttr('href').attr('tabindex', 0);
  3084. $link.children('[data-submenu]').attr({
  3085. 'aria-hidden': true,
  3086. 'tabindex': 0,
  3087. 'role': 'group'
  3088. });
  3089. _this._events($link);
  3090. });
  3091. this.$submenus.each(function () {
  3092. var $menu = $(this),
  3093. $back = $menu.find('.js-drilldown-back');
  3094. if (!$back.length) {
  3095. switch (_this.options.backButtonPosition) {
  3096. case "bottom":
  3097. $menu.append(_this.options.backButton);
  3098. break;
  3099. case "top":
  3100. $menu.prepend(_this.options.backButton);
  3101. break;
  3102. default:
  3103. console.error("Unsupported backButtonPosition value '" + _this.options.backButtonPosition + "'");
  3104. }
  3105. }
  3106. _this._back($menu);
  3107. });
  3108. this.$submenus.addClass('invisible');
  3109. if (!this.options.autoHeight) {
  3110. this.$submenus.addClass('drilldown-submenu-cover-previous');
  3111. } // create a wrapper on element if it doesn't exist.
  3112. if (!this.$element.parent().hasClass('is-drilldown')) {
  3113. this.$wrapper = $(this.options.wrapper).addClass('is-drilldown');
  3114. if (this.options.animateHeight) this.$wrapper.addClass('animate-height');
  3115. this.$element.wrap(this.$wrapper);
  3116. } // set wrapper
  3117. this.$wrapper = this.$element.parent();
  3118. this.$wrapper.css(this._getMaxDims());
  3119. }
  3120. }, {
  3121. key: "_resize",
  3122. value: function _resize() {
  3123. this.$wrapper.css({
  3124. 'max-width': 'none',
  3125. 'min-height': 'none'
  3126. }); // _getMaxDims has side effects (boo) but calling it should update all other necessary heights & widths
  3127. this.$wrapper.css(this._getMaxDims());
  3128. }
  3129. /**
  3130. * Adds event handlers to elements in the menu.
  3131. * @function
  3132. * @private
  3133. * @param {jQuery} $elem - the current menu item to add handlers to.
  3134. */
  3135. }, {
  3136. key: "_events",
  3137. value: function _events($elem) {
  3138. var _this = this;
  3139. $elem.off('click.zf.drilldown').on('click.zf.drilldown', function (e) {
  3140. if ($(e.target).parentsUntil('ul', 'li').hasClass('is-drilldown-submenu-parent')) {
  3141. e.stopImmediatePropagation();
  3142. e.preventDefault();
  3143. } // if(e.target !== e.currentTarget.firstElementChild){
  3144. // return false;
  3145. // }
  3146. _this._show($elem.parent('li'));
  3147. if (_this.options.closeOnClick) {
  3148. var $body = $('body');
  3149. $body.off('.zf.drilldown').on('click.zf.drilldown', function (e) {
  3150. if (e.target === _this.$element[0] || $.contains(_this.$element[0], e.target)) {
  3151. return;
  3152. }
  3153. e.preventDefault();
  3154. _this._hideAll();
  3155. $body.off('.zf.drilldown');
  3156. });
  3157. }
  3158. });
  3159. }
  3160. /**
  3161. * Adds event handlers to the menu element.
  3162. * @function
  3163. * @private
  3164. */
  3165. }, {
  3166. key: "_registerEvents",
  3167. value: function _registerEvents() {
  3168. if (this.options.scrollTop) {
  3169. this._bindHandler = this._scrollTop.bind(this);
  3170. this.$element.on('open.zf.drilldown hide.zf.drilldown closed.zf.drilldown', this._bindHandler);
  3171. }
  3172. this.$element.on('mutateme.zf.trigger', this._resize.bind(this));
  3173. }
  3174. /**
  3175. * Scroll to Top of Element or data-scroll-top-element
  3176. * @function
  3177. * @fires Drilldown#scrollme
  3178. */
  3179. }, {
  3180. key: "_scrollTop",
  3181. value: function _scrollTop() {
  3182. var _this = this;
  3183. var $scrollTopElement = _this.options.scrollTopElement != '' ? $(_this.options.scrollTopElement) : _this.$element,
  3184. scrollPos = parseInt($scrollTopElement.offset().top + _this.options.scrollTopOffset, 10);
  3185. $('html, body').stop(true).animate({
  3186. scrollTop: scrollPos
  3187. }, _this.options.animationDuration, _this.options.animationEasing, function () {
  3188. /**
  3189. * Fires after the menu has scrolled
  3190. * @event Drilldown#scrollme
  3191. */
  3192. if (this === $('html')[0]) _this.$element.trigger('scrollme.zf.drilldown');
  3193. });
  3194. }
  3195. /**
  3196. * Adds keydown event listener to `li`'s in the menu.
  3197. * @private
  3198. */
  3199. }, {
  3200. key: "_keyboardEvents",
  3201. value: function _keyboardEvents() {
  3202. var _this = this;
  3203. this.$menuItems.add(this.$element.find('.js-drilldown-back > a, .is-submenu-parent-item > a')).on('keydown.zf.drilldown', function (e) {
  3204. var $element = $(this),
  3205. $elements = $element.parent('li').parent('ul').children('li').children('a'),
  3206. $prevElement,
  3207. $nextElement;
  3208. $elements.each(function (i) {
  3209. if ($(this).is($element)) {
  3210. $prevElement = $elements.eq(Math.max(0, i - 1));
  3211. $nextElement = $elements.eq(Math.min(i + 1, $elements.length - 1));
  3212. return;
  3213. }
  3214. });
  3215. Keyboard.handleKey(e, 'Drilldown', {
  3216. next: function next() {
  3217. if ($element.is(_this.$submenuAnchors)) {
  3218. _this._show($element.parent('li'));
  3219. $element.parent('li').one(transitionend($element), function () {
  3220. $element.parent('li').find('ul li a').not('.js-drilldown-back a').first().focus();
  3221. });
  3222. return true;
  3223. }
  3224. },
  3225. previous: function previous() {
  3226. _this._hide($element.parent('li').parent('ul'));
  3227. $element.parent('li').parent('ul').one(transitionend($element), function () {
  3228. setTimeout(function () {
  3229. $element.parent('li').parent('ul').parent('li').children('a').first().focus();
  3230. }, 1);
  3231. });
  3232. return true;
  3233. },
  3234. up: function up() {
  3235. $prevElement.focus(); // Don't tap focus on first element in root ul
  3236. return !$element.is(_this.$element.find('> li:first-child > a'));
  3237. },
  3238. down: function down() {
  3239. $nextElement.focus(); // Don't tap focus on last element in root ul
  3240. return !$element.is(_this.$element.find('> li:last-child > a'));
  3241. },
  3242. close: function close() {
  3243. // Don't close on element in root ul
  3244. if (!$element.is(_this.$element.find('> li > a'))) {
  3245. _this._hide($element.parent().parent());
  3246. $element.parent().parent().siblings('a').focus();
  3247. }
  3248. },
  3249. open: function open() {
  3250. if (_this.options.parentLink && $element.attr('href')) {
  3251. // Link with href
  3252. return false;
  3253. } else if (!$element.is(_this.$menuItems)) {
  3254. // not menu item means back button
  3255. _this._hide($element.parent('li').parent('ul'));
  3256. $element.parent('li').parent('ul').one(transitionend($element), function () {
  3257. setTimeout(function () {
  3258. $element.parent('li').parent('ul').parent('li').children('a').first().focus();
  3259. }, 1);
  3260. });
  3261. return true;
  3262. } else if ($element.is(_this.$submenuAnchors)) {
  3263. // Sub menu item
  3264. _this._show($element.parent('li'));
  3265. $element.parent('li').one(transitionend($element), function () {
  3266. $element.parent('li').find('ul li a').not('.js-drilldown-back a').first().focus();
  3267. });
  3268. return true;
  3269. }
  3270. },
  3271. handled: function handled(preventDefault) {
  3272. if (preventDefault) {
  3273. e.preventDefault();
  3274. }
  3275. e.stopImmediatePropagation();
  3276. }
  3277. });
  3278. }); // end keyboardAccess
  3279. }
  3280. /**
  3281. * Closes all open elements, and returns to root menu.
  3282. * @function
  3283. * @fires Drilldown#closed
  3284. */
  3285. }, {
  3286. key: "_hideAll",
  3287. value: function _hideAll() {
  3288. var $elem = this.$element.find('.is-drilldown-submenu.is-active').addClass('is-closing');
  3289. if (this.options.autoHeight) this.$wrapper.css({
  3290. height: $elem.parent().closest('ul').data('calcHeight')
  3291. });
  3292. $elem.one(transitionend($elem), function (e) {
  3293. $elem.removeClass('is-active is-closing');
  3294. });
  3295. /**
  3296. * Fires when the menu is fully closed.
  3297. * @event Drilldown#closed
  3298. */
  3299. this.$element.trigger('closed.zf.drilldown');
  3300. }
  3301. /**
  3302. * Adds event listener for each `back` button, and closes open menus.
  3303. * @function
  3304. * @fires Drilldown#back
  3305. * @param {jQuery} $elem - the current sub-menu to add `back` event.
  3306. */
  3307. }, {
  3308. key: "_back",
  3309. value: function _back($elem) {
  3310. var _this = this;
  3311. $elem.off('click.zf.drilldown');
  3312. $elem.children('.js-drilldown-back').on('click.zf.drilldown', function (e) {
  3313. e.stopImmediatePropagation(); // console.log('mouseup on back');
  3314. _this._hide($elem); // If there is a parent submenu, call show
  3315. var parentSubMenu = $elem.parent('li').parent('ul').parent('li');
  3316. if (parentSubMenu.length) {
  3317. _this._show(parentSubMenu);
  3318. }
  3319. });
  3320. }
  3321. /**
  3322. * Adds event listener to menu items w/o submenus to close open menus on click.
  3323. * @function
  3324. * @private
  3325. */
  3326. }, {
  3327. key: "_menuLinkEvents",
  3328. value: function _menuLinkEvents() {
  3329. var _this = this;
  3330. this.$menuItems.not('.is-drilldown-submenu-parent').off('click.zf.drilldown').on('click.zf.drilldown', function (e) {
  3331. // e.stopImmediatePropagation();
  3332. setTimeout(function () {
  3333. _this._hideAll();
  3334. }, 0);
  3335. });
  3336. }
  3337. /**
  3338. * Sets the CSS classes for submenu to show it.
  3339. * @function
  3340. * @private
  3341. * @param {jQuery} $elem - the target submenu (`ul` tag)
  3342. * @param {boolean} trigger - trigger drilldown event
  3343. */
  3344. }, {
  3345. key: "_setShowSubMenuClasses",
  3346. value: function _setShowSubMenuClasses($elem, trigger) {
  3347. $elem.addClass('is-active').removeClass('invisible').attr('aria-hidden', false);
  3348. $elem.parent('li').attr('aria-expanded', true);
  3349. if (trigger === true) {
  3350. this.$element.trigger('open.zf.drilldown', [$elem]);
  3351. }
  3352. }
  3353. /**
  3354. * Sets the CSS classes for submenu to hide it.
  3355. * @function
  3356. * @private
  3357. * @param {jQuery} $elem - the target submenu (`ul` tag)
  3358. * @param {boolean} trigger - trigger drilldown event
  3359. */
  3360. }, {
  3361. key: "_setHideSubMenuClasses",
  3362. value: function _setHideSubMenuClasses($elem, trigger) {
  3363. $elem.removeClass('is-active').addClass('invisible').attr('aria-hidden', true);
  3364. $elem.parent('li').attr('aria-expanded', false);
  3365. if (trigger === true) {
  3366. $elem.trigger('hide.zf.drilldown', [$elem]);
  3367. }
  3368. }
  3369. /**
  3370. * Opens a specific drilldown (sub)menu no matter which (sub)menu in it is currently visible.
  3371. * Compared to _show() this lets you jump into any submenu without clicking through every submenu on the way to it.
  3372. * @function
  3373. * @fires Drilldown#open
  3374. * @param {jQuery} $elem - the target (sub)menu (`ul` tag)
  3375. * @param {boolean} autoFocus - if true the first link in the target (sub)menu gets auto focused
  3376. */
  3377. }, {
  3378. key: "_showMenu",
  3379. value: function _showMenu($elem, autoFocus) {
  3380. var _this = this; // Reset drilldown
  3381. var $expandedSubmenus = this.$element.find('li[aria-expanded="true"] > ul[data-submenu]');
  3382. $expandedSubmenus.each(function (index) {
  3383. _this._setHideSubMenuClasses($(this));
  3384. }); // Save the menu as the currently displayed one.
  3385. this.$currentMenu = $elem; // If target menu is root, focus first link & exit
  3386. if ($elem.is('[data-drilldown]')) {
  3387. if (autoFocus === true) $elem.find('li[role="treeitem"] > a').first().focus();
  3388. if (this.options.autoHeight) this.$wrapper.css('height', $elem.data('calcHeight'));
  3389. return;
  3390. } // Find all submenus on way to root incl. the element itself
  3391. var $submenus = $elem.children().first().parentsUntil('[data-drilldown]', '[data-submenu]'); // Open target menu and all submenus on its way to root
  3392. $submenus.each(function (index) {
  3393. // Update height of first child (target menu) if autoHeight option true
  3394. if (index === 0 && _this.options.autoHeight) {
  3395. _this.$wrapper.css('height', $(this).data('calcHeight'));
  3396. }
  3397. var isLastChild = index == $submenus.length - 1; // Add transitionsend listener to last child (root due to reverse order) to open target menu's first link
  3398. // Last child makes sure the event gets always triggered even if going through several menus
  3399. if (isLastChild === true) {
  3400. $(this).one(transitionend($(this)), function () {
  3401. if (autoFocus === true) {
  3402. $elem.find('li[role="treeitem"] > a').first().focus();
  3403. }
  3404. });
  3405. }
  3406. _this._setShowSubMenuClasses($(this), isLastChild);
  3407. });
  3408. }
  3409. /**
  3410. * Opens a submenu.
  3411. * @function
  3412. * @fires Drilldown#open
  3413. * @param {jQuery} $elem - the current element with a submenu to open, i.e. the `li` tag.
  3414. */
  3415. }, {
  3416. key: "_show",
  3417. value: function _show($elem) {
  3418. var $submenu = $elem.children('[data-submenu]');
  3419. $elem.attr('aria-expanded', true);
  3420. this.$currentMenu = $submenu;
  3421. $submenu.addClass('is-active').removeClass('invisible').attr('aria-hidden', false);
  3422. if (this.options.autoHeight) {
  3423. this.$wrapper.css({
  3424. height: $submenu.data('calcHeight')
  3425. });
  3426. }
  3427. /**
  3428. * Fires when the submenu has opened.
  3429. * @event Drilldown#open
  3430. */
  3431. this.$element.trigger('open.zf.drilldown', [$elem]);
  3432. }
  3433. /**
  3434. * Hides a submenu
  3435. * @function
  3436. * @fires Drilldown#hide
  3437. * @param {jQuery} $elem - the current sub-menu to hide, i.e. the `ul` tag.
  3438. */
  3439. }, {
  3440. key: "_hide",
  3441. value: function _hide($elem) {
  3442. if (this.options.autoHeight) this.$wrapper.css({
  3443. height: $elem.parent().closest('ul').data('calcHeight')
  3444. });
  3445. $elem.parent('li').attr('aria-expanded', false);
  3446. $elem.attr('aria-hidden', true);
  3447. $elem.addClass('is-closing').one(transitionend($elem), function () {
  3448. $elem.removeClass('is-active is-closing');
  3449. $elem.blur().addClass('invisible');
  3450. });
  3451. /**
  3452. * Fires when the submenu has closed.
  3453. * @event Drilldown#hide
  3454. */
  3455. $elem.trigger('hide.zf.drilldown', [$elem]);
  3456. }
  3457. /**
  3458. * Iterates through the nested menus to calculate the min-height, and max-width for the menu.
  3459. * Prevents content jumping.
  3460. * @function
  3461. * @private
  3462. */
  3463. }, {
  3464. key: "_getMaxDims",
  3465. value: function _getMaxDims() {
  3466. var maxHeight = 0,
  3467. result = {},
  3468. _this = this; // Recalculate menu heights and total max height
  3469. this.$submenus.add(this.$element).each(function () {
  3470. var numOfElems = $(this).children('li').length;
  3471. var height = Box.GetDimensions(this).height;
  3472. maxHeight = height > maxHeight ? height : maxHeight;
  3473. if (_this.options.autoHeight) {
  3474. $(this).data('calcHeight', height);
  3475. }
  3476. });
  3477. if (this.options.autoHeight) result['height'] = this.$currentMenu.data('calcHeight');else result['min-height'] = "".concat(maxHeight, "px");
  3478. result['max-width'] = "".concat(this.$element[0].getBoundingClientRect().width, "px");
  3479. return result;
  3480. }
  3481. /**
  3482. * Destroys the Drilldown Menu
  3483. * @function
  3484. */
  3485. }, {
  3486. key: "_destroy",
  3487. value: function _destroy() {
  3488. if (this.options.scrollTop) this.$element.off('.zf.drilldown', this._bindHandler);
  3489. this._hideAll();
  3490. this.$element.off('mutateme.zf.trigger');
  3491. Nest.Burn(this.$element, 'drilldown');
  3492. this.$element.unwrap().find('.js-drilldown-back, .is-submenu-parent-item').remove().end().find('.is-active, .is-closing, .is-drilldown-submenu').removeClass('is-active is-closing is-drilldown-submenu').end().find('[data-submenu]').removeAttr('aria-hidden tabindex role');
  3493. this.$submenuAnchors.each(function () {
  3494. $(this).off('.zf.drilldown');
  3495. });
  3496. this.$element.find('[data-is-parent-link]').detach();
  3497. this.$submenus.removeClass('drilldown-submenu-cover-previous invisible');
  3498. this.$element.find('a').each(function () {
  3499. var $link = $(this);
  3500. $link.removeAttr('tabindex');
  3501. if ($link.data('savedHref')) {
  3502. $link.attr('href', $link.data('savedHref')).removeData('savedHref');
  3503. } else {
  3504. return;
  3505. }
  3506. });
  3507. }
  3508. }]);
  3509. return Drilldown;
  3510. }(Plugin);
  3511. Drilldown.defaults = {
  3512. /**
  3513. * Drilldowns depend on styles in order to function properly; in the default build of Foundation these are
  3514. * on the `drilldown` class. This option auto-applies this class to the drilldown upon initialization.
  3515. * @option
  3516. * @type {boolian}
  3517. * @default true
  3518. */
  3519. autoApplyClass: true,
  3520. /**
  3521. * Markup used for JS generated back button. Prepended or appended (see backButtonPosition) to submenu lists and deleted on `destroy` method, 'js-drilldown-back' class required. Remove the backslash (`\`) if copy and pasting.
  3522. * @option
  3523. * @type {string}
  3524. * @default '<li class="js-drilldown-back"><a tabindex="0">Back</a></li>'
  3525. */
  3526. backButton: '<li class="js-drilldown-back"><a tabindex="0">Back</a></li>',
  3527. /**
  3528. * Position the back button either at the top or bottom of drilldown submenus. Can be `'left'` or `'bottom'`.
  3529. * @option
  3530. * @type {string}
  3531. * @default top
  3532. */
  3533. backButtonPosition: 'top',
  3534. /**
  3535. * Markup used to wrap drilldown menu. Use a class name for independent styling; the JS applied class: `is-drilldown` is required. Remove the backslash (`\`) if copy and pasting.
  3536. * @option
  3537. * @type {string}
  3538. * @default '<div></div>'
  3539. */
  3540. wrapper: '<div></div>',
  3541. /**
  3542. * Adds the parent link to the submenu.
  3543. * @option
  3544. * @type {boolean}
  3545. * @default false
  3546. */
  3547. parentLink: false,
  3548. /**
  3549. * Allow the menu to return to root list on body click.
  3550. * @option
  3551. * @type {boolean}
  3552. * @default false
  3553. */
  3554. closeOnClick: false,
  3555. /**
  3556. * Allow the menu to auto adjust height.
  3557. * @option
  3558. * @type {boolean}
  3559. * @default false
  3560. */
  3561. autoHeight: false,
  3562. /**
  3563. * Animate the auto adjust height.
  3564. * @option
  3565. * @type {boolean}
  3566. * @default false
  3567. */
  3568. animateHeight: false,
  3569. /**
  3570. * Scroll to the top of the menu after opening a submenu or navigating back using the menu back button
  3571. * @option
  3572. * @type {boolean}
  3573. * @default false
  3574. */
  3575. scrollTop: false,
  3576. /**
  3577. * String jquery selector (for example 'body') of element to take offset().top from, if empty string the drilldown menu offset().top is taken
  3578. * @option
  3579. * @type {string}
  3580. * @default ''
  3581. */
  3582. scrollTopElement: '',
  3583. /**
  3584. * ScrollTop offset
  3585. * @option
  3586. * @type {number}
  3587. * @default 0
  3588. */
  3589. scrollTopOffset: 0,
  3590. /**
  3591. * Scroll animation duration
  3592. * @option
  3593. * @type {number}
  3594. * @default 500
  3595. */
  3596. animationDuration: 500,
  3597. /**
  3598. * Scroll animation easing. Can be `'swing'` or `'linear'`.
  3599. * @option
  3600. * @type {string}
  3601. * @see {@link https://api.jquery.com/animate|JQuery animate}
  3602. * @default 'swing'
  3603. */
  3604. animationEasing: 'swing' // holdOpen: false
  3605. };
  3606. var POSITIONS = ['left', 'right', 'top', 'bottom'];
  3607. var VERTICAL_ALIGNMENTS = ['top', 'bottom', 'center'];
  3608. var HORIZONTAL_ALIGNMENTS = ['left', 'right', 'center'];
  3609. var ALIGNMENTS = {
  3610. 'left': VERTICAL_ALIGNMENTS,
  3611. 'right': VERTICAL_ALIGNMENTS,
  3612. 'top': HORIZONTAL_ALIGNMENTS,
  3613. 'bottom': HORIZONTAL_ALIGNMENTS
  3614. };
  3615. function nextItem(item, array) {
  3616. var currentIdx = array.indexOf(item);
  3617. if (currentIdx === array.length - 1) {
  3618. return array[0];
  3619. } else {
  3620. return array[currentIdx + 1];
  3621. }
  3622. }
  3623. var Positionable =
  3624. /*#__PURE__*/
  3625. function (_Plugin) {
  3626. _inherits(Positionable, _Plugin);
  3627. function Positionable() {
  3628. _classCallCheck(this, Positionable);
  3629. return _possibleConstructorReturn(this, _getPrototypeOf(Positionable).apply(this, arguments));
  3630. }
  3631. _createClass(Positionable, [{
  3632. key: "_init",
  3633. /**
  3634. * Abstract class encapsulating the tether-like explicit positioning logic
  3635. * including repositioning based on overlap.
  3636. * Expects classes to define defaults for vOffset, hOffset, position,
  3637. * alignment, allowOverlap, and allowBottomOverlap. They can do this by
  3638. * extending the defaults, or (for now recommended due to the way docs are
  3639. * generated) by explicitly declaring them.
  3640. *
  3641. **/
  3642. value: function _init() {
  3643. this.triedPositions = {};
  3644. this.position = this.options.position === 'auto' ? this._getDefaultPosition() : this.options.position;
  3645. this.alignment = this.options.alignment === 'auto' ? this._getDefaultAlignment() : this.options.alignment;
  3646. this.originalPosition = this.position;
  3647. this.originalAlignment = this.alignment;
  3648. }
  3649. }, {
  3650. key: "_getDefaultPosition",
  3651. value: function _getDefaultPosition() {
  3652. return 'bottom';
  3653. }
  3654. }, {
  3655. key: "_getDefaultAlignment",
  3656. value: function _getDefaultAlignment() {
  3657. switch (this.position) {
  3658. case 'bottom':
  3659. case 'top':
  3660. return rtl() ? 'right' : 'left';
  3661. case 'left':
  3662. case 'right':
  3663. return 'bottom';
  3664. }
  3665. }
  3666. /**
  3667. * Adjusts the positionable possible positions by iterating through alignments
  3668. * and positions.
  3669. * @function
  3670. * @private
  3671. */
  3672. }, {
  3673. key: "_reposition",
  3674. value: function _reposition() {
  3675. if (this._alignmentsExhausted(this.position)) {
  3676. this.position = nextItem(this.position, POSITIONS);
  3677. this.alignment = ALIGNMENTS[this.position][0];
  3678. } else {
  3679. this._realign();
  3680. }
  3681. }
  3682. /**
  3683. * Adjusts the dropdown pane possible positions by iterating through alignments
  3684. * on the current position.
  3685. * @function
  3686. * @private
  3687. */
  3688. }, {
  3689. key: "_realign",
  3690. value: function _realign() {
  3691. this._addTriedPosition(this.position, this.alignment);
  3692. this.alignment = nextItem(this.alignment, ALIGNMENTS[this.position]);
  3693. }
  3694. }, {
  3695. key: "_addTriedPosition",
  3696. value: function _addTriedPosition(position, alignment) {
  3697. this.triedPositions[position] = this.triedPositions[position] || [];
  3698. this.triedPositions[position].push(alignment);
  3699. }
  3700. }, {
  3701. key: "_positionsExhausted",
  3702. value: function _positionsExhausted() {
  3703. var isExhausted = true;
  3704. for (var i = 0; i < POSITIONS.length; i++) {
  3705. isExhausted = isExhausted && this._alignmentsExhausted(POSITIONS[i]);
  3706. }
  3707. return isExhausted;
  3708. }
  3709. }, {
  3710. key: "_alignmentsExhausted",
  3711. value: function _alignmentsExhausted(position) {
  3712. return this.triedPositions[position] && this.triedPositions[position].length == ALIGNMENTS[position].length;
  3713. } // When we're trying to center, we don't want to apply offset that's going to
  3714. // take us just off center, so wrap around to return 0 for the appropriate
  3715. // offset in those alignments. TODO: Figure out if we want to make this
  3716. // configurable behavior... it feels more intuitive, especially for tooltips, but
  3717. // it's possible someone might actually want to start from center and then nudge
  3718. // slightly off.
  3719. }, {
  3720. key: "_getVOffset",
  3721. value: function _getVOffset() {
  3722. return this.options.vOffset;
  3723. }
  3724. }, {
  3725. key: "_getHOffset",
  3726. value: function _getHOffset() {
  3727. return this.options.hOffset;
  3728. }
  3729. }, {
  3730. key: "_setPosition",
  3731. value: function _setPosition($anchor, $element, $parent) {
  3732. if ($anchor.attr('aria-expanded') === 'false') {
  3733. return false;
  3734. }
  3735. var $eleDims = Box.GetDimensions($element),
  3736. $anchorDims = Box.GetDimensions($anchor);
  3737. if (!this.options.allowOverlap) {
  3738. // restore original position & alignment before checking overlap
  3739. this.position = this.originalPosition;
  3740. this.alignment = this.originalAlignment;
  3741. }
  3742. $element.offset(Box.GetExplicitOffsets($element, $anchor, this.position, this.alignment, this._getVOffset(), this._getHOffset()));
  3743. if (!this.options.allowOverlap) {
  3744. var minOverlap = 100000000; // default coordinates to how we start, in case we can't figure out better
  3745. var minCoordinates = {
  3746. position: this.position,
  3747. alignment: this.alignment
  3748. };
  3749. while (!this._positionsExhausted()) {
  3750. var overlap = Box.OverlapArea($element, $parent, false, false, this.options.allowBottomOverlap);
  3751. if (overlap === 0) {
  3752. return;
  3753. }
  3754. if (overlap < minOverlap) {
  3755. minOverlap = overlap;
  3756. minCoordinates = {
  3757. position: this.position,
  3758. alignment: this.alignment
  3759. };
  3760. }
  3761. this._reposition();
  3762. $element.offset(Box.GetExplicitOffsets($element, $anchor, this.position, this.alignment, this._getVOffset(), this._getHOffset()));
  3763. } // If we get through the entire loop, there was no non-overlapping
  3764. // position available. Pick the version with least overlap.
  3765. this.position = minCoordinates.position;
  3766. this.alignment = minCoordinates.alignment;
  3767. $element.offset(Box.GetExplicitOffsets($element, $anchor, this.position, this.alignment, this._getVOffset(), this._getHOffset()));
  3768. }
  3769. }
  3770. }]);
  3771. return Positionable;
  3772. }(Plugin);
  3773. Positionable.defaults = {
  3774. /**
  3775. * Position of positionable relative to anchor. Can be left, right, bottom, top, or auto.
  3776. * @option
  3777. * @type {string}
  3778. * @default 'auto'
  3779. */
  3780. position: 'auto',
  3781. /**
  3782. * Alignment of positionable relative to anchor. Can be left, right, bottom, top, center, or auto.
  3783. * @option
  3784. * @type {string}
  3785. * @default 'auto'
  3786. */
  3787. alignment: 'auto',
  3788. /**
  3789. * Allow overlap of container/window. If false, dropdown positionable first
  3790. * try to position as defined by data-position and data-alignment, but
  3791. * reposition if it would cause an overflow.
  3792. * @option
  3793. * @type {boolean}
  3794. * @default false
  3795. */
  3796. allowOverlap: false,
  3797. /**
  3798. * Allow overlap of only the bottom of the container. This is the most common
  3799. * behavior for dropdowns, allowing the dropdown to extend the bottom of the
  3800. * screen but not otherwise influence or break out of the container.
  3801. * @option
  3802. * @type {boolean}
  3803. * @default true
  3804. */
  3805. allowBottomOverlap: true,
  3806. /**
  3807. * Number of pixels the positionable should be separated vertically from anchor
  3808. * @option
  3809. * @type {number}
  3810. * @default 0
  3811. */
  3812. vOffset: 0,
  3813. /**
  3814. * Number of pixels the positionable should be separated horizontally from anchor
  3815. * @option
  3816. * @type {number}
  3817. * @default 0
  3818. */
  3819. hOffset: 0
  3820. };
  3821. /**
  3822. * Dropdown module.
  3823. * @module foundation.dropdown
  3824. * @requires foundation.util.keyboard
  3825. * @requires foundation.util.box
  3826. * @requires foundation.util.triggers
  3827. */
  3828. var Dropdown =
  3829. /*#__PURE__*/
  3830. function (_Positionable) {
  3831. _inherits(Dropdown, _Positionable);
  3832. function Dropdown() {
  3833. _classCallCheck(this, Dropdown);
  3834. return _possibleConstructorReturn(this, _getPrototypeOf(Dropdown).apply(this, arguments));
  3835. }
  3836. _createClass(Dropdown, [{
  3837. key: "_setup",
  3838. /**
  3839. * Creates a new instance of a dropdown.
  3840. * @class
  3841. * @name Dropdown
  3842. * @param {jQuery} element - jQuery object to make into a dropdown.
  3843. * Object should be of the dropdown panel, rather than its anchor.
  3844. * @param {Object} options - Overrides to the default plugin settings.
  3845. */
  3846. value: function _setup(element, options) {
  3847. this.$element = element;
  3848. this.options = $.extend({}, Dropdown.defaults, this.$element.data(), options);
  3849. this.className = 'Dropdown'; // ie9 back compat
  3850. // Triggers init is idempotent, just need to make sure it is initialized
  3851. Triggers.init($);
  3852. this._init();
  3853. Keyboard.register('Dropdown', {
  3854. 'ENTER': 'toggle',
  3855. 'SPACE': 'toggle',
  3856. 'ESCAPE': 'close'
  3857. });
  3858. }
  3859. /**
  3860. * Initializes the plugin by setting/checking options and attributes, adding helper variables, and saving the anchor.
  3861. * @function
  3862. * @private
  3863. */
  3864. }, {
  3865. key: "_init",
  3866. value: function _init() {
  3867. var $id = this.$element.attr('id');
  3868. this.$anchors = $("[data-toggle=\"".concat($id, "\"]")).length ? $("[data-toggle=\"".concat($id, "\"]")) : $("[data-open=\"".concat($id, "\"]"));
  3869. this.$anchors.attr({
  3870. 'aria-controls': $id,
  3871. 'data-is-focus': false,
  3872. 'data-yeti-box': $id,
  3873. 'aria-haspopup': true,
  3874. 'aria-expanded': false
  3875. });
  3876. this._setCurrentAnchor(this.$anchors.first());
  3877. if (this.options.parentClass) {
  3878. this.$parent = this.$element.parents('.' + this.options.parentClass);
  3879. } else {
  3880. this.$parent = null;
  3881. } // Set [aria-labelledby] on the Dropdown if it is not set
  3882. if (typeof this.$element.attr('aria-labelledby') === 'undefined') {
  3883. // Get the anchor ID or create one
  3884. if (typeof this.$currentAnchor.attr('id') === 'undefined') {
  3885. this.$currentAnchor.attr('id', GetYoDigits(6, 'dd-anchor'));
  3886. }
  3887. this.$element.attr('aria-labelledby', this.$currentAnchor.attr('id'));
  3888. }
  3889. this.$element.attr({
  3890. 'aria-hidden': 'true',
  3891. 'data-yeti-box': $id,
  3892. 'data-resize': $id
  3893. });
  3894. _get(_getPrototypeOf(Dropdown.prototype), "_init", this).call(this);
  3895. this._events();
  3896. }
  3897. }, {
  3898. key: "_getDefaultPosition",
  3899. value: function _getDefaultPosition() {
  3900. // handle legacy classnames
  3901. var position = this.$element[0].className.match(/(top|left|right|bottom)/g);
  3902. if (position) {
  3903. return position[0];
  3904. } else {
  3905. return 'bottom';
  3906. }
  3907. }
  3908. }, {
  3909. key: "_getDefaultAlignment",
  3910. value: function _getDefaultAlignment() {
  3911. // handle legacy float approach
  3912. var horizontalPosition = /float-(\S+)/.exec(this.$currentAnchor.attr('class'));
  3913. if (horizontalPosition) {
  3914. return horizontalPosition[1];
  3915. }
  3916. return _get(_getPrototypeOf(Dropdown.prototype), "_getDefaultAlignment", this).call(this);
  3917. }
  3918. /**
  3919. * Sets the position and orientation of the dropdown pane, checks for collisions if allow-overlap is not true.
  3920. * Recursively calls itself if a collision is detected, with a new position class.
  3921. * @function
  3922. * @private
  3923. */
  3924. }, {
  3925. key: "_setPosition",
  3926. value: function _setPosition() {
  3927. this.$element.removeClass("has-position-".concat(this.position, " has-alignment-").concat(this.alignment));
  3928. _get(_getPrototypeOf(Dropdown.prototype), "_setPosition", this).call(this, this.$currentAnchor, this.$element, this.$parent);
  3929. this.$element.addClass("has-position-".concat(this.position, " has-alignment-").concat(this.alignment));
  3930. }
  3931. /**
  3932. * Make it a current anchor.
  3933. * Current anchor as the reference for the position of Dropdown panes.
  3934. * @param {HTML} el - DOM element of the anchor.
  3935. * @function
  3936. * @private
  3937. */
  3938. }, {
  3939. key: "_setCurrentAnchor",
  3940. value: function _setCurrentAnchor(el) {
  3941. this.$currentAnchor = $(el);
  3942. }
  3943. /**
  3944. * Adds event listeners to the element utilizing the triggers utility library.
  3945. * @function
  3946. * @private
  3947. */
  3948. }, {
  3949. key: "_events",
  3950. value: function _events() {
  3951. var _this = this;
  3952. this.$element.on({
  3953. 'open.zf.trigger': this.open.bind(this),
  3954. 'close.zf.trigger': this.close.bind(this),
  3955. 'toggle.zf.trigger': this.toggle.bind(this),
  3956. 'resizeme.zf.trigger': this._setPosition.bind(this)
  3957. });
  3958. this.$anchors.off('click.zf.trigger').on('click.zf.trigger', function () {
  3959. _this._setCurrentAnchor(this);
  3960. });
  3961. if (this.options.hover) {
  3962. this.$anchors.off('mouseenter.zf.dropdown mouseleave.zf.dropdown').on('mouseenter.zf.dropdown', function () {
  3963. _this._setCurrentAnchor(this);
  3964. var bodyData = $('body').data();
  3965. if (typeof bodyData.whatinput === 'undefined' || bodyData.whatinput === 'mouse') {
  3966. clearTimeout(_this.timeout);
  3967. _this.timeout = setTimeout(function () {
  3968. _this.open();
  3969. _this.$anchors.data('hover', true);
  3970. }, _this.options.hoverDelay);
  3971. }
  3972. }).on('mouseleave.zf.dropdown', ignoreMousedisappear(function () {
  3973. clearTimeout(_this.timeout);
  3974. _this.timeout = setTimeout(function () {
  3975. _this.close();
  3976. _this.$anchors.data('hover', false);
  3977. }, _this.options.hoverDelay);
  3978. }));
  3979. if (this.options.hoverPane) {
  3980. this.$element.off('mouseenter.zf.dropdown mouseleave.zf.dropdown').on('mouseenter.zf.dropdown', function () {
  3981. clearTimeout(_this.timeout);
  3982. }).on('mouseleave.zf.dropdown', ignoreMousedisappear(function () {
  3983. clearTimeout(_this.timeout);
  3984. _this.timeout = setTimeout(function () {
  3985. _this.close();
  3986. _this.$anchors.data('hover', false);
  3987. }, _this.options.hoverDelay);
  3988. }));
  3989. }
  3990. }
  3991. this.$anchors.add(this.$element).on('keydown.zf.dropdown', function (e) {
  3992. var $target = $(this),
  3993. visibleFocusableElements = Keyboard.findFocusable(_this.$element);
  3994. Keyboard.handleKey(e, 'Dropdown', {
  3995. open: function open() {
  3996. if ($target.is(_this.$anchors) && !$target.is('input, textarea')) {
  3997. _this.open();
  3998. _this.$element.attr('tabindex', -1).focus();
  3999. e.preventDefault();
  4000. }
  4001. },
  4002. close: function close() {
  4003. _this.close();
  4004. _this.$anchors.focus();
  4005. }
  4006. });
  4007. });
  4008. }
  4009. /**
  4010. * Adds an event handler to the body to close any dropdowns on a click.
  4011. * @function
  4012. * @private
  4013. */
  4014. }, {
  4015. key: "_addBodyHandler",
  4016. value: function _addBodyHandler() {
  4017. var $body = $(document.body).not(this.$element),
  4018. _this = this;
  4019. $body.off('click.zf.dropdown').on('click.zf.dropdown', function (e) {
  4020. if (_this.$anchors.is(e.target) || _this.$anchors.find(e.target).length) {
  4021. return;
  4022. }
  4023. if (_this.$element.is(e.target) || _this.$element.find(e.target).length) {
  4024. return;
  4025. }
  4026. _this.close();
  4027. $body.off('click.zf.dropdown');
  4028. });
  4029. }
  4030. /**
  4031. * Opens the dropdown pane, and fires a bubbling event to close other dropdowns.
  4032. * @function
  4033. * @fires Dropdown#closeme
  4034. * @fires Dropdown#show
  4035. */
  4036. }, {
  4037. key: "open",
  4038. value: function open() {
  4039. // var _this = this;
  4040. /**
  4041. * Fires to close other open dropdowns, typically when dropdown is opening
  4042. * @event Dropdown#closeme
  4043. */
  4044. this.$element.trigger('closeme.zf.dropdown', this.$element.attr('id'));
  4045. this.$anchors.addClass('hover').attr({
  4046. 'aria-expanded': true
  4047. }); // this.$element/*.show()*/;
  4048. this.$element.addClass('is-opening');
  4049. this._setPosition();
  4050. this.$element.removeClass('is-opening').addClass('is-open').attr({
  4051. 'aria-hidden': false
  4052. });
  4053. if (this.options.autoFocus) {
  4054. var $focusable = Keyboard.findFocusable(this.$element);
  4055. if ($focusable.length) {
  4056. $focusable.eq(0).focus();
  4057. }
  4058. }
  4059. if (this.options.closeOnClick) {
  4060. this._addBodyHandler();
  4061. }
  4062. if (this.options.trapFocus) {
  4063. Keyboard.trapFocus(this.$element);
  4064. }
  4065. /**
  4066. * Fires once the dropdown is visible.
  4067. * @event Dropdown#show
  4068. */
  4069. this.$element.trigger('show.zf.dropdown', [this.$element]);
  4070. }
  4071. /**
  4072. * Closes the open dropdown pane.
  4073. * @function
  4074. * @fires Dropdown#hide
  4075. */
  4076. }, {
  4077. key: "close",
  4078. value: function close() {
  4079. if (!this.$element.hasClass('is-open')) {
  4080. return false;
  4081. }
  4082. this.$element.removeClass('is-open').attr({
  4083. 'aria-hidden': true
  4084. });
  4085. this.$anchors.removeClass('hover').attr('aria-expanded', false);
  4086. /**
  4087. * Fires once the dropdown is no longer visible.
  4088. * @event Dropdown#hide
  4089. */
  4090. this.$element.trigger('hide.zf.dropdown', [this.$element]);
  4091. if (this.options.trapFocus) {
  4092. Keyboard.releaseFocus(this.$element);
  4093. }
  4094. }
  4095. /**
  4096. * Toggles the dropdown pane's visibility.
  4097. * @function
  4098. */
  4099. }, {
  4100. key: "toggle",
  4101. value: function toggle() {
  4102. if (this.$element.hasClass('is-open')) {
  4103. if (this.$anchors.data('hover')) return;
  4104. this.close();
  4105. } else {
  4106. this.open();
  4107. }
  4108. }
  4109. /**
  4110. * Destroys the dropdown.
  4111. * @function
  4112. */
  4113. }, {
  4114. key: "_destroy",
  4115. value: function _destroy() {
  4116. this.$element.off('.zf.trigger').hide();
  4117. this.$anchors.off('.zf.dropdown');
  4118. $(document.body).off('click.zf.dropdown');
  4119. }
  4120. }]);
  4121. return Dropdown;
  4122. }(Positionable);
  4123. Dropdown.defaults = {
  4124. /**
  4125. * Class that designates bounding container of Dropdown (default: window)
  4126. * @option
  4127. * @type {?string}
  4128. * @default null
  4129. */
  4130. parentClass: null,
  4131. /**
  4132. * Amount of time to delay opening a submenu on hover event.
  4133. * @option
  4134. * @type {number}
  4135. * @default 250
  4136. */
  4137. hoverDelay: 250,
  4138. /**
  4139. * Allow submenus to open on hover events
  4140. * @option
  4141. * @type {boolean}
  4142. * @default false
  4143. */
  4144. hover: false,
  4145. /**
  4146. * Don't close dropdown when hovering over dropdown pane
  4147. * @option
  4148. * @type {boolean}
  4149. * @default false
  4150. */
  4151. hoverPane: false,
  4152. /**
  4153. * Number of pixels between the dropdown pane and the triggering element on open.
  4154. * @option
  4155. * @type {number}
  4156. * @default 0
  4157. */
  4158. vOffset: 0,
  4159. /**
  4160. * Number of pixels between the dropdown pane and the triggering element on open.
  4161. * @option
  4162. * @type {number}
  4163. * @default 0
  4164. */
  4165. hOffset: 0,
  4166. /**
  4167. * Position of dropdown. Can be left, right, bottom, top, or auto.
  4168. * @option
  4169. * @type {string}
  4170. * @default 'auto'
  4171. */
  4172. position: 'auto',
  4173. /**
  4174. * Alignment of dropdown relative to anchor. Can be left, right, bottom, top, center, or auto.
  4175. * @option
  4176. * @type {string}
  4177. * @default 'auto'
  4178. */
  4179. alignment: 'auto',
  4180. /**
  4181. * Allow overlap of container/window. If false, dropdown will first try to position as defined by data-position and data-alignment, but reposition if it would cause an overflow.
  4182. * @option
  4183. * @type {boolean}
  4184. * @default false
  4185. */
  4186. allowOverlap: false,
  4187. /**
  4188. * Allow overlap of only the bottom of the container. This is the most common
  4189. * behavior for dropdowns, allowing the dropdown to extend the bottom of the
  4190. * screen but not otherwise influence or break out of the container.
  4191. * @option
  4192. * @type {boolean}
  4193. * @default true
  4194. */
  4195. allowBottomOverlap: true,
  4196. /**
  4197. * Allow the plugin to trap focus to the dropdown pane if opened with keyboard commands.
  4198. * @option
  4199. * @type {boolean}
  4200. * @default false
  4201. */
  4202. trapFocus: false,
  4203. /**
  4204. * Allow the plugin to set focus to the first focusable element within the pane, regardless of method of opening.
  4205. * @option
  4206. * @type {boolean}
  4207. * @default false
  4208. */
  4209. autoFocus: false,
  4210. /**
  4211. * Allows a click on the body to close the dropdown.
  4212. * @option
  4213. * @type {boolean}
  4214. * @default false
  4215. */
  4216. closeOnClick: false
  4217. };
  4218. /**
  4219. * DropdownMenu module.
  4220. * @module foundation.dropdown-menu
  4221. * @requires foundation.util.keyboard
  4222. * @requires foundation.util.box
  4223. * @requires foundation.util.nest
  4224. */
  4225. var DropdownMenu =
  4226. /*#__PURE__*/
  4227. function (_Plugin) {
  4228. _inherits(DropdownMenu, _Plugin);
  4229. function DropdownMenu() {
  4230. _classCallCheck(this, DropdownMenu);
  4231. return _possibleConstructorReturn(this, _getPrototypeOf(DropdownMenu).apply(this, arguments));
  4232. }
  4233. _createClass(DropdownMenu, [{
  4234. key: "_setup",
  4235. /**
  4236. * Creates a new instance of DropdownMenu.
  4237. * @class
  4238. * @name DropdownMenu
  4239. * @fires DropdownMenu#init
  4240. * @param {jQuery} element - jQuery object to make into a dropdown menu.
  4241. * @param {Object} options - Overrides to the default plugin settings.
  4242. */
  4243. value: function _setup(element, options) {
  4244. this.$element = element;
  4245. this.options = $.extend({}, DropdownMenu.defaults, this.$element.data(), options);
  4246. this.className = 'DropdownMenu'; // ie9 back compat
  4247. this._init();
  4248. Keyboard.register('DropdownMenu', {
  4249. 'ENTER': 'open',
  4250. 'SPACE': 'open',
  4251. 'ARROW_RIGHT': 'next',
  4252. 'ARROW_UP': 'up',
  4253. 'ARROW_DOWN': 'down',
  4254. 'ARROW_LEFT': 'previous',
  4255. 'ESCAPE': 'close'
  4256. });
  4257. }
  4258. /**
  4259. * Initializes the plugin, and calls _prepareMenu
  4260. * @private
  4261. * @function
  4262. */
  4263. }, {
  4264. key: "_init",
  4265. value: function _init() {
  4266. Nest.Feather(this.$element, 'dropdown');
  4267. var subs = this.$element.find('li.is-dropdown-submenu-parent');
  4268. this.$element.children('.is-dropdown-submenu-parent').children('.is-dropdown-submenu').addClass('first-sub');
  4269. this.$menuItems = this.$element.find('[role="menuitem"]');
  4270. this.$tabs = this.$element.children('[role="menuitem"]');
  4271. this.$tabs.find('ul.is-dropdown-submenu').addClass(this.options.verticalClass);
  4272. if (this.options.alignment === 'auto') {
  4273. if (this.$element.hasClass(this.options.rightClass) || rtl() || this.$element.parents('.top-bar-right').is('*')) {
  4274. this.options.alignment = 'right';
  4275. subs.addClass('opens-left');
  4276. } else {
  4277. this.options.alignment = 'left';
  4278. subs.addClass('opens-right');
  4279. }
  4280. } else {
  4281. if (this.options.alignment === 'right') {
  4282. subs.addClass('opens-left');
  4283. } else {
  4284. subs.addClass('opens-right');
  4285. }
  4286. }
  4287. this.changed = false;
  4288. this._events();
  4289. }
  4290. }, {
  4291. key: "_isVertical",
  4292. value: function _isVertical() {
  4293. return this.$tabs.css('display') === 'block' || this.$element.css('flex-direction') === 'column';
  4294. }
  4295. }, {
  4296. key: "_isRtl",
  4297. value: function _isRtl() {
  4298. return this.$element.hasClass('align-right') || rtl() && !this.$element.hasClass('align-left');
  4299. }
  4300. /**
  4301. * Adds event listeners to elements within the menu
  4302. * @private
  4303. * @function
  4304. */
  4305. }, {
  4306. key: "_events",
  4307. value: function _events() {
  4308. var _this = this,
  4309. hasTouch = 'ontouchstart' in window || typeof window.ontouchstart !== 'undefined',
  4310. parClass = 'is-dropdown-submenu-parent'; // used for onClick and in the keyboard handlers
  4311. var handleClickFn = function handleClickFn(e) {
  4312. var $elem = $(e.target).parentsUntil('ul', ".".concat(parClass)),
  4313. hasSub = $elem.hasClass(parClass),
  4314. hasClicked = $elem.attr('data-is-click') === 'true',
  4315. $sub = $elem.children('.is-dropdown-submenu');
  4316. if (hasSub) {
  4317. if (hasClicked) {
  4318. if (!_this.options.closeOnClick || !_this.options.clickOpen && !hasTouch || _this.options.forceFollow && hasTouch) {
  4319. return;
  4320. } else {
  4321. e.stopImmediatePropagation();
  4322. e.preventDefault();
  4323. _this._hide($elem);
  4324. }
  4325. } else {
  4326. e.preventDefault();
  4327. e.stopImmediatePropagation();
  4328. _this._show($sub);
  4329. $elem.add($elem.parentsUntil(_this.$element, ".".concat(parClass))).attr('data-is-click', true);
  4330. }
  4331. }
  4332. };
  4333. if (this.options.clickOpen || hasTouch) {
  4334. this.$menuItems.on('click.zf.dropdownmenu touchstart.zf.dropdownmenu', handleClickFn);
  4335. } // Handle Leaf element Clicks
  4336. if (_this.options.closeOnClickInside) {
  4337. this.$menuItems.on('click.zf.dropdownmenu', function (e) {
  4338. var $elem = $(this),
  4339. hasSub = $elem.hasClass(parClass);
  4340. if (!hasSub) {
  4341. _this._hide();
  4342. }
  4343. });
  4344. }
  4345. if (!this.options.disableHover) {
  4346. this.$menuItems.on('mouseenter.zf.dropdownmenu', function (e) {
  4347. var $elem = $(this),
  4348. hasSub = $elem.hasClass(parClass);
  4349. if (hasSub) {
  4350. clearTimeout($elem.data('_delay'));
  4351. $elem.data('_delay', setTimeout(function () {
  4352. _this._show($elem.children('.is-dropdown-submenu'));
  4353. }, _this.options.hoverDelay));
  4354. }
  4355. }).on('mouseleave.zf.dropdownMenu', ignoreMousedisappear(function (e) {
  4356. var $elem = $(this),
  4357. hasSub = $elem.hasClass(parClass);
  4358. if (hasSub && _this.options.autoclose) {
  4359. if ($elem.attr('data-is-click') === 'true' && _this.options.clickOpen) {
  4360. return false;
  4361. }
  4362. clearTimeout($elem.data('_delay'));
  4363. $elem.data('_delay', setTimeout(function () {
  4364. _this._hide($elem);
  4365. }, _this.options.closingTime));
  4366. }
  4367. }));
  4368. }
  4369. this.$menuItems.on('keydown.zf.dropdownmenu', function (e) {
  4370. var $element = $(e.target).parentsUntil('ul', '[role="menuitem"]'),
  4371. isTab = _this.$tabs.index($element) > -1,
  4372. $elements = isTab ? _this.$tabs : $element.siblings('li').add($element),
  4373. $prevElement,
  4374. $nextElement;
  4375. $elements.each(function (i) {
  4376. if ($(this).is($element)) {
  4377. $prevElement = $elements.eq(i - 1);
  4378. $nextElement = $elements.eq(i + 1);
  4379. return;
  4380. }
  4381. });
  4382. var nextSibling = function nextSibling() {
  4383. $nextElement.children('a:first').focus();
  4384. e.preventDefault();
  4385. },
  4386. prevSibling = function prevSibling() {
  4387. $prevElement.children('a:first').focus();
  4388. e.preventDefault();
  4389. },
  4390. openSub = function openSub() {
  4391. var $sub = $element.children('ul.is-dropdown-submenu');
  4392. if ($sub.length) {
  4393. _this._show($sub);
  4394. $element.find('li > a:first').focus();
  4395. e.preventDefault();
  4396. } else {
  4397. return;
  4398. }
  4399. },
  4400. closeSub = function closeSub() {
  4401. //if ($element.is(':first-child')) {
  4402. var close = $element.parent('ul').parent('li');
  4403. close.children('a:first').focus();
  4404. _this._hide(close);
  4405. e.preventDefault(); //}
  4406. };
  4407. var functions = {
  4408. open: openSub,
  4409. close: function close() {
  4410. _this._hide(_this.$element);
  4411. _this.$menuItems.eq(0).children('a').focus(); // focus to first element
  4412. e.preventDefault();
  4413. },
  4414. handled: function handled() {
  4415. e.stopImmediatePropagation();
  4416. }
  4417. };
  4418. if (isTab) {
  4419. if (_this._isVertical()) {
  4420. // vertical menu
  4421. if (_this._isRtl()) {
  4422. // right aligned
  4423. $.extend(functions, {
  4424. down: nextSibling,
  4425. up: prevSibling,
  4426. next: closeSub,
  4427. previous: openSub
  4428. });
  4429. } else {
  4430. // left aligned
  4431. $.extend(functions, {
  4432. down: nextSibling,
  4433. up: prevSibling,
  4434. next: openSub,
  4435. previous: closeSub
  4436. });
  4437. }
  4438. } else {
  4439. // horizontal menu
  4440. if (_this._isRtl()) {
  4441. // right aligned
  4442. $.extend(functions, {
  4443. next: prevSibling,
  4444. previous: nextSibling,
  4445. down: openSub,
  4446. up: closeSub
  4447. });
  4448. } else {
  4449. // left aligned
  4450. $.extend(functions, {
  4451. next: nextSibling,
  4452. previous: prevSibling,
  4453. down: openSub,
  4454. up: closeSub
  4455. });
  4456. }
  4457. }
  4458. } else {
  4459. // not tabs -> one sub
  4460. if (_this._isRtl()) {
  4461. // right aligned
  4462. $.extend(functions, {
  4463. next: closeSub,
  4464. previous: openSub,
  4465. down: nextSibling,
  4466. up: prevSibling
  4467. });
  4468. } else {
  4469. // left aligned
  4470. $.extend(functions, {
  4471. next: openSub,
  4472. previous: closeSub,
  4473. down: nextSibling,
  4474. up: prevSibling
  4475. });
  4476. }
  4477. }
  4478. Keyboard.handleKey(e, 'DropdownMenu', functions);
  4479. });
  4480. }
  4481. /**
  4482. * Adds an event handler to the body to close any dropdowns on a click.
  4483. * @function
  4484. * @private
  4485. */
  4486. }, {
  4487. key: "_addBodyHandler",
  4488. value: function _addBodyHandler() {
  4489. var $body = $(document.body),
  4490. _this = this;
  4491. $body.off('mouseup.zf.dropdownmenu touchend.zf.dropdownmenu').on('mouseup.zf.dropdownmenu touchend.zf.dropdownmenu', function (e) {
  4492. var $link = _this.$element.find(e.target);
  4493. if ($link.length) {
  4494. return;
  4495. }
  4496. _this._hide();
  4497. $body.off('mouseup.zf.dropdownmenu touchend.zf.dropdownmenu');
  4498. });
  4499. }
  4500. /**
  4501. * Opens a dropdown pane, and checks for collisions first.
  4502. * @param {jQuery} $sub - ul element that is a submenu to show
  4503. * @function
  4504. * @private
  4505. * @fires Dropdownmenu#show
  4506. */
  4507. }, {
  4508. key: "_show",
  4509. value: function _show($sub) {
  4510. var idx = this.$tabs.index(this.$tabs.filter(function (i, el) {
  4511. return $(el).find($sub).length > 0;
  4512. }));
  4513. var $sibs = $sub.parent('li.is-dropdown-submenu-parent').siblings('li.is-dropdown-submenu-parent');
  4514. this._hide($sibs, idx);
  4515. $sub.css('visibility', 'hidden').addClass('js-dropdown-active').parent('li.is-dropdown-submenu-parent').addClass('is-active');
  4516. var clear = Box.ImNotTouchingYou($sub, null, true);
  4517. if (!clear) {
  4518. var oldClass = this.options.alignment === 'left' ? '-right' : '-left',
  4519. $parentLi = $sub.parent('.is-dropdown-submenu-parent');
  4520. $parentLi.removeClass("opens".concat(oldClass)).addClass("opens-".concat(this.options.alignment));
  4521. clear = Box.ImNotTouchingYou($sub, null, true);
  4522. if (!clear) {
  4523. $parentLi.removeClass("opens-".concat(this.options.alignment)).addClass('opens-inner');
  4524. }
  4525. this.changed = true;
  4526. }
  4527. $sub.css('visibility', '');
  4528. if (this.options.closeOnClick) {
  4529. this._addBodyHandler();
  4530. }
  4531. /**
  4532. * Fires when the new dropdown pane is visible.
  4533. * @event Dropdownmenu#show
  4534. */
  4535. this.$element.trigger('show.zf.dropdownmenu', [$sub]);
  4536. }
  4537. /**
  4538. * Hides a single, currently open dropdown pane, if passed a parameter, otherwise, hides everything.
  4539. * @function
  4540. * @param {jQuery} $elem - element with a submenu to hide
  4541. * @param {Number} idx - index of the $tabs collection to hide
  4542. * @private
  4543. */
  4544. }, {
  4545. key: "_hide",
  4546. value: function _hide($elem, idx) {
  4547. var $toClose;
  4548. if ($elem && $elem.length) {
  4549. $toClose = $elem;
  4550. } else if (typeof idx !== 'undefined') {
  4551. $toClose = this.$tabs.not(function (i, el) {
  4552. return i === idx;
  4553. });
  4554. } else {
  4555. $toClose = this.$element;
  4556. }
  4557. var somethingToClose = $toClose.hasClass('is-active') || $toClose.find('.is-active').length > 0;
  4558. if (somethingToClose) {
  4559. $toClose.find('li.is-active').add($toClose).attr({
  4560. 'data-is-click': false
  4561. }).removeClass('is-active');
  4562. $toClose.find('ul.js-dropdown-active').removeClass('js-dropdown-active');
  4563. if (this.changed || $toClose.find('opens-inner').length) {
  4564. var oldClass = this.options.alignment === 'left' ? 'right' : 'left';
  4565. $toClose.find('li.is-dropdown-submenu-parent').add($toClose).removeClass("opens-inner opens-".concat(this.options.alignment)).addClass("opens-".concat(oldClass));
  4566. this.changed = false;
  4567. }
  4568. /**
  4569. * Fires when the open menus are closed.
  4570. * @event Dropdownmenu#hide
  4571. */
  4572. this.$element.trigger('hide.zf.dropdownmenu', [$toClose]);
  4573. }
  4574. }
  4575. /**
  4576. * Destroys the plugin.
  4577. * @function
  4578. */
  4579. }, {
  4580. key: "_destroy",
  4581. value: function _destroy() {
  4582. this.$menuItems.off('.zf.dropdownmenu').removeAttr('data-is-click').removeClass('is-right-arrow is-left-arrow is-down-arrow opens-right opens-left opens-inner');
  4583. $(document.body).off('.zf.dropdownmenu');
  4584. Nest.Burn(this.$element, 'dropdown');
  4585. }
  4586. }]);
  4587. return DropdownMenu;
  4588. }(Plugin);
  4589. /**
  4590. * Default settings for plugin
  4591. */
  4592. DropdownMenu.defaults = {
  4593. /**
  4594. * Disallows hover events from opening submenus
  4595. * @option
  4596. * @type {boolean}
  4597. * @default false
  4598. */
  4599. disableHover: false,
  4600. /**
  4601. * Allow a submenu to automatically close on a mouseleave event, if not clicked open.
  4602. * @option
  4603. * @type {boolean}
  4604. * @default true
  4605. */
  4606. autoclose: true,
  4607. /**
  4608. * Amount of time to delay opening a submenu on hover event.
  4609. * @option
  4610. * @type {number}
  4611. * @default 50
  4612. */
  4613. hoverDelay: 50,
  4614. /**
  4615. * Allow a submenu to open/remain open on parent click event. Allows cursor to move away from menu.
  4616. * @option
  4617. * @type {boolean}
  4618. * @default false
  4619. */
  4620. clickOpen: false,
  4621. /**
  4622. * Amount of time to delay closing a submenu on a mouseleave event.
  4623. * @option
  4624. * @type {number}
  4625. * @default 500
  4626. */
  4627. closingTime: 500,
  4628. /**
  4629. * Position of the menu relative to what direction the submenus should open. Handled by JS. Can be `'auto'`, `'left'` or `'right'`.
  4630. * @option
  4631. * @type {string}
  4632. * @default 'auto'
  4633. */
  4634. alignment: 'auto',
  4635. /**
  4636. * Allow clicks on the body to close any open submenus.
  4637. * @option
  4638. * @type {boolean}
  4639. * @default true
  4640. */
  4641. closeOnClick: true,
  4642. /**
  4643. * Allow clicks on leaf anchor links to close any open submenus.
  4644. * @option
  4645. * @type {boolean}
  4646. * @default true
  4647. */
  4648. closeOnClickInside: true,
  4649. /**
  4650. * Class applied to vertical oriented menus, Foundation default is `vertical`. Update this if using your own class.
  4651. * @option
  4652. * @type {string}
  4653. * @default 'vertical'
  4654. */
  4655. verticalClass: 'vertical',
  4656. /**
  4657. * Class applied to right-side oriented menus, Foundation default is `align-right`. Update this if using your own class.
  4658. * @option
  4659. * @type {string}
  4660. * @default 'align-right'
  4661. */
  4662. rightClass: 'align-right',
  4663. /**
  4664. * Boolean to force overide the clicking of links to perform default action, on second touch event for mobile.
  4665. * @option
  4666. * @type {boolean}
  4667. * @default true
  4668. */
  4669. forceFollow: true
  4670. };
  4671. /**
  4672. * Equalizer module.
  4673. * @module foundation.equalizer
  4674. * @requires foundation.util.mediaQuery
  4675. * @requires foundation.util.imageLoader if equalizer contains images
  4676. */
  4677. var Equalizer =
  4678. /*#__PURE__*/
  4679. function (_Plugin) {
  4680. _inherits(Equalizer, _Plugin);
  4681. function Equalizer() {
  4682. _classCallCheck(this, Equalizer);
  4683. return _possibleConstructorReturn(this, _getPrototypeOf(Equalizer).apply(this, arguments));
  4684. }
  4685. _createClass(Equalizer, [{
  4686. key: "_setup",
  4687. /**
  4688. * Creates a new instance of Equalizer.
  4689. * @class
  4690. * @name Equalizer
  4691. * @fires Equalizer#init
  4692. * @param {Object} element - jQuery object to add the trigger to.
  4693. * @param {Object} options - Overrides to the default plugin settings.
  4694. */
  4695. value: function _setup(element, options) {
  4696. this.$element = element;
  4697. this.options = $.extend({}, Equalizer.defaults, this.$element.data(), options);
  4698. this.className = 'Equalizer'; // ie9 back compat
  4699. this._init();
  4700. }
  4701. /**
  4702. * Initializes the Equalizer plugin and calls functions to get equalizer functioning on load.
  4703. * @private
  4704. */
  4705. }, {
  4706. key: "_init",
  4707. value: function _init() {
  4708. var eqId = this.$element.attr('data-equalizer') || '';
  4709. var $watched = this.$element.find("[data-equalizer-watch=\"".concat(eqId, "\"]"));
  4710. MediaQuery._init();
  4711. this.$watched = $watched.length ? $watched : this.$element.find('[data-equalizer-watch]');
  4712. this.$element.attr('data-resize', eqId || GetYoDigits(6, 'eq'));
  4713. this.$element.attr('data-mutate', eqId || GetYoDigits(6, 'eq'));
  4714. this.hasNested = this.$element.find('[data-equalizer]').length > 0;
  4715. this.isNested = this.$element.parentsUntil(document.body, '[data-equalizer]').length > 0;
  4716. this.isOn = false;
  4717. this._bindHandler = {
  4718. onResizeMeBound: this._onResizeMe.bind(this),
  4719. onPostEqualizedBound: this._onPostEqualized.bind(this)
  4720. };
  4721. var imgs = this.$element.find('img');
  4722. var tooSmall;
  4723. if (this.options.equalizeOn) {
  4724. tooSmall = this._checkMQ();
  4725. $(window).on('changed.zf.mediaquery', this._checkMQ.bind(this));
  4726. } else {
  4727. this._events();
  4728. }
  4729. if (typeof tooSmall !== 'undefined' && tooSmall === false || typeof tooSmall === 'undefined') {
  4730. if (imgs.length) {
  4731. onImagesLoaded(imgs, this._reflow.bind(this));
  4732. } else {
  4733. this._reflow();
  4734. }
  4735. }
  4736. }
  4737. /**
  4738. * Removes event listeners if the breakpoint is too small.
  4739. * @private
  4740. */
  4741. }, {
  4742. key: "_pauseEvents",
  4743. value: function _pauseEvents() {
  4744. this.isOn = false;
  4745. this.$element.off({
  4746. '.zf.equalizer': this._bindHandler.onPostEqualizedBound,
  4747. 'resizeme.zf.trigger': this._bindHandler.onResizeMeBound,
  4748. 'mutateme.zf.trigger': this._bindHandler.onResizeMeBound
  4749. });
  4750. }
  4751. /**
  4752. * function to handle $elements resizeme.zf.trigger, with bound this on _bindHandler.onResizeMeBound
  4753. * @private
  4754. */
  4755. }, {
  4756. key: "_onResizeMe",
  4757. value: function _onResizeMe(e) {
  4758. this._reflow();
  4759. }
  4760. /**
  4761. * function to handle $elements postequalized.zf.equalizer, with bound this on _bindHandler.onPostEqualizedBound
  4762. * @private
  4763. */
  4764. }, {
  4765. key: "_onPostEqualized",
  4766. value: function _onPostEqualized(e) {
  4767. if (e.target !== this.$element[0]) {
  4768. this._reflow();
  4769. }
  4770. }
  4771. /**
  4772. * Initializes events for Equalizer.
  4773. * @private
  4774. */
  4775. }, {
  4776. key: "_events",
  4777. value: function _events() {
  4778. this._pauseEvents();
  4779. if (this.hasNested) {
  4780. this.$element.on('postequalized.zf.equalizer', this._bindHandler.onPostEqualizedBound);
  4781. } else {
  4782. this.$element.on('resizeme.zf.trigger', this._bindHandler.onResizeMeBound);
  4783. this.$element.on('mutateme.zf.trigger', this._bindHandler.onResizeMeBound);
  4784. }
  4785. this.isOn = true;
  4786. }
  4787. /**
  4788. * Checks the current breakpoint to the minimum required size.
  4789. * @private
  4790. */
  4791. }, {
  4792. key: "_checkMQ",
  4793. value: function _checkMQ() {
  4794. var tooSmall = !MediaQuery.is(this.options.equalizeOn);
  4795. if (tooSmall) {
  4796. if (this.isOn) {
  4797. this._pauseEvents();
  4798. this.$watched.css('height', 'auto');
  4799. }
  4800. } else {
  4801. if (!this.isOn) {
  4802. this._events();
  4803. }
  4804. }
  4805. return tooSmall;
  4806. }
  4807. /**
  4808. * A noop version for the plugin
  4809. * @private
  4810. */
  4811. }, {
  4812. key: "_killswitch",
  4813. value: function _killswitch() {
  4814. return;
  4815. }
  4816. /**
  4817. * Calls necessary functions to update Equalizer upon DOM change
  4818. * @private
  4819. */
  4820. }, {
  4821. key: "_reflow",
  4822. value: function _reflow() {
  4823. if (!this.options.equalizeOnStack) {
  4824. if (this._isStacked()) {
  4825. this.$watched.css('height', 'auto');
  4826. return false;
  4827. }
  4828. }
  4829. if (this.options.equalizeByRow) {
  4830. this.getHeightsByRow(this.applyHeightByRow.bind(this));
  4831. } else {
  4832. this.getHeights(this.applyHeight.bind(this));
  4833. }
  4834. }
  4835. /**
  4836. * Manually determines if the first 2 elements are *NOT* stacked.
  4837. * @private
  4838. */
  4839. }, {
  4840. key: "_isStacked",
  4841. value: function _isStacked() {
  4842. if (!this.$watched[0] || !this.$watched[1]) {
  4843. return true;
  4844. }
  4845. return this.$watched[0].getBoundingClientRect().top !== this.$watched[1].getBoundingClientRect().top;
  4846. }
  4847. /**
  4848. * Finds the outer heights of children contained within an Equalizer parent and returns them in an array
  4849. * @param {Function} cb - A non-optional callback to return the heights array to.
  4850. * @returns {Array} heights - An array of heights of children within Equalizer container
  4851. */
  4852. }, {
  4853. key: "getHeights",
  4854. value: function getHeights(cb) {
  4855. var heights = [];
  4856. for (var i = 0, len = this.$watched.length; i < len; i++) {
  4857. this.$watched[i].style.height = 'auto';
  4858. heights.push(this.$watched[i].offsetHeight);
  4859. }
  4860. cb(heights);
  4861. }
  4862. /**
  4863. * Finds the outer heights of children contained within an Equalizer parent and returns them in an array
  4864. * @param {Function} cb - A non-optional callback to return the heights array to.
  4865. * @returns {Array} groups - An array of heights of children within Equalizer container grouped by row with element,height and max as last child
  4866. */
  4867. }, {
  4868. key: "getHeightsByRow",
  4869. value: function getHeightsByRow(cb) {
  4870. var lastElTopOffset = this.$watched.length ? this.$watched.first().offset().top : 0,
  4871. groups = [],
  4872. group = 0; //group by Row
  4873. groups[group] = [];
  4874. for (var i = 0, len = this.$watched.length; i < len; i++) {
  4875. this.$watched[i].style.height = 'auto'; //maybe could use this.$watched[i].offsetTop
  4876. var elOffsetTop = $(this.$watched[i]).offset().top;
  4877. if (elOffsetTop != lastElTopOffset) {
  4878. group++;
  4879. groups[group] = [];
  4880. lastElTopOffset = elOffsetTop;
  4881. }
  4882. groups[group].push([this.$watched[i], this.$watched[i].offsetHeight]);
  4883. }
  4884. for (var j = 0, ln = groups.length; j < ln; j++) {
  4885. var heights = $(groups[j]).map(function () {
  4886. return this[1];
  4887. }).get();
  4888. var max = Math.max.apply(null, heights);
  4889. groups[j].push(max);
  4890. }
  4891. cb(groups);
  4892. }
  4893. /**
  4894. * Changes the CSS height property of each child in an Equalizer parent to match the tallest
  4895. * @param {array} heights - An array of heights of children within Equalizer container
  4896. * @fires Equalizer#preequalized
  4897. * @fires Equalizer#postequalized
  4898. */
  4899. }, {
  4900. key: "applyHeight",
  4901. value: function applyHeight(heights) {
  4902. var max = Math.max.apply(null, heights);
  4903. /**
  4904. * Fires before the heights are applied
  4905. * @event Equalizer#preequalized
  4906. */
  4907. this.$element.trigger('preequalized.zf.equalizer');
  4908. this.$watched.css('height', max);
  4909. /**
  4910. * Fires when the heights have been applied
  4911. * @event Equalizer#postequalized
  4912. */
  4913. this.$element.trigger('postequalized.zf.equalizer');
  4914. }
  4915. /**
  4916. * Changes the CSS height property of each child in an Equalizer parent to match the tallest by row
  4917. * @param {array} groups - An array of heights of children within Equalizer container grouped by row with element,height and max as last child
  4918. * @fires Equalizer#preequalized
  4919. * @fires Equalizer#preequalizedrow
  4920. * @fires Equalizer#postequalizedrow
  4921. * @fires Equalizer#postequalized
  4922. */
  4923. }, {
  4924. key: "applyHeightByRow",
  4925. value: function applyHeightByRow(groups) {
  4926. /**
  4927. * Fires before the heights are applied
  4928. */
  4929. this.$element.trigger('preequalized.zf.equalizer');
  4930. for (var i = 0, len = groups.length; i < len; i++) {
  4931. var groupsILength = groups[i].length,
  4932. max = groups[i][groupsILength - 1];
  4933. if (groupsILength <= 2) {
  4934. $(groups[i][0][0]).css({
  4935. 'height': 'auto'
  4936. });
  4937. continue;
  4938. }
  4939. /**
  4940. * Fires before the heights per row are applied
  4941. * @event Equalizer#preequalizedrow
  4942. */
  4943. this.$element.trigger('preequalizedrow.zf.equalizer');
  4944. for (var j = 0, lenJ = groupsILength - 1; j < lenJ; j++) {
  4945. $(groups[i][j][0]).css({
  4946. 'height': max
  4947. });
  4948. }
  4949. /**
  4950. * Fires when the heights per row have been applied
  4951. * @event Equalizer#postequalizedrow
  4952. */
  4953. this.$element.trigger('postequalizedrow.zf.equalizer');
  4954. }
  4955. /**
  4956. * Fires when the heights have been applied
  4957. */
  4958. this.$element.trigger('postequalized.zf.equalizer');
  4959. }
  4960. /**
  4961. * Destroys an instance of Equalizer.
  4962. * @function
  4963. */
  4964. }, {
  4965. key: "_destroy",
  4966. value: function _destroy() {
  4967. this._pauseEvents();
  4968. this.$watched.css('height', 'auto');
  4969. }
  4970. }]);
  4971. return Equalizer;
  4972. }(Plugin);
  4973. /**
  4974. * Default settings for plugin
  4975. */
  4976. Equalizer.defaults = {
  4977. /**
  4978. * Enable height equalization when stacked on smaller screens.
  4979. * @option
  4980. * @type {boolean}
  4981. * @default false
  4982. */
  4983. equalizeOnStack: false,
  4984. /**
  4985. * Enable height equalization row by row.
  4986. * @option
  4987. * @type {boolean}
  4988. * @default false
  4989. */
  4990. equalizeByRow: false,
  4991. /**
  4992. * String representing the minimum breakpoint size the plugin should equalize heights on.
  4993. * @option
  4994. * @type {string}
  4995. * @default ''
  4996. */
  4997. equalizeOn: ''
  4998. };
  4999. /**
  5000. * Interchange module.
  5001. * @module foundation.interchange
  5002. * @requires foundation.util.mediaQuery
  5003. */
  5004. var Interchange =
  5005. /*#__PURE__*/
  5006. function (_Plugin) {
  5007. _inherits(Interchange, _Plugin);
  5008. function Interchange() {
  5009. _classCallCheck(this, Interchange);
  5010. return _possibleConstructorReturn(this, _getPrototypeOf(Interchange).apply(this, arguments));
  5011. }
  5012. _createClass(Interchange, [{
  5013. key: "_setup",
  5014. /**
  5015. * Creates a new instance of Interchange.
  5016. * @class
  5017. * @name Interchange
  5018. * @fires Interchange#init
  5019. * @param {Object} element - jQuery object to add the trigger to.
  5020. * @param {Object} options - Overrides to the default plugin settings.
  5021. */
  5022. value: function _setup(element, options) {
  5023. this.$element = element;
  5024. this.options = $.extend({}, Interchange.defaults, options);
  5025. this.rules = [];
  5026. this.currentPath = '';
  5027. this.className = 'Interchange'; // ie9 back compat
  5028. this._init();
  5029. this._events();
  5030. }
  5031. /**
  5032. * Initializes the Interchange plugin and calls functions to get interchange functioning on load.
  5033. * @function
  5034. * @private
  5035. */
  5036. }, {
  5037. key: "_init",
  5038. value: function _init() {
  5039. MediaQuery._init();
  5040. var id = this.$element[0].id || GetYoDigits(6, 'interchange');
  5041. this.$element.attr({
  5042. 'data-resize': id,
  5043. 'id': id
  5044. });
  5045. this._addBreakpoints();
  5046. this._generateRules();
  5047. this._reflow();
  5048. }
  5049. /**
  5050. * Initializes events for Interchange.
  5051. * @function
  5052. * @private
  5053. */
  5054. }, {
  5055. key: "_events",
  5056. value: function _events() {
  5057. var _this2 = this;
  5058. this.$element.off('resizeme.zf.trigger').on('resizeme.zf.trigger', function () {
  5059. return _this2._reflow();
  5060. });
  5061. }
  5062. /**
  5063. * Calls necessary functions to update Interchange upon DOM change
  5064. * @function
  5065. * @private
  5066. */
  5067. }, {
  5068. key: "_reflow",
  5069. value: function _reflow() {
  5070. var match; // Iterate through each rule, but only save the last match
  5071. for (var i in this.rules) {
  5072. if (this.rules.hasOwnProperty(i)) {
  5073. var rule = this.rules[i];
  5074. if (window.matchMedia(rule.query).matches) {
  5075. match = rule;
  5076. }
  5077. }
  5078. }
  5079. if (match) {
  5080. this.replace(match.path);
  5081. }
  5082. }
  5083. /**
  5084. * Gets the Foundation breakpoints and adds them to the Interchange.SPECIAL_QUERIES object.
  5085. * @function
  5086. * @private
  5087. */
  5088. }, {
  5089. key: "_addBreakpoints",
  5090. value: function _addBreakpoints() {
  5091. for (var i in MediaQuery.queries) {
  5092. if (MediaQuery.queries.hasOwnProperty(i)) {
  5093. var query = MediaQuery.queries[i];
  5094. Interchange.SPECIAL_QUERIES[query.name] = query.value;
  5095. }
  5096. }
  5097. }
  5098. /**
  5099. * Checks the Interchange element for the provided media query + content pairings
  5100. * @function
  5101. * @private
  5102. * @param {Object} element - jQuery object that is an Interchange instance
  5103. * @returns {Array} scenarios - Array of objects that have 'mq' and 'path' keys with corresponding keys
  5104. */
  5105. }, {
  5106. key: "_generateRules",
  5107. value: function _generateRules(element) {
  5108. var rulesList = [];
  5109. var rules;
  5110. if (this.options.rules) {
  5111. rules = this.options.rules;
  5112. } else {
  5113. rules = this.$element.data('interchange');
  5114. }
  5115. rules = typeof rules === 'string' ? rules.match(/\[.*?, .*?\]/g) : rules;
  5116. for (var i in rules) {
  5117. if (rules.hasOwnProperty(i)) {
  5118. var rule = rules[i].slice(1, -1).split(', ');
  5119. var path = rule.slice(0, -1).join('');
  5120. var query = rule[rule.length - 1];
  5121. if (Interchange.SPECIAL_QUERIES[query]) {
  5122. query = Interchange.SPECIAL_QUERIES[query];
  5123. }
  5124. rulesList.push({
  5125. path: path,
  5126. query: query
  5127. });
  5128. }
  5129. }
  5130. this.rules = rulesList;
  5131. }
  5132. /**
  5133. * Update the `src` property of an image, or change the HTML of a container, to the specified path.
  5134. * @function
  5135. * @param {String} path - Path to the image or HTML partial.
  5136. * @fires Interchange#replaced
  5137. */
  5138. }, {
  5139. key: "replace",
  5140. value: function replace(path) {
  5141. if (this.currentPath === path) return;
  5142. var _this = this,
  5143. trigger = 'replaced.zf.interchange'; // Replacing images
  5144. if (this.$element[0].nodeName === 'IMG') {
  5145. this.$element.attr('src', path).on('load', function () {
  5146. _this.currentPath = path;
  5147. }).trigger(trigger);
  5148. } // Replacing background images
  5149. else if (path.match(/\.(gif|jpg|jpeg|png|svg|tiff)([?#].*)?/i)) {
  5150. path = path.replace(/\(/g, '%28').replace(/\)/g, '%29');
  5151. this.$element.css({
  5152. 'background-image': 'url(' + path + ')'
  5153. }).trigger(trigger);
  5154. } // Replacing HTML
  5155. else {
  5156. $.get(path, function (response) {
  5157. _this.$element.html(response).trigger(trigger);
  5158. $(response).foundation();
  5159. _this.currentPath = path;
  5160. });
  5161. }
  5162. /**
  5163. * Fires when content in an Interchange element is done being loaded.
  5164. * @event Interchange#replaced
  5165. */
  5166. // this.$element.trigger('replaced.zf.interchange');
  5167. }
  5168. /**
  5169. * Destroys an instance of interchange.
  5170. * @function
  5171. */
  5172. }, {
  5173. key: "_destroy",
  5174. value: function _destroy() {
  5175. this.$element.off('resizeme.zf.trigger');
  5176. }
  5177. }]);
  5178. return Interchange;
  5179. }(Plugin);
  5180. /**
  5181. * Default settings for plugin
  5182. */
  5183. Interchange.defaults = {
  5184. /**
  5185. * Rules to be applied to Interchange elements. Set with the `data-interchange` array notation.
  5186. * @option
  5187. * @type {?array}
  5188. * @default null
  5189. */
  5190. rules: null
  5191. };
  5192. Interchange.SPECIAL_QUERIES = {
  5193. 'landscape': 'screen and (orientation: landscape)',
  5194. 'portrait': 'screen and (orientation: portrait)',
  5195. 'retina': 'only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx)'
  5196. };
  5197. /**
  5198. * SmoothScroll module.
  5199. * @module foundation.smooth-scroll
  5200. */
  5201. var SmoothScroll =
  5202. /*#__PURE__*/
  5203. function (_Plugin) {
  5204. _inherits(SmoothScroll, _Plugin);
  5205. function SmoothScroll() {
  5206. _classCallCheck(this, SmoothScroll);
  5207. return _possibleConstructorReturn(this, _getPrototypeOf(SmoothScroll).apply(this, arguments));
  5208. }
  5209. _createClass(SmoothScroll, [{
  5210. key: "_setup",
  5211. /**
  5212. * Creates a new instance of SmoothScroll.
  5213. * @class
  5214. * @name SmoothScroll
  5215. * @fires SmoothScroll#init
  5216. * @param {Object} element - jQuery object to add the trigger to.
  5217. * @param {Object} options - Overrides to the default plugin settings.
  5218. */
  5219. value: function _setup(element, options) {
  5220. this.$element = element;
  5221. this.options = $.extend({}, SmoothScroll.defaults, this.$element.data(), options);
  5222. this.className = 'SmoothScroll'; // ie9 back compat
  5223. this._init();
  5224. }
  5225. /**
  5226. * Initialize the SmoothScroll plugin
  5227. * @private
  5228. */
  5229. }, {
  5230. key: "_init",
  5231. value: function _init() {
  5232. var id = this.$element[0].id || GetYoDigits(6, 'smooth-scroll');
  5233. this.$element.attr({
  5234. id: id
  5235. });
  5236. this._events();
  5237. }
  5238. /**
  5239. * Initializes events for SmoothScroll.
  5240. * @private
  5241. */
  5242. }, {
  5243. key: "_events",
  5244. value: function _events() {
  5245. this._linkClickListener = this._handleLinkClick.bind(this);
  5246. this.$element.on('click.zf.smoothScroll', this._linkClickListener);
  5247. this.$element.on('click.zf.smoothScroll', 'a[href^="#"]', this._linkClickListener);
  5248. }
  5249. /**
  5250. * Handle the given event to smoothly scroll to the anchor pointed by the event target.
  5251. * @param {*} e - event
  5252. * @function
  5253. * @private
  5254. */
  5255. }, {
  5256. key: "_handleLinkClick",
  5257. value: function _handleLinkClick(e) {
  5258. var _this = this;
  5259. // Follow the link if it does not point to an anchor.
  5260. if (!$(e.currentTarget).is('a[href^="#"]')) return;
  5261. var arrival = e.currentTarget.getAttribute('href');
  5262. this._inTransition = true;
  5263. SmoothScroll.scrollToLoc(arrival, this.options, function () {
  5264. _this._inTransition = false;
  5265. });
  5266. e.preventDefault();
  5267. }
  5268. }, {
  5269. key: "_destroy",
  5270. /**
  5271. * Destroys the SmoothScroll instance.
  5272. * @function
  5273. */
  5274. value: function _destroy() {
  5275. this.$element.off('click.zf.smoothScroll', this._linkClickListener);
  5276. this.$element.off('click.zf.smoothScroll', 'a[href^="#"]', this._linkClickListener);
  5277. }
  5278. }], [{
  5279. key: "scrollToLoc",
  5280. /**
  5281. * Function to scroll to a given location on the page.
  5282. * @param {String} loc - A properly formatted jQuery id selector. Example: '#foo'
  5283. * @param {Object} options - The options to use.
  5284. * @param {Function} callback - The callback function.
  5285. * @static
  5286. * @function
  5287. */
  5288. value: function scrollToLoc(loc) {
  5289. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : SmoothScroll.defaults;
  5290. var callback = arguments.length > 2 ? arguments[2] : undefined;
  5291. var $loc = $(loc); // Do nothing if target does not exist to prevent errors
  5292. if (!$loc.length) return false;
  5293. var scrollPos = Math.round($loc.offset().top - options.threshold / 2 - options.offset);
  5294. $('html, body').stop(true).animate({
  5295. scrollTop: scrollPos
  5296. }, options.animationDuration, options.animationEasing, function () {
  5297. if (typeof callback === 'function') {
  5298. callback();
  5299. }
  5300. });
  5301. }
  5302. }]);
  5303. return SmoothScroll;
  5304. }(Plugin);
  5305. /**
  5306. * Default settings for plugin.
  5307. */
  5308. SmoothScroll.defaults = {
  5309. /**
  5310. * Amount of time, in ms, the animated scrolling should take between locations.
  5311. * @option
  5312. * @type {number}
  5313. * @default 500
  5314. */
  5315. animationDuration: 500,
  5316. /**
  5317. * Animation style to use when scrolling between locations. Can be `'swing'` or `'linear'`.
  5318. * @option
  5319. * @type {string}
  5320. * @default 'linear'
  5321. * @see {@link https://api.jquery.com/animate|Jquery animate}
  5322. */
  5323. animationEasing: 'linear',
  5324. /**
  5325. * Number of pixels to use as a marker for location changes.
  5326. * @option
  5327. * @type {number}
  5328. * @default 50
  5329. */
  5330. threshold: 50,
  5331. /**
  5332. * Number of pixels to offset the scroll of the page on item click if using a sticky nav bar.
  5333. * @option
  5334. * @type {number}
  5335. * @default 0
  5336. */
  5337. offset: 0
  5338. };
  5339. /**
  5340. * Magellan module.
  5341. * @module foundation.magellan
  5342. * @requires foundation.smoothScroll
  5343. */
  5344. var Magellan =
  5345. /*#__PURE__*/
  5346. function (_Plugin) {
  5347. _inherits(Magellan, _Plugin);
  5348. function Magellan() {
  5349. _classCallCheck(this, Magellan);
  5350. return _possibleConstructorReturn(this, _getPrototypeOf(Magellan).apply(this, arguments));
  5351. }
  5352. _createClass(Magellan, [{
  5353. key: "_setup",
  5354. /**
  5355. * Creates a new instance of Magellan.
  5356. * @class
  5357. * @name Magellan
  5358. * @fires Magellan#init
  5359. * @param {Object} element - jQuery object to add the trigger to.
  5360. * @param {Object} options - Overrides to the default plugin settings.
  5361. */
  5362. value: function _setup(element, options) {
  5363. this.$element = element;
  5364. this.options = $.extend({}, Magellan.defaults, this.$element.data(), options);
  5365. this.className = 'Magellan'; // ie9 back compat
  5366. this._init();
  5367. this.calcPoints();
  5368. }
  5369. /**
  5370. * Initializes the Magellan plugin and calls functions to get equalizer functioning on load.
  5371. * @private
  5372. */
  5373. }, {
  5374. key: "_init",
  5375. value: function _init() {
  5376. var id = this.$element[0].id || GetYoDigits(6, 'magellan');
  5377. this.$targets = $('[data-magellan-target]');
  5378. this.$links = this.$element.find('a');
  5379. this.$element.attr({
  5380. 'data-resize': id,
  5381. 'data-scroll': id,
  5382. 'id': id
  5383. });
  5384. this.$active = $();
  5385. this.scrollPos = parseInt(window.pageYOffset, 10);
  5386. this._events();
  5387. }
  5388. /**
  5389. * Calculates an array of pixel values that are the demarcation lines between locations on the page.
  5390. * Can be invoked if new elements are added or the size of a location changes.
  5391. * @function
  5392. */
  5393. }, {
  5394. key: "calcPoints",
  5395. value: function calcPoints() {
  5396. var _this = this,
  5397. body = document.body,
  5398. html = document.documentElement;
  5399. this.points = [];
  5400. this.winHeight = Math.round(Math.max(window.innerHeight, html.clientHeight));
  5401. this.docHeight = Math.round(Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight));
  5402. this.$targets.each(function () {
  5403. var $tar = $(this),
  5404. pt = Math.round($tar.offset().top - _this.options.threshold);
  5405. $tar.targetPoint = pt;
  5406. _this.points.push(pt);
  5407. });
  5408. }
  5409. /**
  5410. * Initializes events for Magellan.
  5411. * @private
  5412. */
  5413. }, {
  5414. key: "_events",
  5415. value: function _events() {
  5416. var _this = this,
  5417. $body = $('html, body'),
  5418. opts = {
  5419. duration: _this.options.animationDuration,
  5420. easing: _this.options.animationEasing
  5421. };
  5422. $(window).one('load', function () {
  5423. if (_this.options.deepLinking) {
  5424. if (location.hash) {
  5425. _this.scrollToLoc(location.hash);
  5426. }
  5427. }
  5428. _this.calcPoints();
  5429. _this._updateActive();
  5430. });
  5431. _this.onLoadListener = onLoad($(window), function () {
  5432. _this.$element.on({
  5433. 'resizeme.zf.trigger': _this.reflow.bind(_this),
  5434. 'scrollme.zf.trigger': _this._updateActive.bind(_this)
  5435. }).on('click.zf.magellan', 'a[href^="#"]', function (e) {
  5436. e.preventDefault();
  5437. var arrival = this.getAttribute('href');
  5438. _this.scrollToLoc(arrival);
  5439. });
  5440. });
  5441. this._deepLinkScroll = function (e) {
  5442. if (_this.options.deepLinking) {
  5443. _this.scrollToLoc(window.location.hash);
  5444. }
  5445. };
  5446. $(window).on('hashchange', this._deepLinkScroll);
  5447. }
  5448. /**
  5449. * Function to scroll to a given location on the page.
  5450. * @param {String} loc - a properly formatted jQuery id selector. Example: '#foo'
  5451. * @function
  5452. */
  5453. }, {
  5454. key: "scrollToLoc",
  5455. value: function scrollToLoc(loc) {
  5456. this._inTransition = true;
  5457. var _this = this;
  5458. var options = {
  5459. animationEasing: this.options.animationEasing,
  5460. animationDuration: this.options.animationDuration,
  5461. threshold: this.options.threshold,
  5462. offset: this.options.offset
  5463. };
  5464. SmoothScroll.scrollToLoc(loc, options, function () {
  5465. _this._inTransition = false;
  5466. });
  5467. }
  5468. /**
  5469. * Calls necessary functions to update Magellan upon DOM change
  5470. * @function
  5471. */
  5472. }, {
  5473. key: "reflow",
  5474. value: function reflow() {
  5475. this.calcPoints();
  5476. this._updateActive();
  5477. }
  5478. /**
  5479. * Updates the visibility of an active location link, and updates the url hash for the page, if deepLinking enabled.
  5480. * @private
  5481. * @function
  5482. * @fires Magellan#update
  5483. */
  5484. }, {
  5485. key: "_updateActive",
  5486. value: function _updateActive()
  5487. /*evt, elem, scrollPos*/
  5488. {
  5489. var _this2 = this;
  5490. if (this._inTransition) return;
  5491. var newScrollPos = parseInt(window.pageYOffset, 10);
  5492. var isScrollingUp = this.scrollPos > newScrollPos;
  5493. this.scrollPos = newScrollPos;
  5494. var activeIdx; // Before the first point: no link
  5495. if (newScrollPos < this.points[0]) ;
  5496. /* do nothing */
  5497. // At the bottom of the page: last link
  5498. else if (newScrollPos + this.winHeight === this.docHeight) {
  5499. activeIdx = this.points.length - 1;
  5500. } // Otherwhise, use the last visible link
  5501. else {
  5502. var visibleLinks = this.points.filter(function (p, i) {
  5503. return p - _this2.options.offset - (isScrollingUp ? _this2.options.threshold : 0) <= newScrollPos;
  5504. });
  5505. activeIdx = visibleLinks.length ? visibleLinks.length - 1 : 0;
  5506. } // Get the new active link
  5507. var $oldActive = this.$active;
  5508. var activeHash = '';
  5509. if (typeof activeIdx !== 'undefined') {
  5510. this.$active = this.$links.filter('[href="#' + this.$targets.eq(activeIdx).data('magellan-target') + '"]');
  5511. if (this.$active.length) activeHash = this.$active[0].getAttribute('href');
  5512. } else {
  5513. this.$active = $();
  5514. }
  5515. var isNewActive = !(!this.$active.length && !$oldActive.length) && !this.$active.is($oldActive);
  5516. var isNewHash = activeHash !== window.location.hash; // Update the active link element
  5517. if (isNewActive) {
  5518. $oldActive.removeClass(this.options.activeClass);
  5519. this.$active.addClass(this.options.activeClass);
  5520. } // Update the hash (it may have changed with the same active link)
  5521. if (this.options.deepLinking && isNewHash) {
  5522. if (window.history.pushState) {
  5523. // Set or remove the hash (see: https://stackoverflow.com/a/5298684/4317384
  5524. var url = activeHash ? activeHash : window.location.pathname + window.location.search;
  5525. window.history.pushState(null, null, url);
  5526. } else {
  5527. window.location.hash = activeHash;
  5528. }
  5529. }
  5530. if (isNewActive) {
  5531. /**
  5532. * Fires when magellan is finished updating to the new active element.
  5533. * @event Magellan#update
  5534. */
  5535. this.$element.trigger('update.zf.magellan', [this.$active]);
  5536. }
  5537. }
  5538. /**
  5539. * Destroys an instance of Magellan and resets the url of the window.
  5540. * @function
  5541. */
  5542. }, {
  5543. key: "_destroy",
  5544. value: function _destroy() {
  5545. this.$element.off('.zf.trigger .zf.magellan').find(".".concat(this.options.activeClass)).removeClass(this.options.activeClass);
  5546. if (this.options.deepLinking) {
  5547. var hash = this.$active[0].getAttribute('href');
  5548. window.location.hash.replace(hash, '');
  5549. }
  5550. $(window).off('hashchange', this._deepLinkScroll);
  5551. if (this.onLoadListener) $(window).off(this.onLoadListener);
  5552. }
  5553. }]);
  5554. return Magellan;
  5555. }(Plugin);
  5556. /**
  5557. * Default settings for plugin
  5558. */
  5559. Magellan.defaults = {
  5560. /**
  5561. * Amount of time, in ms, the animated scrolling should take between locations.
  5562. * @option
  5563. * @type {number}
  5564. * @default 500
  5565. */
  5566. animationDuration: 500,
  5567. /**
  5568. * Animation style to use when scrolling between locations. Can be `'swing'` or `'linear'`.
  5569. * @option
  5570. * @type {string}
  5571. * @default 'linear'
  5572. * @see {@link https://api.jquery.com/animate|Jquery animate}
  5573. */
  5574. animationEasing: 'linear',
  5575. /**
  5576. * Number of pixels to use as a marker for location changes.
  5577. * @option
  5578. * @type {number}
  5579. * @default 50
  5580. */
  5581. threshold: 50,
  5582. /**
  5583. * Class applied to the active locations link on the magellan container.
  5584. * @option
  5585. * @type {string}
  5586. * @default 'is-active'
  5587. */
  5588. activeClass: 'is-active',
  5589. /**
  5590. * Allows the script to manipulate the url of the current page, and if supported, alter the history.
  5591. * @option
  5592. * @type {boolean}
  5593. * @default false
  5594. */
  5595. deepLinking: false,
  5596. /**
  5597. * Number of pixels to offset the scroll of the page on item click if using a sticky nav bar.
  5598. * @option
  5599. * @type {number}
  5600. * @default 0
  5601. */
  5602. offset: 0
  5603. };
  5604. /**
  5605. * OffCanvas module.
  5606. * @module foundation.offcanvas
  5607. * @requires foundation.util.keyboard
  5608. * @requires foundation.util.mediaQuery
  5609. * @requires foundation.util.triggers
  5610. */
  5611. var OffCanvas =
  5612. /*#__PURE__*/
  5613. function (_Plugin) {
  5614. _inherits(OffCanvas, _Plugin);
  5615. function OffCanvas() {
  5616. _classCallCheck(this, OffCanvas);
  5617. return _possibleConstructorReturn(this, _getPrototypeOf(OffCanvas).apply(this, arguments));
  5618. }
  5619. _createClass(OffCanvas, [{
  5620. key: "_setup",
  5621. /**
  5622. * Creates a new instance of an off-canvas wrapper.
  5623. * @class
  5624. * @name OffCanvas
  5625. * @fires OffCanvas#init
  5626. * @param {Object} element - jQuery object to initialize.
  5627. * @param {Object} options - Overrides to the default plugin settings.
  5628. */
  5629. value: function _setup(element, options) {
  5630. var _this2 = this;
  5631. this.className = 'OffCanvas'; // ie9 back compat
  5632. this.$element = element;
  5633. this.options = $.extend({}, OffCanvas.defaults, this.$element.data(), options);
  5634. this.contentClasses = {
  5635. base: [],
  5636. reveal: []
  5637. };
  5638. this.$lastTrigger = $();
  5639. this.$triggers = $();
  5640. this.position = 'left';
  5641. this.$content = $();
  5642. this.nested = !!this.options.nested; // Defines the CSS transition/position classes of the off-canvas content container.
  5643. $(['push', 'overlap']).each(function (index, val) {
  5644. _this2.contentClasses.base.push('has-transition-' + val);
  5645. });
  5646. $(['left', 'right', 'top', 'bottom']).each(function (index, val) {
  5647. _this2.contentClasses.base.push('has-position-' + val);
  5648. _this2.contentClasses.reveal.push('has-reveal-' + val);
  5649. }); // Triggers init is idempotent, just need to make sure it is initialized
  5650. Triggers.init($);
  5651. MediaQuery._init();
  5652. this._init();
  5653. this._events();
  5654. Keyboard.register('OffCanvas', {
  5655. 'ESCAPE': 'close'
  5656. });
  5657. }
  5658. /**
  5659. * Initializes the off-canvas wrapper by adding the exit overlay (if needed).
  5660. * @function
  5661. * @private
  5662. */
  5663. }, {
  5664. key: "_init",
  5665. value: function _init() {
  5666. var id = this.$element.attr('id');
  5667. this.$element.attr('aria-hidden', 'true'); // Find off-canvas content, either by ID (if specified), by siblings or by closest selector (fallback)
  5668. if (this.options.contentId) {
  5669. this.$content = $('#' + this.options.contentId);
  5670. } else if (this.$element.siblings('[data-off-canvas-content]').length) {
  5671. this.$content = this.$element.siblings('[data-off-canvas-content]').first();
  5672. } else {
  5673. this.$content = this.$element.closest('[data-off-canvas-content]').first();
  5674. }
  5675. if (!this.options.contentId) {
  5676. // Assume that the off-canvas element is nested if it isn't a sibling of the content
  5677. this.nested = this.$element.siblings('[data-off-canvas-content]').length === 0;
  5678. } else if (this.options.contentId && this.options.nested === null) {
  5679. // Warning if using content ID without setting the nested option
  5680. // Once the element is nested it is required to work properly in this case
  5681. console.warn('Remember to use the nested option if using the content ID option!');
  5682. }
  5683. if (this.nested === true) {
  5684. // Force transition overlap if nested
  5685. this.options.transition = 'overlap'; // Remove appropriate classes if already assigned in markup
  5686. this.$element.removeClass('is-transition-push');
  5687. }
  5688. this.$element.addClass("is-transition-".concat(this.options.transition, " is-closed")); // Find triggers that affect this element and add aria-expanded to them
  5689. this.$triggers = $(document).find('[data-open="' + id + '"], [data-close="' + id + '"], [data-toggle="' + id + '"]').attr('aria-expanded', 'false').attr('aria-controls', id); // Get position by checking for related CSS class
  5690. this.position = this.$element.is('.position-left, .position-top, .position-right, .position-bottom') ? this.$element.attr('class').match(/position\-(left|top|right|bottom)/)[1] : this.position; // Add an overlay over the content if necessary
  5691. if (this.options.contentOverlay === true) {
  5692. var overlay = document.createElement('div');
  5693. var overlayPosition = $(this.$element).css("position") === 'fixed' ? 'is-overlay-fixed' : 'is-overlay-absolute';
  5694. overlay.setAttribute('class', 'js-off-canvas-overlay ' + overlayPosition);
  5695. this.$overlay = $(overlay);
  5696. if (overlayPosition === 'is-overlay-fixed') {
  5697. $(this.$overlay).insertAfter(this.$element);
  5698. } else {
  5699. this.$content.append(this.$overlay);
  5700. }
  5701. } // Get the revealOn option from the class.
  5702. var revealOnRegExp = new RegExp(RegExpEscape(this.options.revealClass) + '([^\\s]+)', 'g');
  5703. var revealOnClass = revealOnRegExp.exec(this.$element[0].className);
  5704. if (revealOnClass) {
  5705. this.options.isRevealed = true;
  5706. this.options.revealOn = this.options.revealOn || revealOnClass[1];
  5707. } // Ensure the `reveal-on-*` class is set.
  5708. if (this.options.isRevealed === true && this.options.revealOn) {
  5709. this.$element.first().addClass("".concat(this.options.revealClass).concat(this.options.revealOn));
  5710. this._setMQChecker();
  5711. }
  5712. if (this.options.transitionTime) {
  5713. this.$element.css('transition-duration', this.options.transitionTime);
  5714. } // Initally remove all transition/position CSS classes from off-canvas content container.
  5715. this._removeContentClasses();
  5716. }
  5717. /**
  5718. * Adds event handlers to the off-canvas wrapper and the exit overlay.
  5719. * @function
  5720. * @private
  5721. */
  5722. }, {
  5723. key: "_events",
  5724. value: function _events() {
  5725. this.$element.off('.zf.trigger .zf.offcanvas').on({
  5726. 'open.zf.trigger': this.open.bind(this),
  5727. 'close.zf.trigger': this.close.bind(this),
  5728. 'toggle.zf.trigger': this.toggle.bind(this),
  5729. 'keydown.zf.offcanvas': this._handleKeyboard.bind(this)
  5730. });
  5731. if (this.options.closeOnClick === true) {
  5732. var $target = this.options.contentOverlay ? this.$overlay : this.$content;
  5733. $target.on({
  5734. 'click.zf.offcanvas': this.close.bind(this)
  5735. });
  5736. }
  5737. }
  5738. /**
  5739. * Applies event listener for elements that will reveal at certain breakpoints.
  5740. * @private
  5741. */
  5742. }, {
  5743. key: "_setMQChecker",
  5744. value: function _setMQChecker() {
  5745. var _this = this;
  5746. this.onLoadListener = onLoad($(window), function () {
  5747. if (MediaQuery.atLeast(_this.options.revealOn)) {
  5748. _this.reveal(true);
  5749. }
  5750. });
  5751. $(window).on('changed.zf.mediaquery', function () {
  5752. if (MediaQuery.atLeast(_this.options.revealOn)) {
  5753. _this.reveal(true);
  5754. } else {
  5755. _this.reveal(false);
  5756. }
  5757. });
  5758. }
  5759. /**
  5760. * Removes the CSS transition/position classes of the off-canvas content container.
  5761. * Removing the classes is important when another off-canvas gets opened that uses the same content container.
  5762. * @param {Boolean} hasReveal - true if related off-canvas element is revealed.
  5763. * @private
  5764. */
  5765. }, {
  5766. key: "_removeContentClasses",
  5767. value: function _removeContentClasses(hasReveal) {
  5768. if (typeof hasReveal !== 'boolean') {
  5769. this.$content.removeClass(this.contentClasses.base.join(' '));
  5770. } else if (hasReveal === false) {
  5771. this.$content.removeClass("has-reveal-".concat(this.position));
  5772. }
  5773. }
  5774. /**
  5775. * Adds the CSS transition/position classes of the off-canvas content container, based on the opening off-canvas element.
  5776. * Beforehand any transition/position class gets removed.
  5777. * @param {Boolean} hasReveal - true if related off-canvas element is revealed.
  5778. * @private
  5779. */
  5780. }, {
  5781. key: "_addContentClasses",
  5782. value: function _addContentClasses(hasReveal) {
  5783. this._removeContentClasses(hasReveal);
  5784. if (typeof hasReveal !== 'boolean') {
  5785. this.$content.addClass("has-transition-".concat(this.options.transition, " has-position-").concat(this.position));
  5786. } else if (hasReveal === true) {
  5787. this.$content.addClass("has-reveal-".concat(this.position));
  5788. }
  5789. }
  5790. /**
  5791. * Handles the revealing/hiding the off-canvas at breakpoints, not the same as open.
  5792. * @param {Boolean} isRevealed - true if element should be revealed.
  5793. * @function
  5794. */
  5795. }, {
  5796. key: "reveal",
  5797. value: function reveal(isRevealed) {
  5798. if (isRevealed) {
  5799. this.close();
  5800. this.isRevealed = true;
  5801. this.$element.attr('aria-hidden', 'false');
  5802. this.$element.off('open.zf.trigger toggle.zf.trigger');
  5803. this.$element.removeClass('is-closed');
  5804. } else {
  5805. this.isRevealed = false;
  5806. this.$element.attr('aria-hidden', 'true');
  5807. this.$element.off('open.zf.trigger toggle.zf.trigger').on({
  5808. 'open.zf.trigger': this.open.bind(this),
  5809. 'toggle.zf.trigger': this.toggle.bind(this)
  5810. });
  5811. this.$element.addClass('is-closed');
  5812. }
  5813. this._addContentClasses(isRevealed);
  5814. }
  5815. /**
  5816. * Stops scrolling of the body when offcanvas is open on mobile Safari and other troublesome browsers.
  5817. * @private
  5818. */
  5819. }, {
  5820. key: "_stopScrolling",
  5821. value: function _stopScrolling(event) {
  5822. return false;
  5823. } // Taken and adapted from http://stackoverflow.com/questions/16889447/prevent-full-page-scrolling-ios
  5824. // Only really works for y, not sure how to extend to x or if we need to.
  5825. }, {
  5826. key: "_recordScrollable",
  5827. value: function _recordScrollable(event) {
  5828. var elem = this; // called from event handler context with this as elem
  5829. // If the element is scrollable (content overflows), then...
  5830. if (elem.scrollHeight !== elem.clientHeight) {
  5831. // If we're at the top, scroll down one pixel to allow scrolling up
  5832. if (elem.scrollTop === 0) {
  5833. elem.scrollTop = 1;
  5834. } // If we're at the bottom, scroll up one pixel to allow scrolling down
  5835. if (elem.scrollTop === elem.scrollHeight - elem.clientHeight) {
  5836. elem.scrollTop = elem.scrollHeight - elem.clientHeight - 1;
  5837. }
  5838. }
  5839. elem.allowUp = elem.scrollTop > 0;
  5840. elem.allowDown = elem.scrollTop < elem.scrollHeight - elem.clientHeight;
  5841. elem.lastY = event.originalEvent.pageY;
  5842. }
  5843. }, {
  5844. key: "_stopScrollPropagation",
  5845. value: function _stopScrollPropagation(event) {
  5846. var elem = this; // called from event handler context with this as elem
  5847. var up = event.pageY < elem.lastY;
  5848. var down = !up;
  5849. elem.lastY = event.pageY;
  5850. if (up && elem.allowUp || down && elem.allowDown) {
  5851. event.stopPropagation();
  5852. } else {
  5853. event.preventDefault();
  5854. }
  5855. }
  5856. /**
  5857. * Opens the off-canvas menu.
  5858. * @function
  5859. * @param {Object} event - Event object passed from listener.
  5860. * @param {jQuery} trigger - element that triggered the off-canvas to open.
  5861. * @fires Offcanvas#opened
  5862. * @todo also trigger 'open' event?
  5863. */
  5864. }, {
  5865. key: "open",
  5866. value: function open(event, trigger) {
  5867. if (this.$element.hasClass('is-open') || this.isRevealed) {
  5868. return;
  5869. }
  5870. var _this = this;
  5871. if (trigger) {
  5872. this.$lastTrigger = trigger;
  5873. }
  5874. if (this.options.forceTo === 'top') {
  5875. window.scrollTo(0, 0);
  5876. } else if (this.options.forceTo === 'bottom') {
  5877. window.scrollTo(0, document.body.scrollHeight);
  5878. }
  5879. if (this.options.transitionTime && this.options.transition !== 'overlap') {
  5880. this.$element.siblings('[data-off-canvas-content]').css('transition-duration', this.options.transitionTime);
  5881. } else {
  5882. this.$element.siblings('[data-off-canvas-content]').css('transition-duration', '');
  5883. }
  5884. this.$element.addClass('is-open').removeClass('is-closed');
  5885. this.$triggers.attr('aria-expanded', 'true');
  5886. this.$element.attr('aria-hidden', 'false');
  5887. this.$content.addClass('is-open-' + this.position); // If `contentScroll` is set to false, add class and disable scrolling on touch devices.
  5888. if (this.options.contentScroll === false) {
  5889. $('body').addClass('is-off-canvas-open').on('touchmove', this._stopScrolling);
  5890. this.$element.on('touchstart', this._recordScrollable);
  5891. this.$element.on('touchmove', this._stopScrollPropagation);
  5892. }
  5893. if (this.options.contentOverlay === true) {
  5894. this.$overlay.addClass('is-visible');
  5895. }
  5896. if (this.options.closeOnClick === true && this.options.contentOverlay === true) {
  5897. this.$overlay.addClass('is-closable');
  5898. }
  5899. if (this.options.autoFocus === true) {
  5900. this.$element.one(transitionend(this.$element), function () {
  5901. if (!_this.$element.hasClass('is-open')) {
  5902. return; // exit if prematurely closed
  5903. }
  5904. var canvasFocus = _this.$element.find('[data-autofocus]');
  5905. if (canvasFocus.length) {
  5906. canvasFocus.eq(0).focus();
  5907. } else {
  5908. _this.$element.find('a, button').eq(0).focus();
  5909. }
  5910. });
  5911. }
  5912. if (this.options.trapFocus === true) {
  5913. this.$content.attr('tabindex', '-1');
  5914. Keyboard.trapFocus(this.$element);
  5915. }
  5916. this._addContentClasses();
  5917. /**
  5918. * Fires when the off-canvas menu opens.
  5919. * @event Offcanvas#opened
  5920. */
  5921. this.$element.trigger('opened.zf.offcanvas');
  5922. }
  5923. /**
  5924. * Closes the off-canvas menu.
  5925. * @function
  5926. * @param {Function} cb - optional cb to fire after closure.
  5927. * @fires Offcanvas#closed
  5928. */
  5929. }, {
  5930. key: "close",
  5931. value: function close(cb) {
  5932. if (!this.$element.hasClass('is-open') || this.isRevealed) {
  5933. return;
  5934. }
  5935. var _this = this;
  5936. this.$element.removeClass('is-open');
  5937. this.$element.attr('aria-hidden', 'true')
  5938. /**
  5939. * Fires when the off-canvas menu opens.
  5940. * @event Offcanvas#closed
  5941. */
  5942. .trigger('closed.zf.offcanvas');
  5943. this.$content.removeClass('is-open-left is-open-top is-open-right is-open-bottom'); // If `contentScroll` is set to false, remove class and re-enable scrolling on touch devices.
  5944. if (this.options.contentScroll === false) {
  5945. $('body').removeClass('is-off-canvas-open').off('touchmove', this._stopScrolling);
  5946. this.$element.off('touchstart', this._recordScrollable);
  5947. this.$element.off('touchmove', this._stopScrollPropagation);
  5948. }
  5949. if (this.options.contentOverlay === true) {
  5950. this.$overlay.removeClass('is-visible');
  5951. }
  5952. if (this.options.closeOnClick === true && this.options.contentOverlay === true) {
  5953. this.$overlay.removeClass('is-closable');
  5954. }
  5955. this.$triggers.attr('aria-expanded', 'false');
  5956. if (this.options.trapFocus === true) {
  5957. this.$content.removeAttr('tabindex');
  5958. Keyboard.releaseFocus(this.$element);
  5959. } // Listen to transitionEnd and add class when done.
  5960. this.$element.one(transitionend(this.$element), function (e) {
  5961. _this.$element.addClass('is-closed');
  5962. _this._removeContentClasses();
  5963. });
  5964. }
  5965. /**
  5966. * Toggles the off-canvas menu open or closed.
  5967. * @function
  5968. * @param {Object} event - Event object passed from listener.
  5969. * @param {jQuery} trigger - element that triggered the off-canvas to open.
  5970. */
  5971. }, {
  5972. key: "toggle",
  5973. value: function toggle(event, trigger) {
  5974. if (this.$element.hasClass('is-open')) {
  5975. this.close(event, trigger);
  5976. } else {
  5977. this.open(event, trigger);
  5978. }
  5979. }
  5980. /**
  5981. * Handles keyboard input when detected. When the escape key is pressed, the off-canvas menu closes, and focus is restored to the element that opened the menu.
  5982. * @function
  5983. * @private
  5984. */
  5985. }, {
  5986. key: "_handleKeyboard",
  5987. value: function _handleKeyboard(e) {
  5988. var _this3 = this;
  5989. Keyboard.handleKey(e, 'OffCanvas', {
  5990. close: function close() {
  5991. _this3.close();
  5992. _this3.$lastTrigger.focus();
  5993. return true;
  5994. },
  5995. handled: function handled() {
  5996. e.stopPropagation();
  5997. e.preventDefault();
  5998. }
  5999. });
  6000. }
  6001. /**
  6002. * Destroys the offcanvas plugin.
  6003. * @function
  6004. */
  6005. }, {
  6006. key: "_destroy",
  6007. value: function _destroy() {
  6008. this.close();
  6009. this.$element.off('.zf.trigger .zf.offcanvas');
  6010. this.$overlay.off('.zf.offcanvas');
  6011. if (this.onLoadListener) $(window).off(this.onLoadListener);
  6012. }
  6013. }]);
  6014. return OffCanvas;
  6015. }(Plugin);
  6016. OffCanvas.defaults = {
  6017. /**
  6018. * Allow the user to click outside of the menu to close it.
  6019. * @option
  6020. * @type {boolean}
  6021. * @default true
  6022. */
  6023. closeOnClick: true,
  6024. /**
  6025. * Adds an overlay on top of `[data-off-canvas-content]`.
  6026. * @option
  6027. * @type {boolean}
  6028. * @default true
  6029. */
  6030. contentOverlay: true,
  6031. /**
  6032. * Target an off-canvas content container by ID that may be placed anywhere. If null the closest content container will be taken.
  6033. * @option
  6034. * @type {?string}
  6035. * @default null
  6036. */
  6037. contentId: null,
  6038. /**
  6039. * Define the off-canvas element is nested in an off-canvas content. This is required when using the contentId option for a nested element.
  6040. * @option
  6041. * @type {boolean}
  6042. * @default null
  6043. */
  6044. nested: null,
  6045. /**
  6046. * Enable/disable scrolling of the main content when an off canvas panel is open.
  6047. * @option
  6048. * @type {boolean}
  6049. * @default true
  6050. */
  6051. contentScroll: true,
  6052. /**
  6053. * Amount of time in ms the open and close transition requires. If none selected, pulls from body style.
  6054. * @option
  6055. * @type {number}
  6056. * @default null
  6057. */
  6058. transitionTime: null,
  6059. /**
  6060. * Type of transition for the offcanvas menu. Options are 'push', 'detached' or 'slide'.
  6061. * @option
  6062. * @type {string}
  6063. * @default push
  6064. */
  6065. transition: 'push',
  6066. /**
  6067. * Force the page to scroll to top or bottom on open.
  6068. * @option
  6069. * @type {?string}
  6070. * @default null
  6071. */
  6072. forceTo: null,
  6073. /**
  6074. * Allow the offcanvas to remain open for certain breakpoints.
  6075. * @option
  6076. * @type {boolean}
  6077. * @default false
  6078. */
  6079. isRevealed: false,
  6080. /**
  6081. * Breakpoint at which to reveal. JS will use a RegExp to target standard classes, if changing classnames, pass your class with the `revealClass` option.
  6082. * @option
  6083. * @type {?string}
  6084. * @default null
  6085. */
  6086. revealOn: null,
  6087. /**
  6088. * Force focus to the offcanvas on open. If true, will focus the opening trigger on close.
  6089. * @option
  6090. * @type {boolean}
  6091. * @default true
  6092. */
  6093. autoFocus: true,
  6094. /**
  6095. * Class used to force an offcanvas to remain open. Foundation defaults for this are `reveal-for-large` & `reveal-for-medium`.
  6096. * @option
  6097. * @type {string}
  6098. * @default reveal-for-
  6099. * @todo improve the regex testing for this.
  6100. */
  6101. revealClass: 'reveal-for-',
  6102. /**
  6103. * Triggers optional focus trapping when opening an offcanvas. Sets tabindex of [data-off-canvas-content] to -1 for accessibility purposes.
  6104. * @option
  6105. * @type {boolean}
  6106. * @default false
  6107. */
  6108. trapFocus: false
  6109. };
  6110. /**
  6111. * Orbit module.
  6112. * @module foundation.orbit
  6113. * @requires foundation.util.keyboard
  6114. * @requires foundation.util.motion
  6115. * @requires foundation.util.timer
  6116. * @requires foundation.util.imageLoader
  6117. * @requires foundation.util.touch
  6118. */
  6119. var Orbit =
  6120. /*#__PURE__*/
  6121. function (_Plugin) {
  6122. _inherits(Orbit, _Plugin);
  6123. function Orbit() {
  6124. _classCallCheck(this, Orbit);
  6125. return _possibleConstructorReturn(this, _getPrototypeOf(Orbit).apply(this, arguments));
  6126. }
  6127. _createClass(Orbit, [{
  6128. key: "_setup",
  6129. /**
  6130. * Creates a new instance of an orbit carousel.
  6131. * @class
  6132. * @name Orbit
  6133. * @param {jQuery} element - jQuery object to make into an Orbit Carousel.
  6134. * @param {Object} options - Overrides to the default plugin settings.
  6135. */
  6136. value: function _setup(element, options) {
  6137. this.$element = element;
  6138. this.options = $.extend({}, Orbit.defaults, this.$element.data(), options);
  6139. this.className = 'Orbit'; // ie9 back compat
  6140. Touch.init($); // Touch init is idempotent, we just need to make sure it's initialied.
  6141. this._init();
  6142. Keyboard.register('Orbit', {
  6143. 'ltr': {
  6144. 'ARROW_RIGHT': 'next',
  6145. 'ARROW_LEFT': 'previous'
  6146. },
  6147. 'rtl': {
  6148. 'ARROW_LEFT': 'next',
  6149. 'ARROW_RIGHT': 'previous'
  6150. }
  6151. });
  6152. }
  6153. /**
  6154. * Initializes the plugin by creating jQuery collections, setting attributes, and starting the animation.
  6155. * @function
  6156. * @private
  6157. */
  6158. }, {
  6159. key: "_init",
  6160. value: function _init() {
  6161. // @TODO: consider discussion on PR #9278 about DOM pollution by changeSlide
  6162. this._reset();
  6163. this.$wrapper = this.$element.find(".".concat(this.options.containerClass));
  6164. this.$slides = this.$element.find(".".concat(this.options.slideClass));
  6165. var $images = this.$element.find('img'),
  6166. initActive = this.$slides.filter('.is-active'),
  6167. id = this.$element[0].id || GetYoDigits(6, 'orbit');
  6168. this.$element.attr({
  6169. 'data-resize': id,
  6170. 'id': id
  6171. });
  6172. if (!initActive.length) {
  6173. this.$slides.eq(0).addClass('is-active');
  6174. }
  6175. if (!this.options.useMUI) {
  6176. this.$slides.addClass('no-motionui');
  6177. }
  6178. if ($images.length) {
  6179. onImagesLoaded($images, this._prepareForOrbit.bind(this));
  6180. } else {
  6181. this._prepareForOrbit(); //hehe
  6182. }
  6183. if (this.options.bullets) {
  6184. this._loadBullets();
  6185. }
  6186. this._events();
  6187. if (this.options.autoPlay && this.$slides.length > 1) {
  6188. this.geoSync();
  6189. }
  6190. if (this.options.accessible) {
  6191. // allow wrapper to be focusable to enable arrow navigation
  6192. this.$wrapper.attr('tabindex', 0);
  6193. }
  6194. }
  6195. /**
  6196. * Creates a jQuery collection of bullets, if they are being used.
  6197. * @function
  6198. * @private
  6199. */
  6200. }, {
  6201. key: "_loadBullets",
  6202. value: function _loadBullets() {
  6203. this.$bullets = this.$element.find(".".concat(this.options.boxOfBullets)).find('button');
  6204. }
  6205. /**
  6206. * Sets a `timer` object on the orbit, and starts the counter for the next slide.
  6207. * @function
  6208. */
  6209. }, {
  6210. key: "geoSync",
  6211. value: function geoSync() {
  6212. var _this = this;
  6213. this.timer = new Timer(this.$element, {
  6214. duration: this.options.timerDelay,
  6215. infinite: false
  6216. }, function () {
  6217. _this.changeSlide(true);
  6218. });
  6219. this.timer.start();
  6220. }
  6221. /**
  6222. * Sets wrapper and slide heights for the orbit.
  6223. * @function
  6224. * @private
  6225. */
  6226. }, {
  6227. key: "_prepareForOrbit",
  6228. value: function _prepareForOrbit() {
  6229. this._setWrapperHeight();
  6230. }
  6231. /**
  6232. * Calulates the height of each slide in the collection, and uses the tallest one for the wrapper height.
  6233. * @function
  6234. * @private
  6235. * @param {Function} cb - a callback function to fire when complete.
  6236. */
  6237. }, {
  6238. key: "_setWrapperHeight",
  6239. value: function _setWrapperHeight(cb) {
  6240. //rewrite this to `for` loop
  6241. var max = 0,
  6242. temp,
  6243. counter = 0,
  6244. _this = this;
  6245. this.$slides.each(function () {
  6246. temp = this.getBoundingClientRect().height;
  6247. $(this).attr('data-slide', counter); // hide all slides but the active one
  6248. if (!/mui/g.test($(this)[0].className) && _this.$slides.filter('.is-active')[0] !== _this.$slides.eq(counter)[0]) {
  6249. $(this).css({
  6250. 'display': 'none'
  6251. });
  6252. }
  6253. max = temp > max ? temp : max;
  6254. counter++;
  6255. });
  6256. if (counter === this.$slides.length) {
  6257. this.$wrapper.css({
  6258. 'height': max
  6259. }); //only change the wrapper height property once.
  6260. if (cb) {
  6261. cb(max);
  6262. } //fire callback with max height dimension.
  6263. }
  6264. }
  6265. /**
  6266. * Sets the max-height of each slide.
  6267. * @function
  6268. * @private
  6269. */
  6270. }, {
  6271. key: "_setSlideHeight",
  6272. value: function _setSlideHeight(height) {
  6273. this.$slides.each(function () {
  6274. $(this).css('max-height', height);
  6275. });
  6276. }
  6277. /**
  6278. * Adds event listeners to basically everything within the element.
  6279. * @function
  6280. * @private
  6281. */
  6282. }, {
  6283. key: "_events",
  6284. value: function _events() {
  6285. var _this = this; //***************************************
  6286. //**Now using custom event - thanks to:**
  6287. //** Yohai Ararat of Toronto **
  6288. //***************************************
  6289. //
  6290. this.$element.off('.resizeme.zf.trigger').on({
  6291. 'resizeme.zf.trigger': this._prepareForOrbit.bind(this)
  6292. });
  6293. if (this.$slides.length > 1) {
  6294. if (this.options.swipe) {
  6295. this.$slides.off('swipeleft.zf.orbit swiperight.zf.orbit').on('swipeleft.zf.orbit', function (e) {
  6296. e.preventDefault();
  6297. _this.changeSlide(true);
  6298. }).on('swiperight.zf.orbit', function (e) {
  6299. e.preventDefault();
  6300. _this.changeSlide(false);
  6301. });
  6302. } //***************************************
  6303. if (this.options.autoPlay) {
  6304. this.$slides.on('click.zf.orbit', function () {
  6305. _this.$element.data('clickedOn', _this.$element.data('clickedOn') ? false : true);
  6306. _this.timer[_this.$element.data('clickedOn') ? 'pause' : 'start']();
  6307. });
  6308. if (this.options.pauseOnHover) {
  6309. this.$element.on('mouseenter.zf.orbit', function () {
  6310. _this.timer.pause();
  6311. }).on('mouseleave.zf.orbit', function () {
  6312. if (!_this.$element.data('clickedOn')) {
  6313. _this.timer.start();
  6314. }
  6315. });
  6316. }
  6317. }
  6318. if (this.options.navButtons) {
  6319. var $controls = this.$element.find(".".concat(this.options.nextClass, ", .").concat(this.options.prevClass));
  6320. $controls.attr('tabindex', 0) //also need to handle enter/return and spacebar key presses
  6321. .on('click.zf.orbit touchend.zf.orbit', function (e) {
  6322. e.preventDefault();
  6323. _this.changeSlide($(this).hasClass(_this.options.nextClass));
  6324. });
  6325. }
  6326. if (this.options.bullets) {
  6327. this.$bullets.on('click.zf.orbit touchend.zf.orbit', function () {
  6328. if (/is-active/g.test(this.className)) {
  6329. return false;
  6330. } //if this is active, kick out of function.
  6331. var idx = $(this).data('slide'),
  6332. ltr = idx > _this.$slides.filter('.is-active').data('slide'),
  6333. $slide = _this.$slides.eq(idx);
  6334. _this.changeSlide(ltr, $slide, idx);
  6335. });
  6336. }
  6337. if (this.options.accessible) {
  6338. this.$wrapper.add(this.$bullets).on('keydown.zf.orbit', function (e) {
  6339. // handle keyboard event with keyboard util
  6340. Keyboard.handleKey(e, 'Orbit', {
  6341. next: function next() {
  6342. _this.changeSlide(true);
  6343. },
  6344. previous: function previous() {
  6345. _this.changeSlide(false);
  6346. },
  6347. handled: function handled() {
  6348. // if bullet is focused, make sure focus moves
  6349. if ($(e.target).is(_this.$bullets)) {
  6350. _this.$bullets.filter('.is-active').focus();
  6351. }
  6352. }
  6353. });
  6354. });
  6355. }
  6356. }
  6357. }
  6358. /**
  6359. * Resets Orbit so it can be reinitialized
  6360. */
  6361. }, {
  6362. key: "_reset",
  6363. value: function _reset() {
  6364. // Don't do anything if there are no slides (first run)
  6365. if (typeof this.$slides == 'undefined') {
  6366. return;
  6367. }
  6368. if (this.$slides.length > 1) {
  6369. // Remove old events
  6370. this.$element.off('.zf.orbit').find('*').off('.zf.orbit'); // Restart timer if autoPlay is enabled
  6371. if (this.options.autoPlay) {
  6372. this.timer.restart();
  6373. } // Reset all sliddes
  6374. this.$slides.each(function (el) {
  6375. $(el).removeClass('is-active is-active is-in').removeAttr('aria-live').hide();
  6376. }); // Show the first slide
  6377. this.$slides.first().addClass('is-active').show(); // Triggers when the slide has finished animating
  6378. this.$element.trigger('slidechange.zf.orbit', [this.$slides.first()]); // Select first bullet if bullets are present
  6379. if (this.options.bullets) {
  6380. this._updateBullets(0);
  6381. }
  6382. }
  6383. }
  6384. /**
  6385. * Changes the current slide to a new one.
  6386. * @function
  6387. * @param {Boolean} isLTR - if true the slide moves from right to left, if false the slide moves from left to right.
  6388. * @param {jQuery} chosenSlide - the jQuery element of the slide to show next, if one is selected.
  6389. * @param {Number} idx - the index of the new slide in its collection, if one chosen.
  6390. * @fires Orbit#slidechange
  6391. */
  6392. }, {
  6393. key: "changeSlide",
  6394. value: function changeSlide(isLTR, chosenSlide, idx) {
  6395. if (!this.$slides) {
  6396. return;
  6397. } // Don't freak out if we're in the middle of cleanup
  6398. var $curSlide = this.$slides.filter('.is-active').eq(0);
  6399. if (/mui/g.test($curSlide[0].className)) {
  6400. return false;
  6401. } //if the slide is currently animating, kick out of the function
  6402. var $firstSlide = this.$slides.first(),
  6403. $lastSlide = this.$slides.last(),
  6404. dirIn = isLTR ? 'Right' : 'Left',
  6405. dirOut = isLTR ? 'Left' : 'Right',
  6406. _this = this,
  6407. $newSlide;
  6408. if (!chosenSlide) {
  6409. //most of the time, this will be auto played or clicked from the navButtons.
  6410. $newSlide = isLTR ? //if wrapping enabled, check to see if there is a `next` or `prev` sibling, if not, select the first or last slide to fill in. if wrapping not enabled, attempt to select `next` or `prev`, if there's nothing there, the function will kick out on next step. CRAZY NESTED TERNARIES!!!!!
  6411. this.options.infiniteWrap ? $curSlide.next(".".concat(this.options.slideClass)).length ? $curSlide.next(".".concat(this.options.slideClass)) : $firstSlide : $curSlide.next(".".concat(this.options.slideClass)) : //pick next slide if moving left to right
  6412. this.options.infiniteWrap ? $curSlide.prev(".".concat(this.options.slideClass)).length ? $curSlide.prev(".".concat(this.options.slideClass)) : $lastSlide : $curSlide.prev(".".concat(this.options.slideClass)); //pick prev slide if moving right to left
  6413. } else {
  6414. $newSlide = chosenSlide;
  6415. }
  6416. if ($newSlide.length) {
  6417. /**
  6418. * Triggers before the next slide starts animating in and only if a next slide has been found.
  6419. * @event Orbit#beforeslidechange
  6420. */
  6421. this.$element.trigger('beforeslidechange.zf.orbit', [$curSlide, $newSlide]);
  6422. if (this.options.bullets) {
  6423. idx = idx || this.$slides.index($newSlide); //grab index to update bullets
  6424. this._updateBullets(idx);
  6425. }
  6426. if (this.options.useMUI && !this.$element.is(':hidden')) {
  6427. Motion.animateIn($newSlide.addClass('is-active'), this.options["animInFrom".concat(dirIn)], function () {
  6428. $newSlide.css({
  6429. 'display': 'block'
  6430. }).attr('aria-live', 'polite');
  6431. });
  6432. Motion.animateOut($curSlide.removeClass('is-active'), this.options["animOutTo".concat(dirOut)], function () {
  6433. $curSlide.removeAttr('aria-live');
  6434. if (_this.options.autoPlay && !_this.timer.isPaused) {
  6435. _this.timer.restart();
  6436. } //do stuff?
  6437. });
  6438. } else {
  6439. $curSlide.removeClass('is-active is-in').removeAttr('aria-live').hide();
  6440. $newSlide.addClass('is-active is-in').attr('aria-live', 'polite').show();
  6441. if (this.options.autoPlay && !this.timer.isPaused) {
  6442. this.timer.restart();
  6443. }
  6444. }
  6445. /**
  6446. * Triggers when the slide has finished animating in.
  6447. * @event Orbit#slidechange
  6448. */
  6449. this.$element.trigger('slidechange.zf.orbit', [$newSlide]);
  6450. }
  6451. }
  6452. /**
  6453. * Updates the active state of the bullets, if displayed.
  6454. * @function
  6455. * @private
  6456. * @param {Number} idx - the index of the current slide.
  6457. */
  6458. }, {
  6459. key: "_updateBullets",
  6460. value: function _updateBullets(idx) {
  6461. var $oldBullet = this.$element.find(".".concat(this.options.boxOfBullets)).find('.is-active').removeClass('is-active').blur(),
  6462. span = $oldBullet.find('span:last').detach(),
  6463. $newBullet = this.$bullets.eq(idx).addClass('is-active').append(span);
  6464. }
  6465. /**
  6466. * Destroys the carousel and hides the element.
  6467. * @function
  6468. */
  6469. }, {
  6470. key: "_destroy",
  6471. value: function _destroy() {
  6472. this.$element.off('.zf.orbit').find('*').off('.zf.orbit').end().hide();
  6473. }
  6474. }]);
  6475. return Orbit;
  6476. }(Plugin);
  6477. Orbit.defaults = {
  6478. /**
  6479. * Tells the JS to look for and loadBullets.
  6480. * @option
  6481. * @type {boolean}
  6482. * @default true
  6483. */
  6484. bullets: true,
  6485. /**
  6486. * Tells the JS to apply event listeners to nav buttons
  6487. * @option
  6488. * @type {boolean}
  6489. * @default true
  6490. */
  6491. navButtons: true,
  6492. /**
  6493. * motion-ui animation class to apply
  6494. * @option
  6495. * @type {string}
  6496. * @default 'slide-in-right'
  6497. */
  6498. animInFromRight: 'slide-in-right',
  6499. /**
  6500. * motion-ui animation class to apply
  6501. * @option
  6502. * @type {string}
  6503. * @default 'slide-out-right'
  6504. */
  6505. animOutToRight: 'slide-out-right',
  6506. /**
  6507. * motion-ui animation class to apply
  6508. * @option
  6509. * @type {string}
  6510. * @default 'slide-in-left'
  6511. *
  6512. */
  6513. animInFromLeft: 'slide-in-left',
  6514. /**
  6515. * motion-ui animation class to apply
  6516. * @option
  6517. * @type {string}
  6518. * @default 'slide-out-left'
  6519. */
  6520. animOutToLeft: 'slide-out-left',
  6521. /**
  6522. * Allows Orbit to automatically animate on page load.
  6523. * @option
  6524. * @type {boolean}
  6525. * @default true
  6526. */
  6527. autoPlay: true,
  6528. /**
  6529. * Amount of time, in ms, between slide transitions
  6530. * @option
  6531. * @type {number}
  6532. * @default 5000
  6533. */
  6534. timerDelay: 5000,
  6535. /**
  6536. * Allows Orbit to infinitely loop through the slides
  6537. * @option
  6538. * @type {boolean}
  6539. * @default true
  6540. */
  6541. infiniteWrap: true,
  6542. /**
  6543. * Allows the Orbit slides to bind to swipe events for mobile, requires an additional util library
  6544. * @option
  6545. * @type {boolean}
  6546. * @default true
  6547. */
  6548. swipe: true,
  6549. /**
  6550. * Allows the timing function to pause animation on hover.
  6551. * @option
  6552. * @type {boolean}
  6553. * @default true
  6554. */
  6555. pauseOnHover: true,
  6556. /**
  6557. * Allows Orbit to bind keyboard events to the slider, to animate frames with arrow keys
  6558. * @option
  6559. * @type {boolean}
  6560. * @default true
  6561. */
  6562. accessible: true,
  6563. /**
  6564. * Class applied to the container of Orbit
  6565. * @option
  6566. * @type {string}
  6567. * @default 'orbit-container'
  6568. */
  6569. containerClass: 'orbit-container',
  6570. /**
  6571. * Class applied to individual slides.
  6572. * @option
  6573. * @type {string}
  6574. * @default 'orbit-slide'
  6575. */
  6576. slideClass: 'orbit-slide',
  6577. /**
  6578. * Class applied to the bullet container. You're welcome.
  6579. * @option
  6580. * @type {string}
  6581. * @default 'orbit-bullets'
  6582. */
  6583. boxOfBullets: 'orbit-bullets',
  6584. /**
  6585. * Class applied to the `next` navigation button.
  6586. * @option
  6587. * @type {string}
  6588. * @default 'orbit-next'
  6589. */
  6590. nextClass: 'orbit-next',
  6591. /**
  6592. * Class applied to the `previous` navigation button.
  6593. * @option
  6594. * @type {string}
  6595. * @default 'orbit-previous'
  6596. */
  6597. prevClass: 'orbit-previous',
  6598. /**
  6599. * Boolean to flag the js to use motion ui classes or not. Default to true for backwards compatibility.
  6600. * @option
  6601. * @type {boolean}
  6602. * @default true
  6603. */
  6604. useMUI: true
  6605. };
  6606. var MenuPlugins = {
  6607. dropdown: {
  6608. cssClass: 'dropdown',
  6609. plugin: DropdownMenu
  6610. },
  6611. drilldown: {
  6612. cssClass: 'drilldown',
  6613. plugin: Drilldown
  6614. },
  6615. accordion: {
  6616. cssClass: 'accordion-menu',
  6617. plugin: AccordionMenu
  6618. }
  6619. }; // import "foundation.util.triggers.js";
  6620. /**
  6621. * ResponsiveMenu module.
  6622. * @module foundation.responsiveMenu
  6623. * @requires foundation.util.triggers
  6624. * @requires foundation.util.mediaQuery
  6625. */
  6626. var ResponsiveMenu =
  6627. /*#__PURE__*/
  6628. function (_Plugin) {
  6629. _inherits(ResponsiveMenu, _Plugin);
  6630. function ResponsiveMenu() {
  6631. _classCallCheck(this, ResponsiveMenu);
  6632. return _possibleConstructorReturn(this, _getPrototypeOf(ResponsiveMenu).apply(this, arguments));
  6633. }
  6634. _createClass(ResponsiveMenu, [{
  6635. key: "_setup",
  6636. /**
  6637. * Creates a new instance of a responsive menu.
  6638. * @class
  6639. * @name ResponsiveMenu
  6640. * @fires ResponsiveMenu#init
  6641. * @param {jQuery} element - jQuery object to make into a dropdown menu.
  6642. * @param {Object} options - Overrides to the default plugin settings.
  6643. */
  6644. value: function _setup(element, options) {
  6645. this.$element = $(element);
  6646. this.rules = this.$element.data('responsive-menu');
  6647. this.currentMq = null;
  6648. this.currentPlugin = null;
  6649. this.className = 'ResponsiveMenu'; // ie9 back compat
  6650. this._init();
  6651. this._events();
  6652. }
  6653. /**
  6654. * Initializes the Menu by parsing the classes from the 'data-ResponsiveMenu' attribute on the element.
  6655. * @function
  6656. * @private
  6657. */
  6658. }, {
  6659. key: "_init",
  6660. value: function _init() {
  6661. MediaQuery._init(); // The first time an Interchange plugin is initialized, this.rules is converted from a string of "classes" to an object of rules
  6662. if (typeof this.rules === 'string') {
  6663. var rulesTree = {}; // Parse rules from "classes" pulled from data attribute
  6664. var rules = this.rules.split(' '); // Iterate through every rule found
  6665. for (var i = 0; i < rules.length; i++) {
  6666. var rule = rules[i].split('-');
  6667. var ruleSize = rule.length > 1 ? rule[0] : 'small';
  6668. var rulePlugin = rule.length > 1 ? rule[1] : rule[0];
  6669. if (MenuPlugins[rulePlugin] !== null) {
  6670. rulesTree[ruleSize] = MenuPlugins[rulePlugin];
  6671. }
  6672. }
  6673. this.rules = rulesTree;
  6674. }
  6675. if (!$.isEmptyObject(this.rules)) {
  6676. this._checkMediaQueries();
  6677. } // Add data-mutate since children may need it.
  6678. this.$element.attr('data-mutate', this.$element.attr('data-mutate') || GetYoDigits(6, 'responsive-menu'));
  6679. }
  6680. /**
  6681. * Initializes events for the Menu.
  6682. * @function
  6683. * @private
  6684. */
  6685. }, {
  6686. key: "_events",
  6687. value: function _events() {
  6688. var _this = this;
  6689. $(window).on('changed.zf.mediaquery', function () {
  6690. _this._checkMediaQueries();
  6691. }); // $(window).on('resize.zf.ResponsiveMenu', function() {
  6692. // _this._checkMediaQueries();
  6693. // });
  6694. }
  6695. /**
  6696. * Checks the current screen width against available media queries. If the media query has changed, and the plugin needed has changed, the plugins will swap out.
  6697. * @function
  6698. * @private
  6699. */
  6700. }, {
  6701. key: "_checkMediaQueries",
  6702. value: function _checkMediaQueries() {
  6703. var matchedMq,
  6704. _this = this; // Iterate through each rule and find the last matching rule
  6705. $.each(this.rules, function (key) {
  6706. if (MediaQuery.atLeast(key)) {
  6707. matchedMq = key;
  6708. }
  6709. }); // No match? No dice
  6710. if (!matchedMq) return; // Plugin already initialized? We good
  6711. if (this.currentPlugin instanceof this.rules[matchedMq].plugin) return; // Remove existing plugin-specific CSS classes
  6712. $.each(MenuPlugins, function (key, value) {
  6713. _this.$element.removeClass(value.cssClass);
  6714. }); // Add the CSS class for the new plugin
  6715. this.$element.addClass(this.rules[matchedMq].cssClass); // Create an instance of the new plugin
  6716. if (this.currentPlugin) this.currentPlugin.destroy();
  6717. this.currentPlugin = new this.rules[matchedMq].plugin(this.$element, {});
  6718. }
  6719. /**
  6720. * Destroys the instance of the current plugin on this element, as well as the window resize handler that switches the plugins out.
  6721. * @function
  6722. */
  6723. }, {
  6724. key: "_destroy",
  6725. value: function _destroy() {
  6726. this.currentPlugin.destroy();
  6727. $(window).off('.zf.ResponsiveMenu');
  6728. }
  6729. }]);
  6730. return ResponsiveMenu;
  6731. }(Plugin);
  6732. ResponsiveMenu.defaults = {};
  6733. /**
  6734. * ResponsiveToggle module.
  6735. * @module foundation.responsiveToggle
  6736. * @requires foundation.util.mediaQuery
  6737. * @requires foundation.util.motion
  6738. */
  6739. var ResponsiveToggle =
  6740. /*#__PURE__*/
  6741. function (_Plugin) {
  6742. _inherits(ResponsiveToggle, _Plugin);
  6743. function ResponsiveToggle() {
  6744. _classCallCheck(this, ResponsiveToggle);
  6745. return _possibleConstructorReturn(this, _getPrototypeOf(ResponsiveToggle).apply(this, arguments));
  6746. }
  6747. _createClass(ResponsiveToggle, [{
  6748. key: "_setup",
  6749. /**
  6750. * Creates a new instance of Tab Bar.
  6751. * @class
  6752. * @name ResponsiveToggle
  6753. * @fires ResponsiveToggle#init
  6754. * @param {jQuery} element - jQuery object to attach tab bar functionality to.
  6755. * @param {Object} options - Overrides to the default plugin settings.
  6756. */
  6757. value: function _setup(element, options) {
  6758. this.$element = $(element);
  6759. this.options = $.extend({}, ResponsiveToggle.defaults, this.$element.data(), options);
  6760. this.className = 'ResponsiveToggle'; // ie9 back compat
  6761. this._init();
  6762. this._events();
  6763. }
  6764. /**
  6765. * Initializes the tab bar by finding the target element, toggling element, and running update().
  6766. * @function
  6767. * @private
  6768. */
  6769. }, {
  6770. key: "_init",
  6771. value: function _init() {
  6772. MediaQuery._init();
  6773. var targetID = this.$element.data('responsive-toggle');
  6774. if (!targetID) {
  6775. console.error('Your tab bar needs an ID of a Menu as the value of data-tab-bar.');
  6776. }
  6777. this.$targetMenu = $("#".concat(targetID));
  6778. this.$toggler = this.$element.find('[data-toggle]').filter(function () {
  6779. var target = $(this).data('toggle');
  6780. return target === targetID || target === "";
  6781. });
  6782. this.options = $.extend({}, this.options, this.$targetMenu.data()); // If they were set, parse the animation classes
  6783. if (this.options.animate) {
  6784. var input = this.options.animate.split(' ');
  6785. this.animationIn = input[0];
  6786. this.animationOut = input[1] || null;
  6787. }
  6788. this._update();
  6789. }
  6790. /**
  6791. * Adds necessary event handlers for the tab bar to work.
  6792. * @function
  6793. * @private
  6794. */
  6795. }, {
  6796. key: "_events",
  6797. value: function _events() {
  6798. this._updateMqHandler = this._update.bind(this);
  6799. $(window).on('changed.zf.mediaquery', this._updateMqHandler);
  6800. this.$toggler.on('click.zf.responsiveToggle', this.toggleMenu.bind(this));
  6801. }
  6802. /**
  6803. * Checks the current media query to determine if the tab bar should be visible or hidden.
  6804. * @function
  6805. * @private
  6806. */
  6807. }, {
  6808. key: "_update",
  6809. value: function _update() {
  6810. // Mobile
  6811. if (!MediaQuery.atLeast(this.options.hideFor)) {
  6812. this.$element.show();
  6813. this.$targetMenu.hide();
  6814. } // Desktop
  6815. else {
  6816. this.$element.hide();
  6817. this.$targetMenu.show();
  6818. }
  6819. }
  6820. /**
  6821. * Toggles the element attached to the tab bar. The toggle only happens if the screen is small enough to allow it.
  6822. * @function
  6823. * @fires ResponsiveToggle#toggled
  6824. */
  6825. }, {
  6826. key: "toggleMenu",
  6827. value: function toggleMenu() {
  6828. var _this2 = this;
  6829. if (!MediaQuery.atLeast(this.options.hideFor)) {
  6830. /**
  6831. * Fires when the element attached to the tab bar toggles.
  6832. * @event ResponsiveToggle#toggled
  6833. */
  6834. if (this.options.animate) {
  6835. if (this.$targetMenu.is(':hidden')) {
  6836. Motion.animateIn(this.$targetMenu, this.animationIn, function () {
  6837. _this2.$element.trigger('toggled.zf.responsiveToggle');
  6838. _this2.$targetMenu.find('[data-mutate]').triggerHandler('mutateme.zf.trigger');
  6839. });
  6840. } else {
  6841. Motion.animateOut(this.$targetMenu, this.animationOut, function () {
  6842. _this2.$element.trigger('toggled.zf.responsiveToggle');
  6843. });
  6844. }
  6845. } else {
  6846. this.$targetMenu.toggle(0);
  6847. this.$targetMenu.find('[data-mutate]').trigger('mutateme.zf.trigger');
  6848. this.$element.trigger('toggled.zf.responsiveToggle');
  6849. }
  6850. }
  6851. }
  6852. }, {
  6853. key: "_destroy",
  6854. value: function _destroy() {
  6855. this.$element.off('.zf.responsiveToggle');
  6856. this.$toggler.off('.zf.responsiveToggle');
  6857. $(window).off('changed.zf.mediaquery', this._updateMqHandler);
  6858. }
  6859. }]);
  6860. return ResponsiveToggle;
  6861. }(Plugin);
  6862. ResponsiveToggle.defaults = {
  6863. /**
  6864. * The breakpoint after which the menu is always shown, and the tab bar is hidden.
  6865. * @option
  6866. * @type {string}
  6867. * @default 'medium'
  6868. */
  6869. hideFor: 'medium',
  6870. /**
  6871. * To decide if the toggle should be animated or not.
  6872. * @option
  6873. * @type {boolean}
  6874. * @default false
  6875. */
  6876. animate: false
  6877. };
  6878. /**
  6879. * Reveal module.
  6880. * @module foundation.reveal
  6881. * @requires foundation.util.keyboard
  6882. * @requires foundation.util.triggers
  6883. * @requires foundation.util.mediaQuery
  6884. * @requires foundation.util.motion if using animations
  6885. */
  6886. var Reveal =
  6887. /*#__PURE__*/
  6888. function (_Plugin) {
  6889. _inherits(Reveal, _Plugin);
  6890. function Reveal() {
  6891. _classCallCheck(this, Reveal);
  6892. return _possibleConstructorReturn(this, _getPrototypeOf(Reveal).apply(this, arguments));
  6893. }
  6894. _createClass(Reveal, [{
  6895. key: "_setup",
  6896. /**
  6897. * Creates a new instance of Reveal.
  6898. * @class
  6899. * @name Reveal
  6900. * @param {jQuery} element - jQuery object to use for the modal.
  6901. * @param {Object} options - optional parameters.
  6902. */
  6903. value: function _setup(element, options) {
  6904. this.$element = element;
  6905. this.options = $.extend({}, Reveal.defaults, this.$element.data(), options);
  6906. this.className = 'Reveal'; // ie9 back compat
  6907. this._init(); // Triggers init is idempotent, just need to make sure it is initialized
  6908. Triggers.init($);
  6909. Keyboard.register('Reveal', {
  6910. 'ESCAPE': 'close'
  6911. });
  6912. }
  6913. /**
  6914. * Initializes the modal by adding the overlay and close buttons, (if selected).
  6915. * @private
  6916. */
  6917. }, {
  6918. key: "_init",
  6919. value: function _init() {
  6920. var _this2 = this;
  6921. MediaQuery._init();
  6922. this.id = this.$element.attr('id');
  6923. this.isActive = false;
  6924. this.cached = {
  6925. mq: MediaQuery.current
  6926. };
  6927. this.$anchor = $("[data-open=\"".concat(this.id, "\"]")).length ? $("[data-open=\"".concat(this.id, "\"]")) : $("[data-toggle=\"".concat(this.id, "\"]"));
  6928. this.$anchor.attr({
  6929. 'aria-controls': this.id,
  6930. 'aria-haspopup': true,
  6931. 'tabindex': 0
  6932. });
  6933. if (this.options.fullScreen || this.$element.hasClass('full')) {
  6934. this.options.fullScreen = true;
  6935. this.options.overlay = false;
  6936. }
  6937. if (this.options.overlay && !this.$overlay) {
  6938. this.$overlay = this._makeOverlay(this.id);
  6939. }
  6940. this.$element.attr({
  6941. 'role': 'dialog',
  6942. 'aria-hidden': true,
  6943. 'data-yeti-box': this.id,
  6944. 'data-resize': this.id
  6945. });
  6946. if (this.$overlay) {
  6947. this.$element.detach().appendTo(this.$overlay);
  6948. } else {
  6949. this.$element.detach().appendTo($(this.options.appendTo));
  6950. this.$element.addClass('without-overlay');
  6951. }
  6952. this._events();
  6953. if (this.options.deepLink && window.location.hash === "#".concat(this.id)) {
  6954. this.onLoadListener = onLoad($(window), function () {
  6955. return _this2.open();
  6956. });
  6957. }
  6958. }
  6959. /**
  6960. * Creates an overlay div to display behind the modal.
  6961. * @private
  6962. */
  6963. }, {
  6964. key: "_makeOverlay",
  6965. value: function _makeOverlay() {
  6966. var additionalOverlayClasses = '';
  6967. if (this.options.additionalOverlayClasses) {
  6968. additionalOverlayClasses = ' ' + this.options.additionalOverlayClasses;
  6969. }
  6970. return $('<div></div>').addClass('reveal-overlay' + additionalOverlayClasses).appendTo(this.options.appendTo);
  6971. }
  6972. /**
  6973. * Updates position of modal
  6974. * TODO: Figure out if we actually need to cache these values or if it doesn't matter
  6975. * @private
  6976. */
  6977. }, {
  6978. key: "_updatePosition",
  6979. value: function _updatePosition() {
  6980. var width = this.$element.outerWidth();
  6981. var outerWidth = $(window).width();
  6982. var height = this.$element.outerHeight();
  6983. var outerHeight = $(window).height();
  6984. var left,
  6985. top = null;
  6986. if (this.options.hOffset === 'auto') {
  6987. left = parseInt((outerWidth - width) / 2, 10);
  6988. } else {
  6989. left = parseInt(this.options.hOffset, 10);
  6990. }
  6991. if (this.options.vOffset === 'auto') {
  6992. if (height > outerHeight) {
  6993. top = parseInt(Math.min(100, outerHeight / 10), 10);
  6994. } else {
  6995. top = parseInt((outerHeight - height) / 4, 10);
  6996. }
  6997. } else if (this.options.vOffset !== null) {
  6998. top = parseInt(this.options.vOffset, 10);
  6999. }
  7000. if (top !== null) {
  7001. this.$element.css({
  7002. top: top + 'px'
  7003. });
  7004. } // only worry about left if we don't have an overlay or we have a horizontal offset,
  7005. // otherwise we're perfectly in the middle
  7006. if (!this.$overlay || this.options.hOffset !== 'auto') {
  7007. this.$element.css({
  7008. left: left + 'px'
  7009. });
  7010. this.$element.css({
  7011. margin: '0px'
  7012. });
  7013. }
  7014. }
  7015. /**
  7016. * Adds event handlers for the modal.
  7017. * @private
  7018. */
  7019. }, {
  7020. key: "_events",
  7021. value: function _events() {
  7022. var _this3 = this;
  7023. var _this = this;
  7024. this.$element.on({
  7025. 'open.zf.trigger': this.open.bind(this),
  7026. 'close.zf.trigger': function closeZfTrigger(event, $element) {
  7027. if (event.target === _this.$element[0] || $(event.target).parents('[data-closable]')[0] === $element) {
  7028. // only close reveal when it's explicitly called
  7029. return _this3.close.apply(_this3);
  7030. }
  7031. },
  7032. 'toggle.zf.trigger': this.toggle.bind(this),
  7033. 'resizeme.zf.trigger': function resizemeZfTrigger() {
  7034. _this._updatePosition();
  7035. }
  7036. });
  7037. if (this.options.closeOnClick && this.options.overlay) {
  7038. this.$overlay.off('.zf.reveal').on('click.zf.reveal', function (e) {
  7039. if (e.target === _this.$element[0] || $.contains(_this.$element[0], e.target) || !$.contains(document, e.target)) {
  7040. return;
  7041. }
  7042. _this.close();
  7043. });
  7044. }
  7045. if (this.options.deepLink) {
  7046. $(window).on("hashchange.zf.reveal:".concat(this.id), this._handleState.bind(this));
  7047. }
  7048. }
  7049. /**
  7050. * Handles modal methods on back/forward button clicks or any other event that triggers hashchange.
  7051. * @private
  7052. */
  7053. }, {
  7054. key: "_handleState",
  7055. value: function _handleState(e) {
  7056. if (window.location.hash === '#' + this.id && !this.isActive) {
  7057. this.open();
  7058. } else {
  7059. this.close();
  7060. }
  7061. }
  7062. /**
  7063. * Disables the scroll when Reveal is shown to prevent the background from shifting
  7064. * @param {number} scrollTop - Scroll to visually apply, window current scroll by default
  7065. */
  7066. }, {
  7067. key: "_disableScroll",
  7068. value: function _disableScroll(scrollTop) {
  7069. scrollTop = scrollTop || $(window).scrollTop();
  7070. if ($(document).height() > $(window).height()) {
  7071. $("html").css("top", -scrollTop);
  7072. }
  7073. }
  7074. /**
  7075. * Reenables the scroll when Reveal closes
  7076. * @param {number} scrollTop - Scroll to restore, html "top" property by default (as set by `_disableScroll`)
  7077. */
  7078. }, {
  7079. key: "_enableScroll",
  7080. value: function _enableScroll(scrollTop) {
  7081. scrollTop = scrollTop || parseInt($("html").css("top"));
  7082. if ($(document).height() > $(window).height()) {
  7083. $("html").css("top", "");
  7084. $(window).scrollTop(-scrollTop);
  7085. }
  7086. }
  7087. /**
  7088. * Opens the modal controlled by `this.$anchor`, and closes all others by default.
  7089. * @function
  7090. * @fires Reveal#closeme
  7091. * @fires Reveal#open
  7092. */
  7093. }, {
  7094. key: "open",
  7095. value: function open() {
  7096. var _this4 = this;
  7097. // either update or replace browser history
  7098. var hash = "#".concat(this.id);
  7099. if (this.options.deepLink && window.location.hash !== hash) {
  7100. if (window.history.pushState) {
  7101. if (this.options.updateHistory) {
  7102. window.history.pushState({}, '', hash);
  7103. } else {
  7104. window.history.replaceState({}, '', hash);
  7105. }
  7106. } else {
  7107. window.location.hash = hash;
  7108. }
  7109. } // Remember anchor that opened it to set focus back later, have general anchors as fallback
  7110. this.$activeAnchor = $(document.activeElement).is(this.$anchor) ? $(document.activeElement) : this.$anchor;
  7111. this.isActive = true; // Make elements invisible, but remove display: none so we can get size and positioning
  7112. this.$element.css({
  7113. 'visibility': 'hidden'
  7114. }).show().scrollTop(0);
  7115. if (this.options.overlay) {
  7116. this.$overlay.css({
  7117. 'visibility': 'hidden'
  7118. }).show();
  7119. }
  7120. this._updatePosition();
  7121. this.$element.hide().css({
  7122. 'visibility': ''
  7123. });
  7124. if (this.$overlay) {
  7125. this.$overlay.css({
  7126. 'visibility': ''
  7127. }).hide();
  7128. if (this.$element.hasClass('fast')) {
  7129. this.$overlay.addClass('fast');
  7130. } else if (this.$element.hasClass('slow')) {
  7131. this.$overlay.addClass('slow');
  7132. }
  7133. }
  7134. if (!this.options.multipleOpened) {
  7135. /**
  7136. * Fires immediately before the modal opens.
  7137. * Closes any other modals that are currently open
  7138. * @event Reveal#closeme
  7139. */
  7140. this.$element.trigger('closeme.zf.reveal', this.id);
  7141. }
  7142. this._disableScroll();
  7143. var _this = this; // Motion UI method of reveal
  7144. if (this.options.animationIn) {
  7145. var afterAnimation = function afterAnimation() {
  7146. _this.$element.attr({
  7147. 'aria-hidden': false,
  7148. 'tabindex': -1
  7149. }).focus();
  7150. _this._addGlobalClasses();
  7151. Keyboard.trapFocus(_this.$element);
  7152. };
  7153. if (this.options.overlay) {
  7154. Motion.animateIn(this.$overlay, 'fade-in');
  7155. }
  7156. Motion.animateIn(this.$element, this.options.animationIn, function () {
  7157. if (_this4.$element) {
  7158. // protect against object having been removed
  7159. _this4.focusableElements = Keyboard.findFocusable(_this4.$element);
  7160. afterAnimation();
  7161. }
  7162. });
  7163. } // jQuery method of reveal
  7164. else {
  7165. if (this.options.overlay) {
  7166. this.$overlay.show(0);
  7167. }
  7168. this.$element.show(this.options.showDelay);
  7169. } // handle accessibility
  7170. this.$element.attr({
  7171. 'aria-hidden': false,
  7172. 'tabindex': -1
  7173. }).focus();
  7174. Keyboard.trapFocus(this.$element);
  7175. this._addGlobalClasses();
  7176. this._addGlobalListeners();
  7177. /**
  7178. * Fires when the modal has successfully opened.
  7179. * @event Reveal#open
  7180. */
  7181. this.$element.trigger('open.zf.reveal');
  7182. }
  7183. /**
  7184. * Adds classes and listeners on document required by open modals.
  7185. *
  7186. * The following classes are added and updated:
  7187. * - `.is-reveal-open` - Prevents the scroll on document
  7188. * - `.zf-has-scroll` - Displays a disabled scrollbar on document if required like if the
  7189. * scroll was not disabled. This prevent a "shift" of the page content due
  7190. * the scrollbar disappearing when the modal opens.
  7191. *
  7192. * @private
  7193. */
  7194. }, {
  7195. key: "_addGlobalClasses",
  7196. value: function _addGlobalClasses() {
  7197. var updateScrollbarClass = function updateScrollbarClass() {
  7198. $('html').toggleClass('zf-has-scroll', !!($(document).height() > $(window).height()));
  7199. };
  7200. this.$element.on('resizeme.zf.trigger.revealScrollbarListener', function () {
  7201. return updateScrollbarClass();
  7202. });
  7203. updateScrollbarClass();
  7204. $('html').addClass('is-reveal-open');
  7205. }
  7206. /**
  7207. * Removes classes and listeners on document that were required by open modals.
  7208. * @private
  7209. */
  7210. }, {
  7211. key: "_removeGlobalClasses",
  7212. value: function _removeGlobalClasses() {
  7213. this.$element.off('resizeme.zf.trigger.revealScrollbarListener');
  7214. $('html').removeClass('is-reveal-open');
  7215. $('html').removeClass('zf-has-scroll');
  7216. }
  7217. /**
  7218. * Adds extra event handlers for the body and window if necessary.
  7219. * @private
  7220. */
  7221. }, {
  7222. key: "_addGlobalListeners",
  7223. value: function _addGlobalListeners() {
  7224. var _this = this;
  7225. if (!this.$element) {
  7226. return;
  7227. } // If we're in the middle of cleanup, don't freak out
  7228. this.focusableElements = Keyboard.findFocusable(this.$element);
  7229. if (!this.options.overlay && this.options.closeOnClick && !this.options.fullScreen) {
  7230. $('body').on('click.zf.reveal', function (e) {
  7231. if (e.target === _this.$element[0] || $.contains(_this.$element[0], e.target) || !$.contains(document, e.target)) {
  7232. return;
  7233. }
  7234. _this.close();
  7235. });
  7236. }
  7237. if (this.options.closeOnEsc) {
  7238. $(window).on('keydown.zf.reveal', function (e) {
  7239. Keyboard.handleKey(e, 'Reveal', {
  7240. close: function close() {
  7241. if (_this.options.closeOnEsc) {
  7242. _this.close();
  7243. }
  7244. }
  7245. });
  7246. });
  7247. }
  7248. }
  7249. /**
  7250. * Closes the modal.
  7251. * @function
  7252. * @fires Reveal#closed
  7253. */
  7254. }, {
  7255. key: "close",
  7256. value: function close() {
  7257. if (!this.isActive || !this.$element.is(':visible')) {
  7258. return false;
  7259. }
  7260. var _this = this; // Motion UI method of hiding
  7261. if (this.options.animationOut) {
  7262. if (this.options.overlay) {
  7263. Motion.animateOut(this.$overlay, 'fade-out');
  7264. }
  7265. Motion.animateOut(this.$element, this.options.animationOut, finishUp);
  7266. } // jQuery method of hiding
  7267. else {
  7268. this.$element.hide(this.options.hideDelay);
  7269. if (this.options.overlay) {
  7270. this.$overlay.hide(0, finishUp);
  7271. } else {
  7272. finishUp();
  7273. }
  7274. } // Conditionals to remove extra event listeners added on open
  7275. if (this.options.closeOnEsc) {
  7276. $(window).off('keydown.zf.reveal');
  7277. }
  7278. if (!this.options.overlay && this.options.closeOnClick) {
  7279. $('body').off('click.zf.reveal');
  7280. }
  7281. this.$element.off('keydown.zf.reveal');
  7282. function finishUp() {
  7283. // Get the current top before the modal is closed and restore the scroll after.
  7284. // TODO: use component properties instead of HTML properties
  7285. // See https://github.com/zurb/foundation-sites/pull/10786
  7286. var scrollTop = parseInt($("html").css("top"));
  7287. if ($('.reveal:visible').length === 0) {
  7288. _this._removeGlobalClasses(); // also remove .is-reveal-open from the html element when there is no opened reveal
  7289. }
  7290. Keyboard.releaseFocus(_this.$element);
  7291. _this.$element.attr('aria-hidden', true);
  7292. _this._enableScroll(scrollTop);
  7293. /**
  7294. * Fires when the modal is done closing.
  7295. * @event Reveal#closed
  7296. */
  7297. _this.$element.trigger('closed.zf.reveal');
  7298. }
  7299. /**
  7300. * Resets the modal content
  7301. * This prevents a running video to keep going in the background
  7302. */
  7303. if (this.options.resetOnClose) {
  7304. this.$element.html(this.$element.html());
  7305. }
  7306. this.isActive = false; // If deepLink and we did not switched to an other modal...
  7307. if (_this.options.deepLink && window.location.hash === "#".concat(this.id)) {
  7308. // Remove the history hash
  7309. if (window.history.replaceState) {
  7310. var urlWithoutHash = window.location.pathname + window.location.search;
  7311. if (this.options.updateHistory) {
  7312. window.history.pushState({}, '', urlWithoutHash); // remove the hash
  7313. } else {
  7314. window.history.replaceState('', document.title, urlWithoutHash);
  7315. }
  7316. } else {
  7317. window.location.hash = '';
  7318. }
  7319. }
  7320. this.$activeAnchor.focus();
  7321. }
  7322. /**
  7323. * Toggles the open/closed state of a modal.
  7324. * @function
  7325. */
  7326. }, {
  7327. key: "toggle",
  7328. value: function toggle() {
  7329. if (this.isActive) {
  7330. this.close();
  7331. } else {
  7332. this.open();
  7333. }
  7334. }
  7335. }, {
  7336. key: "_destroy",
  7337. /**
  7338. * Destroys an instance of a modal.
  7339. * @function
  7340. */
  7341. value: function _destroy() {
  7342. if (this.options.overlay) {
  7343. this.$element.appendTo($(this.options.appendTo)); // move $element outside of $overlay to prevent error unregisterPlugin()
  7344. this.$overlay.hide().off().remove();
  7345. }
  7346. this.$element.hide().off();
  7347. this.$anchor.off('.zf');
  7348. $(window).off(".zf.reveal:".concat(this.id));
  7349. if (this.onLoadListener) $(window).off(this.onLoadListener);
  7350. if ($('.reveal:visible').length === 0) {
  7351. this._removeGlobalClasses(); // also remove .is-reveal-open from the html element when there is no opened reveal
  7352. }
  7353. }
  7354. }]);
  7355. return Reveal;
  7356. }(Plugin);
  7357. Reveal.defaults = {
  7358. /**
  7359. * Motion-UI class to use for animated elements. If none used, defaults to simple show/hide.
  7360. * @option
  7361. * @type {string}
  7362. * @default ''
  7363. */
  7364. animationIn: '',
  7365. /**
  7366. * Motion-UI class to use for animated elements. If none used, defaults to simple show/hide.
  7367. * @option
  7368. * @type {string}
  7369. * @default ''
  7370. */
  7371. animationOut: '',
  7372. /**
  7373. * Time, in ms, to delay the opening of a modal after a click if no animation used.
  7374. * @option
  7375. * @type {number}
  7376. * @default 0
  7377. */
  7378. showDelay: 0,
  7379. /**
  7380. * Time, in ms, to delay the closing of a modal after a click if no animation used.
  7381. * @option
  7382. * @type {number}
  7383. * @default 0
  7384. */
  7385. hideDelay: 0,
  7386. /**
  7387. * Allows a click on the body/overlay to close the modal.
  7388. * @option
  7389. * @type {boolean}
  7390. * @default true
  7391. */
  7392. closeOnClick: true,
  7393. /**
  7394. * Allows the modal to close if the user presses the `ESCAPE` key.
  7395. * @option
  7396. * @type {boolean}
  7397. * @default true
  7398. */
  7399. closeOnEsc: true,
  7400. /**
  7401. * If true, allows multiple modals to be displayed at once.
  7402. * @option
  7403. * @type {boolean}
  7404. * @default false
  7405. */
  7406. multipleOpened: false,
  7407. /**
  7408. * Distance, in pixels, the modal should push down from the top of the screen.
  7409. * @option
  7410. * @type {number|string}
  7411. * @default auto
  7412. */
  7413. vOffset: 'auto',
  7414. /**
  7415. * Distance, in pixels, the modal should push in from the side of the screen.
  7416. * @option
  7417. * @type {number|string}
  7418. * @default auto
  7419. */
  7420. hOffset: 'auto',
  7421. /**
  7422. * Allows the modal to be fullscreen, completely blocking out the rest of the view. JS checks for this as well.
  7423. * @option
  7424. * @type {boolean}
  7425. * @default false
  7426. */
  7427. fullScreen: false,
  7428. /**
  7429. * Allows the modal to generate an overlay div, which will cover the view when modal opens.
  7430. * @option
  7431. * @type {boolean}
  7432. * @default true
  7433. */
  7434. overlay: true,
  7435. /**
  7436. * Allows the modal to remove and reinject markup on close. Should be true if using video elements w/o using provider's api, otherwise, videos will continue to play in the background.
  7437. * @option
  7438. * @type {boolean}
  7439. * @default false
  7440. */
  7441. resetOnClose: false,
  7442. /**
  7443. * Link the location hash to the modal.
  7444. * Set the location hash when the modal is opened/closed, and open/close the modal when the location changes.
  7445. * @option
  7446. * @type {boolean}
  7447. * @default false
  7448. */
  7449. deepLink: false,
  7450. /**
  7451. * If `deepLink` is enabled, update the browser history with the open modal
  7452. * @option
  7453. * @default false
  7454. */
  7455. updateHistory: false,
  7456. /**
  7457. * Allows the modal to append to custom div.
  7458. * @option
  7459. * @type {string}
  7460. * @default "body"
  7461. */
  7462. appendTo: "body",
  7463. /**
  7464. * Allows adding additional class names to the reveal overlay.
  7465. * @option
  7466. * @type {string}
  7467. * @default ''
  7468. */
  7469. additionalOverlayClasses: ''
  7470. };
  7471. /**
  7472. * Slider module.
  7473. * @module foundation.slider
  7474. * @requires foundation.util.motion
  7475. * @requires foundation.util.triggers
  7476. * @requires foundation.util.keyboard
  7477. * @requires foundation.util.touch
  7478. */
  7479. var Slider =
  7480. /*#__PURE__*/
  7481. function (_Plugin) {
  7482. _inherits(Slider, _Plugin);
  7483. function Slider() {
  7484. _classCallCheck(this, Slider);
  7485. return _possibleConstructorReturn(this, _getPrototypeOf(Slider).apply(this, arguments));
  7486. }
  7487. _createClass(Slider, [{
  7488. key: "_setup",
  7489. /**
  7490. * Creates a new instance of a slider control.
  7491. * @class
  7492. * @name Slider
  7493. * @param {jQuery} element - jQuery object to make into a slider control.
  7494. * @param {Object} options - Overrides to the default plugin settings.
  7495. */
  7496. value: function _setup(element, options) {
  7497. this.$element = element;
  7498. this.options = $.extend({}, Slider.defaults, this.$element.data(), options);
  7499. this.className = 'Slider'; // ie9 back compat
  7500. // Touch and Triggers inits are idempotent, we just need to make sure it's initialied.
  7501. Touch.init($);
  7502. Triggers.init($);
  7503. this._init();
  7504. Keyboard.register('Slider', {
  7505. 'ltr': {
  7506. 'ARROW_RIGHT': 'increase',
  7507. 'ARROW_UP': 'increase',
  7508. 'ARROW_DOWN': 'decrease',
  7509. 'ARROW_LEFT': 'decrease',
  7510. 'SHIFT_ARROW_RIGHT': 'increase_fast',
  7511. 'SHIFT_ARROW_UP': 'increase_fast',
  7512. 'SHIFT_ARROW_DOWN': 'decrease_fast',
  7513. 'SHIFT_ARROW_LEFT': 'decrease_fast',
  7514. 'HOME': 'min',
  7515. 'END': 'max'
  7516. },
  7517. 'rtl': {
  7518. 'ARROW_LEFT': 'increase',
  7519. 'ARROW_RIGHT': 'decrease',
  7520. 'SHIFT_ARROW_LEFT': 'increase_fast',
  7521. 'SHIFT_ARROW_RIGHT': 'decrease_fast'
  7522. }
  7523. });
  7524. }
  7525. /**
  7526. * Initilizes the plugin by reading/setting attributes, creating collections and setting the initial position of the handle(s).
  7527. * @function
  7528. * @private
  7529. */
  7530. }, {
  7531. key: "_init",
  7532. value: function _init() {
  7533. this.inputs = this.$element.find('input');
  7534. this.handles = this.$element.find('[data-slider-handle]');
  7535. this.$handle = this.handles.eq(0);
  7536. this.$input = this.inputs.length ? this.inputs.eq(0) : $("#".concat(this.$handle.attr('aria-controls')));
  7537. this.$fill = this.$element.find('[data-slider-fill]').css(this.options.vertical ? 'height' : 'width', 0);
  7538. if (this.options.disabled || this.$element.hasClass(this.options.disabledClass)) {
  7539. this.options.disabled = true;
  7540. this.$element.addClass(this.options.disabledClass);
  7541. }
  7542. if (!this.inputs.length) {
  7543. this.inputs = $().add(this.$input);
  7544. this.options.binding = true;
  7545. }
  7546. this._setInitAttr(0);
  7547. if (this.handles[1]) {
  7548. this.options.doubleSided = true;
  7549. this.$handle2 = this.handles.eq(1);
  7550. this.$input2 = this.inputs.length > 1 ? this.inputs.eq(1) : $("#".concat(this.$handle2.attr('aria-controls')));
  7551. if (!this.inputs[1]) {
  7552. this.inputs = this.inputs.add(this.$input2);
  7553. }
  7554. this._setInitAttr(1);
  7555. } // Set handle positions
  7556. this.setHandles();
  7557. this._events();
  7558. }
  7559. }, {
  7560. key: "setHandles",
  7561. value: function setHandles() {
  7562. var _this2 = this;
  7563. if (this.handles[1]) {
  7564. this._setHandlePos(this.$handle, this.inputs.eq(0).val(), true, function () {
  7565. _this2._setHandlePos(_this2.$handle2, _this2.inputs.eq(1).val(), true);
  7566. });
  7567. } else {
  7568. this._setHandlePos(this.$handle, this.inputs.eq(0).val(), true);
  7569. }
  7570. }
  7571. }, {
  7572. key: "_reflow",
  7573. value: function _reflow() {
  7574. this.setHandles();
  7575. }
  7576. /**
  7577. * @function
  7578. * @private
  7579. * @param {Number} value - floating point (the value) to be transformed using to a relative position on the slider (the inverse of _value)
  7580. */
  7581. }, {
  7582. key: "_pctOfBar",
  7583. value: function _pctOfBar(value) {
  7584. var pctOfBar = percent(value - this.options.start, this.options.end - this.options.start);
  7585. switch (this.options.positionValueFunction) {
  7586. case "pow":
  7587. pctOfBar = this._logTransform(pctOfBar);
  7588. break;
  7589. case "log":
  7590. pctOfBar = this._powTransform(pctOfBar);
  7591. break;
  7592. }
  7593. return pctOfBar.toFixed(2);
  7594. }
  7595. /**
  7596. * @function
  7597. * @private
  7598. * @param {Number} pctOfBar - floating point, the relative position of the slider (typically between 0-1) to be transformed to a value
  7599. */
  7600. }, {
  7601. key: "_value",
  7602. value: function _value(pctOfBar) {
  7603. switch (this.options.positionValueFunction) {
  7604. case "pow":
  7605. pctOfBar = this._powTransform(pctOfBar);
  7606. break;
  7607. case "log":
  7608. pctOfBar = this._logTransform(pctOfBar);
  7609. break;
  7610. }
  7611. var value = (this.options.end - this.options.start) * pctOfBar + parseFloat(this.options.start);
  7612. return value;
  7613. }
  7614. /**
  7615. * @function
  7616. * @private
  7617. * @param {Number} value - floating point (typically between 0-1) to be transformed using the log function
  7618. */
  7619. }, {
  7620. key: "_logTransform",
  7621. value: function _logTransform(value) {
  7622. return baseLog(this.options.nonLinearBase, value * (this.options.nonLinearBase - 1) + 1);
  7623. }
  7624. /**
  7625. * @function
  7626. * @private
  7627. * @param {Number} value - floating point (typically between 0-1) to be transformed using the power function
  7628. */
  7629. }, {
  7630. key: "_powTransform",
  7631. value: function _powTransform(value) {
  7632. return (Math.pow(this.options.nonLinearBase, value) - 1) / (this.options.nonLinearBase - 1);
  7633. }
  7634. /**
  7635. * Sets the position of the selected handle and fill bar.
  7636. * @function
  7637. * @private
  7638. * @param {jQuery} $hndl - the selected handle to move.
  7639. * @param {Number} location - floating point between the start and end values of the slider bar.
  7640. * @param {Function} cb - callback function to fire on completion.
  7641. * @fires Slider#moved
  7642. * @fires Slider#changed
  7643. */
  7644. }, {
  7645. key: "_setHandlePos",
  7646. value: function _setHandlePos($hndl, location, noInvert, cb) {
  7647. // don't move if the slider has been disabled since its initialization
  7648. if (this.$element.hasClass(this.options.disabledClass)) {
  7649. return;
  7650. } //might need to alter that slightly for bars that will have odd number selections.
  7651. location = parseFloat(location); //on input change events, convert string to number...grumble.
  7652. // prevent slider from running out of bounds, if value exceeds the limits set through options, override the value to min/max
  7653. if (location < this.options.start) {
  7654. location = this.options.start;
  7655. } else if (location > this.options.end) {
  7656. location = this.options.end;
  7657. }
  7658. var isDbl = this.options.doubleSided; //this is for single-handled vertical sliders, it adjusts the value to account for the slider being "upside-down"
  7659. //for click and drag events, it's weird due to the scale(-1, 1) css property
  7660. if (this.options.vertical && !noInvert) {
  7661. location = this.options.end - location;
  7662. }
  7663. if (isDbl) {
  7664. //this block is to prevent 2 handles from crossing eachother. Could/should be improved.
  7665. if (this.handles.index($hndl) === 0) {
  7666. var h2Val = parseFloat(this.$handle2.attr('aria-valuenow'));
  7667. location = location >= h2Val ? h2Val - this.options.step : location;
  7668. } else {
  7669. var h1Val = parseFloat(this.$handle.attr('aria-valuenow'));
  7670. location = location <= h1Val ? h1Val + this.options.step : location;
  7671. }
  7672. }
  7673. var _this = this,
  7674. vert = this.options.vertical,
  7675. hOrW = vert ? 'height' : 'width',
  7676. lOrT = vert ? 'top' : 'left',
  7677. handleDim = $hndl[0].getBoundingClientRect()[hOrW],
  7678. elemDim = this.$element[0].getBoundingClientRect()[hOrW],
  7679. //percentage of bar min/max value based on click or drag point
  7680. pctOfBar = this._pctOfBar(location),
  7681. //number of actual pixels to shift the handle, based on the percentage obtained above
  7682. pxToMove = (elemDim - handleDim) * pctOfBar,
  7683. //percentage of bar to shift the handle
  7684. movement = (percent(pxToMove, elemDim) * 100).toFixed(this.options.decimal); //fixing the decimal value for the location number, is passed to other methods as a fixed floating-point value
  7685. location = parseFloat(location.toFixed(this.options.decimal)); // declare empty object for css adjustments, only used with 2 handled-sliders
  7686. var css = {};
  7687. this._setValues($hndl, location); // TODO update to calculate based on values set to respective inputs??
  7688. if (isDbl) {
  7689. var isLeftHndl = this.handles.index($hndl) === 0,
  7690. //empty variable, will be used for min-height/width for fill bar
  7691. dim,
  7692. //percentage w/h of the handle compared to the slider bar
  7693. handlePct = ~~(percent(handleDim, elemDim) * 100); //if left handle, the math is slightly different than if it's the right handle, and the left/top property needs to be changed for the fill bar
  7694. if (isLeftHndl) {
  7695. //left or top percentage value to apply to the fill bar.
  7696. css[lOrT] = "".concat(movement, "%"); //calculate the new min-height/width for the fill bar.
  7697. dim = parseFloat(this.$handle2[0].style[lOrT]) - movement + handlePct; //this callback is necessary to prevent errors and allow the proper placement and initialization of a 2-handled slider
  7698. //plus, it means we don't care if 'dim' isNaN on init, it won't be in the future.
  7699. if (cb && typeof cb === 'function') {
  7700. cb();
  7701. } //this is only needed for the initialization of 2 handled sliders
  7702. } else {
  7703. //just caching the value of the left/bottom handle's left/top property
  7704. var handlePos = parseFloat(this.$handle[0].style[lOrT]); //calculate the new min-height/width for the fill bar. Use isNaN to prevent false positives for numbers <= 0
  7705. //based on the percentage of movement of the handle being manipulated, less the opposing handle's left/top position, plus the percentage w/h of the handle itself
  7706. dim = movement - (isNaN(handlePos) ? (this.options.initialStart - this.options.start) / ((this.options.end - this.options.start) / 100) : handlePos) + handlePct;
  7707. } // assign the min-height/width to our css object
  7708. css["min-".concat(hOrW)] = "".concat(dim, "%");
  7709. }
  7710. this.$element.one('finished.zf.animate', function () {
  7711. /**
  7712. * Fires when the handle is done moving.
  7713. * @event Slider#moved
  7714. */
  7715. _this.$element.trigger('moved.zf.slider', [$hndl]);
  7716. }); //because we don't know exactly how the handle will be moved, check the amount of time it should take to move.
  7717. var moveTime = this.$element.data('dragging') ? 1000 / 60 : this.options.moveTime;
  7718. Move(moveTime, $hndl, function () {
  7719. // adjusting the left/top property of the handle, based on the percentage calculated above
  7720. // if movement isNaN, that is because the slider is hidden and we cannot determine handle width,
  7721. // fall back to next best guess.
  7722. if (isNaN(movement)) {
  7723. $hndl.css(lOrT, "".concat(pctOfBar * 100, "%"));
  7724. } else {
  7725. $hndl.css(lOrT, "".concat(movement, "%"));
  7726. }
  7727. if (!_this.options.doubleSided) {
  7728. //if single-handled, a simple method to expand the fill bar
  7729. _this.$fill.css(hOrW, "".concat(pctOfBar * 100, "%"));
  7730. } else {
  7731. //otherwise, use the css object we created above
  7732. _this.$fill.css(css);
  7733. }
  7734. });
  7735. /**
  7736. * Fires when the value has not been change for a given time.
  7737. * @event Slider#changed
  7738. */
  7739. clearTimeout(_this.timeout);
  7740. _this.timeout = setTimeout(function () {
  7741. _this.$element.trigger('changed.zf.slider', [$hndl]);
  7742. }, _this.options.changedDelay);
  7743. }
  7744. /**
  7745. * Sets the initial attribute for the slider element.
  7746. * @function
  7747. * @private
  7748. * @param {Number} idx - index of the current handle/input to use.
  7749. */
  7750. }, {
  7751. key: "_setInitAttr",
  7752. value: function _setInitAttr(idx) {
  7753. var initVal = idx === 0 ? this.options.initialStart : this.options.initialEnd;
  7754. var id = this.inputs.eq(idx).attr('id') || GetYoDigits(6, 'slider');
  7755. this.inputs.eq(idx).attr({
  7756. 'id': id,
  7757. 'max': this.options.end,
  7758. 'min': this.options.start,
  7759. 'step': this.options.step
  7760. });
  7761. this.inputs.eq(idx).val(initVal);
  7762. this.handles.eq(idx).attr({
  7763. 'role': 'slider',
  7764. 'aria-controls': id,
  7765. 'aria-valuemax': this.options.end,
  7766. 'aria-valuemin': this.options.start,
  7767. 'aria-valuenow': initVal,
  7768. 'aria-orientation': this.options.vertical ? 'vertical' : 'horizontal',
  7769. 'tabindex': 0
  7770. });
  7771. }
  7772. /**
  7773. * Sets the input and `aria-valuenow` values for the slider element.
  7774. * @function
  7775. * @private
  7776. * @param {jQuery} $handle - the currently selected handle.
  7777. * @param {Number} val - floating point of the new value.
  7778. */
  7779. }, {
  7780. key: "_setValues",
  7781. value: function _setValues($handle, val) {
  7782. var idx = this.options.doubleSided ? this.handles.index($handle) : 0;
  7783. this.inputs.eq(idx).val(val);
  7784. $handle.attr('aria-valuenow', val);
  7785. }
  7786. /**
  7787. * Handles events on the slider element.
  7788. * Calculates the new location of the current handle.
  7789. * If there are two handles and the bar was clicked, it determines which handle to move.
  7790. * @function
  7791. * @private
  7792. * @param {Object} e - the `event` object passed from the listener.
  7793. * @param {jQuery} $handle - the current handle to calculate for, if selected.
  7794. * @param {Number} val - floating point number for the new value of the slider.
  7795. * TODO clean this up, there's a lot of repeated code between this and the _setHandlePos fn.
  7796. */
  7797. }, {
  7798. key: "_handleEvent",
  7799. value: function _handleEvent(e, $handle, val) {
  7800. var value, hasVal;
  7801. if (!val) {
  7802. //click or drag events
  7803. e.preventDefault();
  7804. var _this = this,
  7805. vertical = this.options.vertical,
  7806. param = vertical ? 'height' : 'width',
  7807. direction = vertical ? 'top' : 'left',
  7808. eventOffset = vertical ? e.pageY : e.pageX,
  7809. halfOfHandle = this.$handle[0].getBoundingClientRect()[param] / 2,
  7810. barDim = this.$element[0].getBoundingClientRect()[param],
  7811. windowScroll = vertical ? $(window).scrollTop() : $(window).scrollLeft();
  7812. var elemOffset = this.$element.offset()[direction]; // touch events emulated by the touch util give position relative to screen, add window.scroll to event coordinates...
  7813. // best way to guess this is simulated is if clientY == pageY
  7814. if (e.clientY === e.pageY) {
  7815. eventOffset = eventOffset + windowScroll;
  7816. }
  7817. var eventFromBar = eventOffset - elemOffset;
  7818. var barXY;
  7819. if (eventFromBar < 0) {
  7820. barXY = 0;
  7821. } else if (eventFromBar > barDim) {
  7822. barXY = barDim;
  7823. } else {
  7824. barXY = eventFromBar;
  7825. }
  7826. var offsetPct = percent(barXY, barDim);
  7827. value = this._value(offsetPct); // turn everything around for RTL, yay math!
  7828. if (rtl() && !this.options.vertical) {
  7829. value = this.options.end - value;
  7830. }
  7831. value = _this._adjustValue(null, value); //boolean flag for the setHandlePos fn, specifically for vertical sliders
  7832. hasVal = false;
  7833. if (!$handle) {
  7834. //figure out which handle it is, pass it to the next function.
  7835. var firstHndlPos = absPosition(this.$handle, direction, barXY, param),
  7836. secndHndlPos = absPosition(this.$handle2, direction, barXY, param);
  7837. $handle = firstHndlPos <= secndHndlPos ? this.$handle : this.$handle2;
  7838. }
  7839. } else {
  7840. //change event on input
  7841. value = this._adjustValue(null, val);
  7842. hasVal = true;
  7843. }
  7844. this._setHandlePos($handle, value, hasVal);
  7845. }
  7846. /**
  7847. * Adjustes value for handle in regard to step value. returns adjusted value
  7848. * @function
  7849. * @private
  7850. * @param {jQuery} $handle - the selected handle.
  7851. * @param {Number} value - value to adjust. used if $handle is falsy
  7852. */
  7853. }, {
  7854. key: "_adjustValue",
  7855. value: function _adjustValue($handle, value) {
  7856. var val,
  7857. step = this.options.step,
  7858. div = parseFloat(step / 2),
  7859. left,
  7860. prev_val,
  7861. next_val;
  7862. if (!!$handle) {
  7863. val = parseFloat($handle.attr('aria-valuenow'));
  7864. } else {
  7865. val = value;
  7866. }
  7867. if (val >= 0) {
  7868. left = val % step;
  7869. } else {
  7870. left = step + val % step;
  7871. }
  7872. prev_val = val - left;
  7873. next_val = prev_val + step;
  7874. if (left === 0) {
  7875. return val;
  7876. }
  7877. val = val >= prev_val + div ? next_val : prev_val;
  7878. return val;
  7879. }
  7880. /**
  7881. * Adds event listeners to the slider elements.
  7882. * @function
  7883. * @private
  7884. */
  7885. }, {
  7886. key: "_events",
  7887. value: function _events() {
  7888. this._eventsForHandle(this.$handle);
  7889. if (this.handles[1]) {
  7890. this._eventsForHandle(this.$handle2);
  7891. }
  7892. }
  7893. /**
  7894. * Adds event listeners a particular handle
  7895. * @function
  7896. * @private
  7897. * @param {jQuery} $handle - the current handle to apply listeners to.
  7898. */
  7899. }, {
  7900. key: "_eventsForHandle",
  7901. value: function _eventsForHandle($handle) {
  7902. var _this = this,
  7903. curHandle;
  7904. var handleChangeEvent = function handleChangeEvent(e) {
  7905. var idx = _this.inputs.index($(this));
  7906. _this._handleEvent(e, _this.handles.eq(idx), $(this).val());
  7907. }; // IE only triggers the change event when the input loses focus which strictly follows the HTML specification
  7908. // listen for the enter key and trigger a change
  7909. // @see https://html.spec.whatwg.org/multipage/input.html#common-input-element-events
  7910. this.inputs.off('keyup.zf.slider').on('keyup.zf.slider', function (e) {
  7911. if (e.keyCode == 13) handleChangeEvent.call(this, e);
  7912. });
  7913. this.inputs.off('change.zf.slider').on('change.zf.slider', handleChangeEvent);
  7914. if (this.options.clickSelect) {
  7915. this.$element.off('click.zf.slider').on('click.zf.slider', function (e) {
  7916. if (_this.$element.data('dragging')) {
  7917. return false;
  7918. }
  7919. if (!$(e.target).is('[data-slider-handle]')) {
  7920. if (_this.options.doubleSided) {
  7921. _this._handleEvent(e);
  7922. } else {
  7923. _this._handleEvent(e, _this.$handle);
  7924. }
  7925. }
  7926. });
  7927. }
  7928. if (this.options.draggable) {
  7929. this.handles.addTouch();
  7930. var $body = $('body');
  7931. $handle.off('mousedown.zf.slider').on('mousedown.zf.slider', function (e) {
  7932. $handle.addClass('is-dragging');
  7933. _this.$fill.addClass('is-dragging'); //
  7934. _this.$element.data('dragging', true);
  7935. curHandle = $(e.currentTarget);
  7936. $body.on('mousemove.zf.slider', function (e) {
  7937. e.preventDefault();
  7938. _this._handleEvent(e, curHandle);
  7939. }).on('mouseup.zf.slider', function (e) {
  7940. _this._handleEvent(e, curHandle);
  7941. $handle.removeClass('is-dragging');
  7942. _this.$fill.removeClass('is-dragging');
  7943. _this.$element.data('dragging', false);
  7944. $body.off('mousemove.zf.slider mouseup.zf.slider');
  7945. });
  7946. }) // prevent events triggered by touch
  7947. .on('selectstart.zf.slider touchmove.zf.slider', function (e) {
  7948. e.preventDefault();
  7949. });
  7950. }
  7951. $handle.off('keydown.zf.slider').on('keydown.zf.slider', function (e) {
  7952. var _$handle = $(this),
  7953. idx = _this.options.doubleSided ? _this.handles.index(_$handle) : 0,
  7954. oldValue = parseFloat(_this.inputs.eq(idx).val()),
  7955. newValue; // handle keyboard event with keyboard util
  7956. Keyboard.handleKey(e, 'Slider', {
  7957. decrease: function decrease() {
  7958. newValue = oldValue - _this.options.step;
  7959. },
  7960. increase: function increase() {
  7961. newValue = oldValue + _this.options.step;
  7962. },
  7963. decrease_fast: function decrease_fast() {
  7964. newValue = oldValue - _this.options.step * 10;
  7965. },
  7966. increase_fast: function increase_fast() {
  7967. newValue = oldValue + _this.options.step * 10;
  7968. },
  7969. min: function min() {
  7970. newValue = _this.options.start;
  7971. },
  7972. max: function max() {
  7973. newValue = _this.options.end;
  7974. },
  7975. handled: function handled() {
  7976. // only set handle pos when event was handled specially
  7977. e.preventDefault();
  7978. _this._setHandlePos(_$handle, newValue, true);
  7979. }
  7980. });
  7981. /*if (newValue) { // if pressed key has special function, update value
  7982. e.preventDefault();
  7983. _this._setHandlePos(_$handle, newValue);
  7984. }*/
  7985. });
  7986. }
  7987. /**
  7988. * Destroys the slider plugin.
  7989. */
  7990. }, {
  7991. key: "_destroy",
  7992. value: function _destroy() {
  7993. this.handles.off('.zf.slider');
  7994. this.inputs.off('.zf.slider');
  7995. this.$element.off('.zf.slider');
  7996. clearTimeout(this.timeout);
  7997. }
  7998. }]);
  7999. return Slider;
  8000. }(Plugin);
  8001. Slider.defaults = {
  8002. /**
  8003. * Minimum value for the slider scale.
  8004. * @option
  8005. * @type {number}
  8006. * @default 0
  8007. */
  8008. start: 0,
  8009. /**
  8010. * Maximum value for the slider scale.
  8011. * @option
  8012. * @type {number}
  8013. * @default 100
  8014. */
  8015. end: 100,
  8016. /**
  8017. * Minimum value change per change event.
  8018. * @option
  8019. * @type {number}
  8020. * @default 1
  8021. */
  8022. step: 1,
  8023. /**
  8024. * Value at which the handle/input *(left handle/first input)* should be set to on initialization.
  8025. * @option
  8026. * @type {number}
  8027. * @default 0
  8028. */
  8029. initialStart: 0,
  8030. /**
  8031. * Value at which the right handle/second input should be set to on initialization.
  8032. * @option
  8033. * @type {number}
  8034. * @default 100
  8035. */
  8036. initialEnd: 100,
  8037. /**
  8038. * Allows the input to be located outside the container and visible. Set to by the JS
  8039. * @option
  8040. * @type {boolean}
  8041. * @default false
  8042. */
  8043. binding: false,
  8044. /**
  8045. * Allows the user to click/tap on the slider bar to select a value.
  8046. * @option
  8047. * @type {boolean}
  8048. * @default true
  8049. */
  8050. clickSelect: true,
  8051. /**
  8052. * Set to true and use the `vertical` class to change alignment to vertical.
  8053. * @option
  8054. * @type {boolean}
  8055. * @default false
  8056. */
  8057. vertical: false,
  8058. /**
  8059. * Allows the user to drag the slider handle(s) to select a value.
  8060. * @option
  8061. * @type {boolean}
  8062. * @default true
  8063. */
  8064. draggable: true,
  8065. /**
  8066. * Disables the slider and prevents event listeners from being applied. Double checked by JS with `disabledClass`.
  8067. * @option
  8068. * @type {boolean}
  8069. * @default false
  8070. */
  8071. disabled: false,
  8072. /**
  8073. * Allows the use of two handles. Double checked by the JS. Changes some logic handling.
  8074. * @option
  8075. * @type {boolean}
  8076. * @default false
  8077. */
  8078. doubleSided: false,
  8079. /**
  8080. * Potential future feature.
  8081. */
  8082. // steps: 100,
  8083. /**
  8084. * Number of decimal places the plugin should go to for floating point precision.
  8085. * @option
  8086. * @type {number}
  8087. * @default 2
  8088. */
  8089. decimal: 2,
  8090. /**
  8091. * Time delay for dragged elements.
  8092. */
  8093. // dragDelay: 0,
  8094. /**
  8095. * Time, in ms, to animate the movement of a slider handle if user clicks/taps on the bar. Needs to be manually set if updating the transition time in the Sass settings.
  8096. * @option
  8097. * @type {number}
  8098. * @default 200
  8099. */
  8100. moveTime: 200,
  8101. //update this if changing the transition time in the sass
  8102. /**
  8103. * Class applied to disabled sliders.
  8104. * @option
  8105. * @type {string}
  8106. * @default 'disabled'
  8107. */
  8108. disabledClass: 'disabled',
  8109. /**
  8110. * Will invert the default layout for a vertical<span data-tooltip title="who would do this???"> </span>slider.
  8111. * @option
  8112. * @type {boolean}
  8113. * @default false
  8114. */
  8115. invertVertical: false,
  8116. /**
  8117. * Milliseconds before the `changed.zf-slider` event is triggered after value change.
  8118. * @option
  8119. * @type {number}
  8120. * @default 500
  8121. */
  8122. changedDelay: 500,
  8123. /**
  8124. * Basevalue for non-linear sliders
  8125. * @option
  8126. * @type {number}
  8127. * @default 5
  8128. */
  8129. nonLinearBase: 5,
  8130. /**
  8131. * Basevalue for non-linear sliders, possible values are: `'linear'`, `'pow'` & `'log'`. Pow and Log use the nonLinearBase setting.
  8132. * @option
  8133. * @type {string}
  8134. * @default 'linear'
  8135. */
  8136. positionValueFunction: 'linear'
  8137. };
  8138. function percent(frac, num) {
  8139. return frac / num;
  8140. }
  8141. function absPosition($handle, dir, clickPos, param) {
  8142. return Math.abs($handle.position()[dir] + $handle[param]() / 2 - clickPos);
  8143. }
  8144. function baseLog(base, value) {
  8145. return Math.log(value) / Math.log(base);
  8146. }
  8147. /**
  8148. * Sticky module.
  8149. * @module foundation.sticky
  8150. * @requires foundation.util.triggers
  8151. * @requires foundation.util.mediaQuery
  8152. */
  8153. var Sticky =
  8154. /*#__PURE__*/
  8155. function (_Plugin) {
  8156. _inherits(Sticky, _Plugin);
  8157. function Sticky() {
  8158. _classCallCheck(this, Sticky);
  8159. return _possibleConstructorReturn(this, _getPrototypeOf(Sticky).apply(this, arguments));
  8160. }
  8161. _createClass(Sticky, [{
  8162. key: "_setup",
  8163. /**
  8164. * Creates a new instance of a sticky thing.
  8165. * @class
  8166. * @name Sticky
  8167. * @param {jQuery} element - jQuery object to make sticky.
  8168. * @param {Object} options - options object passed when creating the element programmatically.
  8169. */
  8170. value: function _setup(element, options) {
  8171. this.$element = element;
  8172. this.options = $.extend({}, Sticky.defaults, this.$element.data(), options);
  8173. this.className = 'Sticky'; // ie9 back compat
  8174. // Triggers init is idempotent, just need to make sure it is initialized
  8175. Triggers.init($);
  8176. this._init();
  8177. }
  8178. /**
  8179. * Initializes the sticky element by adding classes, getting/setting dimensions, breakpoints and attributes
  8180. * @function
  8181. * @private
  8182. */
  8183. }, {
  8184. key: "_init",
  8185. value: function _init() {
  8186. MediaQuery._init();
  8187. var $parent = this.$element.parent('[data-sticky-container]'),
  8188. id = this.$element[0].id || GetYoDigits(6, 'sticky'),
  8189. _this = this;
  8190. if ($parent.length) {
  8191. this.$container = $parent;
  8192. } else {
  8193. this.wasWrapped = true;
  8194. this.$element.wrap(this.options.container);
  8195. this.$container = this.$element.parent();
  8196. }
  8197. this.$container.addClass(this.options.containerClass);
  8198. this.$element.addClass(this.options.stickyClass).attr({
  8199. 'data-resize': id,
  8200. 'data-mutate': id
  8201. });
  8202. if (this.options.anchor !== '') {
  8203. $('#' + _this.options.anchor).attr({
  8204. 'data-mutate': id
  8205. });
  8206. }
  8207. this.scrollCount = this.options.checkEvery;
  8208. this.isStuck = false;
  8209. this.onLoadListener = onLoad($(window), function () {
  8210. //We calculate the container height to have correct values for anchor points offset calculation.
  8211. _this.containerHeight = _this.$element.css("display") == "none" ? 0 : _this.$element[0].getBoundingClientRect().height;
  8212. _this.$container.css('height', _this.containerHeight);
  8213. _this.elemHeight = _this.containerHeight;
  8214. if (_this.options.anchor !== '') {
  8215. _this.$anchor = $('#' + _this.options.anchor);
  8216. } else {
  8217. _this._parsePoints();
  8218. }
  8219. _this._setSizes(function () {
  8220. var scroll = window.pageYOffset;
  8221. _this._calc(false, scroll); //Unstick the element will ensure that proper classes are set.
  8222. if (!_this.isStuck) {
  8223. _this._removeSticky(scroll >= _this.topPoint ? false : true);
  8224. }
  8225. });
  8226. _this._events(id.split('-').reverse().join('-'));
  8227. });
  8228. }
  8229. /**
  8230. * If using multiple elements as anchors, calculates the top and bottom pixel values the sticky thing should stick and unstick on.
  8231. * @function
  8232. * @private
  8233. */
  8234. }, {
  8235. key: "_parsePoints",
  8236. value: function _parsePoints() {
  8237. var top = this.options.topAnchor == "" ? 1 : this.options.topAnchor,
  8238. btm = this.options.btmAnchor == "" ? document.documentElement.scrollHeight : this.options.btmAnchor,
  8239. pts = [top, btm],
  8240. breaks = {};
  8241. for (var i = 0, len = pts.length; i < len && pts[i]; i++) {
  8242. var pt;
  8243. if (typeof pts[i] === 'number') {
  8244. pt = pts[i];
  8245. } else {
  8246. var place = pts[i].split(':'),
  8247. anchor = $("#".concat(place[0]));
  8248. pt = anchor.offset().top;
  8249. if (place[1] && place[1].toLowerCase() === 'bottom') {
  8250. pt += anchor[0].getBoundingClientRect().height;
  8251. }
  8252. }
  8253. breaks[i] = pt;
  8254. }
  8255. this.points = breaks;
  8256. return;
  8257. }
  8258. /**
  8259. * Adds event handlers for the scrolling element.
  8260. * @private
  8261. * @param {String} id - pseudo-random id for unique scroll event listener.
  8262. */
  8263. }, {
  8264. key: "_events",
  8265. value: function _events(id) {
  8266. var _this = this,
  8267. scrollListener = this.scrollListener = "scroll.zf.".concat(id);
  8268. if (this.isOn) {
  8269. return;
  8270. }
  8271. if (this.canStick) {
  8272. this.isOn = true;
  8273. $(window).off(scrollListener).on(scrollListener, function (e) {
  8274. if (_this.scrollCount === 0) {
  8275. _this.scrollCount = _this.options.checkEvery;
  8276. _this._setSizes(function () {
  8277. _this._calc(false, window.pageYOffset);
  8278. });
  8279. } else {
  8280. _this.scrollCount--;
  8281. _this._calc(false, window.pageYOffset);
  8282. }
  8283. });
  8284. }
  8285. this.$element.off('resizeme.zf.trigger').on('resizeme.zf.trigger', function (e, el) {
  8286. _this._eventsHandler(id);
  8287. });
  8288. this.$element.on('mutateme.zf.trigger', function (e, el) {
  8289. _this._eventsHandler(id);
  8290. });
  8291. if (this.$anchor) {
  8292. this.$anchor.on('mutateme.zf.trigger', function (e, el) {
  8293. _this._eventsHandler(id);
  8294. });
  8295. }
  8296. }
  8297. /**
  8298. * Handler for events.
  8299. * @private
  8300. * @param {String} id - pseudo-random id for unique scroll event listener.
  8301. */
  8302. }, {
  8303. key: "_eventsHandler",
  8304. value: function _eventsHandler(id) {
  8305. var _this = this,
  8306. scrollListener = this.scrollListener = "scroll.zf.".concat(id);
  8307. _this._setSizes(function () {
  8308. _this._calc(false);
  8309. if (_this.canStick) {
  8310. if (!_this.isOn) {
  8311. _this._events(id);
  8312. }
  8313. } else if (_this.isOn) {
  8314. _this._pauseListeners(scrollListener);
  8315. }
  8316. });
  8317. }
  8318. /**
  8319. * Removes event handlers for scroll and change events on anchor.
  8320. * @fires Sticky#pause
  8321. * @param {String} scrollListener - unique, namespaced scroll listener attached to `window`
  8322. */
  8323. }, {
  8324. key: "_pauseListeners",
  8325. value: function _pauseListeners(scrollListener) {
  8326. this.isOn = false;
  8327. $(window).off(scrollListener);
  8328. /**
  8329. * Fires when the plugin is paused due to resize event shrinking the view.
  8330. * @event Sticky#pause
  8331. * @private
  8332. */
  8333. this.$element.trigger('pause.zf.sticky');
  8334. }
  8335. /**
  8336. * Called on every `scroll` event and on `_init`
  8337. * fires functions based on booleans and cached values
  8338. * @param {Boolean} checkSizes - true if plugin should recalculate sizes and breakpoints.
  8339. * @param {Number} scroll - current scroll position passed from scroll event cb function. If not passed, defaults to `window.pageYOffset`.
  8340. */
  8341. }, {
  8342. key: "_calc",
  8343. value: function _calc(checkSizes, scroll) {
  8344. if (checkSizes) {
  8345. this._setSizes();
  8346. }
  8347. if (!this.canStick) {
  8348. if (this.isStuck) {
  8349. this._removeSticky(true);
  8350. }
  8351. return false;
  8352. }
  8353. if (!scroll) {
  8354. scroll = window.pageYOffset;
  8355. }
  8356. if (scroll >= this.topPoint) {
  8357. if (scroll <= this.bottomPoint) {
  8358. if (!this.isStuck) {
  8359. this._setSticky();
  8360. }
  8361. } else {
  8362. if (this.isStuck) {
  8363. this._removeSticky(false);
  8364. }
  8365. }
  8366. } else {
  8367. if (this.isStuck) {
  8368. this._removeSticky(true);
  8369. }
  8370. }
  8371. }
  8372. /**
  8373. * Causes the $element to become stuck.
  8374. * Adds `position: fixed;`, and helper classes.
  8375. * @fires Sticky#stuckto
  8376. * @function
  8377. * @private
  8378. */
  8379. }, {
  8380. key: "_setSticky",
  8381. value: function _setSticky() {
  8382. var _this = this,
  8383. stickTo = this.options.stickTo,
  8384. mrgn = stickTo === 'top' ? 'marginTop' : 'marginBottom',
  8385. notStuckTo = stickTo === 'top' ? 'bottom' : 'top',
  8386. css = {};
  8387. css[mrgn] = "".concat(this.options[mrgn], "em");
  8388. css[stickTo] = 0;
  8389. css[notStuckTo] = 'auto';
  8390. this.isStuck = true;
  8391. this.$element.removeClass("is-anchored is-at-".concat(notStuckTo)).addClass("is-stuck is-at-".concat(stickTo)).css(css)
  8392. /**
  8393. * Fires when the $element has become `position: fixed;`
  8394. * Namespaced to `top` or `bottom`, e.g. `sticky.zf.stuckto:top`
  8395. * @event Sticky#stuckto
  8396. */
  8397. .trigger("sticky.zf.stuckto:".concat(stickTo));
  8398. this.$element.on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", function () {
  8399. _this._setSizes();
  8400. });
  8401. }
  8402. /**
  8403. * Causes the $element to become unstuck.
  8404. * Removes `position: fixed;`, and helper classes.
  8405. * Adds other helper classes.
  8406. * @param {Boolean} isTop - tells the function if the $element should anchor to the top or bottom of its $anchor element.
  8407. * @fires Sticky#unstuckfrom
  8408. * @private
  8409. */
  8410. }, {
  8411. key: "_removeSticky",
  8412. value: function _removeSticky(isTop) {
  8413. var stickTo = this.options.stickTo,
  8414. stickToTop = stickTo === 'top',
  8415. css = {},
  8416. anchorPt = (this.points ? this.points[1] - this.points[0] : this.anchorHeight) - this.elemHeight,
  8417. mrgn = stickToTop ? 'marginTop' : 'marginBottom',
  8418. topOrBottom = isTop ? 'top' : 'bottom';
  8419. css[mrgn] = 0;
  8420. css['bottom'] = 'auto';
  8421. if (isTop) {
  8422. css['top'] = 0;
  8423. } else {
  8424. css['top'] = anchorPt;
  8425. }
  8426. this.isStuck = false;
  8427. this.$element.removeClass("is-stuck is-at-".concat(stickTo)).addClass("is-anchored is-at-".concat(topOrBottom)).css(css)
  8428. /**
  8429. * Fires when the $element has become anchored.
  8430. * Namespaced to `top` or `bottom`, e.g. `sticky.zf.unstuckfrom:bottom`
  8431. * @event Sticky#unstuckfrom
  8432. */
  8433. .trigger("sticky.zf.unstuckfrom:".concat(topOrBottom));
  8434. }
  8435. /**
  8436. * Sets the $element and $container sizes for plugin.
  8437. * Calls `_setBreakPoints`.
  8438. * @param {Function} cb - optional callback function to fire on completion of `_setBreakPoints`.
  8439. * @private
  8440. */
  8441. }, {
  8442. key: "_setSizes",
  8443. value: function _setSizes(cb) {
  8444. this.canStick = MediaQuery.is(this.options.stickyOn);
  8445. if (!this.canStick) {
  8446. if (cb && typeof cb === 'function') {
  8447. cb();
  8448. }
  8449. }
  8450. var newElemWidth = this.$container[0].getBoundingClientRect().width,
  8451. comp = window.getComputedStyle(this.$container[0]),
  8452. pdngl = parseInt(comp['padding-left'], 10),
  8453. pdngr = parseInt(comp['padding-right'], 10);
  8454. if (this.$anchor && this.$anchor.length) {
  8455. this.anchorHeight = this.$anchor[0].getBoundingClientRect().height;
  8456. } else {
  8457. this._parsePoints();
  8458. }
  8459. this.$element.css({
  8460. 'max-width': "".concat(newElemWidth - pdngl - pdngr, "px")
  8461. });
  8462. var newContainerHeight = this.$element[0].getBoundingClientRect().height || this.containerHeight;
  8463. if (this.$element.css("display") == "none") {
  8464. newContainerHeight = 0;
  8465. }
  8466. this.containerHeight = newContainerHeight;
  8467. this.$container.css({
  8468. height: newContainerHeight
  8469. });
  8470. this.elemHeight = newContainerHeight;
  8471. if (!this.isStuck) {
  8472. if (this.$element.hasClass('is-at-bottom')) {
  8473. var anchorPt = (this.points ? this.points[1] - this.$container.offset().top : this.anchorHeight) - this.elemHeight;
  8474. this.$element.css('top', anchorPt);
  8475. }
  8476. }
  8477. this._setBreakPoints(newContainerHeight, function () {
  8478. if (cb && typeof cb === 'function') {
  8479. cb();
  8480. }
  8481. });
  8482. }
  8483. /**
  8484. * Sets the upper and lower breakpoints for the element to become sticky/unsticky.
  8485. * @param {Number} elemHeight - px value for sticky.$element height, calculated by `_setSizes`.
  8486. * @param {Function} cb - optional callback function to be called on completion.
  8487. * @private
  8488. */
  8489. }, {
  8490. key: "_setBreakPoints",
  8491. value: function _setBreakPoints(elemHeight, cb) {
  8492. if (!this.canStick) {
  8493. if (cb && typeof cb === 'function') {
  8494. cb();
  8495. } else {
  8496. return false;
  8497. }
  8498. }
  8499. var mTop = emCalc(this.options.marginTop),
  8500. mBtm = emCalc(this.options.marginBottom),
  8501. topPoint = this.points ? this.points[0] : this.$anchor.offset().top,
  8502. bottomPoint = this.points ? this.points[1] : topPoint + this.anchorHeight,
  8503. // topPoint = this.$anchor.offset().top || this.points[0],
  8504. // bottomPoint = topPoint + this.anchorHeight || this.points[1],
  8505. winHeight = window.innerHeight;
  8506. if (this.options.stickTo === 'top') {
  8507. topPoint -= mTop;
  8508. bottomPoint -= elemHeight + mTop;
  8509. } else if (this.options.stickTo === 'bottom') {
  8510. topPoint -= winHeight - (elemHeight + mBtm);
  8511. bottomPoint -= winHeight - mBtm;
  8512. }
  8513. this.topPoint = topPoint;
  8514. this.bottomPoint = bottomPoint;
  8515. if (cb && typeof cb === 'function') {
  8516. cb();
  8517. }
  8518. }
  8519. /**
  8520. * Destroys the current sticky element.
  8521. * Resets the element to the top position first.
  8522. * Removes event listeners, JS-added css properties and classes, and unwraps the $element if the JS added the $container.
  8523. * @function
  8524. */
  8525. }, {
  8526. key: "_destroy",
  8527. value: function _destroy() {
  8528. this._removeSticky(true);
  8529. this.$element.removeClass("".concat(this.options.stickyClass, " is-anchored is-at-top")).css({
  8530. height: '',
  8531. top: '',
  8532. bottom: '',
  8533. 'max-width': ''
  8534. }).off('resizeme.zf.trigger').off('mutateme.zf.trigger');
  8535. if (this.$anchor && this.$anchor.length) {
  8536. this.$anchor.off('change.zf.sticky');
  8537. }
  8538. if (this.scrollListener) $(window).off(this.scrollListener);
  8539. if (this.onLoadListener) $(window).off(this.onLoadListener);
  8540. if (this.wasWrapped) {
  8541. this.$element.unwrap();
  8542. } else {
  8543. this.$container.removeClass(this.options.containerClass).css({
  8544. height: ''
  8545. });
  8546. }
  8547. }
  8548. }]);
  8549. return Sticky;
  8550. }(Plugin);
  8551. Sticky.defaults = {
  8552. /**
  8553. * Customizable container template. Add your own classes for styling and sizing.
  8554. * @option
  8555. * @type {string}
  8556. * @default '&lt;div data-sticky-container&gt;&lt;/div&gt;'
  8557. */
  8558. container: '<div data-sticky-container></div>',
  8559. /**
  8560. * Location in the view the element sticks to. Can be `'top'` or `'bottom'`.
  8561. * @option
  8562. * @type {string}
  8563. * @default 'top'
  8564. */
  8565. stickTo: 'top',
  8566. /**
  8567. * If anchored to a single element, the id of that element.
  8568. * @option
  8569. * @type {string}
  8570. * @default ''
  8571. */
  8572. anchor: '',
  8573. /**
  8574. * If using more than one element as anchor points, the id of the top anchor.
  8575. * @option
  8576. * @type {string}
  8577. * @default ''
  8578. */
  8579. topAnchor: '',
  8580. /**
  8581. * If using more than one element as anchor points, the id of the bottom anchor.
  8582. * @option
  8583. * @type {string}
  8584. * @default ''
  8585. */
  8586. btmAnchor: '',
  8587. /**
  8588. * Margin, in `em`'s to apply to the top of the element when it becomes sticky.
  8589. * @option
  8590. * @type {number}
  8591. * @default 1
  8592. */
  8593. marginTop: 1,
  8594. /**
  8595. * Margin, in `em`'s to apply to the bottom of the element when it becomes sticky.
  8596. * @option
  8597. * @type {number}
  8598. * @default 1
  8599. */
  8600. marginBottom: 1,
  8601. /**
  8602. * Breakpoint string that is the minimum screen size an element should become sticky.
  8603. * @option
  8604. * @type {string}
  8605. * @default 'medium'
  8606. */
  8607. stickyOn: 'medium',
  8608. /**
  8609. * Class applied to sticky element, and removed on destruction. Foundation defaults to `sticky`.
  8610. * @option
  8611. * @type {string}
  8612. * @default 'sticky'
  8613. */
  8614. stickyClass: 'sticky',
  8615. /**
  8616. * Class applied to sticky container. Foundation defaults to `sticky-container`.
  8617. * @option
  8618. * @type {string}
  8619. * @default 'sticky-container'
  8620. */
  8621. containerClass: 'sticky-container',
  8622. /**
  8623. * Number of scroll events between the plugin's recalculating sticky points. Setting it to `0` will cause it to recalc every scroll event, setting it to `-1` will prevent recalc on scroll.
  8624. * @option
  8625. * @type {number}
  8626. * @default -1
  8627. */
  8628. checkEvery: -1
  8629. };
  8630. /**
  8631. * Helper function to calculate em values
  8632. * @param Number {em} - number of em's to calculate into pixels
  8633. */
  8634. function emCalc(em) {
  8635. return parseInt(window.getComputedStyle(document.body, null).fontSize, 10) * em;
  8636. }
  8637. /**
  8638. * Tabs module.
  8639. * @module foundation.tabs
  8640. * @requires foundation.util.keyboard
  8641. * @requires foundation.util.imageLoader if tabs contain images
  8642. */
  8643. var Tabs =
  8644. /*#__PURE__*/
  8645. function (_Plugin) {
  8646. _inherits(Tabs, _Plugin);
  8647. function Tabs() {
  8648. _classCallCheck(this, Tabs);
  8649. return _possibleConstructorReturn(this, _getPrototypeOf(Tabs).apply(this, arguments));
  8650. }
  8651. _createClass(Tabs, [{
  8652. key: "_setup",
  8653. /**
  8654. * Creates a new instance of tabs.
  8655. * @class
  8656. * @name Tabs
  8657. * @fires Tabs#init
  8658. * @param {jQuery} element - jQuery object to make into tabs.
  8659. * @param {Object} options - Overrides to the default plugin settings.
  8660. */
  8661. value: function _setup(element, options) {
  8662. this.$element = element;
  8663. this.options = $.extend({}, Tabs.defaults, this.$element.data(), options);
  8664. this.className = 'Tabs'; // ie9 back compat
  8665. this._init();
  8666. Keyboard.register('Tabs', {
  8667. 'ENTER': 'open',
  8668. 'SPACE': 'open',
  8669. 'ARROW_RIGHT': 'next',
  8670. 'ARROW_UP': 'previous',
  8671. 'ARROW_DOWN': 'next',
  8672. 'ARROW_LEFT': 'previous' // 'TAB': 'next',
  8673. // 'SHIFT_TAB': 'previous'
  8674. });
  8675. }
  8676. /**
  8677. * Initializes the tabs by showing and focusing (if autoFocus=true) the preset active tab.
  8678. * @private
  8679. */
  8680. }, {
  8681. key: "_init",
  8682. value: function _init() {
  8683. var _this2 = this;
  8684. var _this = this;
  8685. this._isInitializing = true;
  8686. this.$element.attr({
  8687. 'role': 'tablist'
  8688. });
  8689. this.$tabTitles = this.$element.find(".".concat(this.options.linkClass));
  8690. this.$tabContent = $("[data-tabs-content=\"".concat(this.$element[0].id, "\"]"));
  8691. this.$tabTitles.each(function () {
  8692. var $elem = $(this),
  8693. $link = $elem.find('a'),
  8694. isActive = $elem.hasClass("".concat(_this.options.linkActiveClass)),
  8695. hash = $link.attr('data-tabs-target') || $link[0].hash.slice(1),
  8696. linkId = $link[0].id ? $link[0].id : "".concat(hash, "-label"),
  8697. $tabContent = $("#".concat(hash));
  8698. $elem.attr({
  8699. 'role': 'presentation'
  8700. });
  8701. $link.attr({
  8702. 'role': 'tab',
  8703. 'aria-controls': hash,
  8704. 'aria-selected': isActive,
  8705. 'id': linkId,
  8706. 'tabindex': isActive ? '0' : '-1'
  8707. });
  8708. $tabContent.attr({
  8709. 'role': 'tabpanel',
  8710. 'aria-labelledby': linkId
  8711. }); // Save up the initial hash to return to it later when going back in history
  8712. if (isActive) {
  8713. _this._initialAnchor = "#".concat(hash);
  8714. }
  8715. if (!isActive) {
  8716. $tabContent.attr('aria-hidden', 'true');
  8717. }
  8718. if (isActive && _this.options.autoFocus) {
  8719. _this.onLoadListener = onLoad($(window), function () {
  8720. $('html, body').animate({
  8721. scrollTop: $elem.offset().top
  8722. }, _this.options.deepLinkSmudgeDelay, function () {
  8723. $link.focus();
  8724. });
  8725. });
  8726. }
  8727. });
  8728. if (this.options.matchHeight) {
  8729. var $images = this.$tabContent.find('img');
  8730. if ($images.length) {
  8731. onImagesLoaded($images, this._setHeight.bind(this));
  8732. } else {
  8733. this._setHeight();
  8734. }
  8735. } // Current context-bound function to open tabs on page load or history hashchange
  8736. this._checkDeepLink = function () {
  8737. var anchor = window.location.hash;
  8738. if (!anchor.length) {
  8739. // If we are still initializing and there is no anchor, then there is nothing to do
  8740. if (_this2._isInitializing) return; // Otherwise, move to the initial anchor
  8741. if (_this2._initialAnchor) anchor = _this2._initialAnchor;
  8742. }
  8743. var $anchor = anchor && $(anchor);
  8744. var $link = anchor && _this2.$element.find('[href$="' + anchor + '"]'); // Whether the anchor element that has been found is part of this element
  8745. var isOwnAnchor = !!($anchor.length && $link.length); // If there is an anchor for the hash, select it
  8746. if ($anchor && $anchor.length && $link && $link.length) {
  8747. _this2.selectTab($anchor, true);
  8748. } // Otherwise, collapse everything
  8749. else {
  8750. _this2._collapse();
  8751. }
  8752. if (isOwnAnchor) {
  8753. // Roll up a little to show the titles
  8754. if (_this2.options.deepLinkSmudge) {
  8755. var offset = _this2.$element.offset();
  8756. $('html, body').animate({
  8757. scrollTop: offset.top
  8758. }, _this2.options.deepLinkSmudgeDelay);
  8759. }
  8760. /**
  8761. * Fires when the plugin has deeplinked at pageload
  8762. * @event Tabs#deeplink
  8763. */
  8764. _this2.$element.trigger('deeplink.zf.tabs', [$link, $anchor]);
  8765. }
  8766. }; //use browser to open a tab, if it exists in this tabset
  8767. if (this.options.deepLink) {
  8768. this._checkDeepLink();
  8769. }
  8770. this._events();
  8771. this._isInitializing = false;
  8772. }
  8773. /**
  8774. * Adds event handlers for items within the tabs.
  8775. * @private
  8776. */
  8777. }, {
  8778. key: "_events",
  8779. value: function _events() {
  8780. this._addKeyHandler();
  8781. this._addClickHandler();
  8782. this._setHeightMqHandler = null;
  8783. if (this.options.matchHeight) {
  8784. this._setHeightMqHandler = this._setHeight.bind(this);
  8785. $(window).on('changed.zf.mediaquery', this._setHeightMqHandler);
  8786. }
  8787. if (this.options.deepLink) {
  8788. $(window).on('hashchange', this._checkDeepLink);
  8789. }
  8790. }
  8791. /**
  8792. * Adds click handlers for items within the tabs.
  8793. * @private
  8794. */
  8795. }, {
  8796. key: "_addClickHandler",
  8797. value: function _addClickHandler() {
  8798. var _this = this;
  8799. this.$element.off('click.zf.tabs').on('click.zf.tabs', ".".concat(this.options.linkClass), function (e) {
  8800. e.preventDefault();
  8801. e.stopPropagation();
  8802. _this._handleTabChange($(this));
  8803. });
  8804. }
  8805. /**
  8806. * Adds keyboard event handlers for items within the tabs.
  8807. * @private
  8808. */
  8809. }, {
  8810. key: "_addKeyHandler",
  8811. value: function _addKeyHandler() {
  8812. var _this = this;
  8813. this.$tabTitles.off('keydown.zf.tabs').on('keydown.zf.tabs', function (e) {
  8814. if (e.which === 9) return;
  8815. var $element = $(this),
  8816. $elements = $element.parent('ul').children('li'),
  8817. $prevElement,
  8818. $nextElement;
  8819. $elements.each(function (i) {
  8820. if ($(this).is($element)) {
  8821. if (_this.options.wrapOnKeys) {
  8822. $prevElement = i === 0 ? $elements.last() : $elements.eq(i - 1);
  8823. $nextElement = i === $elements.length - 1 ? $elements.first() : $elements.eq(i + 1);
  8824. } else {
  8825. $prevElement = $elements.eq(Math.max(0, i - 1));
  8826. $nextElement = $elements.eq(Math.min(i + 1, $elements.length - 1));
  8827. }
  8828. return;
  8829. }
  8830. }); // handle keyboard event with keyboard util
  8831. Keyboard.handleKey(e, 'Tabs', {
  8832. open: function open() {
  8833. $element.find('[role="tab"]').focus();
  8834. _this._handleTabChange($element);
  8835. },
  8836. previous: function previous() {
  8837. $prevElement.find('[role="tab"]').focus();
  8838. _this._handleTabChange($prevElement);
  8839. },
  8840. next: function next() {
  8841. $nextElement.find('[role="tab"]').focus();
  8842. _this._handleTabChange($nextElement);
  8843. },
  8844. handled: function handled() {
  8845. e.stopPropagation();
  8846. e.preventDefault();
  8847. }
  8848. });
  8849. });
  8850. }
  8851. /**
  8852. * Opens the tab `$targetContent` defined by `$target`. Collapses active tab.
  8853. * @param {jQuery} $target - Tab to open.
  8854. * @param {boolean} historyHandled - browser has already handled a history update
  8855. * @fires Tabs#change
  8856. * @function
  8857. */
  8858. }, {
  8859. key: "_handleTabChange",
  8860. value: function _handleTabChange($target, historyHandled) {
  8861. // With `activeCollapse`, if the target is the active Tab, collapse it.
  8862. if ($target.hasClass("".concat(this.options.linkActiveClass))) {
  8863. if (this.options.activeCollapse) {
  8864. this._collapse();
  8865. }
  8866. return;
  8867. }
  8868. var $oldTab = this.$element.find(".".concat(this.options.linkClass, ".").concat(this.options.linkActiveClass)),
  8869. $tabLink = $target.find('[role="tab"]'),
  8870. target = $tabLink.attr('data-tabs-target'),
  8871. anchor = target && target.length ? "#".concat(target) : $tabLink[0].hash,
  8872. $targetContent = this.$tabContent.find(anchor); //close old tab
  8873. this._collapseTab($oldTab); //open new tab
  8874. this._openTab($target); //either replace or update browser history
  8875. if (this.options.deepLink && !historyHandled) {
  8876. if (this.options.updateHistory) {
  8877. history.pushState({}, '', anchor);
  8878. } else {
  8879. history.replaceState({}, '', anchor);
  8880. }
  8881. }
  8882. /**
  8883. * Fires when the plugin has successfully changed tabs.
  8884. * @event Tabs#change
  8885. */
  8886. this.$element.trigger('change.zf.tabs', [$target, $targetContent]); //fire to children a mutation event
  8887. $targetContent.find("[data-mutate]").trigger("mutateme.zf.trigger");
  8888. }
  8889. /**
  8890. * Opens the tab `$targetContent` defined by `$target`.
  8891. * @param {jQuery} $target - Tab to open.
  8892. * @function
  8893. */
  8894. }, {
  8895. key: "_openTab",
  8896. value: function _openTab($target) {
  8897. var $tabLink = $target.find('[role="tab"]'),
  8898. hash = $tabLink.attr('data-tabs-target') || $tabLink[0].hash.slice(1),
  8899. $targetContent = this.$tabContent.find("#".concat(hash));
  8900. $target.addClass("".concat(this.options.linkActiveClass));
  8901. $tabLink.attr({
  8902. 'aria-selected': 'true',
  8903. 'tabindex': '0'
  8904. });
  8905. $targetContent.addClass("".concat(this.options.panelActiveClass)).removeAttr('aria-hidden');
  8906. }
  8907. /**
  8908. * Collapses `$targetContent` defined by `$target`.
  8909. * @param {jQuery} $target - Tab to collapse.
  8910. * @function
  8911. */
  8912. }, {
  8913. key: "_collapseTab",
  8914. value: function _collapseTab($target) {
  8915. var $target_anchor = $target.removeClass("".concat(this.options.linkActiveClass)).find('[role="tab"]').attr({
  8916. 'aria-selected': 'false',
  8917. 'tabindex': -1
  8918. });
  8919. $("#".concat($target_anchor.attr('aria-controls'))).removeClass("".concat(this.options.panelActiveClass)).attr({
  8920. 'aria-hidden': 'true'
  8921. });
  8922. }
  8923. /**
  8924. * Collapses the active Tab.
  8925. * @fires Tabs#collapse
  8926. * @function
  8927. */
  8928. }, {
  8929. key: "_collapse",
  8930. value: function _collapse() {
  8931. var $activeTab = this.$element.find(".".concat(this.options.linkClass, ".").concat(this.options.linkActiveClass));
  8932. if ($activeTab.length) {
  8933. this._collapseTab($activeTab);
  8934. /**
  8935. * Fires when the plugin has successfully collapsed tabs.
  8936. * @event Tabs#collapse
  8937. */
  8938. this.$element.trigger('collapse.zf.tabs', [$activeTab]);
  8939. }
  8940. }
  8941. /**
  8942. * Public method for selecting a content pane to display.
  8943. * @param {jQuery | String} elem - jQuery object or string of the id of the pane to display.
  8944. * @param {boolean} historyHandled - browser has already handled a history update
  8945. * @function
  8946. */
  8947. }, {
  8948. key: "selectTab",
  8949. value: function selectTab(elem, historyHandled) {
  8950. var idStr;
  8951. if (_typeof(elem) === 'object') {
  8952. idStr = elem[0].id;
  8953. } else {
  8954. idStr = elem;
  8955. }
  8956. if (idStr.indexOf('#') < 0) {
  8957. idStr = "#".concat(idStr);
  8958. }
  8959. var $target = this.$tabTitles.has("[href$=\"".concat(idStr, "\"]"));
  8960. this._handleTabChange($target, historyHandled);
  8961. }
  8962. }, {
  8963. key: "_setHeight",
  8964. /**
  8965. * Sets the height of each panel to the height of the tallest panel.
  8966. * If enabled in options, gets called on media query change.
  8967. * If loading content via external source, can be called directly or with _reflow.
  8968. * If enabled with `data-match-height="true"`, tabs sets to equal height
  8969. * @function
  8970. * @private
  8971. */
  8972. value: function _setHeight() {
  8973. var max = 0,
  8974. _this = this; // Lock down the `this` value for the root tabs object
  8975. this.$tabContent.find(".".concat(this.options.panelClass)).css('height', '').each(function () {
  8976. var panel = $(this),
  8977. isActive = panel.hasClass("".concat(_this.options.panelActiveClass)); // get the options from the parent instead of trying to get them from the child
  8978. if (!isActive) {
  8979. panel.css({
  8980. 'visibility': 'hidden',
  8981. 'display': 'block'
  8982. });
  8983. }
  8984. var temp = this.getBoundingClientRect().height;
  8985. if (!isActive) {
  8986. panel.css({
  8987. 'visibility': '',
  8988. 'display': ''
  8989. });
  8990. }
  8991. max = temp > max ? temp : max;
  8992. }).css('height', "".concat(max, "px"));
  8993. }
  8994. /**
  8995. * Destroys an instance of tabs.
  8996. * @fires Tabs#destroyed
  8997. */
  8998. }, {
  8999. key: "_destroy",
  9000. value: function _destroy() {
  9001. this.$element.find(".".concat(this.options.linkClass)).off('.zf.tabs').hide().end().find(".".concat(this.options.panelClass)).hide();
  9002. if (this.options.matchHeight) {
  9003. if (this._setHeightMqHandler != null) {
  9004. $(window).off('changed.zf.mediaquery', this._setHeightMqHandler);
  9005. }
  9006. }
  9007. if (this.options.deepLink) {
  9008. $(window).off('hashchange', this._checkDeepLink);
  9009. }
  9010. if (this.onLoadListener) {
  9011. $(window).off(this.onLoadListener);
  9012. }
  9013. }
  9014. }]);
  9015. return Tabs;
  9016. }(Plugin);
  9017. Tabs.defaults = {
  9018. /**
  9019. * Link the location hash to the active pane.
  9020. * Set the location hash when the active pane changes, and open the corresponding pane when the location changes.
  9021. * @option
  9022. * @type {boolean}
  9023. * @default false
  9024. */
  9025. deepLink: false,
  9026. /**
  9027. * If `deepLink` is enabled, adjust the deep link scroll to make sure the top of the tab panel is visible
  9028. * @option
  9029. * @type {boolean}
  9030. * @default false
  9031. */
  9032. deepLinkSmudge: false,
  9033. /**
  9034. * If `deepLinkSmudge` is enabled, animation time (ms) for the deep link adjustment
  9035. * @option
  9036. * @type {number}
  9037. * @default 300
  9038. */
  9039. deepLinkSmudgeDelay: 300,
  9040. /**
  9041. * If `deepLink` is enabled, update the browser history with the open tab
  9042. * @option
  9043. * @type {boolean}
  9044. * @default false
  9045. */
  9046. updateHistory: false,
  9047. /**
  9048. * Allows the window to scroll to content of active pane on load.
  9049. * Not recommended if more than one tab panel per page.
  9050. * @option
  9051. * @type {boolean}
  9052. * @default false
  9053. */
  9054. autoFocus: false,
  9055. /**
  9056. * Allows keyboard input to 'wrap' around the tab links.
  9057. * @option
  9058. * @type {boolean}
  9059. * @default true
  9060. */
  9061. wrapOnKeys: true,
  9062. /**
  9063. * Allows the tab content panes to match heights if set to true.
  9064. * @option
  9065. * @type {boolean}
  9066. * @default false
  9067. */
  9068. matchHeight: false,
  9069. /**
  9070. * Allows active tabs to collapse when clicked.
  9071. * @option
  9072. * @type {boolean}
  9073. * @default false
  9074. */
  9075. activeCollapse: false,
  9076. /**
  9077. * Class applied to `li`'s in tab link list.
  9078. * @option
  9079. * @type {string}
  9080. * @default 'tabs-title'
  9081. */
  9082. linkClass: 'tabs-title',
  9083. /**
  9084. * Class applied to the active `li` in tab link list.
  9085. * @option
  9086. * @type {string}
  9087. * @default 'is-active'
  9088. */
  9089. linkActiveClass: 'is-active',
  9090. /**
  9091. * Class applied to the content containers.
  9092. * @option
  9093. * @type {string}
  9094. * @default 'tabs-panel'
  9095. */
  9096. panelClass: 'tabs-panel',
  9097. /**
  9098. * Class applied to the active content container.
  9099. * @option
  9100. * @type {string}
  9101. * @default 'is-active'
  9102. */
  9103. panelActiveClass: 'is-active'
  9104. };
  9105. /**
  9106. * Toggler module.
  9107. * @module foundation.toggler
  9108. * @requires foundation.util.motion
  9109. * @requires foundation.util.triggers
  9110. */
  9111. var Toggler =
  9112. /*#__PURE__*/
  9113. function (_Plugin) {
  9114. _inherits(Toggler, _Plugin);
  9115. function Toggler() {
  9116. _classCallCheck(this, Toggler);
  9117. return _possibleConstructorReturn(this, _getPrototypeOf(Toggler).apply(this, arguments));
  9118. }
  9119. _createClass(Toggler, [{
  9120. key: "_setup",
  9121. /**
  9122. * Creates a new instance of Toggler.
  9123. * @class
  9124. * @name Toggler
  9125. * @fires Toggler#init
  9126. * @param {Object} element - jQuery object to add the trigger to.
  9127. * @param {Object} options - Overrides to the default plugin settings.
  9128. */
  9129. value: function _setup(element, options) {
  9130. this.$element = element;
  9131. this.options = $.extend({}, Toggler.defaults, element.data(), options);
  9132. this.className = '';
  9133. this.className = 'Toggler'; // ie9 back compat
  9134. // Triggers init is idempotent, just need to make sure it is initialized
  9135. Triggers.init($);
  9136. this._init();
  9137. this._events();
  9138. }
  9139. /**
  9140. * Initializes the Toggler plugin by parsing the toggle class from data-toggler, or animation classes from data-animate.
  9141. * @function
  9142. * @private
  9143. */
  9144. }, {
  9145. key: "_init",
  9146. value: function _init() {
  9147. var input; // Parse animation classes if they were set
  9148. if (this.options.animate) {
  9149. input = this.options.animate.split(' ');
  9150. this.animationIn = input[0];
  9151. this.animationOut = input[1] || null;
  9152. } // Otherwise, parse toggle class
  9153. else {
  9154. input = this.$element.data('toggler'); // Allow for a . at the beginning of the string
  9155. this.className = input[0] === '.' ? input.slice(1) : input;
  9156. } // Add ARIA attributes to triggers:
  9157. var id = this.$element[0].id,
  9158. $triggers = $("[data-open~=\"".concat(id, "\"], [data-close~=\"").concat(id, "\"], [data-toggle~=\"").concat(id, "\"]")); // - aria-expanded: according to the element visibility.
  9159. $triggers.attr('aria-expanded', !this.$element.is(':hidden')); // - aria-controls: adding the element id to it if not already in it.
  9160. $triggers.each(function (index, trigger) {
  9161. var $trigger = $(trigger);
  9162. var controls = $trigger.attr('aria-controls') || '';
  9163. var containsId = new RegExp("\\b".concat(RegExpEscape(id), "\\b")).test(controls);
  9164. if (!containsId) $trigger.attr('aria-controls', controls ? "".concat(controls, " ").concat(id) : id);
  9165. });
  9166. }
  9167. /**
  9168. * Initializes events for the toggle trigger.
  9169. * @function
  9170. * @private
  9171. */
  9172. }, {
  9173. key: "_events",
  9174. value: function _events() {
  9175. this.$element.off('toggle.zf.trigger').on('toggle.zf.trigger', this.toggle.bind(this));
  9176. }
  9177. /**
  9178. * Toggles the target class on the target element. An event is fired from the original trigger depending on if the resultant state was "on" or "off".
  9179. * @function
  9180. * @fires Toggler#on
  9181. * @fires Toggler#off
  9182. */
  9183. }, {
  9184. key: "toggle",
  9185. value: function toggle() {
  9186. this[this.options.animate ? '_toggleAnimate' : '_toggleClass']();
  9187. }
  9188. }, {
  9189. key: "_toggleClass",
  9190. value: function _toggleClass() {
  9191. this.$element.toggleClass(this.className);
  9192. var isOn = this.$element.hasClass(this.className);
  9193. if (isOn) {
  9194. /**
  9195. * Fires if the target element has the class after a toggle.
  9196. * @event Toggler#on
  9197. */
  9198. this.$element.trigger('on.zf.toggler');
  9199. } else {
  9200. /**
  9201. * Fires if the target element does not have the class after a toggle.
  9202. * @event Toggler#off
  9203. */
  9204. this.$element.trigger('off.zf.toggler');
  9205. }
  9206. this._updateARIA(isOn);
  9207. this.$element.find('[data-mutate]').trigger('mutateme.zf.trigger');
  9208. }
  9209. }, {
  9210. key: "_toggleAnimate",
  9211. value: function _toggleAnimate() {
  9212. var _this = this;
  9213. if (this.$element.is(':hidden')) {
  9214. Motion.animateIn(this.$element, this.animationIn, function () {
  9215. _this._updateARIA(true);
  9216. this.trigger('on.zf.toggler');
  9217. this.find('[data-mutate]').trigger('mutateme.zf.trigger');
  9218. });
  9219. } else {
  9220. Motion.animateOut(this.$element, this.animationOut, function () {
  9221. _this._updateARIA(false);
  9222. this.trigger('off.zf.toggler');
  9223. this.find('[data-mutate]').trigger('mutateme.zf.trigger');
  9224. });
  9225. }
  9226. }
  9227. }, {
  9228. key: "_updateARIA",
  9229. value: function _updateARIA(isOn) {
  9230. var id = this.$element[0].id;
  9231. $("[data-open=\"".concat(id, "\"], [data-close=\"").concat(id, "\"], [data-toggle=\"").concat(id, "\"]")).attr({
  9232. 'aria-expanded': isOn ? true : false
  9233. });
  9234. }
  9235. /**
  9236. * Destroys the instance of Toggler on the element.
  9237. * @function
  9238. */
  9239. }, {
  9240. key: "_destroy",
  9241. value: function _destroy() {
  9242. this.$element.off('.zf.toggler');
  9243. }
  9244. }]);
  9245. return Toggler;
  9246. }(Plugin);
  9247. Toggler.defaults = {
  9248. /**
  9249. * Tells the plugin if the element should animated when toggled.
  9250. * @option
  9251. * @type {boolean}
  9252. * @default false
  9253. */
  9254. animate: false
  9255. };
  9256. /**
  9257. * Tooltip module.
  9258. * @module foundation.tooltip
  9259. * @requires foundation.util.box
  9260. * @requires foundation.util.mediaQuery
  9261. * @requires foundation.util.triggers
  9262. */
  9263. var Tooltip =
  9264. /*#__PURE__*/
  9265. function (_Positionable) {
  9266. _inherits(Tooltip, _Positionable);
  9267. function Tooltip() {
  9268. _classCallCheck(this, Tooltip);
  9269. return _possibleConstructorReturn(this, _getPrototypeOf(Tooltip).apply(this, arguments));
  9270. }
  9271. _createClass(Tooltip, [{
  9272. key: "_setup",
  9273. /**
  9274. * Creates a new instance of a Tooltip.
  9275. * @class
  9276. * @name Tooltip
  9277. * @fires Tooltip#init
  9278. * @param {jQuery} element - jQuery object to attach a tooltip to.
  9279. * @param {Object} options - object to extend the default configuration.
  9280. */
  9281. value: function _setup(element, options) {
  9282. this.$element = element;
  9283. this.options = $.extend({}, Tooltip.defaults, this.$element.data(), options);
  9284. this.className = 'Tooltip'; // ie9 back compat
  9285. this.isActive = false;
  9286. this.isClick = false; // Triggers init is idempotent, just need to make sure it is initialized
  9287. Triggers.init($);
  9288. this._init();
  9289. }
  9290. /**
  9291. * Initializes the tooltip by setting the creating the tip element, adding it's text, setting private variables and setting attributes on the anchor.
  9292. * @private
  9293. */
  9294. }, {
  9295. key: "_init",
  9296. value: function _init() {
  9297. MediaQuery._init();
  9298. var elemId = this.$element.attr('aria-describedby') || GetYoDigits(6, 'tooltip');
  9299. this.options.tipText = this.options.tipText || this.$element.attr('title');
  9300. this.template = this.options.template ? $(this.options.template) : this._buildTemplate(elemId);
  9301. if (this.options.allowHtml) {
  9302. this.template.appendTo(document.body).html(this.options.tipText).hide();
  9303. } else {
  9304. this.template.appendTo(document.body).text(this.options.tipText).hide();
  9305. }
  9306. this.$element.attr({
  9307. 'title': '',
  9308. 'aria-describedby': elemId,
  9309. 'data-yeti-box': elemId,
  9310. 'data-toggle': elemId,
  9311. 'data-resize': elemId
  9312. }).addClass(this.options.triggerClass);
  9313. _get(_getPrototypeOf(Tooltip.prototype), "_init", this).call(this);
  9314. this._events();
  9315. }
  9316. }, {
  9317. key: "_getDefaultPosition",
  9318. value: function _getDefaultPosition() {
  9319. // handle legacy classnames
  9320. var position = this.$element[0].className.match(/\b(top|left|right|bottom)\b/g);
  9321. return position ? position[0] : 'top';
  9322. }
  9323. }, {
  9324. key: "_getDefaultAlignment",
  9325. value: function _getDefaultAlignment() {
  9326. return 'center';
  9327. }
  9328. }, {
  9329. key: "_getHOffset",
  9330. value: function _getHOffset() {
  9331. if (this.position === 'left' || this.position === 'right') {
  9332. return this.options.hOffset + this.options.tooltipWidth;
  9333. } else {
  9334. return this.options.hOffset;
  9335. }
  9336. }
  9337. }, {
  9338. key: "_getVOffset",
  9339. value: function _getVOffset() {
  9340. if (this.position === 'top' || this.position === 'bottom') {
  9341. return this.options.vOffset + this.options.tooltipHeight;
  9342. } else {
  9343. return this.options.vOffset;
  9344. }
  9345. }
  9346. /**
  9347. * builds the tooltip element, adds attributes, and returns the template.
  9348. * @private
  9349. */
  9350. }, {
  9351. key: "_buildTemplate",
  9352. value: function _buildTemplate(id) {
  9353. var templateClasses = "".concat(this.options.tooltipClass, " ").concat(this.options.templateClasses).trim();
  9354. var $template = $('<div></div>').addClass(templateClasses).attr({
  9355. 'role': 'tooltip',
  9356. 'aria-hidden': true,
  9357. 'data-is-active': false,
  9358. 'data-is-focus': false,
  9359. 'id': id
  9360. });
  9361. return $template;
  9362. }
  9363. /**
  9364. * sets the position class of an element and recursively calls itself until there are no more possible positions to attempt, or the tooltip element is no longer colliding.
  9365. * if the tooltip is larger than the screen width, default to full width - any user selected margin
  9366. * @private
  9367. */
  9368. }, {
  9369. key: "_setPosition",
  9370. value: function _setPosition() {
  9371. _get(_getPrototypeOf(Tooltip.prototype), "_setPosition", this).call(this, this.$element, this.template);
  9372. }
  9373. /**
  9374. * reveals the tooltip, and fires an event to close any other open tooltips on the page
  9375. * @fires Tooltip#closeme
  9376. * @fires Tooltip#show
  9377. * @function
  9378. */
  9379. }, {
  9380. key: "show",
  9381. value: function show() {
  9382. if (this.options.showOn !== 'all' && !MediaQuery.is(this.options.showOn)) {
  9383. // console.error('The screen is too small to display this tooltip');
  9384. return false;
  9385. }
  9386. var _this = this;
  9387. this.template.css('visibility', 'hidden').show();
  9388. this._setPosition();
  9389. this.template.removeClass('top bottom left right').addClass(this.position);
  9390. this.template.removeClass('align-top align-bottom align-left align-right align-center').addClass('align-' + this.alignment);
  9391. /**
  9392. * Fires to close all other open tooltips on the page
  9393. * @event Closeme#tooltip
  9394. */
  9395. this.$element.trigger('closeme.zf.tooltip', this.template.attr('id'));
  9396. this.template.attr({
  9397. 'data-is-active': true,
  9398. 'aria-hidden': false
  9399. });
  9400. _this.isActive = true; // console.log(this.template);
  9401. this.template.stop().hide().css('visibility', '').fadeIn(this.options.fadeInDuration, function () {//maybe do stuff?
  9402. });
  9403. /**
  9404. * Fires when the tooltip is shown
  9405. * @event Tooltip#show
  9406. */
  9407. this.$element.trigger('show.zf.tooltip');
  9408. }
  9409. /**
  9410. * Hides the current tooltip, and resets the positioning class if it was changed due to collision
  9411. * @fires Tooltip#hide
  9412. * @function
  9413. */
  9414. }, {
  9415. key: "hide",
  9416. value: function hide() {
  9417. // console.log('hiding', this.$element.data('yeti-box'));
  9418. var _this = this;
  9419. this.template.stop().attr({
  9420. 'aria-hidden': true,
  9421. 'data-is-active': false
  9422. }).fadeOut(this.options.fadeOutDuration, function () {
  9423. _this.isActive = false;
  9424. _this.isClick = false;
  9425. });
  9426. /**
  9427. * fires when the tooltip is hidden
  9428. * @event Tooltip#hide
  9429. */
  9430. this.$element.trigger('hide.zf.tooltip');
  9431. }
  9432. /**
  9433. * adds event listeners for the tooltip and its anchor
  9434. * TODO combine some of the listeners like focus and mouseenter, etc.
  9435. * @private
  9436. */
  9437. }, {
  9438. key: "_events",
  9439. value: function _events() {
  9440. var _this = this;
  9441. var $template = this.template;
  9442. var isFocus = false;
  9443. if (!this.options.disableHover) {
  9444. this.$element.on('mouseenter.zf.tooltip', function (e) {
  9445. if (!_this.isActive) {
  9446. _this.timeout = setTimeout(function () {
  9447. _this.show();
  9448. }, _this.options.hoverDelay);
  9449. }
  9450. }).on('mouseleave.zf.tooltip', ignoreMousedisappear(function (e) {
  9451. clearTimeout(_this.timeout);
  9452. if (!isFocus || _this.isClick && !_this.options.clickOpen) {
  9453. _this.hide();
  9454. }
  9455. }));
  9456. }
  9457. if (this.options.clickOpen) {
  9458. this.$element.on('mousedown.zf.tooltip', function (e) {
  9459. e.stopImmediatePropagation();
  9460. if (_this.isClick) ; else {
  9461. _this.isClick = true;
  9462. if ((_this.options.disableHover || !_this.$element.attr('tabindex')) && !_this.isActive) {
  9463. _this.show();
  9464. }
  9465. }
  9466. });
  9467. } else {
  9468. this.$element.on('mousedown.zf.tooltip', function (e) {
  9469. e.stopImmediatePropagation();
  9470. _this.isClick = true;
  9471. });
  9472. }
  9473. if (!this.options.disableForTouch) {
  9474. this.$element.on('tap.zf.tooltip touchend.zf.tooltip', function (e) {
  9475. _this.isActive ? _this.hide() : _this.show();
  9476. });
  9477. }
  9478. this.$element.on({
  9479. // 'toggle.zf.trigger': this.toggle.bind(this),
  9480. // 'close.zf.trigger': this.hide.bind(this)
  9481. 'close.zf.trigger': this.hide.bind(this)
  9482. });
  9483. this.$element.on('focus.zf.tooltip', function (e) {
  9484. isFocus = true;
  9485. if (_this.isClick) {
  9486. // If we're not showing open on clicks, we need to pretend a click-launched focus isn't
  9487. // a real focus, otherwise on hover and come back we get bad behavior
  9488. if (!_this.options.clickOpen) {
  9489. isFocus = false;
  9490. }
  9491. return false;
  9492. } else {
  9493. _this.show();
  9494. }
  9495. }).on('focusout.zf.tooltip', function (e) {
  9496. isFocus = false;
  9497. _this.isClick = false;
  9498. _this.hide();
  9499. }).on('resizeme.zf.trigger', function () {
  9500. if (_this.isActive) {
  9501. _this._setPosition();
  9502. }
  9503. });
  9504. }
  9505. /**
  9506. * adds a toggle method, in addition to the static show() & hide() functions
  9507. * @function
  9508. */
  9509. }, {
  9510. key: "toggle",
  9511. value: function toggle() {
  9512. if (this.isActive) {
  9513. this.hide();
  9514. } else {
  9515. this.show();
  9516. }
  9517. }
  9518. /**
  9519. * Destroys an instance of tooltip, removes template element from the view.
  9520. * @function
  9521. */
  9522. }, {
  9523. key: "_destroy",
  9524. value: function _destroy() {
  9525. this.$element.attr('title', this.template.text()).off('.zf.trigger .zf.tooltip').removeClass(this.options.triggerClass).removeClass('top right left bottom').removeAttr('aria-describedby data-disable-hover data-resize data-toggle data-tooltip data-yeti-box');
  9526. this.template.remove();
  9527. }
  9528. }]);
  9529. return Tooltip;
  9530. }(Positionable);
  9531. Tooltip.defaults = {
  9532. disableForTouch: false,
  9533. /**
  9534. * Time, in ms, before a tooltip should open on hover.
  9535. * @option
  9536. * @type {number}
  9537. * @default 200
  9538. */
  9539. hoverDelay: 200,
  9540. /**
  9541. * Time, in ms, a tooltip should take to fade into view.
  9542. * @option
  9543. * @type {number}
  9544. * @default 150
  9545. */
  9546. fadeInDuration: 150,
  9547. /**
  9548. * Time, in ms, a tooltip should take to fade out of view.
  9549. * @option
  9550. * @type {number}
  9551. * @default 150
  9552. */
  9553. fadeOutDuration: 150,
  9554. /**
  9555. * Disables hover events from opening the tooltip if set to true
  9556. * @option
  9557. * @type {boolean}
  9558. * @default false
  9559. */
  9560. disableHover: false,
  9561. /**
  9562. * Optional addtional classes to apply to the tooltip template on init.
  9563. * @option
  9564. * @type {string}
  9565. * @default ''
  9566. */
  9567. templateClasses: '',
  9568. /**
  9569. * Non-optional class added to tooltip templates. Foundation default is 'tooltip'.
  9570. * @option
  9571. * @type {string}
  9572. * @default 'tooltip'
  9573. */
  9574. tooltipClass: 'tooltip',
  9575. /**
  9576. * Class applied to the tooltip anchor element.
  9577. * @option
  9578. * @type {string}
  9579. * @default 'has-tip'
  9580. */
  9581. triggerClass: 'has-tip',
  9582. /**
  9583. * Minimum breakpoint size at which to open the tooltip.
  9584. * @option
  9585. * @type {string}
  9586. * @default 'small'
  9587. */
  9588. showOn: 'small',
  9589. /**
  9590. * Custom template to be used to generate markup for tooltip.
  9591. * @option
  9592. * @type {string}
  9593. * @default ''
  9594. */
  9595. template: '',
  9596. /**
  9597. * Text displayed in the tooltip template on open.
  9598. * @option
  9599. * @type {string}
  9600. * @default ''
  9601. */
  9602. tipText: '',
  9603. touchCloseText: 'Tap to close.',
  9604. /**
  9605. * Allows the tooltip to remain open if triggered with a click or touch event.
  9606. * @option
  9607. * @type {boolean}
  9608. * @default true
  9609. */
  9610. clickOpen: true,
  9611. /**
  9612. * Position of tooltip. Can be left, right, bottom, top, or auto.
  9613. * @option
  9614. * @type {string}
  9615. * @default 'auto'
  9616. */
  9617. position: 'auto',
  9618. /**
  9619. * Alignment of tooltip relative to anchor. Can be left, right, bottom, top, center, or auto.
  9620. * @option
  9621. * @type {string}
  9622. * @default 'auto'
  9623. */
  9624. alignment: 'auto',
  9625. /**
  9626. * Allow overlap of container/window. If false, tooltip will first try to
  9627. * position as defined by data-position and data-alignment, but reposition if
  9628. * it would cause an overflow. @option
  9629. * @type {boolean}
  9630. * @default false
  9631. */
  9632. allowOverlap: false,
  9633. /**
  9634. * Allow overlap of only the bottom of the container. This is the most common
  9635. * behavior for dropdowns, allowing the dropdown to extend the bottom of the
  9636. * screen but not otherwise influence or break out of the container.
  9637. * Less common for tooltips.
  9638. * @option
  9639. * @type {boolean}
  9640. * @default false
  9641. */
  9642. allowBottomOverlap: false,
  9643. /**
  9644. * Distance, in pixels, the template should push away from the anchor on the Y axis.
  9645. * @option
  9646. * @type {number}
  9647. * @default 0
  9648. */
  9649. vOffset: 0,
  9650. /**
  9651. * Distance, in pixels, the template should push away from the anchor on the X axis
  9652. * @option
  9653. * @type {number}
  9654. * @default 0
  9655. */
  9656. hOffset: 0,
  9657. /**
  9658. * Distance, in pixels, the template spacing auto-adjust for a vertical tooltip
  9659. * @option
  9660. * @type {number}
  9661. * @default 14
  9662. */
  9663. tooltipHeight: 14,
  9664. /**
  9665. * Distance, in pixels, the template spacing auto-adjust for a horizontal tooltip
  9666. * @option
  9667. * @type {number}
  9668. * @default 12
  9669. */
  9670. tooltipWidth: 12,
  9671. /**
  9672. * Allow HTML in tooltip. Warning: If you are loading user-generated content into tooltips,
  9673. * allowing HTML may open yourself up to XSS attacks.
  9674. * @option
  9675. * @type {boolean}
  9676. * @default false
  9677. */
  9678. allowHtml: false
  9679. };
  9680. var MenuPlugins$1 = {
  9681. tabs: {
  9682. cssClass: 'tabs',
  9683. plugin: Tabs
  9684. },
  9685. accordion: {
  9686. cssClass: 'accordion',
  9687. plugin: Accordion
  9688. }
  9689. };
  9690. /**
  9691. * ResponsiveAccordionTabs module.
  9692. * @module foundation.responsiveAccordionTabs
  9693. * @requires foundation.util.motion
  9694. * @requires foundation.accordion
  9695. * @requires foundation.tabs
  9696. */
  9697. var ResponsiveAccordionTabs =
  9698. /*#__PURE__*/
  9699. function (_Plugin) {
  9700. _inherits(ResponsiveAccordionTabs, _Plugin);
  9701. function ResponsiveAccordionTabs() {
  9702. _classCallCheck(this, ResponsiveAccordionTabs);
  9703. return _possibleConstructorReturn(this, _getPrototypeOf(ResponsiveAccordionTabs).apply(this, arguments));
  9704. }
  9705. _createClass(ResponsiveAccordionTabs, [{
  9706. key: "_setup",
  9707. /**
  9708. * Creates a new instance of a responsive accordion tabs.
  9709. * @class
  9710. * @name ResponsiveAccordionTabs
  9711. * @fires ResponsiveAccordionTabs#init
  9712. * @param {jQuery} element - jQuery object to make into Responsive Accordion Tabs.
  9713. * @param {Object} options - Overrides to the default plugin settings.
  9714. */
  9715. value: function _setup(element, options) {
  9716. this.$element = $(element);
  9717. this.options = $.extend({}, this.$element.data(), options);
  9718. this.rules = this.$element.data('responsive-accordion-tabs');
  9719. this.currentMq = null;
  9720. this.currentPlugin = null;
  9721. this.className = 'ResponsiveAccordionTabs'; // ie9 back compat
  9722. if (!this.$element.attr('id')) {
  9723. this.$element.attr('id', GetYoDigits(6, 'responsiveaccordiontabs'));
  9724. }
  9725. this._init();
  9726. this._events();
  9727. }
  9728. /**
  9729. * Initializes the Menu by parsing the classes from the 'data-responsive-accordion-tabs' attribute on the element.
  9730. * @function
  9731. * @private
  9732. */
  9733. }, {
  9734. key: "_init",
  9735. value: function _init() {
  9736. MediaQuery._init(); // The first time an Interchange plugin is initialized, this.rules is converted from a string of "classes" to an object of rules
  9737. if (typeof this.rules === 'string') {
  9738. var rulesTree = {}; // Parse rules from "classes" pulled from data attribute
  9739. var rules = this.rules.split(' '); // Iterate through every rule found
  9740. for (var i = 0; i < rules.length; i++) {
  9741. var rule = rules[i].split('-');
  9742. var ruleSize = rule.length > 1 ? rule[0] : 'small';
  9743. var rulePlugin = rule.length > 1 ? rule[1] : rule[0];
  9744. if (MenuPlugins$1[rulePlugin] !== null) {
  9745. rulesTree[ruleSize] = MenuPlugins$1[rulePlugin];
  9746. }
  9747. }
  9748. this.rules = rulesTree;
  9749. }
  9750. this._getAllOptions();
  9751. if (!$.isEmptyObject(this.rules)) {
  9752. this._checkMediaQueries();
  9753. }
  9754. }
  9755. }, {
  9756. key: "_getAllOptions",
  9757. value: function _getAllOptions() {
  9758. //get all defaults and options
  9759. var _this = this;
  9760. _this.allOptions = {};
  9761. for (var key in MenuPlugins$1) {
  9762. if (MenuPlugins$1.hasOwnProperty(key)) {
  9763. var obj = MenuPlugins$1[key];
  9764. try {
  9765. var dummyPlugin = $('<ul></ul>');
  9766. var tmpPlugin = new obj.plugin(dummyPlugin, _this.options);
  9767. for (var keyKey in tmpPlugin.options) {
  9768. if (tmpPlugin.options.hasOwnProperty(keyKey) && keyKey !== 'zfPlugin') {
  9769. var objObj = tmpPlugin.options[keyKey];
  9770. _this.allOptions[keyKey] = objObj;
  9771. }
  9772. }
  9773. tmpPlugin.destroy();
  9774. } catch (e) {}
  9775. }
  9776. }
  9777. }
  9778. /**
  9779. * Initializes events for the Menu.
  9780. * @function
  9781. * @private
  9782. */
  9783. }, {
  9784. key: "_events",
  9785. value: function _events() {
  9786. this._changedZfMediaQueryHandler = this._checkMediaQueries.bind(this);
  9787. $(window).on('changed.zf.mediaquery', this._changedZfMediaQueryHandler);
  9788. }
  9789. /**
  9790. * Checks the current screen width against available media queries. If the media query has changed, and the plugin needed has changed, the plugins will swap out.
  9791. * @function
  9792. * @private
  9793. */
  9794. }, {
  9795. key: "_checkMediaQueries",
  9796. value: function _checkMediaQueries() {
  9797. var matchedMq,
  9798. _this = this; // Iterate through each rule and find the last matching rule
  9799. $.each(this.rules, function (key) {
  9800. if (MediaQuery.atLeast(key)) {
  9801. matchedMq = key;
  9802. }
  9803. }); // No match? No dice
  9804. if (!matchedMq) return; // Plugin already initialized? We good
  9805. if (this.currentPlugin instanceof this.rules[matchedMq].plugin) return; // Remove existing plugin-specific CSS classes
  9806. $.each(MenuPlugins$1, function (key, value) {
  9807. _this.$element.removeClass(value.cssClass);
  9808. }); // Add the CSS class for the new plugin
  9809. this.$element.addClass(this.rules[matchedMq].cssClass); // Create an instance of the new plugin
  9810. if (this.currentPlugin) {
  9811. //don't know why but on nested elements data zfPlugin get's lost
  9812. if (!this.currentPlugin.$element.data('zfPlugin') && this.storezfData) this.currentPlugin.$element.data('zfPlugin', this.storezfData);
  9813. this.currentPlugin.destroy();
  9814. }
  9815. this._handleMarkup(this.rules[matchedMq].cssClass);
  9816. this.currentPlugin = new this.rules[matchedMq].plugin(this.$element, {});
  9817. this.storezfData = this.currentPlugin.$element.data('zfPlugin');
  9818. }
  9819. }, {
  9820. key: "_handleMarkup",
  9821. value: function _handleMarkup(toSet) {
  9822. var _this = this,
  9823. fromString = 'accordion';
  9824. var $panels = $('[data-tabs-content=' + this.$element.attr('id') + ']');
  9825. if ($panels.length) fromString = 'tabs';
  9826. if (fromString === toSet) {
  9827. return;
  9828. }
  9829. var tabsTitle = _this.allOptions.linkClass ? _this.allOptions.linkClass : 'tabs-title';
  9830. var tabsPanel = _this.allOptions.panelClass ? _this.allOptions.panelClass : 'tabs-panel';
  9831. this.$element.removeAttr('role');
  9832. var $liHeads = this.$element.children('.' + tabsTitle + ',[data-accordion-item]').removeClass(tabsTitle).removeClass('accordion-item').removeAttr('data-accordion-item');
  9833. var $liHeadsA = $liHeads.children('a').removeClass('accordion-title');
  9834. if (fromString === 'tabs') {
  9835. $panels = $panels.children('.' + tabsPanel).removeClass(tabsPanel).removeAttr('role').removeAttr('aria-hidden').removeAttr('aria-labelledby');
  9836. $panels.children('a').removeAttr('role').removeAttr('aria-controls').removeAttr('aria-selected');
  9837. } else {
  9838. $panels = $liHeads.children('[data-tab-content]').removeClass('accordion-content');
  9839. }
  9840. $panels.css({
  9841. display: '',
  9842. visibility: ''
  9843. });
  9844. $liHeads.css({
  9845. display: '',
  9846. visibility: ''
  9847. });
  9848. if (toSet === 'accordion') {
  9849. $panels.each(function (key, value) {
  9850. $(value).appendTo($liHeads.get(key)).addClass('accordion-content').attr('data-tab-content', '').removeClass('is-active').css({
  9851. height: ''
  9852. });
  9853. $('[data-tabs-content=' + _this.$element.attr('id') + ']').after('<div id="tabs-placeholder-' + _this.$element.attr('id') + '"></div>').detach();
  9854. $liHeads.addClass('accordion-item').attr('data-accordion-item', '');
  9855. $liHeadsA.addClass('accordion-title');
  9856. });
  9857. } else if (toSet === 'tabs') {
  9858. var $tabsContent = $('[data-tabs-content=' + _this.$element.attr('id') + ']');
  9859. var $placeholder = $('#tabs-placeholder-' + _this.$element.attr('id'));
  9860. if ($placeholder.length) {
  9861. $tabsContent = $('<div class="tabs-content"></div>').insertAfter($placeholder).attr('data-tabs-content', _this.$element.attr('id'));
  9862. $placeholder.remove();
  9863. } else {
  9864. $tabsContent = $('<div class="tabs-content"></div>').insertAfter(_this.$element).attr('data-tabs-content', _this.$element.attr('id'));
  9865. }
  9866. $panels.each(function (key, value) {
  9867. var tempValue = $(value).appendTo($tabsContent).addClass(tabsPanel);
  9868. var hash = $liHeadsA.get(key).hash.slice(1);
  9869. var id = $(value).attr('id') || GetYoDigits(6, 'accordion');
  9870. if (hash !== id) {
  9871. if (hash !== '') {
  9872. $(value).attr('id', hash);
  9873. } else {
  9874. hash = id;
  9875. $(value).attr('id', hash);
  9876. $($liHeadsA.get(key)).attr('href', $($liHeadsA.get(key)).attr('href').replace('#', '') + '#' + hash);
  9877. }
  9878. }
  9879. var isActive = $($liHeads.get(key)).hasClass('is-active');
  9880. if (isActive) {
  9881. tempValue.addClass('is-active');
  9882. }
  9883. });
  9884. $liHeads.addClass(tabsTitle);
  9885. }
  9886. }
  9887. /**
  9888. * Destroys the instance of the current plugin on this element, as well as the window resize handler that switches the plugins out.
  9889. * @function
  9890. */
  9891. }, {
  9892. key: "_destroy",
  9893. value: function _destroy() {
  9894. if (this.currentPlugin) this.currentPlugin.destroy();
  9895. $(window).off('changed.zf.mediaquery', this._changedZfMediaQueryHandler);
  9896. }
  9897. }]);
  9898. return ResponsiveAccordionTabs;
  9899. }(Plugin);
  9900. ResponsiveAccordionTabs.defaults = {};
  9901. Foundation.addToJquery($); // Add Foundation Utils to Foundation global namespace for backwards
  9902. // compatibility.
  9903. Foundation.rtl = rtl;
  9904. Foundation.GetYoDigits = GetYoDigits;
  9905. Foundation.transitionend = transitionend;
  9906. Foundation.RegExpEscape = RegExpEscape;
  9907. Foundation.onLoad = onLoad;
  9908. Foundation.Box = Box;
  9909. Foundation.onImagesLoaded = onImagesLoaded;
  9910. Foundation.Keyboard = Keyboard;
  9911. Foundation.MediaQuery = MediaQuery;
  9912. Foundation.Motion = Motion;
  9913. Foundation.Move = Move;
  9914. Foundation.Nest = Nest;
  9915. Foundation.Timer = Timer; // Touch and Triggers previously were almost purely sede effect driven,
  9916. // so no need to add it to Foundation, just init them.
  9917. Touch.init($);
  9918. Triggers.init($, Foundation);
  9919. MediaQuery._init();
  9920. Foundation.plugin(Abide, 'Abide');
  9921. Foundation.plugin(Accordion, 'Accordion');
  9922. Foundation.plugin(AccordionMenu, 'AccordionMenu');
  9923. Foundation.plugin(Drilldown, 'Drilldown');
  9924. Foundation.plugin(Dropdown, 'Dropdown');
  9925. Foundation.plugin(DropdownMenu, 'DropdownMenu');
  9926. Foundation.plugin(Equalizer, 'Equalizer');
  9927. Foundation.plugin(Interchange, 'Interchange');
  9928. Foundation.plugin(Magellan, 'Magellan');
  9929. Foundation.plugin(OffCanvas, 'OffCanvas');
  9930. Foundation.plugin(Orbit, 'Orbit');
  9931. Foundation.plugin(ResponsiveMenu, 'ResponsiveMenu');
  9932. Foundation.plugin(ResponsiveToggle, 'ResponsiveToggle');
  9933. Foundation.plugin(Reveal, 'Reveal');
  9934. Foundation.plugin(Slider, 'Slider');
  9935. Foundation.plugin(SmoothScroll, 'SmoothScroll');
  9936. Foundation.plugin(Sticky, 'Sticky');
  9937. Foundation.plugin(Tabs, 'Tabs');
  9938. Foundation.plugin(Toggler, 'Toggler');
  9939. Foundation.plugin(Tooltip, 'Tooltip');
  9940. Foundation.plugin(ResponsiveAccordionTabs, 'ResponsiveAccordionTabs');
  9941. exports.CoreUtils = foundation_core_utils;
  9942. exports.Core = Foundation;
  9943. exports.Foundation = Foundation;
  9944. exports.Box = Box;
  9945. exports.onImagesLoaded = onImagesLoaded;
  9946. exports.Keyboard = Keyboard;
  9947. exports.MediaQuery = MediaQuery;
  9948. exports.Motion = Motion;
  9949. exports.Move = Move;
  9950. exports.Nest = Nest;
  9951. exports.Timer = Timer;
  9952. exports.Touch = Touch;
  9953. exports.Triggers = Triggers;
  9954. exports.Abide = Abide;
  9955. exports.Accordion = Accordion;
  9956. exports.AccordionMenu = AccordionMenu;
  9957. exports.Drilldown = Drilldown;
  9958. exports.Dropdown = Dropdown;
  9959. exports.DropdownMenu = DropdownMenu;
  9960. exports.Equalizer = Equalizer;
  9961. exports.Interchange = Interchange;
  9962. exports.Magellan = Magellan;
  9963. exports.OffCanvas = OffCanvas;
  9964. exports.Orbit = Orbit;
  9965. exports.ResponsiveMenu = ResponsiveMenu;
  9966. exports.ResponsiveToggle = ResponsiveToggle;
  9967. exports.Reveal = Reveal;
  9968. exports.Slider = Slider;
  9969. exports.SmoothScroll = SmoothScroll;
  9970. exports.Sticky = Sticky;
  9971. exports.Tabs = Tabs;
  9972. exports.Toggler = Toggler;
  9973. exports.Tooltip = Tooltip;
  9974. exports.ResponsiveAccordionTabs = ResponsiveAccordionTabs;
  9975. exports.default = Foundation;
  9976. //# sourceMappingURL=foundation.cjs.js.map