foundation.esm.js 342 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763
  1. import $ from 'jquery';
  2. function _typeof(obj) {
  3. if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
  4. _typeof = function (obj) {
  5. return typeof obj;
  6. };
  7. } else {
  8. _typeof = function (obj) {
  9. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  10. };
  11. }
  12. return _typeof(obj);
  13. }
  14. function _classCallCheck(instance, Constructor) {
  15. if (!(instance instanceof Constructor)) {
  16. throw new TypeError("Cannot call a class as a function");
  17. }
  18. }
  19. function _defineProperties(target, props) {
  20. for (var i = 0; i < props.length; i++) {
  21. var descriptor = props[i];
  22. descriptor.enumerable = descriptor.enumerable || false;
  23. descriptor.configurable = true;
  24. if ("value" in descriptor) descriptor.writable = true;
  25. Object.defineProperty(target, descriptor.key, descriptor);
  26. }
  27. }
  28. function _createClass(Constructor, protoProps, staticProps) {
  29. if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  30. if (staticProps) _defineProperties(Constructor, staticProps);
  31. return Constructor;
  32. }
  33. function _inherits(subClass, superClass) {
  34. if (typeof superClass !== "function" && superClass !== null) {
  35. throw new TypeError("Super expression must either be null or a function");
  36. }
  37. subClass.prototype = Object.create(superClass && superClass.prototype, {
  38. constructor: {
  39. value: subClass,
  40. writable: true,
  41. configurable: true
  42. }
  43. });
  44. if (superClass) _setPrototypeOf(subClass, superClass);
  45. }
  46. function _getPrototypeOf(o) {
  47. _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
  48. return o.__proto__ || Object.getPrototypeOf(o);
  49. };
  50. return _getPrototypeOf(o);
  51. }
  52. function _setPrototypeOf(o, p) {
  53. _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
  54. o.__proto__ = p;
  55. return o;
  56. };
  57. return _setPrototypeOf(o, p);
  58. }
  59. function _assertThisInitialized(self) {
  60. if (self === void 0) {
  61. throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  62. }
  63. return self;
  64. }
  65. function _possibleConstructorReturn(self, call) {
  66. if (call && (typeof call === "object" || typeof call === "function")) {
  67. return call;
  68. }
  69. return _assertThisInitialized(self);
  70. }
  71. function _superPropBase(object, property) {
  72. while (!Object.prototype.hasOwnProperty.call(object, property)) {
  73. object = _getPrototypeOf(object);
  74. if (object === null) break;
  75. }
  76. return object;
  77. }
  78. function _get(target, property, receiver) {
  79. if (typeof Reflect !== "undefined" && Reflect.get) {
  80. _get = Reflect.get;
  81. } else {
  82. _get = function _get(target, property, receiver) {
  83. var base = _superPropBase(target, property);
  84. if (!base) return;
  85. var desc = Object.getOwnPropertyDescriptor(base, property);
  86. if (desc.get) {
  87. return desc.get.call(receiver);
  88. }
  89. return desc.value;
  90. };
  91. }
  92. return _get(target, property, receiver || target);
  93. }
  94. /**
  95. * Returns a boolean for RTL support
  96. */
  97. function rtl() {
  98. return $('html').attr('dir') === 'rtl';
  99. }
  100. /**
  101. * returns a random base-36 uid with namespacing
  102. * @function
  103. * @param {Number} length - number of random base-36 digits desired. Increase for more random strings.
  104. * @param {String} namespace - name of plugin to be incorporated in uid, optional.
  105. * @default {String} '' - if no plugin name is provided, nothing is appended to the uid.
  106. * @returns {String} - unique id
  107. */
  108. function GetYoDigits(length, namespace) {
  109. length = length || 6;
  110. return Math.round(Math.pow(36, length + 1) - Math.random() * Math.pow(36, length)).toString(36).slice(1) + (namespace ? "-".concat(namespace) : '');
  111. }
  112. /**
  113. * Escape a string so it can be used as a regexp pattern
  114. * @function
  115. * @see https://stackoverflow.com/a/9310752/4317384
  116. *
  117. * @param {String} str - string to escape.
  118. * @returns {String} - escaped string
  119. */
  120. function RegExpEscape(str) {
  121. return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
  122. }
  123. function transitionend($elem) {
  124. var transitions = {
  125. 'transition': 'transitionend',
  126. 'WebkitTransition': 'webkitTransitionEnd',
  127. 'MozTransition': 'transitionend',
  128. 'OTransition': 'otransitionend'
  129. };
  130. var elem = document.createElement('div'),
  131. end;
  132. for (var t in transitions) {
  133. if (typeof elem.style[t] !== 'undefined') {
  134. end = transitions[t];
  135. }
  136. }
  137. if (end) {
  138. return end;
  139. } else {
  140. end = setTimeout(function () {
  141. $elem.triggerHandler('transitionend', [$elem]);
  142. }, 1);
  143. return 'transitionend';
  144. }
  145. }
  146. /**
  147. * Return an event type to listen for window load.
  148. *
  149. * If `$elem` is passed, an event will be triggered on `$elem`. If window is already loaded, the event will still be triggered.
  150. * If `handler` is passed, attach it to the event on `$elem`.
  151. * Calling `onLoad` without handler allows you to get the event type that will be triggered before attaching the handler by yourself.
  152. * @function
  153. *
  154. * @param {Object} [] $elem - jQuery element on which the event will be triggered if passed.
  155. * @param {Function} [] handler - function to attach to the event.
  156. * @returns {String} - event type that should or will be triggered.
  157. */
  158. function onLoad($elem, handler) {
  159. var didLoad = document.readyState === 'complete';
  160. var eventType = (didLoad ? '_didLoad' : 'load') + '.zf.util.onLoad';
  161. var cb = function cb() {
  162. return $elem.triggerHandler(eventType);
  163. };
  164. if ($elem) {
  165. if (handler) $elem.one(eventType, handler);
  166. if (didLoad) setTimeout(cb);else $(window).one('load', cb);
  167. }
  168. return eventType;
  169. }
  170. /**
  171. * Retuns an handler for the `mouseleave` that ignore disappeared mouses.
  172. *
  173. * If the mouse "disappeared" from the document (like when going on a browser UI element, See https://git.io/zf-11410),
  174. * the event is ignored.
  175. * - If the `ignoreLeaveWindow` is `true`, the event is ignored when the user actually left the window
  176. * (like by switching to an other window with [Alt]+[Tab]).
  177. * - If the `ignoreReappear` is `true`, the event will be ignored when the mouse will reappear later on the document
  178. * outside of the element it left.
  179. *
  180. * @function
  181. *
  182. * @param {Function} [] handler - handler for the filtered `mouseleave` event to watch.
  183. * @param {Object} [] options - object of options:
  184. * - {Boolean} [false] ignoreLeaveWindow - also ignore when the user switched windows.
  185. * - {Boolean} [false] ignoreReappear - also ignore when the mouse reappeared outside of the element it left.
  186. * @returns {Function} - filtered handler to use to listen on the `mouseleave` event.
  187. */
  188. function ignoreMousedisappear(handler) {
  189. var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
  190. _ref$ignoreLeaveWindo = _ref.ignoreLeaveWindow,
  191. ignoreLeaveWindow = _ref$ignoreLeaveWindo === void 0 ? false : _ref$ignoreLeaveWindo,
  192. _ref$ignoreReappear = _ref.ignoreReappear,
  193. ignoreReappear = _ref$ignoreReappear === void 0 ? false : _ref$ignoreReappear;
  194. return function leaveEventHandler(eLeave) {
  195. for (var _len = arguments.length, rest = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  196. rest[_key - 1] = arguments[_key];
  197. }
  198. var callback = handler.bind.apply(handler, [this, eLeave].concat(rest)); // The mouse left: call the given callback if the mouse entered elsewhere
  199. if (eLeave.relatedTarget !== null) {
  200. return callback();
  201. } // Otherwise, check if the mouse actually left the window.
  202. // In firefox if the user switched between windows, the window sill have the focus by the time
  203. // the event is triggered. We have to debounce the event to test this case.
  204. setTimeout(function leaveEventDebouncer() {
  205. if (!ignoreLeaveWindow && document.hasFocus && !document.hasFocus()) {
  206. return callback();
  207. } // Otherwise, wait for the mouse to reeapear outside of the element,
  208. if (!ignoreReappear) {
  209. $(document).one('mouseenter', function reenterEventHandler(eReenter) {
  210. if (!$(eLeave.currentTarget).has(eReenter.target).length) {
  211. // Fill where the mouse finally entered.
  212. eLeave.relatedTarget = eReenter.target;
  213. callback();
  214. }
  215. });
  216. }
  217. }, 0);
  218. };
  219. }
  220. var foundation_core_utils = /*#__PURE__*/Object.freeze({
  221. rtl: rtl,
  222. GetYoDigits: GetYoDigits,
  223. RegExpEscape: RegExpEscape,
  224. transitionend: transitionend,
  225. onLoad: onLoad,
  226. ignoreMousedisappear: ignoreMousedisappear
  227. });
  228. // Authors & copyright(c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas, David Knight. MIT license
  229. /* eslint-disable */
  230. window.matchMedia || (window.matchMedia = function () {
  231. var styleMedia = window.styleMedia || window.media; // For those that don't support matchMedium
  232. if (!styleMedia) {
  233. var style = document.createElement('style'),
  234. script = document.getElementsByTagName('script')[0],
  235. info = null;
  236. style.type = 'text/css';
  237. style.id = 'matchmediajs-test';
  238. if (!script) {
  239. document.head.appendChild(style);
  240. } else {
  241. script.parentNode.insertBefore(style, script);
  242. } // 'style.currentStyle' is used by IE <= 8 and 'window.getComputedStyle' for all other browsers
  243. info = 'getComputedStyle' in window && window.getComputedStyle(style, null) || style.currentStyle;
  244. styleMedia = {
  245. matchMedium: function matchMedium(media) {
  246. var text = '@media ' + media + '{ #matchmediajs-test { width: 1px; } }'; // 'style.styleSheet' is used by IE <= 8 and 'style.textContent' for all other browsers
  247. if (style.styleSheet) {
  248. style.styleSheet.cssText = text;
  249. } else {
  250. style.textContent = text;
  251. } // Test if media query is true or false
  252. return info.width === '1px';
  253. }
  254. };
  255. }
  256. return function (media) {
  257. return {
  258. matches: styleMedia.matchMedium(media || 'all'),
  259. media: media || 'all'
  260. };
  261. };
  262. }());
  263. /* eslint-enable */
  264. var MediaQuery = {
  265. queries: [],
  266. current: '',
  267. /**
  268. * Initializes the media query helper, by extracting the breakpoint list from the CSS and activating the breakpoint watcher.
  269. * @function
  270. * @private
  271. */
  272. _init: function _init() {
  273. var self = this;
  274. var $meta = $('meta.foundation-mq');
  275. if (!$meta.length) {
  276. $('<meta class="foundation-mq">').appendTo(document.head);
  277. }
  278. var extractedStyles = $('.foundation-mq').css('font-family');
  279. var namedQueries;
  280. namedQueries = parseStyleToObject(extractedStyles);
  281. for (var key in namedQueries) {
  282. if (namedQueries.hasOwnProperty(key)) {
  283. self.queries.push({
  284. name: key,
  285. value: "only screen and (min-width: ".concat(namedQueries[key], ")")
  286. });
  287. }
  288. }
  289. this.current = this._getCurrentSize();
  290. this._watcher();
  291. },
  292. /**
  293. * Checks if the screen is at least as wide as a breakpoint.
  294. * @function
  295. * @param {String} size - Name of the breakpoint to check.
  296. * @returns {Boolean} `true` if the breakpoint matches, `false` if it's smaller.
  297. */
  298. atLeast: function atLeast(size) {
  299. var query = this.get(size);
  300. if (query) {
  301. return window.matchMedia(query).matches;
  302. }
  303. return false;
  304. },
  305. /**
  306. * Checks if the screen matches to a breakpoint.
  307. * @function
  308. * @param {String} size - Name of the breakpoint to check, either 'small only' or 'small'. Omitting 'only' falls back to using atLeast() method.
  309. * @returns {Boolean} `true` if the breakpoint matches, `false` if it does not.
  310. */
  311. is: function is(size) {
  312. size = size.trim().split(' ');
  313. if (size.length > 1 && size[1] === 'only') {
  314. if (size[0] === this._getCurrentSize()) return true;
  315. } else {
  316. return this.atLeast(size[0]);
  317. }
  318. return false;
  319. },
  320. /**
  321. * Gets the media query of a breakpoint.
  322. * @function
  323. * @param {String} size - Name of the breakpoint to get.
  324. * @returns {String|null} - The media query of the breakpoint, or `null` if the breakpoint doesn't exist.
  325. */
  326. get: function get(size) {
  327. for (var i in this.queries) {
  328. if (this.queries.hasOwnProperty(i)) {
  329. var query = this.queries[i];
  330. if (size === query.name) return query.value;
  331. }
  332. }
  333. return null;
  334. },
  335. /**
  336. * Gets the current breakpoint name by testing every breakpoint and returning the last one to match (the biggest one).
  337. * @function
  338. * @private
  339. * @returns {String} Name of the current breakpoint.
  340. */
  341. _getCurrentSize: function _getCurrentSize() {
  342. var matched;
  343. for (var i = 0; i < this.queries.length; i++) {
  344. var query = this.queries[i];
  345. if (window.matchMedia(query.value).matches) {
  346. matched = query;
  347. }
  348. }
  349. if (_typeof(matched) === 'object') {
  350. return matched.name;
  351. } else {
  352. return matched;
  353. }
  354. },
  355. /**
  356. * Activates the breakpoint watcher, which fires an event on the window whenever the breakpoint changes.
  357. * @function
  358. * @private
  359. */
  360. _watcher: function _watcher() {
  361. var _this = this;
  362. $(window).off('resize.zf.mediaquery').on('resize.zf.mediaquery', function () {
  363. var newSize = _this._getCurrentSize(),
  364. currentSize = _this.current;
  365. if (newSize !== currentSize) {
  366. // Change the current media query
  367. _this.current = newSize; // Broadcast the media query change on the window
  368. $(window).trigger('changed.zf.mediaquery', [newSize, currentSize]);
  369. }
  370. });
  371. }
  372. }; // Thank you: https://github.com/sindresorhus/query-string
  373. function parseStyleToObject(str) {
  374. var styleObject = {};
  375. if (typeof str !== 'string') {
  376. return styleObject;
  377. }
  378. str = str.trim().slice(1, -1); // browsers re-quote string style values
  379. if (!str) {
  380. return styleObject;
  381. }
  382. styleObject = str.split('&').reduce(function (ret, param) {
  383. var parts = param.replace(/\+/g, ' ').split('=');
  384. var key = parts[0];
  385. var val = parts[1];
  386. key = decodeURIComponent(key); // missing `=` should be `null`:
  387. // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
  388. val = typeof val === 'undefined' ? null : decodeURIComponent(val);
  389. if (!ret.hasOwnProperty(key)) {
  390. ret[key] = val;
  391. } else if (Array.isArray(ret[key])) {
  392. ret[key].push(val);
  393. } else {
  394. ret[key] = [ret[key], val];
  395. }
  396. return ret;
  397. }, {});
  398. return styleObject;
  399. }
  400. var FOUNDATION_VERSION = '6.5.3'; // Global Foundation object
  401. // This is attached to the window, or used as a module for AMD/Browserify
  402. var Foundation = {
  403. version: FOUNDATION_VERSION,
  404. /**
  405. * Stores initialized plugins.
  406. */
  407. _plugins: {},
  408. /**
  409. * Stores generated unique ids for plugin instances
  410. */
  411. _uuids: [],
  412. /**
  413. * Defines a Foundation plugin, adding it to the `Foundation` namespace and the list of plugins to initialize when reflowing.
  414. * @param {Object} plugin - The constructor of the plugin.
  415. */
  416. plugin: function plugin(_plugin, name) {
  417. // Object key to use when adding to global Foundation object
  418. // Examples: Foundation.Reveal, Foundation.OffCanvas
  419. var className = name || functionName(_plugin); // Object key to use when storing the plugin, also used to create the identifying data attribute for the plugin
  420. // Examples: data-reveal, data-off-canvas
  421. var attrName = hyphenate(className); // Add to the Foundation object and the plugins list (for reflowing)
  422. this._plugins[attrName] = this[className] = _plugin;
  423. },
  424. /**
  425. * @function
  426. * Populates the _uuids array with pointers to each individual plugin instance.
  427. * Adds the `zfPlugin` data-attribute to programmatically created plugins to allow use of $(selector).foundation(method) calls.
  428. * Also fires the initialization event for each plugin, consolidating repetitive code.
  429. * @param {Object} plugin - an instance of a plugin, usually `this` in context.
  430. * @param {String} name - the name of the plugin, passed as a camelCased string.
  431. * @fires Plugin#init
  432. */
  433. registerPlugin: function registerPlugin(plugin, name) {
  434. var pluginName = name ? hyphenate(name) : functionName(plugin.constructor).toLowerCase();
  435. plugin.uuid = GetYoDigits(6, pluginName);
  436. if (!plugin.$element.attr("data-".concat(pluginName))) {
  437. plugin.$element.attr("data-".concat(pluginName), plugin.uuid);
  438. }
  439. if (!plugin.$element.data('zfPlugin')) {
  440. plugin.$element.data('zfPlugin', plugin);
  441. }
  442. /**
  443. * Fires when the plugin has initialized.
  444. * @event Plugin#init
  445. */
  446. plugin.$element.trigger("init.zf.".concat(pluginName));
  447. this._uuids.push(plugin.uuid);
  448. return;
  449. },
  450. /**
  451. * @function
  452. * Removes the plugins uuid from the _uuids array.
  453. * Removes the zfPlugin data attribute, as well as the data-plugin-name attribute.
  454. * Also fires the destroyed event for the plugin, consolidating repetitive code.
  455. * @param {Object} plugin - an instance of a plugin, usually `this` in context.
  456. * @fires Plugin#destroyed
  457. */
  458. unregisterPlugin: function unregisterPlugin(plugin) {
  459. var pluginName = hyphenate(functionName(plugin.$element.data('zfPlugin').constructor));
  460. this._uuids.splice(this._uuids.indexOf(plugin.uuid), 1);
  461. plugin.$element.removeAttr("data-".concat(pluginName)).removeData('zfPlugin')
  462. /**
  463. * Fires when the plugin has been destroyed.
  464. * @event Plugin#destroyed
  465. */
  466. .trigger("destroyed.zf.".concat(pluginName));
  467. for (var prop in plugin) {
  468. plugin[prop] = null; //clean up script to prep for garbage collection.
  469. }
  470. return;
  471. },
  472. /**
  473. * @function
  474. * Causes one or more active plugins to re-initialize, resetting event listeners, recalculating positions, etc.
  475. * @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'`
  476. * @default If no argument is passed, reflow all currently active plugins.
  477. */
  478. reInit: function reInit(plugins) {
  479. var isJQ = plugins instanceof $;
  480. try {
  481. if (isJQ) {
  482. plugins.each(function () {
  483. $(this).data('zfPlugin')._init();
  484. });
  485. } else {
  486. var type = _typeof(plugins),
  487. _this = this,
  488. fns = {
  489. 'object': function object(plgs) {
  490. plgs.forEach(function (p) {
  491. p = hyphenate(p);
  492. $('[data-' + p + ']').foundation('_init');
  493. });
  494. },
  495. 'string': function string() {
  496. plugins = hyphenate(plugins);
  497. $('[data-' + plugins + ']').foundation('_init');
  498. },
  499. 'undefined': function undefined() {
  500. this['object'](Object.keys(_this._plugins));
  501. }
  502. };
  503. fns[type](plugins);
  504. }
  505. } catch (err) {
  506. console.error(err);
  507. } finally {
  508. return plugins;
  509. }
  510. },
  511. /**
  512. * Initialize plugins on any elements within `elem` (and `elem` itself) that aren't already initialized.
  513. * @param {Object} elem - jQuery object containing the element to check inside. Also checks the element itself, unless it's the `document` object.
  514. * @param {String|Array} plugins - A list of plugins to initialize. Leave this out to initialize everything.
  515. */
  516. reflow: function reflow(elem, plugins) {
  517. // If plugins is undefined, just grab everything
  518. if (typeof plugins === 'undefined') {
  519. plugins = Object.keys(this._plugins);
  520. } // If plugins is a string, convert it to an array with one item
  521. else if (typeof plugins === 'string') {
  522. plugins = [plugins];
  523. }
  524. var _this = this; // Iterate through each plugin
  525. $.each(plugins, function (i, name) {
  526. // Get the current plugin
  527. var plugin = _this._plugins[name]; // Localize the search to all elements inside elem, as well as elem itself, unless elem === document
  528. var $elem = $(elem).find('[data-' + name + ']').addBack('[data-' + name + ']'); // For each plugin found, initialize it
  529. $elem.each(function () {
  530. var $el = $(this),
  531. opts = {}; // Don't double-dip on plugins
  532. if ($el.data('zfPlugin')) {
  533. console.warn("Tried to initialize " + name + " on an element that already has a Foundation plugin.");
  534. return;
  535. }
  536. if ($el.attr('data-options')) {
  537. var thing = $el.attr('data-options').split(';').forEach(function (e, i) {
  538. var opt = e.split(':').map(function (el) {
  539. return el.trim();
  540. });
  541. if (opt[0]) opts[opt[0]] = parseValue(opt[1]);
  542. });
  543. }
  544. try {
  545. $el.data('zfPlugin', new plugin($(this), opts));
  546. } catch (er) {
  547. console.error(er);
  548. } finally {
  549. return;
  550. }
  551. });
  552. });
  553. },
  554. getFnName: functionName,
  555. addToJquery: function addToJquery($$$1) {
  556. // TODO: consider not making this a jQuery function
  557. // TODO: need way to reflow vs. re-initialize
  558. /**
  559. * The Foundation jQuery method.
  560. * @param {String|Array} method - An action to perform on the current jQuery object.
  561. */
  562. var foundation = function foundation(method) {
  563. var type = _typeof(method),
  564. $noJS = $$$1('.no-js');
  565. if ($noJS.length) {
  566. $noJS.removeClass('no-js');
  567. }
  568. if (type === 'undefined') {
  569. //needs to initialize the Foundation object, or an individual plugin.
  570. MediaQuery._init();
  571. Foundation.reflow(this);
  572. } else if (type === 'string') {
  573. //an individual method to invoke on a plugin or group of plugins
  574. var args = Array.prototype.slice.call(arguments, 1); //collect all the arguments, if necessary
  575. var plugClass = this.data('zfPlugin'); //determine the class of plugin
  576. if (typeof plugClass !== 'undefined' && typeof plugClass[method] !== 'undefined') {
  577. //make sure both the class and method exist
  578. if (this.length === 1) {
  579. //if there's only one, call it directly.
  580. plugClass[method].apply(plugClass, args);
  581. } else {
  582. this.each(function (i, el) {
  583. //otherwise loop through the jQuery collection and invoke the method on each
  584. plugClass[method].apply($$$1(el).data('zfPlugin'), args);
  585. });
  586. }
  587. } else {
  588. //error for no class or no method
  589. throw new ReferenceError("We're sorry, '" + method + "' is not an available method for " + (plugClass ? functionName(plugClass) : 'this element') + '.');
  590. }
  591. } else {
  592. //error for invalid argument type
  593. 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."));
  594. }
  595. return this;
  596. };
  597. $$$1.fn.foundation = foundation;
  598. return $$$1;
  599. }
  600. };
  601. Foundation.util = {
  602. /**
  603. * Function for applying a debounce effect to a function call.
  604. * @function
  605. * @param {Function} func - Function to be called at end of timeout.
  606. * @param {Number} delay - Time in ms to delay the call of `func`.
  607. * @returns function
  608. */
  609. throttle: function throttle(func, delay) {
  610. var timer = null;
  611. return function () {
  612. var context = this,
  613. args = arguments;
  614. if (timer === null) {
  615. timer = setTimeout(function () {
  616. func.apply(context, args);
  617. timer = null;
  618. }, delay);
  619. }
  620. };
  621. }
  622. };
  623. window.Foundation = Foundation; // Polyfill for requestAnimationFrame
  624. (function () {
  625. if (!Date.now || !window.Date.now) window.Date.now = Date.now = function () {
  626. return new Date().getTime();
  627. };
  628. var vendors = ['webkit', 'moz'];
  629. for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
  630. var vp = vendors[i];
  631. window.requestAnimationFrame = window[vp + 'RequestAnimationFrame'];
  632. window.cancelAnimationFrame = window[vp + 'CancelAnimationFrame'] || window[vp + 'CancelRequestAnimationFrame'];
  633. }
  634. if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
  635. var lastTime = 0;
  636. window.requestAnimationFrame = function (callback) {
  637. var now = Date.now();
  638. var nextTime = Math.max(lastTime + 16, now);
  639. return setTimeout(function () {
  640. callback(lastTime = nextTime);
  641. }, nextTime - now);
  642. };
  643. window.cancelAnimationFrame = clearTimeout;
  644. }
  645. /**
  646. * Polyfill for performance.now, required by rAF
  647. */
  648. if (!window.performance || !window.performance.now) {
  649. window.performance = {
  650. start: Date.now(),
  651. now: function now() {
  652. return Date.now() - this.start;
  653. }
  654. };
  655. }
  656. })();
  657. if (!Function.prototype.bind) {
  658. Function.prototype.bind = function (oThis) {
  659. if (typeof this !== 'function') {
  660. // closest thing possible to the ECMAScript 5
  661. // internal IsCallable function
  662. throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
  663. }
  664. var aArgs = Array.prototype.slice.call(arguments, 1),
  665. fToBind = this,
  666. fNOP = function fNOP() {},
  667. fBound = function fBound() {
  668. return fToBind.apply(this instanceof fNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
  669. };
  670. if (this.prototype) {
  671. // native functions don't have a prototype
  672. fNOP.prototype = this.prototype;
  673. }
  674. fBound.prototype = new fNOP();
  675. return fBound;
  676. };
  677. } // Polyfill to get the name of a function in IE9
  678. function functionName(fn) {
  679. if (typeof Function.prototype.name === 'undefined') {
  680. var funcNameRegex = /function\s([^(]{1,})\(/;
  681. var results = funcNameRegex.exec(fn.toString());
  682. return results && results.length > 1 ? results[1].trim() : "";
  683. } else if (typeof fn.prototype === 'undefined') {
  684. return fn.constructor.name;
  685. } else {
  686. return fn.prototype.constructor.name;
  687. }
  688. }
  689. function parseValue(str) {
  690. if ('true' === str) return true;else if ('false' === str) return false;else if (!isNaN(str * 1)) return parseFloat(str);
  691. return str;
  692. } // Convert PascalCase to kebab-case
  693. // Thank you: http://stackoverflow.com/a/8955580
  694. function hyphenate(str) {
  695. return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
  696. }
  697. var Box = {
  698. ImNotTouchingYou: ImNotTouchingYou,
  699. OverlapArea: OverlapArea,
  700. GetDimensions: GetDimensions,
  701. GetOffsets: GetOffsets,
  702. GetExplicitOffsets: GetExplicitOffsets
  703. /**
  704. * Compares the dimensions of an element to a container and determines collision events with container.
  705. * @function
  706. * @param {jQuery} element - jQuery object to test for collisions.
  707. * @param {jQuery} parent - jQuery object to use as bounding container.
  708. * @param {Boolean} lrOnly - set to true to check left and right values only.
  709. * @param {Boolean} tbOnly - set to true to check top and bottom values only.
  710. * @default if no parent object passed, detects collisions with `window`.
  711. * @returns {Boolean} - true if collision free, false if a collision in any direction.
  712. */
  713. };
  714. function ImNotTouchingYou(element, parent, lrOnly, tbOnly, ignoreBottom) {
  715. return OverlapArea(element, parent, lrOnly, tbOnly, ignoreBottom) === 0;
  716. }
  717. function OverlapArea(element, parent, lrOnly, tbOnly, ignoreBottom) {
  718. var eleDims = GetDimensions(element),
  719. topOver,
  720. bottomOver,
  721. leftOver,
  722. rightOver;
  723. if (parent) {
  724. var parDims = GetDimensions(parent);
  725. bottomOver = parDims.height + parDims.offset.top - (eleDims.offset.top + eleDims.height);
  726. topOver = eleDims.offset.top - parDims.offset.top;
  727. leftOver = eleDims.offset.left - parDims.offset.left;
  728. rightOver = parDims.width + parDims.offset.left - (eleDims.offset.left + eleDims.width);
  729. } else {
  730. bottomOver = eleDims.windowDims.height + eleDims.windowDims.offset.top - (eleDims.offset.top + eleDims.height);
  731. topOver = eleDims.offset.top - eleDims.windowDims.offset.top;
  732. leftOver = eleDims.offset.left - eleDims.windowDims.offset.left;
  733. rightOver = eleDims.windowDims.width - (eleDims.offset.left + eleDims.width);
  734. }
  735. bottomOver = ignoreBottom ? 0 : Math.min(bottomOver, 0);
  736. topOver = Math.min(topOver, 0);
  737. leftOver = Math.min(leftOver, 0);
  738. rightOver = Math.min(rightOver, 0);
  739. if (lrOnly) {
  740. return leftOver + rightOver;
  741. }
  742. if (tbOnly) {
  743. return topOver + bottomOver;
  744. } // use sum of squares b/c we care about overlap area.
  745. return Math.sqrt(topOver * topOver + bottomOver * bottomOver + leftOver * leftOver + rightOver * rightOver);
  746. }
  747. /**
  748. * Uses native methods to return an object of dimension values.
  749. * @function
  750. * @param {jQuery || HTML} element - jQuery object or DOM element for which to get the dimensions. Can be any element other that document or window.
  751. * @returns {Object} - nested object of integer pixel values
  752. * TODO - if element is window, return only those values.
  753. */
  754. function GetDimensions(elem) {
  755. elem = elem.length ? elem[0] : elem;
  756. if (elem === window || elem === document) {
  757. throw new Error("I'm sorry, Dave. I'm afraid I can't do that.");
  758. }
  759. var rect = elem.getBoundingClientRect(),
  760. parRect = elem.parentNode.getBoundingClientRect(),
  761. winRect = document.body.getBoundingClientRect(),
  762. winY = window.pageYOffset,
  763. winX = window.pageXOffset;
  764. return {
  765. width: rect.width,
  766. height: rect.height,
  767. offset: {
  768. top: rect.top + winY,
  769. left: rect.left + winX
  770. },
  771. parentDims: {
  772. width: parRect.width,
  773. height: parRect.height,
  774. offset: {
  775. top: parRect.top + winY,
  776. left: parRect.left + winX
  777. }
  778. },
  779. windowDims: {
  780. width: winRect.width,
  781. height: winRect.height,
  782. offset: {
  783. top: winY,
  784. left: winX
  785. }
  786. }
  787. };
  788. }
  789. /**
  790. * Returns an object of top and left integer pixel values for dynamically rendered elements,
  791. * such as: Tooltip, Reveal, and Dropdown. Maintained for backwards compatibility, and where
  792. * you don't know alignment, but generally from
  793. * 6.4 forward you should use GetExplicitOffsets, as GetOffsets conflates position and alignment.
  794. * @function
  795. * @param {jQuery} element - jQuery object for the element being positioned.
  796. * @param {jQuery} anchor - jQuery object for the element's anchor point.
  797. * @param {String} position - a string relating to the desired position of the element, relative to it's anchor
  798. * @param {Number} vOffset - integer pixel value of desired vertical separation between anchor and element.
  799. * @param {Number} hOffset - integer pixel value of desired horizontal separation between anchor and element.
  800. * @param {Boolean} isOverflow - if a collision event is detected, sets to true to default the element to full width - any desired offset.
  801. * TODO alter/rewrite to work with `em` values as well/instead of pixels
  802. */
  803. function GetOffsets(element, anchor, position, vOffset, hOffset, isOverflow) {
  804. console.log("NOTE: GetOffsets is deprecated in favor of GetExplicitOffsets and will be removed in 6.5");
  805. switch (position) {
  806. case 'top':
  807. return rtl() ? GetExplicitOffsets(element, anchor, 'top', 'left', vOffset, hOffset, isOverflow) : GetExplicitOffsets(element, anchor, 'top', 'right', vOffset, hOffset, isOverflow);
  808. case 'bottom':
  809. return rtl() ? GetExplicitOffsets(element, anchor, 'bottom', 'left', vOffset, hOffset, isOverflow) : GetExplicitOffsets(element, anchor, 'bottom', 'right', vOffset, hOffset, isOverflow);
  810. case 'center top':
  811. return GetExplicitOffsets(element, anchor, 'top', 'center', vOffset, hOffset, isOverflow);
  812. case 'center bottom':
  813. return GetExplicitOffsets(element, anchor, 'bottom', 'center', vOffset, hOffset, isOverflow);
  814. case 'center left':
  815. return GetExplicitOffsets(element, anchor, 'left', 'center', vOffset, hOffset, isOverflow);
  816. case 'center right':
  817. return GetExplicitOffsets(element, anchor, 'right', 'center', vOffset, hOffset, isOverflow);
  818. case 'left bottom':
  819. return GetExplicitOffsets(element, anchor, 'bottom', 'left', vOffset, hOffset, isOverflow);
  820. case 'right bottom':
  821. return GetExplicitOffsets(element, anchor, 'bottom', 'right', vOffset, hOffset, isOverflow);
  822. // Backwards compatibility... this along with the reveal and reveal full
  823. // classes are the only ones that didn't reference anchor
  824. case 'center':
  825. return {
  826. left: $eleDims.windowDims.offset.left + $eleDims.windowDims.width / 2 - $eleDims.width / 2 + hOffset,
  827. top: $eleDims.windowDims.offset.top + $eleDims.windowDims.height / 2 - ($eleDims.height / 2 + vOffset)
  828. };
  829. case 'reveal':
  830. return {
  831. left: ($eleDims.windowDims.width - $eleDims.width) / 2 + hOffset,
  832. top: $eleDims.windowDims.offset.top + vOffset
  833. };
  834. case 'reveal full':
  835. return {
  836. left: $eleDims.windowDims.offset.left,
  837. top: $eleDims.windowDims.offset.top
  838. };
  839. break;
  840. default:
  841. return {
  842. left: rtl() ? $anchorDims.offset.left - $eleDims.width + $anchorDims.width - hOffset : $anchorDims.offset.left + hOffset,
  843. top: $anchorDims.offset.top + $anchorDims.height + vOffset
  844. };
  845. }
  846. }
  847. function GetExplicitOffsets(element, anchor, position, alignment, vOffset, hOffset, isOverflow) {
  848. var $eleDims = GetDimensions(element),
  849. $anchorDims = anchor ? GetDimensions(anchor) : null;
  850. var topVal, leftVal; // set position related attribute
  851. switch (position) {
  852. case 'top':
  853. topVal = $anchorDims.offset.top - ($eleDims.height + vOffset);
  854. break;
  855. case 'bottom':
  856. topVal = $anchorDims.offset.top + $anchorDims.height + vOffset;
  857. break;
  858. case 'left':
  859. leftVal = $anchorDims.offset.left - ($eleDims.width + hOffset);
  860. break;
  861. case 'right':
  862. leftVal = $anchorDims.offset.left + $anchorDims.width + hOffset;
  863. break;
  864. } // set alignment related attribute
  865. switch (position) {
  866. case 'top':
  867. case 'bottom':
  868. switch (alignment) {
  869. case 'left':
  870. leftVal = $anchorDims.offset.left + hOffset;
  871. break;
  872. case 'right':
  873. leftVal = $anchorDims.offset.left - $eleDims.width + $anchorDims.width - hOffset;
  874. break;
  875. case 'center':
  876. leftVal = isOverflow ? hOffset : $anchorDims.offset.left + $anchorDims.width / 2 - $eleDims.width / 2 + hOffset;
  877. break;
  878. }
  879. break;
  880. case 'right':
  881. case 'left':
  882. switch (alignment) {
  883. case 'bottom':
  884. topVal = $anchorDims.offset.top - vOffset + $anchorDims.height - $eleDims.height;
  885. break;
  886. case 'top':
  887. topVal = $anchorDims.offset.top + vOffset;
  888. break;
  889. case 'center':
  890. topVal = $anchorDims.offset.top + vOffset + $anchorDims.height / 2 - $eleDims.height / 2;
  891. break;
  892. }
  893. break;
  894. }
  895. return {
  896. top: topVal,
  897. left: leftVal
  898. };
  899. }
  900. /**
  901. * Runs a callback function when images are fully loaded.
  902. * @param {Object} images - Image(s) to check if loaded.
  903. * @param {Func} callback - Function to execute when image is fully loaded.
  904. */
  905. function onImagesLoaded(images, callback) {
  906. var unloaded = images.length;
  907. if (unloaded === 0) {
  908. callback();
  909. }
  910. images.each(function () {
  911. // Check if image is loaded
  912. if (this.complete && typeof this.naturalWidth !== 'undefined') {
  913. singleImageLoaded();
  914. } else {
  915. // If the above check failed, simulate loading on detached element.
  916. var image = new Image(); // Still count image as loaded if it finalizes with an error.
  917. var events = "load.zf.images error.zf.images";
  918. $(image).one(events, function me(event) {
  919. // Unbind the event listeners. We're using 'one' but only one of the two events will have fired.
  920. $(this).off(events, me);
  921. singleImageLoaded();
  922. });
  923. image.src = $(this).attr('src');
  924. }
  925. });
  926. function singleImageLoaded() {
  927. unloaded--;
  928. if (unloaded === 0) {
  929. callback();
  930. }
  931. }
  932. }
  933. /*******************************************
  934. * *
  935. * This util was created by Marius Olbertz *
  936. * Please thank Marius on GitHub /owlbertz *
  937. * or the web http://www.mariusolbertz.de/ *
  938. * *
  939. ******************************************/
  940. var keyCodes = {
  941. 9: 'TAB',
  942. 13: 'ENTER',
  943. 27: 'ESCAPE',
  944. 32: 'SPACE',
  945. 35: 'END',
  946. 36: 'HOME',
  947. 37: 'ARROW_LEFT',
  948. 38: 'ARROW_UP',
  949. 39: 'ARROW_RIGHT',
  950. 40: 'ARROW_DOWN'
  951. };
  952. var commands = {}; // Functions pulled out to be referenceable from internals
  953. function findFocusable($element) {
  954. if (!$element) {
  955. return false;
  956. }
  957. 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 () {
  958. if (!$(this).is(':visible') || $(this).attr('tabindex') < 0) {
  959. return false;
  960. } //only have visible elements and those that have a tabindex greater or equal 0
  961. return true;
  962. });
  963. }
  964. function parseKey(event) {
  965. 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
  966. key = key.replace(/\W+/, '');
  967. if (event.shiftKey) key = "SHIFT_".concat(key);
  968. if (event.ctrlKey) key = "CTRL_".concat(key);
  969. if (event.altKey) key = "ALT_".concat(key); // Remove trailing underscore, in case only modifiers were used (e.g. only `CTRL_ALT`)
  970. key = key.replace(/_$/, '');
  971. return key;
  972. }
  973. var Keyboard = {
  974. keys: getKeyCodes(keyCodes),
  975. /**
  976. * Parses the (keyboard) event and returns a String that represents its key
  977. * Can be used like Foundation.parseKey(event) === Foundation.keys.SPACE
  978. * @param {Event} event - the event generated by the event handler
  979. * @return String key - String that represents the key pressed
  980. */
  981. parseKey: parseKey,
  982. /**
  983. * Handles the given (keyboard) event
  984. * @param {Event} event - the event generated by the event handler
  985. * @param {String} component - Foundation component's name, e.g. Slider or Reveal
  986. * @param {Objects} functions - collection of functions that are to be executed
  987. */
  988. handleKey: function handleKey(event, component, functions) {
  989. var commandList = commands[component],
  990. keyCode = this.parseKey(event),
  991. cmds,
  992. command,
  993. fn;
  994. if (!commandList) return console.warn('Component not defined!');
  995. if (typeof commandList.ltr === 'undefined') {
  996. // this component does not differentiate between ltr and rtl
  997. cmds = commandList; // use plain list
  998. } else {
  999. // merge ltr and rtl: if document is rtl, rtl overwrites ltr and vice versa
  1000. if (rtl()) cmds = $.extend({}, commandList.ltr, commandList.rtl);else cmds = $.extend({}, commandList.rtl, commandList.ltr);
  1001. }
  1002. command = cmds[keyCode];
  1003. fn = functions[command];
  1004. if (fn && typeof fn === 'function') {
  1005. // execute function if exists
  1006. var returnValue = fn.apply();
  1007. if (functions.handled || typeof functions.handled === 'function') {
  1008. // execute function when event was handled
  1009. functions.handled(returnValue);
  1010. }
  1011. } else {
  1012. if (functions.unhandled || typeof functions.unhandled === 'function') {
  1013. // execute function when event was not handled
  1014. functions.unhandled();
  1015. }
  1016. }
  1017. },
  1018. /**
  1019. * Finds all focusable elements within the given `$element`
  1020. * @param {jQuery} $element - jQuery object to search within
  1021. * @return {jQuery} $focusable - all focusable elements within `$element`
  1022. */
  1023. findFocusable: findFocusable,
  1024. /**
  1025. * Returns the component name name
  1026. * @param {Object} component - Foundation component, e.g. Slider or Reveal
  1027. * @return String componentName
  1028. */
  1029. register: function register(componentName, cmds) {
  1030. commands[componentName] = cmds;
  1031. },
  1032. // TODO9438: These references to Keyboard need to not require global. Will 'this' work in this context?
  1033. //
  1034. /**
  1035. * Traps the focus in the given element.
  1036. * @param {jQuery} $element jQuery object to trap the foucs into.
  1037. */
  1038. trapFocus: function trapFocus($element) {
  1039. var $focusable = findFocusable($element),
  1040. $firstFocusable = $focusable.eq(0),
  1041. $lastFocusable = $focusable.eq(-1);
  1042. $element.on('keydown.zf.trapfocus', function (event) {
  1043. if (event.target === $lastFocusable[0] && parseKey(event) === 'TAB') {
  1044. event.preventDefault();
  1045. $firstFocusable.focus();
  1046. } else if (event.target === $firstFocusable[0] && parseKey(event) === 'SHIFT_TAB') {
  1047. event.preventDefault();
  1048. $lastFocusable.focus();
  1049. }
  1050. });
  1051. },
  1052. /**
  1053. * Releases the trapped focus from the given element.
  1054. * @param {jQuery} $element jQuery object to release the focus for.
  1055. */
  1056. releaseFocus: function releaseFocus($element) {
  1057. $element.off('keydown.zf.trapfocus');
  1058. }
  1059. };
  1060. /*
  1061. * Constants for easier comparing.
  1062. * Can be used like Foundation.parseKey(event) === Foundation.keys.SPACE
  1063. */
  1064. function getKeyCodes(kcs) {
  1065. var k = {};
  1066. for (var kc in kcs) {
  1067. k[kcs[kc]] = kcs[kc];
  1068. }
  1069. return k;
  1070. }
  1071. /**
  1072. * Motion module.
  1073. * @module foundation.motion
  1074. */
  1075. var initClasses = ['mui-enter', 'mui-leave'];
  1076. var activeClasses = ['mui-enter-active', 'mui-leave-active'];
  1077. var Motion = {
  1078. animateIn: function animateIn(element, animation, cb) {
  1079. animate(true, element, animation, cb);
  1080. },
  1081. animateOut: function animateOut(element, animation, cb) {
  1082. animate(false, element, animation, cb);
  1083. }
  1084. };
  1085. function Move(duration, elem, fn) {
  1086. var anim,
  1087. prog,
  1088. start = null; // console.log('called');
  1089. if (duration === 0) {
  1090. fn.apply(elem);
  1091. elem.trigger('finished.zf.animate', [elem]).triggerHandler('finished.zf.animate', [elem]);
  1092. return;
  1093. }
  1094. function move(ts) {
  1095. if (!start) start = ts; // console.log(start, ts);
  1096. prog = ts - start;
  1097. fn.apply(elem);
  1098. if (prog < duration) {
  1099. anim = window.requestAnimationFrame(move, elem);
  1100. } else {
  1101. window.cancelAnimationFrame(anim);
  1102. elem.trigger('finished.zf.animate', [elem]).triggerHandler('finished.zf.animate', [elem]);
  1103. }
  1104. }
  1105. anim = window.requestAnimationFrame(move);
  1106. }
  1107. /**
  1108. * Animates an element in or out using a CSS transition class.
  1109. * @function
  1110. * @private
  1111. * @param {Boolean} isIn - Defines if the animation is in or out.
  1112. * @param {Object} element - jQuery or HTML object to animate.
  1113. * @param {String} animation - CSS class to use.
  1114. * @param {Function} cb - Callback to run when animation is finished.
  1115. */
  1116. function animate(isIn, element, animation, cb) {
  1117. element = $(element).eq(0);
  1118. if (!element.length) return;
  1119. var initClass = isIn ? initClasses[0] : initClasses[1];
  1120. var activeClass = isIn ? activeClasses[0] : activeClasses[1]; // Set up the animation
  1121. reset();
  1122. element.addClass(animation).css('transition', 'none');
  1123. requestAnimationFrame(function () {
  1124. element.addClass(initClass);
  1125. if (isIn) element.show();
  1126. }); // Start the animation
  1127. requestAnimationFrame(function () {
  1128. element[0].offsetWidth;
  1129. element.css('transition', '').addClass(activeClass);
  1130. }); // Clean up the animation when it finishes
  1131. element.one(transitionend(element), finish); // Hides the element (for out animations), resets the element, and runs a callback
  1132. function finish() {
  1133. if (!isIn) element.hide();
  1134. reset();
  1135. if (cb) cb.apply(element);
  1136. } // Resets transitions and removes motion-specific classes
  1137. function reset() {
  1138. element[0].style.transitionDuration = 0;
  1139. element.removeClass("".concat(initClass, " ").concat(activeClass, " ").concat(animation));
  1140. }
  1141. }
  1142. var Nest = {
  1143. Feather: function Feather(menu) {
  1144. var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'zf';
  1145. menu.attr('role', 'menubar');
  1146. var items = menu.find('li').attr({
  1147. 'role': 'menuitem'
  1148. }),
  1149. subMenuClass = "is-".concat(type, "-submenu"),
  1150. subItemClass = "".concat(subMenuClass, "-item"),
  1151. hasSubClass = "is-".concat(type, "-submenu-parent"),
  1152. applyAria = type !== 'accordion'; // Accordions handle their own ARIA attriutes.
  1153. items.each(function () {
  1154. var $item = $(this),
  1155. $sub = $item.children('ul');
  1156. if ($sub.length) {
  1157. $item.addClass(hasSubClass);
  1158. if (applyAria) {
  1159. $item.attr({
  1160. 'aria-haspopup': true,
  1161. 'aria-label': $item.children('a:first').text()
  1162. }); // Note: Drilldowns behave differently in how they hide, and so need
  1163. // additional attributes. We should look if this possibly over-generalized
  1164. // utility (Nest) is appropriate when we rework menus in 6.4
  1165. if (type === 'drilldown') {
  1166. $item.attr({
  1167. 'aria-expanded': false
  1168. });
  1169. }
  1170. }
  1171. $sub.addClass("submenu ".concat(subMenuClass)).attr({
  1172. 'data-submenu': '',
  1173. 'role': 'menubar'
  1174. });
  1175. if (type === 'drilldown') {
  1176. $sub.attr({
  1177. 'aria-hidden': true
  1178. });
  1179. }
  1180. }
  1181. if ($item.parent('[data-submenu]').length) {
  1182. $item.addClass("is-submenu-item ".concat(subItemClass));
  1183. }
  1184. });
  1185. return;
  1186. },
  1187. Burn: function Burn(menu, type) {
  1188. var //items = menu.find('li'),
  1189. subMenuClass = "is-".concat(type, "-submenu"),
  1190. subItemClass = "".concat(subMenuClass, "-item"),
  1191. hasSubClass = "is-".concat(type, "-submenu-parent");
  1192. 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', '');
  1193. }
  1194. };
  1195. function Timer(elem, options, cb) {
  1196. var _this = this,
  1197. duration = options.duration,
  1198. //options is an object for easily adding features later.
  1199. nameSpace = Object.keys(elem.data())[0] || 'timer',
  1200. remain = -1,
  1201. start,
  1202. timer;
  1203. this.isPaused = false;
  1204. this.restart = function () {
  1205. remain = -1;
  1206. clearTimeout(timer);
  1207. this.start();
  1208. };
  1209. this.start = function () {
  1210. this.isPaused = false; // if(!elem.data('paused')){ return false; }//maybe implement this sanity check if used for other things.
  1211. clearTimeout(timer);
  1212. remain = remain <= 0 ? duration : remain;
  1213. elem.data('paused', false);
  1214. start = Date.now();
  1215. timer = setTimeout(function () {
  1216. if (options.infinite) {
  1217. _this.restart(); //rerun the timer.
  1218. }
  1219. if (cb && typeof cb === 'function') {
  1220. cb();
  1221. }
  1222. }, remain);
  1223. elem.trigger("timerstart.zf.".concat(nameSpace));
  1224. };
  1225. this.pause = function () {
  1226. this.isPaused = true; //if(elem.data('paused')){ return false; }//maybe implement this sanity check if used for other things.
  1227. clearTimeout(timer);
  1228. elem.data('paused', true);
  1229. var end = Date.now();
  1230. remain = remain - (end - start);
  1231. elem.trigger("timerpaused.zf.".concat(nameSpace));
  1232. };
  1233. }
  1234. var Touch = {};
  1235. var startPosX,
  1236. startPosY,
  1237. startTime,
  1238. elapsedTime,
  1239. startEvent,
  1240. isMoving = false,
  1241. didMoved = false;
  1242. function onTouchEnd(e) {
  1243. this.removeEventListener('touchmove', onTouchMove);
  1244. this.removeEventListener('touchend', onTouchEnd); // If the touch did not move, consider it as a "tap"
  1245. if (!didMoved) {
  1246. var tapEvent = $.Event('tap', startEvent || e);
  1247. $(this).trigger(tapEvent);
  1248. }
  1249. startEvent = null;
  1250. isMoving = false;
  1251. didMoved = false;
  1252. }
  1253. function onTouchMove(e) {
  1254. if ($.spotSwipe.preventDefault) {
  1255. e.preventDefault();
  1256. }
  1257. if (isMoving) {
  1258. var x = e.touches[0].pageX;
  1259. var y = e.touches[0].pageY;
  1260. var dx = startPosX - x;
  1261. var dir;
  1262. didMoved = true;
  1263. elapsedTime = new Date().getTime() - startTime;
  1264. if (Math.abs(dx) >= $.spotSwipe.moveThreshold && elapsedTime <= $.spotSwipe.timeThreshold) {
  1265. dir = dx > 0 ? 'left' : 'right';
  1266. } // else if(Math.abs(dy) >= $.spotSwipe.moveThreshold && elapsedTime <= $.spotSwipe.timeThreshold) {
  1267. // dir = dy > 0 ? 'down' : 'up';
  1268. // }
  1269. if (dir) {
  1270. e.preventDefault();
  1271. onTouchEnd.apply(this, arguments);
  1272. $(this).trigger($.Event('swipe', e), dir).trigger($.Event("swipe".concat(dir), e));
  1273. }
  1274. }
  1275. }
  1276. function onTouchStart(e) {
  1277. if (e.touches.length == 1) {
  1278. startPosX = e.touches[0].pageX;
  1279. startPosY = e.touches[0].pageY;
  1280. startEvent = e;
  1281. isMoving = true;
  1282. didMoved = false;
  1283. startTime = new Date().getTime();
  1284. this.addEventListener('touchmove', onTouchMove, false);
  1285. this.addEventListener('touchend', onTouchEnd, false);
  1286. }
  1287. }
  1288. function init() {
  1289. this.addEventListener && this.addEventListener('touchstart', onTouchStart, false);
  1290. }
  1291. var SpotSwipe =
  1292. /*#__PURE__*/
  1293. function () {
  1294. function SpotSwipe($$$1) {
  1295. _classCallCheck(this, SpotSwipe);
  1296. this.version = '1.0.0';
  1297. this.enabled = 'ontouchstart' in document.documentElement;
  1298. this.preventDefault = false;
  1299. this.moveThreshold = 75;
  1300. this.timeThreshold = 200;
  1301. this.$ = $$$1;
  1302. this._init();
  1303. }
  1304. _createClass(SpotSwipe, [{
  1305. key: "_init",
  1306. value: function _init() {
  1307. var $$$1 = this.$;
  1308. $$$1.event.special.swipe = {
  1309. setup: init
  1310. };
  1311. $$$1.event.special.tap = {
  1312. setup: init
  1313. };
  1314. $$$1.each(['left', 'up', 'down', 'right'], function () {
  1315. $$$1.event.special["swipe".concat(this)] = {
  1316. setup: function setup() {
  1317. $$$1(this).on('swipe', $$$1.noop);
  1318. }
  1319. };
  1320. });
  1321. }
  1322. }]);
  1323. return SpotSwipe;
  1324. }();
  1325. /****************************************************
  1326. * As far as I can tell, both setupSpotSwipe and *
  1327. * setupTouchHandler should be idempotent, *
  1328. * because they directly replace functions & *
  1329. * values, and do not add event handlers directly. *
  1330. ****************************************************/
  1331. Touch.setupSpotSwipe = function ($$$1) {
  1332. $$$1.spotSwipe = new SpotSwipe($$$1);
  1333. };
  1334. /****************************************************
  1335. * Method for adding pseudo drag events to elements *
  1336. ***************************************************/
  1337. Touch.setupTouchHandler = function ($$$1) {
  1338. $$$1.fn.addTouch = function () {
  1339. this.each(function (i, el) {
  1340. $$$1(el).bind('touchstart touchmove touchend touchcancel', function (event) {
  1341. //we pass the original event object because the jQuery event
  1342. //object is normalized to w3c specs and does not provide the TouchList
  1343. handleTouch(event);
  1344. });
  1345. });
  1346. var handleTouch = function handleTouch(event) {
  1347. var touches = event.changedTouches,
  1348. first = touches[0],
  1349. eventTypes = {
  1350. touchstart: 'mousedown',
  1351. touchmove: 'mousemove',
  1352. touchend: 'mouseup'
  1353. },
  1354. type = eventTypes[event.type],
  1355. simulatedEvent;
  1356. if ('MouseEvent' in window && typeof window.MouseEvent === 'function') {
  1357. simulatedEvent = new window.MouseEvent(type, {
  1358. 'bubbles': true,
  1359. 'cancelable': true,
  1360. 'screenX': first.screenX,
  1361. 'screenY': first.screenY,
  1362. 'clientX': first.clientX,
  1363. 'clientY': first.clientY
  1364. });
  1365. } else {
  1366. simulatedEvent = document.createEvent('MouseEvent');
  1367. simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY, false, false, false, false, 0
  1368. /*left*/
  1369. , null);
  1370. }
  1371. first.target.dispatchEvent(simulatedEvent);
  1372. };
  1373. };
  1374. };
  1375. Touch.init = function ($$$1) {
  1376. if (typeof $$$1.spotSwipe === 'undefined') {
  1377. Touch.setupSpotSwipe($$$1);
  1378. Touch.setupTouchHandler($$$1);
  1379. }
  1380. };
  1381. var MutationObserver = function () {
  1382. var prefixes = ['WebKit', 'Moz', 'O', 'Ms', ''];
  1383. for (var i = 0; i < prefixes.length; i++) {
  1384. if ("".concat(prefixes[i], "MutationObserver") in window) {
  1385. return window["".concat(prefixes[i], "MutationObserver")];
  1386. }
  1387. }
  1388. return false;
  1389. }();
  1390. var triggers = function triggers(el, type) {
  1391. el.data(type).split(' ').forEach(function (id) {
  1392. $("#".concat(id))[type === 'close' ? 'trigger' : 'triggerHandler']("".concat(type, ".zf.trigger"), [el]);
  1393. });
  1394. };
  1395. var Triggers = {
  1396. Listeners: {
  1397. Basic: {},
  1398. Global: {}
  1399. },
  1400. Initializers: {}
  1401. };
  1402. Triggers.Listeners.Basic = {
  1403. openListener: function openListener() {
  1404. triggers($(this), 'open');
  1405. },
  1406. closeListener: function closeListener() {
  1407. var id = $(this).data('close');
  1408. if (id) {
  1409. triggers($(this), 'close');
  1410. } else {
  1411. $(this).trigger('close.zf.trigger');
  1412. }
  1413. },
  1414. toggleListener: function toggleListener() {
  1415. var id = $(this).data('toggle');
  1416. if (id) {
  1417. triggers($(this), 'toggle');
  1418. } else {
  1419. $(this).trigger('toggle.zf.trigger');
  1420. }
  1421. },
  1422. closeableListener: function closeableListener(e) {
  1423. e.stopPropagation();
  1424. var animation = $(this).data('closable');
  1425. if (animation !== '') {
  1426. Motion.animateOut($(this), animation, function () {
  1427. $(this).trigger('closed.zf');
  1428. });
  1429. } else {
  1430. $(this).fadeOut().trigger('closed.zf');
  1431. }
  1432. },
  1433. toggleFocusListener: function toggleFocusListener() {
  1434. var id = $(this).data('toggle-focus');
  1435. $("#".concat(id)).triggerHandler('toggle.zf.trigger', [$(this)]);
  1436. }
  1437. }; // Elements with [data-open] will reveal a plugin that supports it when clicked.
  1438. Triggers.Initializers.addOpenListener = function ($elem) {
  1439. $elem.off('click.zf.trigger', Triggers.Listeners.Basic.openListener);
  1440. $elem.on('click.zf.trigger', '[data-open]', Triggers.Listeners.Basic.openListener);
  1441. }; // Elements with [data-close] will close a plugin that supports it when clicked.
  1442. // If used without a value on [data-close], the event will bubble, allowing it to close a parent component.
  1443. Triggers.Initializers.addCloseListener = function ($elem) {
  1444. $elem.off('click.zf.trigger', Triggers.Listeners.Basic.closeListener);
  1445. $elem.on('click.zf.trigger', '[data-close]', Triggers.Listeners.Basic.closeListener);
  1446. }; // Elements with [data-toggle] will toggle a plugin that supports it when clicked.
  1447. Triggers.Initializers.addToggleListener = function ($elem) {
  1448. $elem.off('click.zf.trigger', Triggers.Listeners.Basic.toggleListener);
  1449. $elem.on('click.zf.trigger', '[data-toggle]', Triggers.Listeners.Basic.toggleListener);
  1450. }; // Elements with [data-closable] will respond to close.zf.trigger events.
  1451. Triggers.Initializers.addCloseableListener = function ($elem) {
  1452. $elem.off('close.zf.trigger', Triggers.Listeners.Basic.closeableListener);
  1453. $elem.on('close.zf.trigger', '[data-closeable], [data-closable]', Triggers.Listeners.Basic.closeableListener);
  1454. }; // Elements with [data-toggle-focus] will respond to coming in and out of focus
  1455. Triggers.Initializers.addToggleFocusListener = function ($elem) {
  1456. $elem.off('focus.zf.trigger blur.zf.trigger', Triggers.Listeners.Basic.toggleFocusListener);
  1457. $elem.on('focus.zf.trigger blur.zf.trigger', '[data-toggle-focus]', Triggers.Listeners.Basic.toggleFocusListener);
  1458. }; // More Global/complex listeners and triggers
  1459. Triggers.Listeners.Global = {
  1460. resizeListener: function resizeListener($nodes) {
  1461. if (!MutationObserver) {
  1462. //fallback for IE 9
  1463. $nodes.each(function () {
  1464. $(this).triggerHandler('resizeme.zf.trigger');
  1465. });
  1466. } //trigger all listening elements and signal a resize event
  1467. $nodes.attr('data-events', "resize");
  1468. },
  1469. scrollListener: function scrollListener($nodes) {
  1470. if (!MutationObserver) {
  1471. //fallback for IE 9
  1472. $nodes.each(function () {
  1473. $(this).triggerHandler('scrollme.zf.trigger');
  1474. });
  1475. } //trigger all listening elements and signal a scroll event
  1476. $nodes.attr('data-events', "scroll");
  1477. },
  1478. closeMeListener: function closeMeListener(e, pluginId) {
  1479. var plugin = e.namespace.split('.')[0];
  1480. var plugins = $("[data-".concat(plugin, "]")).not("[data-yeti-box=\"".concat(pluginId, "\"]"));
  1481. plugins.each(function () {
  1482. var _this = $(this);
  1483. _this.triggerHandler('close.zf.trigger', [_this]);
  1484. });
  1485. } // Global, parses whole document.
  1486. };
  1487. Triggers.Initializers.addClosemeListener = function (pluginName) {
  1488. var yetiBoxes = $('[data-yeti-box]'),
  1489. plugNames = ['dropdown', 'tooltip', 'reveal'];
  1490. if (pluginName) {
  1491. if (typeof pluginName === 'string') {
  1492. plugNames.push(pluginName);
  1493. } else if (_typeof(pluginName) === 'object' && typeof pluginName[0] === 'string') {
  1494. plugNames = plugNames.concat(pluginName);
  1495. } else {
  1496. console.error('Plugin names must be strings');
  1497. }
  1498. }
  1499. if (yetiBoxes.length) {
  1500. var listeners = plugNames.map(function (name) {
  1501. return "closeme.zf.".concat(name);
  1502. }).join(' ');
  1503. $(window).off(listeners).on(listeners, Triggers.Listeners.Global.closeMeListener);
  1504. }
  1505. };
  1506. function debounceGlobalListener(debounce, trigger, listener) {
  1507. var timer,
  1508. args = Array.prototype.slice.call(arguments, 3);
  1509. $(window).off(trigger).on(trigger, function (e) {
  1510. if (timer) {
  1511. clearTimeout(timer);
  1512. }
  1513. timer = setTimeout(function () {
  1514. listener.apply(null, args);
  1515. }, debounce || 10); //default time to emit scroll event
  1516. });
  1517. }
  1518. Triggers.Initializers.addResizeListener = function (debounce) {
  1519. var $nodes = $('[data-resize]');
  1520. if ($nodes.length) {
  1521. debounceGlobalListener(debounce, 'resize.zf.trigger', Triggers.Listeners.Global.resizeListener, $nodes);
  1522. }
  1523. };
  1524. Triggers.Initializers.addScrollListener = function (debounce) {
  1525. var $nodes = $('[data-scroll]');
  1526. if ($nodes.length) {
  1527. debounceGlobalListener(debounce, 'scroll.zf.trigger', Triggers.Listeners.Global.scrollListener, $nodes);
  1528. }
  1529. };
  1530. Triggers.Initializers.addMutationEventsListener = function ($elem) {
  1531. if (!MutationObserver) {
  1532. return false;
  1533. }
  1534. var $nodes = $elem.find('[data-resize], [data-scroll], [data-mutate]'); //element callback
  1535. var listeningElementsMutation = function listeningElementsMutation(mutationRecordsList) {
  1536. var $target = $(mutationRecordsList[0].target); //trigger the event handler for the element depending on type
  1537. switch (mutationRecordsList[0].type) {
  1538. case "attributes":
  1539. if ($target.attr("data-events") === "scroll" && mutationRecordsList[0].attributeName === "data-events") {
  1540. $target.triggerHandler('scrollme.zf.trigger', [$target, window.pageYOffset]);
  1541. }
  1542. if ($target.attr("data-events") === "resize" && mutationRecordsList[0].attributeName === "data-events") {
  1543. $target.triggerHandler('resizeme.zf.trigger', [$target]);
  1544. }
  1545. if (mutationRecordsList[0].attributeName === "style") {
  1546. $target.closest("[data-mutate]").attr("data-events", "mutate");
  1547. $target.closest("[data-mutate]").triggerHandler('mutateme.zf.trigger', [$target.closest("[data-mutate]")]);
  1548. }
  1549. break;
  1550. case "childList":
  1551. $target.closest("[data-mutate]").attr("data-events", "mutate");
  1552. $target.closest("[data-mutate]").triggerHandler('mutateme.zf.trigger', [$target.closest("[data-mutate]")]);
  1553. break;
  1554. default:
  1555. return false;
  1556. //nothing
  1557. }
  1558. };
  1559. if ($nodes.length) {
  1560. //for each element that needs to listen for resizing, scrolling, or mutation add a single observer
  1561. for (var i = 0; i <= $nodes.length - 1; i++) {
  1562. var elementObserver = new MutationObserver(listeningElementsMutation);
  1563. elementObserver.observe($nodes[i], {
  1564. attributes: true,
  1565. childList: true,
  1566. characterData: false,
  1567. subtree: true,
  1568. attributeFilter: ["data-events", "style"]
  1569. });
  1570. }
  1571. }
  1572. };
  1573. Triggers.Initializers.addSimpleListeners = function () {
  1574. var $document = $(document);
  1575. Triggers.Initializers.addOpenListener($document);
  1576. Triggers.Initializers.addCloseListener($document);
  1577. Triggers.Initializers.addToggleListener($document);
  1578. Triggers.Initializers.addCloseableListener($document);
  1579. Triggers.Initializers.addToggleFocusListener($document);
  1580. };
  1581. Triggers.Initializers.addGlobalListeners = function () {
  1582. var $document = $(document);
  1583. Triggers.Initializers.addMutationEventsListener($document);
  1584. Triggers.Initializers.addResizeListener();
  1585. Triggers.Initializers.addScrollListener();
  1586. Triggers.Initializers.addClosemeListener();
  1587. };
  1588. Triggers.init = function ($$$1, Foundation) {
  1589. onLoad($$$1(window), function () {
  1590. if ($$$1.triggersInitialized !== true) {
  1591. Triggers.Initializers.addSimpleListeners();
  1592. Triggers.Initializers.addGlobalListeners();
  1593. $$$1.triggersInitialized = true;
  1594. }
  1595. });
  1596. if (Foundation) {
  1597. Foundation.Triggers = Triggers; // Legacy included to be backwards compatible for now.
  1598. Foundation.IHearYou = Triggers.Initializers.addGlobalListeners;
  1599. }
  1600. };
  1601. // {function} _setup (replaces previous constructor),
  1602. // {function} _destroy (replaces previous destroy)
  1603. var Plugin =
  1604. /*#__PURE__*/
  1605. function () {
  1606. function Plugin(element, options) {
  1607. _classCallCheck(this, Plugin);
  1608. this._setup(element, options);
  1609. var pluginName = getPluginName(this);
  1610. this.uuid = GetYoDigits(6, pluginName);
  1611. if (!this.$element.attr("data-".concat(pluginName))) {
  1612. this.$element.attr("data-".concat(pluginName), this.uuid);
  1613. }
  1614. if (!this.$element.data('zfPlugin')) {
  1615. this.$element.data('zfPlugin', this);
  1616. }
  1617. /**
  1618. * Fires when the plugin has initialized.
  1619. * @event Plugin#init
  1620. */
  1621. this.$element.trigger("init.zf.".concat(pluginName));
  1622. }
  1623. _createClass(Plugin, [{
  1624. key: "destroy",
  1625. value: function destroy() {
  1626. this._destroy();
  1627. var pluginName = getPluginName(this);
  1628. this.$element.removeAttr("data-".concat(pluginName)).removeData('zfPlugin')
  1629. /**
  1630. * Fires when the plugin has been destroyed.
  1631. * @event Plugin#destroyed
  1632. */
  1633. .trigger("destroyed.zf.".concat(pluginName));
  1634. for (var prop in this) {
  1635. this[prop] = null; //clean up script to prep for garbage collection.
  1636. }
  1637. }
  1638. }]);
  1639. return Plugin;
  1640. }(); // Convert PascalCase to kebab-case
  1641. // Thank you: http://stackoverflow.com/a/8955580
  1642. function hyphenate$1(str) {
  1643. return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
  1644. }
  1645. function getPluginName(obj) {
  1646. if (typeof obj.constructor.name !== 'undefined') {
  1647. return hyphenate$1(obj.constructor.name);
  1648. } else {
  1649. return hyphenate$1(obj.className);
  1650. }
  1651. }
  1652. /**
  1653. * Abide module.
  1654. * @module foundation.abide
  1655. */
  1656. var Abide =
  1657. /*#__PURE__*/
  1658. function (_Plugin) {
  1659. _inherits(Abide, _Plugin);
  1660. function Abide() {
  1661. _classCallCheck(this, Abide);
  1662. return _possibleConstructorReturn(this, _getPrototypeOf(Abide).apply(this, arguments));
  1663. }
  1664. _createClass(Abide, [{
  1665. key: "_setup",
  1666. /**
  1667. * Creates a new instance of Abide.
  1668. * @class
  1669. * @name Abide
  1670. * @fires Abide#init
  1671. * @param {Object} element - jQuery object to add the trigger to.
  1672. * @param {Object} options - Overrides to the default plugin settings.
  1673. */
  1674. value: function _setup(element) {
  1675. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  1676. this.$element = element;
  1677. this.options = $.extend(true, {}, Abide.defaults, this.$element.data(), options);
  1678. this.className = 'Abide'; // ie9 back compat
  1679. this._init();
  1680. }
  1681. /**
  1682. * Initializes the Abide plugin and calls functions to get Abide functioning on load.
  1683. * @private
  1684. */
  1685. }, {
  1686. key: "_init",
  1687. value: function _init() {
  1688. var _this2 = this;
  1689. this.$inputs = $.merge( // Consider as input to validate:
  1690. this.$element.find('input').not('[type=submit]'), // * all input fields expect submit
  1691. this.$element.find('textarea, select') // * all textareas and select fields
  1692. );
  1693. var $globalErrors = this.$element.find('[data-abide-error]'); // Add a11y attributes to all fields
  1694. if (this.options.a11yAttributes) {
  1695. this.$inputs.each(function (i, input) {
  1696. return _this2.addA11yAttributes($(input));
  1697. });
  1698. $globalErrors.each(function (i, error) {
  1699. return _this2.addGlobalErrorA11yAttributes($(error));
  1700. });
  1701. }
  1702. this._events();
  1703. }
  1704. /**
  1705. * Initializes events for Abide.
  1706. * @private
  1707. */
  1708. }, {
  1709. key: "_events",
  1710. value: function _events() {
  1711. var _this3 = this;
  1712. this.$element.off('.abide').on('reset.zf.abide', function () {
  1713. _this3.resetForm();
  1714. }).on('submit.zf.abide', function () {
  1715. return _this3.validateForm();
  1716. });
  1717. if (this.options.validateOn === 'fieldChange') {
  1718. this.$inputs.off('change.zf.abide').on('change.zf.abide', function (e) {
  1719. _this3.validateInput($(e.target));
  1720. });
  1721. }
  1722. if (this.options.liveValidate) {
  1723. this.$inputs.off('input.zf.abide').on('input.zf.abide', function (e) {
  1724. _this3.validateInput($(e.target));
  1725. });
  1726. }
  1727. if (this.options.validateOnBlur) {
  1728. this.$inputs.off('blur.zf.abide').on('blur.zf.abide', function (e) {
  1729. _this3.validateInput($(e.target));
  1730. });
  1731. }
  1732. }
  1733. /**
  1734. * Calls necessary functions to update Abide upon DOM change
  1735. * @private
  1736. */
  1737. }, {
  1738. key: "_reflow",
  1739. value: function _reflow() {
  1740. this._init();
  1741. }
  1742. /**
  1743. * Checks whether or not a form element has the required attribute and if it's checked or not
  1744. * @param {Object} element - jQuery object to check for required attribute
  1745. * @returns {Boolean} Boolean value depends on whether or not attribute is checked or empty
  1746. */
  1747. }, {
  1748. key: "requiredCheck",
  1749. value: function requiredCheck($el) {
  1750. if (!$el.attr('required')) return true;
  1751. var isGood = true;
  1752. switch ($el[0].type) {
  1753. case 'checkbox':
  1754. isGood = $el[0].checked;
  1755. break;
  1756. case 'select':
  1757. case 'select-one':
  1758. case 'select-multiple':
  1759. var opt = $el.find('option:selected');
  1760. if (!opt.length || !opt.val()) isGood = false;
  1761. break;
  1762. default:
  1763. if (!$el.val() || !$el.val().length) isGood = false;
  1764. }
  1765. return isGood;
  1766. }
  1767. /**
  1768. * Get:
  1769. * - Based on $el, the first element(s) corresponding to `formErrorSelector` in this order:
  1770. * 1. The element's direct sibling('s).
  1771. * 2. The element's parent's children.
  1772. * - Element(s) with the attribute `[data-form-error-for]` set with the element's id.
  1773. *
  1774. * This allows for multiple form errors per input, though if none are found, no form errors will be shown.
  1775. *
  1776. * @param {Object} $el - jQuery object to use as reference to find the form error selector.
  1777. * @returns {Object} jQuery object with the selector.
  1778. */
  1779. }, {
  1780. key: "findFormError",
  1781. value: function findFormError($el) {
  1782. var id = $el[0].id;
  1783. var $error = $el.siblings(this.options.formErrorSelector);
  1784. if (!$error.length) {
  1785. $error = $el.parent().find(this.options.formErrorSelector);
  1786. }
  1787. if (id) {
  1788. $error = $error.add(this.$element.find("[data-form-error-for=\"".concat(id, "\"]")));
  1789. }
  1790. return $error;
  1791. }
  1792. /**
  1793. * Get the first element in this order:
  1794. * 2. The <label> with the attribute `[for="someInputId"]`
  1795. * 3. The `.closest()` <label>
  1796. *
  1797. * @param {Object} $el - jQuery object to check for required attribute
  1798. * @returns {Boolean} Boolean value depends on whether or not attribute is checked or empty
  1799. */
  1800. }, {
  1801. key: "findLabel",
  1802. value: function findLabel($el) {
  1803. var id = $el[0].id;
  1804. var $label = this.$element.find("label[for=\"".concat(id, "\"]"));
  1805. if (!$label.length) {
  1806. return $el.closest('label');
  1807. }
  1808. return $label;
  1809. }
  1810. /**
  1811. * Get the set of labels associated with a set of radio els in this order
  1812. * 2. The <label> with the attribute `[for="someInputId"]`
  1813. * 3. The `.closest()` <label>
  1814. *
  1815. * @param {Object} $el - jQuery object to check for required attribute
  1816. * @returns {Boolean} Boolean value depends on whether or not attribute is checked or empty
  1817. */
  1818. }, {
  1819. key: "findRadioLabels",
  1820. value: function findRadioLabels($els) {
  1821. var _this4 = this;
  1822. var labels = $els.map(function (i, el) {
  1823. var id = el.id;
  1824. var $label = _this4.$element.find("label[for=\"".concat(id, "\"]"));
  1825. if (!$label.length) {
  1826. $label = $(el).closest('label');
  1827. }
  1828. return $label[0];
  1829. });
  1830. return $(labels);
  1831. }
  1832. /**
  1833. * Adds the CSS error class as specified by the Abide settings to the label, input, and the form
  1834. * @param {Object} $el - jQuery object to add the class to
  1835. */
  1836. }, {
  1837. key: "addErrorClasses",
  1838. value: function addErrorClasses($el) {
  1839. var $label = this.findLabel($el);
  1840. var $formError = this.findFormError($el);
  1841. if ($label.length) {
  1842. $label.addClass(this.options.labelErrorClass);
  1843. }
  1844. if ($formError.length) {
  1845. $formError.addClass(this.options.formErrorClass);
  1846. }
  1847. $el.addClass(this.options.inputErrorClass).attr({
  1848. 'data-invalid': '',
  1849. 'aria-invalid': true
  1850. });
  1851. }
  1852. /**
  1853. * Adds [for] and [role=alert] attributes to all form error targetting $el,
  1854. * and [aria-describedby] attribute to $el toward the first form error.
  1855. * @param {Object} $el - jQuery object
  1856. */
  1857. }, {
  1858. key: "addA11yAttributes",
  1859. value: function addA11yAttributes($el) {
  1860. var $errors = this.findFormError($el);
  1861. var $labels = $errors.filter('label');
  1862. var $error = $errors.first();
  1863. if (!$errors.length) return; // Set [aria-describedby] on the input toward the first form error if it is not set
  1864. if (typeof $el.attr('aria-describedby') === 'undefined') {
  1865. // Get the first error ID or create one
  1866. var errorId = $error.attr('id');
  1867. if (typeof errorId === 'undefined') {
  1868. errorId = GetYoDigits(6, 'abide-error');
  1869. $error.attr('id', errorId);
  1870. }
  1871. $el.attr('aria-describedby', errorId);
  1872. }
  1873. if ($labels.filter('[for]').length < $labels.length) {
  1874. // Get the input ID or create one
  1875. var elemId = $el.attr('id');
  1876. if (typeof elemId === 'undefined') {
  1877. elemId = GetYoDigits(6, 'abide-input');
  1878. $el.attr('id', elemId);
  1879. }
  1880. $labels.each(function (i, label) {
  1881. var $label = $(label);
  1882. if (typeof $label.attr('for') === 'undefined') $label.attr('for', elemId);
  1883. });
  1884. } // For each error targeting $el, set [role=alert] if it is not set.
  1885. $errors.each(function (i, label) {
  1886. var $label = $(label);
  1887. if (typeof $label.attr('role') === 'undefined') $label.attr('role', 'alert');
  1888. }).end();
  1889. }
  1890. /**
  1891. * Adds [aria-live] attribute to the given global form error $el.
  1892. * @param {Object} $el - jQuery object to add the attribute to
  1893. */
  1894. }, {
  1895. key: "addGlobalErrorA11yAttributes",
  1896. value: function addGlobalErrorA11yAttributes($el) {
  1897. if (typeof $el.attr('aria-live') === 'undefined') $el.attr('aria-live', this.options.a11yErrorLevel);
  1898. }
  1899. /**
  1900. * Remove CSS error classes etc from an entire radio button group
  1901. * @param {String} groupName - A string that specifies the name of a radio button group
  1902. *
  1903. */
  1904. }, {
  1905. key: "removeRadioErrorClasses",
  1906. value: function removeRadioErrorClasses(groupName) {
  1907. var $els = this.$element.find(":radio[name=\"".concat(groupName, "\"]"));
  1908. var $labels = this.findRadioLabels($els);
  1909. var $formErrors = this.findFormError($els);
  1910. if ($labels.length) {
  1911. $labels.removeClass(this.options.labelErrorClass);
  1912. }
  1913. if ($formErrors.length) {
  1914. $formErrors.removeClass(this.options.formErrorClass);
  1915. }
  1916. $els.removeClass(this.options.inputErrorClass).attr({
  1917. 'data-invalid': null,
  1918. 'aria-invalid': null
  1919. });
  1920. }
  1921. /**
  1922. * Removes CSS error class as specified by the Abide settings from the label, input, and the form
  1923. * @param {Object} $el - jQuery object to remove the class from
  1924. */
  1925. }, {
  1926. key: "removeErrorClasses",
  1927. value: function removeErrorClasses($el) {
  1928. // radios need to clear all of the els
  1929. if ($el[0].type == 'radio') {
  1930. return this.removeRadioErrorClasses($el.attr('name'));
  1931. }
  1932. var $label = this.findLabel($el);
  1933. var $formError = this.findFormError($el);
  1934. if ($label.length) {
  1935. $label.removeClass(this.options.labelErrorClass);
  1936. }
  1937. if ($formError.length) {
  1938. $formError.removeClass(this.options.formErrorClass);
  1939. }
  1940. $el.removeClass(this.options.inputErrorClass).attr({
  1941. 'data-invalid': null,
  1942. 'aria-invalid': null
  1943. });
  1944. }
  1945. /**
  1946. * Goes through a form to find inputs and proceeds to validate them in ways specific to their type.
  1947. * Ignores inputs with data-abide-ignore, type="hidden" or disabled attributes set
  1948. * @fires Abide#invalid
  1949. * @fires Abide#valid
  1950. * @param {Object} element - jQuery object to validate, should be an HTML input
  1951. * @returns {Boolean} goodToGo - If the input is valid or not.
  1952. */
  1953. }, {
  1954. key: "validateInput",
  1955. value: function validateInput($el) {
  1956. var clearRequire = this.requiredCheck($el),
  1957. validated = false,
  1958. customValidator = true,
  1959. validator = $el.attr('data-validator'),
  1960. equalTo = true; // don't validate ignored inputs or hidden inputs or disabled inputs
  1961. if ($el.is('[data-abide-ignore]') || $el.is('[type="hidden"]') || $el.is('[disabled]')) {
  1962. return true;
  1963. }
  1964. switch ($el[0].type) {
  1965. case 'radio':
  1966. validated = this.validateRadio($el.attr('name'));
  1967. break;
  1968. case 'checkbox':
  1969. validated = clearRequire;
  1970. break;
  1971. case 'select':
  1972. case 'select-one':
  1973. case 'select-multiple':
  1974. validated = clearRequire;
  1975. break;
  1976. default:
  1977. validated = this.validateText($el);
  1978. }
  1979. if (validator) {
  1980. customValidator = this.matchValidation($el, validator, $el.attr('required'));
  1981. }
  1982. if ($el.attr('data-equalto')) {
  1983. equalTo = this.options.validators.equalTo($el);
  1984. }
  1985. var goodToGo = [clearRequire, validated, customValidator, equalTo].indexOf(false) === -1;
  1986. var message = (goodToGo ? 'valid' : 'invalid') + '.zf.abide';
  1987. if (goodToGo) {
  1988. // Re-validate inputs that depend on this one with equalto
  1989. var dependentElements = this.$element.find("[data-equalto=\"".concat($el.attr('id'), "\"]"));
  1990. if (dependentElements.length) {
  1991. var _this = this;
  1992. dependentElements.each(function () {
  1993. if ($(this).val()) {
  1994. _this.validateInput($(this));
  1995. }
  1996. });
  1997. }
  1998. }
  1999. this[goodToGo ? 'removeErrorClasses' : 'addErrorClasses']($el);
  2000. /**
  2001. * Fires when the input is done checking for validation. Event trigger is either `valid.zf.abide` or `invalid.zf.abide`
  2002. * Trigger includes the DOM element of the input.
  2003. * @event Abide#valid
  2004. * @event Abide#invalid
  2005. */
  2006. $el.trigger(message, [$el]);
  2007. return goodToGo;
  2008. }
  2009. /**
  2010. * Goes through a form and if there are any invalid inputs, it will display the form error element
  2011. * @returns {Boolean} noError - true if no errors were detected...
  2012. * @fires Abide#formvalid
  2013. * @fires Abide#forminvalid
  2014. */
  2015. }, {
  2016. key: "validateForm",
  2017. value: function validateForm() {
  2018. var _this5 = this;
  2019. var acc = [];
  2020. var _this = this;
  2021. this.$inputs.each(function () {
  2022. acc.push(_this.validateInput($(this)));
  2023. });
  2024. var noError = acc.indexOf(false) === -1;
  2025. this.$element.find('[data-abide-error]').each(function (i, elem) {
  2026. var $elem = $(elem); // Ensure a11y attributes are set
  2027. if (_this5.options.a11yAttributes) _this5.addGlobalErrorA11yAttributes($elem); // Show or hide the error
  2028. $elem.css('display', noError ? 'none' : 'block');
  2029. });
  2030. /**
  2031. * Fires when the form is finished validating. Event trigger is either `formvalid.zf.abide` or `forminvalid.zf.abide`.
  2032. * Trigger includes the element of the form.
  2033. * @event Abide#formvalid
  2034. * @event Abide#forminvalid
  2035. */
  2036. this.$element.trigger((noError ? 'formvalid' : 'forminvalid') + '.zf.abide', [this.$element]);
  2037. return noError;
  2038. }
  2039. /**
  2040. * 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.
  2041. * @param {Object} $el - jQuery object to validate, should be a text input HTML element
  2042. * @param {String} pattern - string value of one of the RegEx patterns in Abide.options.patterns
  2043. * @returns {Boolean} Boolean value depends on whether or not the input value matches the pattern specified
  2044. */
  2045. }, {
  2046. key: "validateText",
  2047. value: function validateText($el, pattern) {
  2048. // A pattern can be passed to this function, or it will be infered from the input's "pattern" attribute, or it's "type" attribute
  2049. pattern = pattern || $el.attr('pattern') || $el.attr('type');
  2050. var inputText = $el.val();
  2051. var valid = false;
  2052. if (inputText.length) {
  2053. // If the pattern attribute on the element is in Abide's list of patterns, then test that regexp
  2054. if (this.options.patterns.hasOwnProperty(pattern)) {
  2055. valid = this.options.patterns[pattern].test(inputText);
  2056. } // If the pattern name isn't also the type attribute of the field, then test it as a regexp
  2057. else if (pattern !== $el.attr('type')) {
  2058. valid = new RegExp(pattern).test(inputText);
  2059. } else {
  2060. valid = true;
  2061. }
  2062. } // An empty field is valid if it's not required
  2063. else if (!$el.prop('required')) {
  2064. valid = true;
  2065. }
  2066. return valid;
  2067. }
  2068. /**
  2069. * 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.
  2070. * @param {String} groupName - A string that specifies the name of a radio button group
  2071. * @returns {Boolean} Boolean value depends on whether or not at least one radio input has been selected (if it's required)
  2072. */
  2073. }, {
  2074. key: "validateRadio",
  2075. value: function validateRadio(groupName) {
  2076. // If at least one radio in the group has the `required` attribute, the group is considered required
  2077. // Per W3C spec, all radio buttons in a group should have `required`, but we're being nice
  2078. var $group = this.$element.find(":radio[name=\"".concat(groupName, "\"]"));
  2079. var valid = false,
  2080. required = false; // For the group to be required, at least one radio needs to be required
  2081. $group.each(function (i, e) {
  2082. if ($(e).attr('required')) {
  2083. required = true;
  2084. }
  2085. });
  2086. if (!required) valid = true;
  2087. if (!valid) {
  2088. // For the group to be valid, at least one radio needs to be checked
  2089. $group.each(function (i, e) {
  2090. if ($(e).prop('checked')) {
  2091. valid = true;
  2092. }
  2093. });
  2094. }
  2095. return valid;
  2096. }
  2097. /**
  2098. * 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.
  2099. * @param {Object} $el - jQuery input element.
  2100. * @param {String} validators - a string of function names matching functions in the Abide.options.validators object.
  2101. * @param {Boolean} required - self explanatory?
  2102. * @returns {Boolean} - true if validations passed.
  2103. */
  2104. }, {
  2105. key: "matchValidation",
  2106. value: function matchValidation($el, validators, required) {
  2107. var _this6 = this;
  2108. required = required ? true : false;
  2109. var clear = validators.split(' ').map(function (v) {
  2110. return _this6.options.validators[v]($el, required, $el.parent());
  2111. });
  2112. return clear.indexOf(false) === -1;
  2113. }
  2114. /**
  2115. * Resets form inputs and styles
  2116. * @fires Abide#formreset
  2117. */
  2118. }, {
  2119. key: "resetForm",
  2120. value: function resetForm() {
  2121. var $form = this.$element,
  2122. opts = this.options;
  2123. $(".".concat(opts.labelErrorClass), $form).not('small').removeClass(opts.labelErrorClass);
  2124. $(".".concat(opts.inputErrorClass), $form).not('small').removeClass(opts.inputErrorClass);
  2125. $("".concat(opts.formErrorSelector, ".").concat(opts.formErrorClass)).removeClass(opts.formErrorClass);
  2126. $form.find('[data-abide-error]').css('display', 'none');
  2127. $(':input', $form).not(':button, :submit, :reset, :hidden, :radio, :checkbox, [data-abide-ignore]').val('').attr({
  2128. 'data-invalid': null,
  2129. 'aria-invalid': null
  2130. });
  2131. $(':input:radio', $form).not('[data-abide-ignore]').prop('checked', false).attr({
  2132. 'data-invalid': null,
  2133. 'aria-invalid': null
  2134. });
  2135. $(':input:checkbox', $form).not('[data-abide-ignore]').prop('checked', false).attr({
  2136. 'data-invalid': null,
  2137. 'aria-invalid': null
  2138. });
  2139. /**
  2140. * Fires when the form has been reset.
  2141. * @event Abide#formreset
  2142. */
  2143. $form.trigger('formreset.zf.abide', [$form]);
  2144. }
  2145. /**
  2146. * Destroys an instance of Abide.
  2147. * Removes error styles and classes from elements, without resetting their values.
  2148. */
  2149. }, {
  2150. key: "_destroy",
  2151. value: function _destroy() {
  2152. var _this = this;
  2153. this.$element.off('.abide').find('[data-abide-error]').css('display', 'none');
  2154. this.$inputs.off('.abide').each(function () {
  2155. _this.removeErrorClasses($(this));
  2156. });
  2157. }
  2158. }]);
  2159. return Abide;
  2160. }(Plugin);
  2161. /**
  2162. * Default settings for plugin
  2163. */
  2164. Abide.defaults = {
  2165. /**
  2166. * The default event to validate inputs. Checkboxes and radios validate immediately.
  2167. * Remove or change this value for manual validation.
  2168. * @option
  2169. * @type {?string}
  2170. * @default 'fieldChange'
  2171. */
  2172. validateOn: 'fieldChange',
  2173. /**
  2174. * Class to be applied to input labels on failed validation.
  2175. * @option
  2176. * @type {string}
  2177. * @default 'is-invalid-label'
  2178. */
  2179. labelErrorClass: 'is-invalid-label',
  2180. /**
  2181. * Class to be applied to inputs on failed validation.
  2182. * @option
  2183. * @type {string}
  2184. * @default 'is-invalid-input'
  2185. */
  2186. inputErrorClass: 'is-invalid-input',
  2187. /**
  2188. * Class selector to use to target Form Errors for show/hide.
  2189. * @option
  2190. * @type {string}
  2191. * @default '.form-error'
  2192. */
  2193. formErrorSelector: '.form-error',
  2194. /**
  2195. * Class added to Form Errors on failed validation.
  2196. * @option
  2197. * @type {string}
  2198. * @default 'is-visible'
  2199. */
  2200. formErrorClass: 'is-visible',
  2201. /**
  2202. * If true, automatically insert when possible:
  2203. * - `[aria-describedby]` on fields
  2204. * - `[role=alert]` on form errors and `[for]` on form error labels
  2205. * - `[aria-live]` on global errors `[data-abide-error]` (see option `a11yErrorLevel`).
  2206. * @option
  2207. * @type {boolean}
  2208. * @default true
  2209. */
  2210. a11yAttributes: true,
  2211. /**
  2212. * [aria-live] attribute value to be applied on global errors `[data-abide-error]`.
  2213. * Options are: 'assertive', 'polite' and 'off'/null
  2214. * @option
  2215. * @see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions
  2216. * @type {string}
  2217. * @default 'assertive'
  2218. */
  2219. a11yErrorLevel: 'assertive',
  2220. /**
  2221. * Set to true to validate text inputs on any value change.
  2222. * @option
  2223. * @type {boolean}
  2224. * @default false
  2225. */
  2226. liveValidate: false,
  2227. /**
  2228. * Set to true to validate inputs on blur.
  2229. * @option
  2230. * @type {boolean}
  2231. * @default false
  2232. */
  2233. validateOnBlur: false,
  2234. patterns: {
  2235. alpha: /^[a-zA-Z]+$/,
  2236. alpha_numeric: /^[a-zA-Z0-9]+$/,
  2237. integer: /^[-+]?\d+$/,
  2238. number: /^[-+]?\d*(?:[\.\,]\d+)?$/,
  2239. // amex, visa, diners
  2240. 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})$/,
  2241. cvv: /^([0-9]){3,4}$/,
  2242. // http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address
  2243. 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])?)+$/,
  2244. // From CommonRegexJS (@talyssonoc)
  2245. // https://github.com/talyssonoc/CommonRegexJS/blob/e2901b9f57222bc14069dc8f0598d5f412555411/lib/commonregex.js#L76
  2246. // For more restrictive URL Regexs, see https://mathiasbynens.be/demo/url-regex.
  2247. 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]))$/,
  2248. // abc.de
  2249. domain: /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,8}$/,
  2250. 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))$/,
  2251. // YYYY-MM-DD
  2252. 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))$/,
  2253. // HH:MM:SS
  2254. time: /^(0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]){2}$/,
  2255. dateISO: /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/,
  2256. // MM/DD/YYYY
  2257. month_day_year: /^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.]\d{4}$/,
  2258. // DD/MM/YYYY
  2259. day_month_year: /^(0[1-9]|[12][0-9]|3[01])[- \/.](0[1-9]|1[012])[- \/.]\d{4}$/,
  2260. // #FFF or #FFFFFF
  2261. color: /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/,
  2262. // Domain || URL
  2263. website: {
  2264. test: function test(text) {
  2265. return Abide.defaults.patterns['domain'].test(text) || Abide.defaults.patterns['url'].test(text);
  2266. }
  2267. }
  2268. },
  2269. /**
  2270. * Optional validation functions to be used. `equalTo` being the only default included function.
  2271. * Functions should return only a boolean if the input is valid or not. Functions are given the following arguments:
  2272. * el : The jQuery element to validate.
  2273. * required : Boolean value of the required attribute be present or not.
  2274. * parent : The direct parent of the input.
  2275. * @option
  2276. */
  2277. validators: {
  2278. equalTo: function equalTo(el, required, parent) {
  2279. return $("#".concat(el.attr('data-equalto'))).val() === el.val();
  2280. }
  2281. }
  2282. };
  2283. /**
  2284. * Accordion module.
  2285. * @module foundation.accordion
  2286. * @requires foundation.util.keyboard
  2287. */
  2288. var Accordion =
  2289. /*#__PURE__*/
  2290. function (_Plugin) {
  2291. _inherits(Accordion, _Plugin);
  2292. function Accordion() {
  2293. _classCallCheck(this, Accordion);
  2294. return _possibleConstructorReturn(this, _getPrototypeOf(Accordion).apply(this, arguments));
  2295. }
  2296. _createClass(Accordion, [{
  2297. key: "_setup",
  2298. /**
  2299. * Creates a new instance of an accordion.
  2300. * @class
  2301. * @name Accordion
  2302. * @fires Accordion#init
  2303. * @param {jQuery} element - jQuery object to make into an accordion.
  2304. * @param {Object} options - a plain object with settings to override the default options.
  2305. */
  2306. value: function _setup(element, options) {
  2307. this.$element = element;
  2308. this.options = $.extend({}, Accordion.defaults, this.$element.data(), options);
  2309. this.className = 'Accordion'; // ie9 back compat
  2310. this._init();
  2311. Keyboard.register('Accordion', {
  2312. 'ENTER': 'toggle',
  2313. 'SPACE': 'toggle',
  2314. 'ARROW_DOWN': 'next',
  2315. 'ARROW_UP': 'previous'
  2316. });
  2317. }
  2318. /**
  2319. * Initializes the accordion by animating the preset active pane(s).
  2320. * @private
  2321. */
  2322. }, {
  2323. key: "_init",
  2324. value: function _init() {
  2325. var _this2 = this;
  2326. this._isInitializing = true;
  2327. this.$element.attr('role', 'tablist');
  2328. this.$tabs = this.$element.children('[data-accordion-item]');
  2329. this.$tabs.each(function (idx, el) {
  2330. var $el = $(el),
  2331. $content = $el.children('[data-tab-content]'),
  2332. id = $content[0].id || GetYoDigits(6, 'accordion'),
  2333. linkId = el.id ? "".concat(el.id, "-label") : "".concat(id, "-label");
  2334. $el.find('a:first').attr({
  2335. 'aria-controls': id,
  2336. 'role': 'tab',
  2337. 'id': linkId,
  2338. 'aria-expanded': false,
  2339. 'aria-selected': false
  2340. });
  2341. $content.attr({
  2342. 'role': 'tabpanel',
  2343. 'aria-labelledby': linkId,
  2344. 'aria-hidden': true,
  2345. 'id': id
  2346. });
  2347. });
  2348. var $initActive = this.$element.find('.is-active').children('[data-tab-content]');
  2349. if ($initActive.length) {
  2350. // Save up the initial hash to return to it later when going back in history
  2351. this._initialAnchor = $initActive.prev('a').attr('href');
  2352. this._openSingleTab($initActive);
  2353. }
  2354. this._checkDeepLink = function () {
  2355. var anchor = window.location.hash;
  2356. if (!anchor.length) {
  2357. // If we are still initializing and there is no anchor, then there is nothing to do
  2358. if (_this2._isInitializing) return; // Otherwise, move to the initial anchor
  2359. if (_this2._initialAnchor) anchor = _this2._initialAnchor;
  2360. }
  2361. var $anchor = anchor && $(anchor);
  2362. var $link = anchor && _this2.$element.find("[href$=\"".concat(anchor, "\"]")); // Whether the anchor element that has been found is part of this element
  2363. var isOwnAnchor = !!($anchor.length && $link.length); // If there is an anchor for the hash, open it (if not already active)
  2364. if ($anchor && $link && $link.length) {
  2365. if (!$link.parent('[data-accordion-item]').hasClass('is-active')) {
  2366. _this2._openSingleTab($anchor);
  2367. }
  2368. } // Otherwise, close everything
  2369. else {
  2370. _this2._closeAllTabs();
  2371. }
  2372. if (isOwnAnchor) {
  2373. // Roll up a little to show the titles
  2374. if (_this2.options.deepLinkSmudge) {
  2375. onLoad($(window), function () {
  2376. var offset = _this2.$element.offset();
  2377. $('html, body').animate({
  2378. scrollTop: offset.top
  2379. }, _this2.options.deepLinkSmudgeDelay);
  2380. });
  2381. }
  2382. /**
  2383. * Fires when the plugin has deeplinked at pageload
  2384. * @event Accordion#deeplink
  2385. */
  2386. _this2.$element.trigger('deeplink.zf.accordion', [$link, $anchor]);
  2387. }
  2388. }; //use browser to open a tab, if it exists in this tabset
  2389. if (this.options.deepLink) {
  2390. this._checkDeepLink();
  2391. }
  2392. this._events();
  2393. this._isInitializing = false;
  2394. }
  2395. /**
  2396. * Adds event handlers for items within the accordion.
  2397. * @private
  2398. */
  2399. }, {
  2400. key: "_events",
  2401. value: function _events() {
  2402. var _this = this;
  2403. this.$tabs.each(function () {
  2404. var $elem = $(this);
  2405. var $tabContent = $elem.children('[data-tab-content]');
  2406. if ($tabContent.length) {
  2407. $elem.children('a').off('click.zf.accordion keydown.zf.accordion').on('click.zf.accordion', function (e) {
  2408. e.preventDefault();
  2409. _this.toggle($tabContent);
  2410. }).on('keydown.zf.accordion', function (e) {
  2411. Keyboard.handleKey(e, 'Accordion', {
  2412. toggle: function toggle() {
  2413. _this.toggle($tabContent);
  2414. },
  2415. next: function next() {
  2416. var $a = $elem.next().find('a').focus();
  2417. if (!_this.options.multiExpand) {
  2418. $a.trigger('click.zf.accordion');
  2419. }
  2420. },
  2421. previous: function previous() {
  2422. var $a = $elem.prev().find('a').focus();
  2423. if (!_this.options.multiExpand) {
  2424. $a.trigger('click.zf.accordion');
  2425. }
  2426. },
  2427. handled: function handled() {
  2428. e.preventDefault();
  2429. e.stopPropagation();
  2430. }
  2431. });
  2432. });
  2433. }
  2434. });
  2435. if (this.options.deepLink) {
  2436. $(window).on('hashchange', this._checkDeepLink);
  2437. }
  2438. }
  2439. /**
  2440. * Toggles the selected content pane's open/close state.
  2441. * @param {jQuery} $target - jQuery object of the pane to toggle (`.accordion-content`).
  2442. * @function
  2443. */
  2444. }, {
  2445. key: "toggle",
  2446. value: function toggle($target) {
  2447. if ($target.closest('[data-accordion]').is('[disabled]')) {
  2448. console.info('Cannot toggle an accordion that is disabled.');
  2449. return;
  2450. }
  2451. if ($target.parent().hasClass('is-active')) {
  2452. this.up($target);
  2453. } else {
  2454. this.down($target);
  2455. } //either replace or update browser history
  2456. if (this.options.deepLink) {
  2457. var anchor = $target.prev('a').attr('href');
  2458. if (this.options.updateHistory) {
  2459. history.pushState({}, '', anchor);
  2460. } else {
  2461. history.replaceState({}, '', anchor);
  2462. }
  2463. }
  2464. }
  2465. /**
  2466. * Opens the accordion tab defined by `$target`.
  2467. * @param {jQuery} $target - Accordion pane to open (`.accordion-content`).
  2468. * @fires Accordion#down
  2469. * @function
  2470. */
  2471. }, {
  2472. key: "down",
  2473. value: function down($target) {
  2474. if ($target.closest('[data-accordion]').is('[disabled]')) {
  2475. console.info('Cannot call down on an accordion that is disabled.');
  2476. return;
  2477. }
  2478. if (this.options.multiExpand) this._openTab($target);else this._openSingleTab($target);
  2479. }
  2480. /**
  2481. * Closes the tab defined by `$target`.
  2482. * It may be ignored if the Accordion options don't allow it.
  2483. *
  2484. * @param {jQuery} $target - Accordion tab to close (`.accordion-content`).
  2485. * @fires Accordion#up
  2486. * @function
  2487. */
  2488. }, {
  2489. key: "up",
  2490. value: function up($target) {
  2491. if (this.$element.is('[disabled]')) {
  2492. console.info('Cannot call up on an accordion that is disabled.');
  2493. return;
  2494. } // Don't close the item if it is already closed
  2495. var $targetItem = $target.parent();
  2496. if (!$targetItem.hasClass('is-active')) return; // Don't close the item if there is no other active item (unless with `allowAllClosed`)
  2497. var $othersItems = $targetItem.siblings();
  2498. if (!this.options.allowAllClosed && !$othersItems.hasClass('is-active')) return;
  2499. this._closeTab($target);
  2500. }
  2501. /**
  2502. * Make the tab defined by `$target` the only opened tab, closing all others tabs.
  2503. * @param {jQuery} $target - Accordion tab to open (`.accordion-content`).
  2504. * @function
  2505. * @private
  2506. */
  2507. }, {
  2508. key: "_openSingleTab",
  2509. value: function _openSingleTab($target) {
  2510. // Close all the others active tabs.
  2511. var $activeContents = this.$element.children('.is-active').children('[data-tab-content]');
  2512. if ($activeContents.length) {
  2513. this._closeTab($activeContents.not($target));
  2514. } // Then open the target.
  2515. this._openTab($target);
  2516. }
  2517. /**
  2518. * Opens the tab defined by `$target`.
  2519. * @param {jQuery} $target - Accordion tab to open (`.accordion-content`).
  2520. * @fires Accordion#down
  2521. * @function
  2522. * @private
  2523. */
  2524. }, {
  2525. key: "_openTab",
  2526. value: function _openTab($target) {
  2527. var _this3 = this;
  2528. var $targetItem = $target.parent();
  2529. var targetContentId = $target.attr('aria-labelledby');
  2530. $target.attr('aria-hidden', false);
  2531. $targetItem.addClass('is-active');
  2532. $("#".concat(targetContentId)).attr({
  2533. 'aria-expanded': true,
  2534. 'aria-selected': true
  2535. });
  2536. $target.slideDown(this.options.slideSpeed, function () {
  2537. /**
  2538. * Fires when the tab is done opening.
  2539. * @event Accordion#down
  2540. */
  2541. _this3.$element.trigger('down.zf.accordion', [$target]);
  2542. });
  2543. }
  2544. /**
  2545. * Closes the tab defined by `$target`.
  2546. * @param {jQuery} $target - Accordion tab to close (`.accordion-content`).
  2547. * @fires Accordion#up
  2548. * @function
  2549. * @private
  2550. */
  2551. }, {
  2552. key: "_closeTab",
  2553. value: function _closeTab($target) {
  2554. var _this4 = this;
  2555. var $targetItem = $target.parent();
  2556. var targetContentId = $target.attr('aria-labelledby');
  2557. $target.attr('aria-hidden', true);
  2558. $targetItem.removeClass('is-active');
  2559. $("#".concat(targetContentId)).attr({
  2560. 'aria-expanded': false,
  2561. 'aria-selected': false
  2562. });
  2563. $target.slideUp(this.options.slideSpeed, function () {
  2564. /**
  2565. * Fires when the tab is done collapsing up.
  2566. * @event Accordion#up
  2567. */
  2568. _this4.$element.trigger('up.zf.accordion', [$target]);
  2569. });
  2570. }
  2571. /**
  2572. * Closes all active tabs
  2573. * @fires Accordion#up
  2574. * @function
  2575. * @private
  2576. */
  2577. }, {
  2578. key: "_closeAllTabs",
  2579. value: function _closeAllTabs() {
  2580. var $activeTabs = this.$element.children('.is-active').children('[data-tab-content]');
  2581. if ($activeTabs.length) {
  2582. this._closeTab($activeTabs);
  2583. }
  2584. }
  2585. /**
  2586. * Destroys an instance of an accordion.
  2587. * @fires Accordion#destroyed
  2588. * @function
  2589. */
  2590. }, {
  2591. key: "_destroy",
  2592. value: function _destroy() {
  2593. this.$element.find('[data-tab-content]').stop(true).slideUp(0).css('display', '');
  2594. this.$element.find('a').off('.zf.accordion');
  2595. if (this.options.deepLink) {
  2596. $(window).off('hashchange', this._checkDeepLink);
  2597. }
  2598. }
  2599. }]);
  2600. return Accordion;
  2601. }(Plugin);
  2602. Accordion.defaults = {
  2603. /**
  2604. * Amount of time to animate the opening of an accordion pane.
  2605. * @option
  2606. * @type {number}
  2607. * @default 250
  2608. */
  2609. slideSpeed: 250,
  2610. /**
  2611. * Allow the accordion to have multiple open panes.
  2612. * @option
  2613. * @type {boolean}
  2614. * @default false
  2615. */
  2616. multiExpand: false,
  2617. /**
  2618. * Allow the accordion to close all panes.
  2619. * @option
  2620. * @type {boolean}
  2621. * @default false
  2622. */
  2623. allowAllClosed: false,
  2624. /**
  2625. * Link the location hash to the open pane.
  2626. * Set the location hash when the opened pane changes, and open and scroll to the corresponding pane when the location changes.
  2627. * @option
  2628. * @type {boolean}
  2629. * @default false
  2630. */
  2631. deepLink: false,
  2632. /**
  2633. * If `deepLink` is enabled, adjust the deep link scroll to make sure the top of the accordion panel is visible
  2634. * @option
  2635. * @type {boolean}
  2636. * @default false
  2637. */
  2638. deepLinkSmudge: false,
  2639. /**
  2640. * If `deepLinkSmudge` is enabled, animation time (ms) for the deep link adjustment
  2641. * @option
  2642. * @type {number}
  2643. * @default 300
  2644. */
  2645. deepLinkSmudgeDelay: 300,
  2646. /**
  2647. * If `deepLink` is enabled, update the browser history with the open accordion
  2648. * @option
  2649. * @type {boolean}
  2650. * @default false
  2651. */
  2652. updateHistory: false
  2653. };
  2654. /**
  2655. * AccordionMenu module.
  2656. * @module foundation.accordionMenu
  2657. * @requires foundation.util.keyboard
  2658. * @requires foundation.util.nest
  2659. */
  2660. var AccordionMenu =
  2661. /*#__PURE__*/
  2662. function (_Plugin) {
  2663. _inherits(AccordionMenu, _Plugin);
  2664. function AccordionMenu() {
  2665. _classCallCheck(this, AccordionMenu);
  2666. return _possibleConstructorReturn(this, _getPrototypeOf(AccordionMenu).apply(this, arguments));
  2667. }
  2668. _createClass(AccordionMenu, [{
  2669. key: "_setup",
  2670. /**
  2671. * Creates a new instance of an accordion menu.
  2672. * @class
  2673. * @name AccordionMenu
  2674. * @fires AccordionMenu#init
  2675. * @param {jQuery} element - jQuery object to make into an accordion menu.
  2676. * @param {Object} options - Overrides to the default plugin settings.
  2677. */
  2678. value: function _setup(element, options) {
  2679. this.$element = element;
  2680. this.options = $.extend({}, AccordionMenu.defaults, this.$element.data(), options);
  2681. this.className = 'AccordionMenu'; // ie9 back compat
  2682. this._init();
  2683. Keyboard.register('AccordionMenu', {
  2684. 'ENTER': 'toggle',
  2685. 'SPACE': 'toggle',
  2686. 'ARROW_RIGHT': 'open',
  2687. 'ARROW_UP': 'up',
  2688. 'ARROW_DOWN': 'down',
  2689. 'ARROW_LEFT': 'close',
  2690. 'ESCAPE': 'closeAll'
  2691. });
  2692. }
  2693. /**
  2694. * Initializes the accordion menu by hiding all nested menus.
  2695. * @private
  2696. */
  2697. }, {
  2698. key: "_init",
  2699. value: function _init() {
  2700. Nest.Feather(this.$element, 'accordion');
  2701. var _this = this;
  2702. this.$element.find('[data-submenu]').not('.is-active').slideUp(0); //.find('a').css('padding-left', '1rem');
  2703. this.$element.attr({
  2704. 'role': 'tree',
  2705. 'aria-multiselectable': this.options.multiOpen
  2706. });
  2707. this.$menuLinks = this.$element.find('.is-accordion-submenu-parent');
  2708. this.$menuLinks.each(function () {
  2709. var linkId = this.id || GetYoDigits(6, 'acc-menu-link'),
  2710. $elem = $(this),
  2711. $sub = $elem.children('[data-submenu]'),
  2712. subId = $sub[0].id || GetYoDigits(6, 'acc-menu'),
  2713. isActive = $sub.hasClass('is-active');
  2714. if (_this.options.parentLink) {
  2715. var $anchor = $elem.children('a');
  2716. $anchor.clone().prependTo($sub).wrap('<li data-is-parent-link class="is-submenu-parent-item is-submenu-item is-accordion-submenu-item"></li>');
  2717. }
  2718. if (_this.options.submenuToggle) {
  2719. $elem.addClass('has-submenu-toggle');
  2720. $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>');
  2721. } else {
  2722. $elem.attr({
  2723. 'aria-controls': subId,
  2724. 'aria-expanded': isActive,
  2725. 'id': linkId
  2726. });
  2727. }
  2728. $sub.attr({
  2729. 'aria-labelledby': linkId,
  2730. 'aria-hidden': !isActive,
  2731. 'role': 'group',
  2732. 'id': subId
  2733. });
  2734. });
  2735. this.$element.find('li').attr({
  2736. 'role': 'treeitem'
  2737. });
  2738. var initPanes = this.$element.find('.is-active');
  2739. if (initPanes.length) {
  2740. var _this = this;
  2741. initPanes.each(function () {
  2742. _this.down($(this));
  2743. });
  2744. }
  2745. this._events();
  2746. }
  2747. /**
  2748. * Adds event handlers for items within the menu.
  2749. * @private
  2750. */
  2751. }, {
  2752. key: "_events",
  2753. value: function _events() {
  2754. var _this = this;
  2755. this.$element.find('li').each(function () {
  2756. var $submenu = $(this).children('[data-submenu]');
  2757. if ($submenu.length) {
  2758. if (_this.options.submenuToggle) {
  2759. $(this).children('.submenu-toggle').off('click.zf.accordionMenu').on('click.zf.accordionMenu', function (e) {
  2760. _this.toggle($submenu);
  2761. });
  2762. } else {
  2763. $(this).children('a').off('click.zf.accordionMenu').on('click.zf.accordionMenu', function (e) {
  2764. e.preventDefault();
  2765. _this.toggle($submenu);
  2766. });
  2767. }
  2768. }
  2769. }).on('keydown.zf.accordionmenu', function (e) {
  2770. var $element = $(this),
  2771. $elements = $element.parent('ul').children('li'),
  2772. $prevElement,
  2773. $nextElement,
  2774. $target = $element.children('[data-submenu]');
  2775. $elements.each(function (i) {
  2776. if ($(this).is($element)) {
  2777. $prevElement = $elements.eq(Math.max(0, i - 1)).find('a').first();
  2778. $nextElement = $elements.eq(Math.min(i + 1, $elements.length - 1)).find('a').first();
  2779. if ($(this).children('[data-submenu]:visible').length) {
  2780. // has open sub menu
  2781. $nextElement = $element.find('li:first-child').find('a').first();
  2782. }
  2783. if ($(this).is(':first-child')) {
  2784. // is first element of sub menu
  2785. $prevElement = $element.parents('li').first().find('a').first();
  2786. } else if ($prevElement.parents('li').first().children('[data-submenu]:visible').length) {
  2787. // if previous element has open sub menu
  2788. $prevElement = $prevElement.parents('li').find('li:last-child').find('a').first();
  2789. }
  2790. if ($(this).is(':last-child')) {
  2791. // is last element of sub menu
  2792. $nextElement = $element.parents('li').first().next('li').find('a').first();
  2793. }
  2794. return;
  2795. }
  2796. });
  2797. Keyboard.handleKey(e, 'AccordionMenu', {
  2798. open: function open() {
  2799. if ($target.is(':hidden')) {
  2800. _this.down($target);
  2801. $target.find('li').first().find('a').first().focus();
  2802. }
  2803. },
  2804. close: function close() {
  2805. if ($target.length && !$target.is(':hidden')) {
  2806. // close active sub of this item
  2807. _this.up($target);
  2808. } else if ($element.parent('[data-submenu]').length) {
  2809. // close currently open sub
  2810. _this.up($element.parent('[data-submenu]'));
  2811. $element.parents('li').first().find('a').first().focus();
  2812. }
  2813. },
  2814. up: function up() {
  2815. $prevElement.focus();
  2816. return true;
  2817. },
  2818. down: function down() {
  2819. $nextElement.focus();
  2820. return true;
  2821. },
  2822. toggle: function toggle() {
  2823. if (_this.options.submenuToggle) {
  2824. return false;
  2825. }
  2826. if ($element.children('[data-submenu]').length) {
  2827. _this.toggle($element.children('[data-submenu]'));
  2828. return true;
  2829. }
  2830. },
  2831. closeAll: function closeAll() {
  2832. _this.hideAll();
  2833. },
  2834. handled: function handled(preventDefault) {
  2835. if (preventDefault) {
  2836. e.preventDefault();
  2837. }
  2838. e.stopImmediatePropagation();
  2839. }
  2840. });
  2841. }); //.attr('tabindex', 0);
  2842. }
  2843. /**
  2844. * Closes all panes of the menu.
  2845. * @function
  2846. */
  2847. }, {
  2848. key: "hideAll",
  2849. value: function hideAll() {
  2850. this.up(this.$element.find('[data-submenu]'));
  2851. }
  2852. /**
  2853. * Opens all panes of the menu.
  2854. * @function
  2855. */
  2856. }, {
  2857. key: "showAll",
  2858. value: function showAll() {
  2859. this.down(this.$element.find('[data-submenu]'));
  2860. }
  2861. /**
  2862. * Toggles the open/close state of a submenu.
  2863. * @function
  2864. * @param {jQuery} $target - the submenu to toggle
  2865. */
  2866. }, {
  2867. key: "toggle",
  2868. value: function toggle($target) {
  2869. if (!$target.is(':animated')) {
  2870. if (!$target.is(':hidden')) {
  2871. this.up($target);
  2872. } else {
  2873. this.down($target);
  2874. }
  2875. }
  2876. }
  2877. /**
  2878. * Opens the sub-menu defined by `$target`.
  2879. * @param {jQuery} $target - Sub-menu to open.
  2880. * @fires AccordionMenu#down
  2881. */
  2882. }, {
  2883. key: "down",
  2884. value: function down($target) {
  2885. var _this2 = this;
  2886. // If having multiple submenus active is disabled, close all the submenus
  2887. // that are not parents or children of the targeted submenu.
  2888. if (!this.options.multiOpen) {
  2889. // The "branch" of the targetted submenu, from the component root to
  2890. // the active submenus nested in it.
  2891. var $targetBranch = $target.parentsUntil(this.$element).add($target).add($target.find('.is-active')); // All the active submenus that are not in the branch.
  2892. var $othersActiveSubmenus = this.$element.find('.is-active').not($targetBranch);
  2893. this.up($othersActiveSubmenus);
  2894. }
  2895. $target.addClass('is-active').attr({
  2896. 'aria-hidden': false
  2897. });
  2898. if (this.options.submenuToggle) {
  2899. $target.prev('.submenu-toggle').attr({
  2900. 'aria-expanded': true
  2901. });
  2902. } else {
  2903. $target.parent('.is-accordion-submenu-parent').attr({
  2904. 'aria-expanded': true
  2905. });
  2906. }
  2907. $target.slideDown(this.options.slideSpeed, function () {
  2908. /**
  2909. * Fires when the menu is done opening.
  2910. * @event AccordionMenu#down
  2911. */
  2912. _this2.$element.trigger('down.zf.accordionMenu', [$target]);
  2913. });
  2914. }
  2915. /**
  2916. * Closes the sub-menu defined by `$target`. All sub-menus inside the target will be closed as well.
  2917. * @param {jQuery} $target - Sub-menu to close.
  2918. * @fires AccordionMenu#up
  2919. */
  2920. }, {
  2921. key: "up",
  2922. value: function up($target) {
  2923. var _this3 = this;
  2924. var $submenus = $target.find('[data-submenu]');
  2925. var $allmenus = $target.add($submenus);
  2926. $submenus.slideUp(0);
  2927. $allmenus.removeClass('is-active').attr('aria-hidden', true);
  2928. if (this.options.submenuToggle) {
  2929. $allmenus.prev('.submenu-toggle').attr('aria-expanded', false);
  2930. } else {
  2931. $allmenus.parent('.is-accordion-submenu-parent').attr('aria-expanded', false);
  2932. }
  2933. $target.slideUp(this.options.slideSpeed, function () {
  2934. /**
  2935. * Fires when the menu is done collapsing up.
  2936. * @event AccordionMenu#up
  2937. */
  2938. _this3.$element.trigger('up.zf.accordionMenu', [$target]);
  2939. });
  2940. }
  2941. /**
  2942. * Destroys an instance of accordion menu.
  2943. * @fires AccordionMenu#destroyed
  2944. */
  2945. }, {
  2946. key: "_destroy",
  2947. value: function _destroy() {
  2948. this.$element.find('[data-submenu]').slideDown(0).css('display', '');
  2949. this.$element.find('a').off('click.zf.accordionMenu');
  2950. this.$element.find('[data-is-parent-link]').detach();
  2951. if (this.options.submenuToggle) {
  2952. this.$element.find('.has-submenu-toggle').removeClass('has-submenu-toggle');
  2953. this.$element.find('.submenu-toggle').remove();
  2954. }
  2955. Nest.Burn(this.$element, 'accordion');
  2956. }
  2957. }]);
  2958. return AccordionMenu;
  2959. }(Plugin);
  2960. AccordionMenu.defaults = {
  2961. /**
  2962. * Adds the parent link to the submenu.
  2963. * @option
  2964. * @type {boolean}
  2965. * @default false
  2966. */
  2967. parentLink: false,
  2968. /**
  2969. * Amount of time to animate the opening of a submenu in ms.
  2970. * @option
  2971. * @type {number}
  2972. * @default 250
  2973. */
  2974. slideSpeed: 250,
  2975. /**
  2976. * Adds a separate submenu toggle button. This allows the parent item to have a link.
  2977. * @option
  2978. * @example true
  2979. */
  2980. submenuToggle: false,
  2981. /**
  2982. * The text used for the submenu toggle if enabled. This is used for screen readers only.
  2983. * @option
  2984. * @example true
  2985. */
  2986. submenuToggleText: 'Toggle menu',
  2987. /**
  2988. * Allow the menu to have multiple open panes.
  2989. * @option
  2990. * @type {boolean}
  2991. * @default true
  2992. */
  2993. multiOpen: true
  2994. };
  2995. /**
  2996. * Drilldown module.
  2997. * @module foundation.drilldown
  2998. * @requires foundation.util.keyboard
  2999. * @requires foundation.util.nest
  3000. * @requires foundation.util.box
  3001. */
  3002. var Drilldown =
  3003. /*#__PURE__*/
  3004. function (_Plugin) {
  3005. _inherits(Drilldown, _Plugin);
  3006. function Drilldown() {
  3007. _classCallCheck(this, Drilldown);
  3008. return _possibleConstructorReturn(this, _getPrototypeOf(Drilldown).apply(this, arguments));
  3009. }
  3010. _createClass(Drilldown, [{
  3011. key: "_setup",
  3012. /**
  3013. * Creates a new instance of a drilldown menu.
  3014. * @class
  3015. * @name Drilldown
  3016. * @param {jQuery} element - jQuery object to make into an accordion menu.
  3017. * @param {Object} options - Overrides to the default plugin settings.
  3018. */
  3019. value: function _setup(element, options) {
  3020. this.$element = element;
  3021. this.options = $.extend({}, Drilldown.defaults, this.$element.data(), options);
  3022. this.className = 'Drilldown'; // ie9 back compat
  3023. this._init();
  3024. Keyboard.register('Drilldown', {
  3025. 'ENTER': 'open',
  3026. 'SPACE': 'open',
  3027. 'ARROW_RIGHT': 'next',
  3028. 'ARROW_UP': 'up',
  3029. 'ARROW_DOWN': 'down',
  3030. 'ARROW_LEFT': 'previous',
  3031. 'ESCAPE': 'close',
  3032. 'TAB': 'down',
  3033. 'SHIFT_TAB': 'up'
  3034. });
  3035. }
  3036. /**
  3037. * Initializes the drilldown by creating jQuery collections of elements
  3038. * @private
  3039. */
  3040. }, {
  3041. key: "_init",
  3042. value: function _init() {
  3043. Nest.Feather(this.$element, 'drilldown');
  3044. if (this.options.autoApplyClass) {
  3045. this.$element.addClass('drilldown');
  3046. }
  3047. this.$element.attr({
  3048. 'role': 'tree',
  3049. 'aria-multiselectable': false
  3050. });
  3051. this.$submenuAnchors = this.$element.find('li.is-drilldown-submenu-parent').children('a');
  3052. this.$submenus = this.$submenuAnchors.parent('li').children('[data-submenu]').attr('role', 'group');
  3053. 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)
  3054. // Used to set the wrapper height when the drilldown is closed/reopened from any (sub)menu
  3055. this.$currentMenu = this.$element;
  3056. this.$element.attr('data-mutate', this.$element.attr('data-drilldown') || GetYoDigits(6, 'drilldown'));
  3057. this._prepareMenu();
  3058. this._registerEvents();
  3059. this._keyboardEvents();
  3060. }
  3061. /**
  3062. * prepares drilldown menu by setting attributes to links and elements
  3063. * sets a min height to prevent content jumping
  3064. * wraps the element if not already wrapped
  3065. * @private
  3066. * @function
  3067. */
  3068. }, {
  3069. key: "_prepareMenu",
  3070. value: function _prepareMenu() {
  3071. var _this = this; // if(!this.options.holdOpen){
  3072. // this._menuLinkEvents();
  3073. // }
  3074. this.$submenuAnchors.each(function () {
  3075. var $link = $(this);
  3076. var $sub = $link.parent();
  3077. if (_this.options.parentLink) {
  3078. $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>');
  3079. }
  3080. $link.data('savedHref', $link.attr('href')).removeAttr('href').attr('tabindex', 0);
  3081. $link.children('[data-submenu]').attr({
  3082. 'aria-hidden': true,
  3083. 'tabindex': 0,
  3084. 'role': 'group'
  3085. });
  3086. _this._events($link);
  3087. });
  3088. this.$submenus.each(function () {
  3089. var $menu = $(this),
  3090. $back = $menu.find('.js-drilldown-back');
  3091. if (!$back.length) {
  3092. switch (_this.options.backButtonPosition) {
  3093. case "bottom":
  3094. $menu.append(_this.options.backButton);
  3095. break;
  3096. case "top":
  3097. $menu.prepend(_this.options.backButton);
  3098. break;
  3099. default:
  3100. console.error("Unsupported backButtonPosition value '" + _this.options.backButtonPosition + "'");
  3101. }
  3102. }
  3103. _this._back($menu);
  3104. });
  3105. this.$submenus.addClass('invisible');
  3106. if (!this.options.autoHeight) {
  3107. this.$submenus.addClass('drilldown-submenu-cover-previous');
  3108. } // create a wrapper on element if it doesn't exist.
  3109. if (!this.$element.parent().hasClass('is-drilldown')) {
  3110. this.$wrapper = $(this.options.wrapper).addClass('is-drilldown');
  3111. if (this.options.animateHeight) this.$wrapper.addClass('animate-height');
  3112. this.$element.wrap(this.$wrapper);
  3113. } // set wrapper
  3114. this.$wrapper = this.$element.parent();
  3115. this.$wrapper.css(this._getMaxDims());
  3116. }
  3117. }, {
  3118. key: "_resize",
  3119. value: function _resize() {
  3120. this.$wrapper.css({
  3121. 'max-width': 'none',
  3122. 'min-height': 'none'
  3123. }); // _getMaxDims has side effects (boo) but calling it should update all other necessary heights & widths
  3124. this.$wrapper.css(this._getMaxDims());
  3125. }
  3126. /**
  3127. * Adds event handlers to elements in the menu.
  3128. * @function
  3129. * @private
  3130. * @param {jQuery} $elem - the current menu item to add handlers to.
  3131. */
  3132. }, {
  3133. key: "_events",
  3134. value: function _events($elem) {
  3135. var _this = this;
  3136. $elem.off('click.zf.drilldown').on('click.zf.drilldown', function (e) {
  3137. if ($(e.target).parentsUntil('ul', 'li').hasClass('is-drilldown-submenu-parent')) {
  3138. e.stopImmediatePropagation();
  3139. e.preventDefault();
  3140. } // if(e.target !== e.currentTarget.firstElementChild){
  3141. // return false;
  3142. // }
  3143. _this._show($elem.parent('li'));
  3144. if (_this.options.closeOnClick) {
  3145. var $body = $('body');
  3146. $body.off('.zf.drilldown').on('click.zf.drilldown', function (e) {
  3147. if (e.target === _this.$element[0] || $.contains(_this.$element[0], e.target)) {
  3148. return;
  3149. }
  3150. e.preventDefault();
  3151. _this._hideAll();
  3152. $body.off('.zf.drilldown');
  3153. });
  3154. }
  3155. });
  3156. }
  3157. /**
  3158. * Adds event handlers to the menu element.
  3159. * @function
  3160. * @private
  3161. */
  3162. }, {
  3163. key: "_registerEvents",
  3164. value: function _registerEvents() {
  3165. if (this.options.scrollTop) {
  3166. this._bindHandler = this._scrollTop.bind(this);
  3167. this.$element.on('open.zf.drilldown hide.zf.drilldown closed.zf.drilldown', this._bindHandler);
  3168. }
  3169. this.$element.on('mutateme.zf.trigger', this._resize.bind(this));
  3170. }
  3171. /**
  3172. * Scroll to Top of Element or data-scroll-top-element
  3173. * @function
  3174. * @fires Drilldown#scrollme
  3175. */
  3176. }, {
  3177. key: "_scrollTop",
  3178. value: function _scrollTop() {
  3179. var _this = this;
  3180. var $scrollTopElement = _this.options.scrollTopElement != '' ? $(_this.options.scrollTopElement) : _this.$element,
  3181. scrollPos = parseInt($scrollTopElement.offset().top + _this.options.scrollTopOffset, 10);
  3182. $('html, body').stop(true).animate({
  3183. scrollTop: scrollPos
  3184. }, _this.options.animationDuration, _this.options.animationEasing, function () {
  3185. /**
  3186. * Fires after the menu has scrolled
  3187. * @event Drilldown#scrollme
  3188. */
  3189. if (this === $('html')[0]) _this.$element.trigger('scrollme.zf.drilldown');
  3190. });
  3191. }
  3192. /**
  3193. * Adds keydown event listener to `li`'s in the menu.
  3194. * @private
  3195. */
  3196. }, {
  3197. key: "_keyboardEvents",
  3198. value: function _keyboardEvents() {
  3199. var _this = this;
  3200. this.$menuItems.add(this.$element.find('.js-drilldown-back > a, .is-submenu-parent-item > a')).on('keydown.zf.drilldown', function (e) {
  3201. var $element = $(this),
  3202. $elements = $element.parent('li').parent('ul').children('li').children('a'),
  3203. $prevElement,
  3204. $nextElement;
  3205. $elements.each(function (i) {
  3206. if ($(this).is($element)) {
  3207. $prevElement = $elements.eq(Math.max(0, i - 1));
  3208. $nextElement = $elements.eq(Math.min(i + 1, $elements.length - 1));
  3209. return;
  3210. }
  3211. });
  3212. Keyboard.handleKey(e, 'Drilldown', {
  3213. next: function next() {
  3214. if ($element.is(_this.$submenuAnchors)) {
  3215. _this._show($element.parent('li'));
  3216. $element.parent('li').one(transitionend($element), function () {
  3217. $element.parent('li').find('ul li a').not('.js-drilldown-back a').first().focus();
  3218. });
  3219. return true;
  3220. }
  3221. },
  3222. previous: function previous() {
  3223. _this._hide($element.parent('li').parent('ul'));
  3224. $element.parent('li').parent('ul').one(transitionend($element), function () {
  3225. setTimeout(function () {
  3226. $element.parent('li').parent('ul').parent('li').children('a').first().focus();
  3227. }, 1);
  3228. });
  3229. return true;
  3230. },
  3231. up: function up() {
  3232. $prevElement.focus(); // Don't tap focus on first element in root ul
  3233. return !$element.is(_this.$element.find('> li:first-child > a'));
  3234. },
  3235. down: function down() {
  3236. $nextElement.focus(); // Don't tap focus on last element in root ul
  3237. return !$element.is(_this.$element.find('> li:last-child > a'));
  3238. },
  3239. close: function close() {
  3240. // Don't close on element in root ul
  3241. if (!$element.is(_this.$element.find('> li > a'))) {
  3242. _this._hide($element.parent().parent());
  3243. $element.parent().parent().siblings('a').focus();
  3244. }
  3245. },
  3246. open: function open() {
  3247. if (_this.options.parentLink && $element.attr('href')) {
  3248. // Link with href
  3249. return false;
  3250. } else if (!$element.is(_this.$menuItems)) {
  3251. // not menu item means back button
  3252. _this._hide($element.parent('li').parent('ul'));
  3253. $element.parent('li').parent('ul').one(transitionend($element), function () {
  3254. setTimeout(function () {
  3255. $element.parent('li').parent('ul').parent('li').children('a').first().focus();
  3256. }, 1);
  3257. });
  3258. return true;
  3259. } else if ($element.is(_this.$submenuAnchors)) {
  3260. // Sub menu item
  3261. _this._show($element.parent('li'));
  3262. $element.parent('li').one(transitionend($element), function () {
  3263. $element.parent('li').find('ul li a').not('.js-drilldown-back a').first().focus();
  3264. });
  3265. return true;
  3266. }
  3267. },
  3268. handled: function handled(preventDefault) {
  3269. if (preventDefault) {
  3270. e.preventDefault();
  3271. }
  3272. e.stopImmediatePropagation();
  3273. }
  3274. });
  3275. }); // end keyboardAccess
  3276. }
  3277. /**
  3278. * Closes all open elements, and returns to root menu.
  3279. * @function
  3280. * @fires Drilldown#closed
  3281. */
  3282. }, {
  3283. key: "_hideAll",
  3284. value: function _hideAll() {
  3285. var $elem = this.$element.find('.is-drilldown-submenu.is-active').addClass('is-closing');
  3286. if (this.options.autoHeight) this.$wrapper.css({
  3287. height: $elem.parent().closest('ul').data('calcHeight')
  3288. });
  3289. $elem.one(transitionend($elem), function (e) {
  3290. $elem.removeClass('is-active is-closing');
  3291. });
  3292. /**
  3293. * Fires when the menu is fully closed.
  3294. * @event Drilldown#closed
  3295. */
  3296. this.$element.trigger('closed.zf.drilldown');
  3297. }
  3298. /**
  3299. * Adds event listener for each `back` button, and closes open menus.
  3300. * @function
  3301. * @fires Drilldown#back
  3302. * @param {jQuery} $elem - the current sub-menu to add `back` event.
  3303. */
  3304. }, {
  3305. key: "_back",
  3306. value: function _back($elem) {
  3307. var _this = this;
  3308. $elem.off('click.zf.drilldown');
  3309. $elem.children('.js-drilldown-back').on('click.zf.drilldown', function (e) {
  3310. e.stopImmediatePropagation(); // console.log('mouseup on back');
  3311. _this._hide($elem); // If there is a parent submenu, call show
  3312. var parentSubMenu = $elem.parent('li').parent('ul').parent('li');
  3313. if (parentSubMenu.length) {
  3314. _this._show(parentSubMenu);
  3315. }
  3316. });
  3317. }
  3318. /**
  3319. * Adds event listener to menu items w/o submenus to close open menus on click.
  3320. * @function
  3321. * @private
  3322. */
  3323. }, {
  3324. key: "_menuLinkEvents",
  3325. value: function _menuLinkEvents() {
  3326. var _this = this;
  3327. this.$menuItems.not('.is-drilldown-submenu-parent').off('click.zf.drilldown').on('click.zf.drilldown', function (e) {
  3328. // e.stopImmediatePropagation();
  3329. setTimeout(function () {
  3330. _this._hideAll();
  3331. }, 0);
  3332. });
  3333. }
  3334. /**
  3335. * Sets the CSS classes for submenu to show it.
  3336. * @function
  3337. * @private
  3338. * @param {jQuery} $elem - the target submenu (`ul` tag)
  3339. * @param {boolean} trigger - trigger drilldown event
  3340. */
  3341. }, {
  3342. key: "_setShowSubMenuClasses",
  3343. value: function _setShowSubMenuClasses($elem, trigger) {
  3344. $elem.addClass('is-active').removeClass('invisible').attr('aria-hidden', false);
  3345. $elem.parent('li').attr('aria-expanded', true);
  3346. if (trigger === true) {
  3347. this.$element.trigger('open.zf.drilldown', [$elem]);
  3348. }
  3349. }
  3350. /**
  3351. * Sets the CSS classes for submenu to hide it.
  3352. * @function
  3353. * @private
  3354. * @param {jQuery} $elem - the target submenu (`ul` tag)
  3355. * @param {boolean} trigger - trigger drilldown event
  3356. */
  3357. }, {
  3358. key: "_setHideSubMenuClasses",
  3359. value: function _setHideSubMenuClasses($elem, trigger) {
  3360. $elem.removeClass('is-active').addClass('invisible').attr('aria-hidden', true);
  3361. $elem.parent('li').attr('aria-expanded', false);
  3362. if (trigger === true) {
  3363. $elem.trigger('hide.zf.drilldown', [$elem]);
  3364. }
  3365. }
  3366. /**
  3367. * Opens a specific drilldown (sub)menu no matter which (sub)menu in it is currently visible.
  3368. * Compared to _show() this lets you jump into any submenu without clicking through every submenu on the way to it.
  3369. * @function
  3370. * @fires Drilldown#open
  3371. * @param {jQuery} $elem - the target (sub)menu (`ul` tag)
  3372. * @param {boolean} autoFocus - if true the first link in the target (sub)menu gets auto focused
  3373. */
  3374. }, {
  3375. key: "_showMenu",
  3376. value: function _showMenu($elem, autoFocus) {
  3377. var _this = this; // Reset drilldown
  3378. var $expandedSubmenus = this.$element.find('li[aria-expanded="true"] > ul[data-submenu]');
  3379. $expandedSubmenus.each(function (index) {
  3380. _this._setHideSubMenuClasses($(this));
  3381. }); // Save the menu as the currently displayed one.
  3382. this.$currentMenu = $elem; // If target menu is root, focus first link & exit
  3383. if ($elem.is('[data-drilldown]')) {
  3384. if (autoFocus === true) $elem.find('li[role="treeitem"] > a').first().focus();
  3385. if (this.options.autoHeight) this.$wrapper.css('height', $elem.data('calcHeight'));
  3386. return;
  3387. } // Find all submenus on way to root incl. the element itself
  3388. var $submenus = $elem.children().first().parentsUntil('[data-drilldown]', '[data-submenu]'); // Open target menu and all submenus on its way to root
  3389. $submenus.each(function (index) {
  3390. // Update height of first child (target menu) if autoHeight option true
  3391. if (index === 0 && _this.options.autoHeight) {
  3392. _this.$wrapper.css('height', $(this).data('calcHeight'));
  3393. }
  3394. var isLastChild = index == $submenus.length - 1; // Add transitionsend listener to last child (root due to reverse order) to open target menu's first link
  3395. // Last child makes sure the event gets always triggered even if going through several menus
  3396. if (isLastChild === true) {
  3397. $(this).one(transitionend($(this)), function () {
  3398. if (autoFocus === true) {
  3399. $elem.find('li[role="treeitem"] > a').first().focus();
  3400. }
  3401. });
  3402. }
  3403. _this._setShowSubMenuClasses($(this), isLastChild);
  3404. });
  3405. }
  3406. /**
  3407. * Opens a submenu.
  3408. * @function
  3409. * @fires Drilldown#open
  3410. * @param {jQuery} $elem - the current element with a submenu to open, i.e. the `li` tag.
  3411. */
  3412. }, {
  3413. key: "_show",
  3414. value: function _show($elem) {
  3415. var $submenu = $elem.children('[data-submenu]');
  3416. $elem.attr('aria-expanded', true);
  3417. this.$currentMenu = $submenu;
  3418. $submenu.addClass('is-active').removeClass('invisible').attr('aria-hidden', false);
  3419. if (this.options.autoHeight) {
  3420. this.$wrapper.css({
  3421. height: $submenu.data('calcHeight')
  3422. });
  3423. }
  3424. /**
  3425. * Fires when the submenu has opened.
  3426. * @event Drilldown#open
  3427. */
  3428. this.$element.trigger('open.zf.drilldown', [$elem]);
  3429. }
  3430. /**
  3431. * Hides a submenu
  3432. * @function
  3433. * @fires Drilldown#hide
  3434. * @param {jQuery} $elem - the current sub-menu to hide, i.e. the `ul` tag.
  3435. */
  3436. }, {
  3437. key: "_hide",
  3438. value: function _hide($elem) {
  3439. if (this.options.autoHeight) this.$wrapper.css({
  3440. height: $elem.parent().closest('ul').data('calcHeight')
  3441. });
  3442. $elem.parent('li').attr('aria-expanded', false);
  3443. $elem.attr('aria-hidden', true);
  3444. $elem.addClass('is-closing').one(transitionend($elem), function () {
  3445. $elem.removeClass('is-active is-closing');
  3446. $elem.blur().addClass('invisible');
  3447. });
  3448. /**
  3449. * Fires when the submenu has closed.
  3450. * @event Drilldown#hide
  3451. */
  3452. $elem.trigger('hide.zf.drilldown', [$elem]);
  3453. }
  3454. /**
  3455. * Iterates through the nested menus to calculate the min-height, and max-width for the menu.
  3456. * Prevents content jumping.
  3457. * @function
  3458. * @private
  3459. */
  3460. }, {
  3461. key: "_getMaxDims",
  3462. value: function _getMaxDims() {
  3463. var maxHeight = 0,
  3464. result = {},
  3465. _this = this; // Recalculate menu heights and total max height
  3466. this.$submenus.add(this.$element).each(function () {
  3467. var numOfElems = $(this).children('li').length;
  3468. var height = Box.GetDimensions(this).height;
  3469. maxHeight = height > maxHeight ? height : maxHeight;
  3470. if (_this.options.autoHeight) {
  3471. $(this).data('calcHeight', height);
  3472. }
  3473. });
  3474. if (this.options.autoHeight) result['height'] = this.$currentMenu.data('calcHeight');else result['min-height'] = "".concat(maxHeight, "px");
  3475. result['max-width'] = "".concat(this.$element[0].getBoundingClientRect().width, "px");
  3476. return result;
  3477. }
  3478. /**
  3479. * Destroys the Drilldown Menu
  3480. * @function
  3481. */
  3482. }, {
  3483. key: "_destroy",
  3484. value: function _destroy() {
  3485. if (this.options.scrollTop) this.$element.off('.zf.drilldown', this._bindHandler);
  3486. this._hideAll();
  3487. this.$element.off('mutateme.zf.trigger');
  3488. Nest.Burn(this.$element, 'drilldown');
  3489. 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');
  3490. this.$submenuAnchors.each(function () {
  3491. $(this).off('.zf.drilldown');
  3492. });
  3493. this.$element.find('[data-is-parent-link]').detach();
  3494. this.$submenus.removeClass('drilldown-submenu-cover-previous invisible');
  3495. this.$element.find('a').each(function () {
  3496. var $link = $(this);
  3497. $link.removeAttr('tabindex');
  3498. if ($link.data('savedHref')) {
  3499. $link.attr('href', $link.data('savedHref')).removeData('savedHref');
  3500. } else {
  3501. return;
  3502. }
  3503. });
  3504. }
  3505. }]);
  3506. return Drilldown;
  3507. }(Plugin);
  3508. Drilldown.defaults = {
  3509. /**
  3510. * Drilldowns depend on styles in order to function properly; in the default build of Foundation these are
  3511. * on the `drilldown` class. This option auto-applies this class to the drilldown upon initialization.
  3512. * @option
  3513. * @type {boolian}
  3514. * @default true
  3515. */
  3516. autoApplyClass: true,
  3517. /**
  3518. * 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.
  3519. * @option
  3520. * @type {string}
  3521. * @default '<li class="js-drilldown-back"><a tabindex="0">Back</a></li>'
  3522. */
  3523. backButton: '<li class="js-drilldown-back"><a tabindex="0">Back</a></li>',
  3524. /**
  3525. * Position the back button either at the top or bottom of drilldown submenus. Can be `'left'` or `'bottom'`.
  3526. * @option
  3527. * @type {string}
  3528. * @default top
  3529. */
  3530. backButtonPosition: 'top',
  3531. /**
  3532. * 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.
  3533. * @option
  3534. * @type {string}
  3535. * @default '<div></div>'
  3536. */
  3537. wrapper: '<div></div>',
  3538. /**
  3539. * Adds the parent link to the submenu.
  3540. * @option
  3541. * @type {boolean}
  3542. * @default false
  3543. */
  3544. parentLink: false,
  3545. /**
  3546. * Allow the menu to return to root list on body click.
  3547. * @option
  3548. * @type {boolean}
  3549. * @default false
  3550. */
  3551. closeOnClick: false,
  3552. /**
  3553. * Allow the menu to auto adjust height.
  3554. * @option
  3555. * @type {boolean}
  3556. * @default false
  3557. */
  3558. autoHeight: false,
  3559. /**
  3560. * Animate the auto adjust height.
  3561. * @option
  3562. * @type {boolean}
  3563. * @default false
  3564. */
  3565. animateHeight: false,
  3566. /**
  3567. * Scroll to the top of the menu after opening a submenu or navigating back using the menu back button
  3568. * @option
  3569. * @type {boolean}
  3570. * @default false
  3571. */
  3572. scrollTop: false,
  3573. /**
  3574. * String jquery selector (for example 'body') of element to take offset().top from, if empty string the drilldown menu offset().top is taken
  3575. * @option
  3576. * @type {string}
  3577. * @default ''
  3578. */
  3579. scrollTopElement: '',
  3580. /**
  3581. * ScrollTop offset
  3582. * @option
  3583. * @type {number}
  3584. * @default 0
  3585. */
  3586. scrollTopOffset: 0,
  3587. /**
  3588. * Scroll animation duration
  3589. * @option
  3590. * @type {number}
  3591. * @default 500
  3592. */
  3593. animationDuration: 500,
  3594. /**
  3595. * Scroll animation easing. Can be `'swing'` or `'linear'`.
  3596. * @option
  3597. * @type {string}
  3598. * @see {@link https://api.jquery.com/animate|JQuery animate}
  3599. * @default 'swing'
  3600. */
  3601. animationEasing: 'swing' // holdOpen: false
  3602. };
  3603. var POSITIONS = ['left', 'right', 'top', 'bottom'];
  3604. var VERTICAL_ALIGNMENTS = ['top', 'bottom', 'center'];
  3605. var HORIZONTAL_ALIGNMENTS = ['left', 'right', 'center'];
  3606. var ALIGNMENTS = {
  3607. 'left': VERTICAL_ALIGNMENTS,
  3608. 'right': VERTICAL_ALIGNMENTS,
  3609. 'top': HORIZONTAL_ALIGNMENTS,
  3610. 'bottom': HORIZONTAL_ALIGNMENTS
  3611. };
  3612. function nextItem(item, array) {
  3613. var currentIdx = array.indexOf(item);
  3614. if (currentIdx === array.length - 1) {
  3615. return array[0];
  3616. } else {
  3617. return array[currentIdx + 1];
  3618. }
  3619. }
  3620. var Positionable =
  3621. /*#__PURE__*/
  3622. function (_Plugin) {
  3623. _inherits(Positionable, _Plugin);
  3624. function Positionable() {
  3625. _classCallCheck(this, Positionable);
  3626. return _possibleConstructorReturn(this, _getPrototypeOf(Positionable).apply(this, arguments));
  3627. }
  3628. _createClass(Positionable, [{
  3629. key: "_init",
  3630. /**
  3631. * Abstract class encapsulating the tether-like explicit positioning logic
  3632. * including repositioning based on overlap.
  3633. * Expects classes to define defaults for vOffset, hOffset, position,
  3634. * alignment, allowOverlap, and allowBottomOverlap. They can do this by
  3635. * extending the defaults, or (for now recommended due to the way docs are
  3636. * generated) by explicitly declaring them.
  3637. *
  3638. **/
  3639. value: function _init() {
  3640. this.triedPositions = {};
  3641. this.position = this.options.position === 'auto' ? this._getDefaultPosition() : this.options.position;
  3642. this.alignment = this.options.alignment === 'auto' ? this._getDefaultAlignment() : this.options.alignment;
  3643. this.originalPosition = this.position;
  3644. this.originalAlignment = this.alignment;
  3645. }
  3646. }, {
  3647. key: "_getDefaultPosition",
  3648. value: function _getDefaultPosition() {
  3649. return 'bottom';
  3650. }
  3651. }, {
  3652. key: "_getDefaultAlignment",
  3653. value: function _getDefaultAlignment() {
  3654. switch (this.position) {
  3655. case 'bottom':
  3656. case 'top':
  3657. return rtl() ? 'right' : 'left';
  3658. case 'left':
  3659. case 'right':
  3660. return 'bottom';
  3661. }
  3662. }
  3663. /**
  3664. * Adjusts the positionable possible positions by iterating through alignments
  3665. * and positions.
  3666. * @function
  3667. * @private
  3668. */
  3669. }, {
  3670. key: "_reposition",
  3671. value: function _reposition() {
  3672. if (this._alignmentsExhausted(this.position)) {
  3673. this.position = nextItem(this.position, POSITIONS);
  3674. this.alignment = ALIGNMENTS[this.position][0];
  3675. } else {
  3676. this._realign();
  3677. }
  3678. }
  3679. /**
  3680. * Adjusts the dropdown pane possible positions by iterating through alignments
  3681. * on the current position.
  3682. * @function
  3683. * @private
  3684. */
  3685. }, {
  3686. key: "_realign",
  3687. value: function _realign() {
  3688. this._addTriedPosition(this.position, this.alignment);
  3689. this.alignment = nextItem(this.alignment, ALIGNMENTS[this.position]);
  3690. }
  3691. }, {
  3692. key: "_addTriedPosition",
  3693. value: function _addTriedPosition(position, alignment) {
  3694. this.triedPositions[position] = this.triedPositions[position] || [];
  3695. this.triedPositions[position].push(alignment);
  3696. }
  3697. }, {
  3698. key: "_positionsExhausted",
  3699. value: function _positionsExhausted() {
  3700. var isExhausted = true;
  3701. for (var i = 0; i < POSITIONS.length; i++) {
  3702. isExhausted = isExhausted && this._alignmentsExhausted(POSITIONS[i]);
  3703. }
  3704. return isExhausted;
  3705. }
  3706. }, {
  3707. key: "_alignmentsExhausted",
  3708. value: function _alignmentsExhausted(position) {
  3709. return this.triedPositions[position] && this.triedPositions[position].length == ALIGNMENTS[position].length;
  3710. } // When we're trying to center, we don't want to apply offset that's going to
  3711. // take us just off center, so wrap around to return 0 for the appropriate
  3712. // offset in those alignments. TODO: Figure out if we want to make this
  3713. // configurable behavior... it feels more intuitive, especially for tooltips, but
  3714. // it's possible someone might actually want to start from center and then nudge
  3715. // slightly off.
  3716. }, {
  3717. key: "_getVOffset",
  3718. value: function _getVOffset() {
  3719. return this.options.vOffset;
  3720. }
  3721. }, {
  3722. key: "_getHOffset",
  3723. value: function _getHOffset() {
  3724. return this.options.hOffset;
  3725. }
  3726. }, {
  3727. key: "_setPosition",
  3728. value: function _setPosition($anchor, $element, $parent) {
  3729. if ($anchor.attr('aria-expanded') === 'false') {
  3730. return false;
  3731. }
  3732. var $eleDims = Box.GetDimensions($element),
  3733. $anchorDims = Box.GetDimensions($anchor);
  3734. if (!this.options.allowOverlap) {
  3735. // restore original position & alignment before checking overlap
  3736. this.position = this.originalPosition;
  3737. this.alignment = this.originalAlignment;
  3738. }
  3739. $element.offset(Box.GetExplicitOffsets($element, $anchor, this.position, this.alignment, this._getVOffset(), this._getHOffset()));
  3740. if (!this.options.allowOverlap) {
  3741. var minOverlap = 100000000; // default coordinates to how we start, in case we can't figure out better
  3742. var minCoordinates = {
  3743. position: this.position,
  3744. alignment: this.alignment
  3745. };
  3746. while (!this._positionsExhausted()) {
  3747. var overlap = Box.OverlapArea($element, $parent, false, false, this.options.allowBottomOverlap);
  3748. if (overlap === 0) {
  3749. return;
  3750. }
  3751. if (overlap < minOverlap) {
  3752. minOverlap = overlap;
  3753. minCoordinates = {
  3754. position: this.position,
  3755. alignment: this.alignment
  3756. };
  3757. }
  3758. this._reposition();
  3759. $element.offset(Box.GetExplicitOffsets($element, $anchor, this.position, this.alignment, this._getVOffset(), this._getHOffset()));
  3760. } // If we get through the entire loop, there was no non-overlapping
  3761. // position available. Pick the version with least overlap.
  3762. this.position = minCoordinates.position;
  3763. this.alignment = minCoordinates.alignment;
  3764. $element.offset(Box.GetExplicitOffsets($element, $anchor, this.position, this.alignment, this._getVOffset(), this._getHOffset()));
  3765. }
  3766. }
  3767. }]);
  3768. return Positionable;
  3769. }(Plugin);
  3770. Positionable.defaults = {
  3771. /**
  3772. * Position of positionable relative to anchor. Can be left, right, bottom, top, or auto.
  3773. * @option
  3774. * @type {string}
  3775. * @default 'auto'
  3776. */
  3777. position: 'auto',
  3778. /**
  3779. * Alignment of positionable relative to anchor. Can be left, right, bottom, top, center, or auto.
  3780. * @option
  3781. * @type {string}
  3782. * @default 'auto'
  3783. */
  3784. alignment: 'auto',
  3785. /**
  3786. * Allow overlap of container/window. If false, dropdown positionable first
  3787. * try to position as defined by data-position and data-alignment, but
  3788. * reposition if it would cause an overflow.
  3789. * @option
  3790. * @type {boolean}
  3791. * @default false
  3792. */
  3793. allowOverlap: false,
  3794. /**
  3795. * Allow overlap of only the bottom of the container. This is the most common
  3796. * behavior for dropdowns, allowing the dropdown to extend the bottom of the
  3797. * screen but not otherwise influence or break out of the container.
  3798. * @option
  3799. * @type {boolean}
  3800. * @default true
  3801. */
  3802. allowBottomOverlap: true,
  3803. /**
  3804. * Number of pixels the positionable should be separated vertically from anchor
  3805. * @option
  3806. * @type {number}
  3807. * @default 0
  3808. */
  3809. vOffset: 0,
  3810. /**
  3811. * Number of pixels the positionable should be separated horizontally from anchor
  3812. * @option
  3813. * @type {number}
  3814. * @default 0
  3815. */
  3816. hOffset: 0
  3817. };
  3818. /**
  3819. * Dropdown module.
  3820. * @module foundation.dropdown
  3821. * @requires foundation.util.keyboard
  3822. * @requires foundation.util.box
  3823. * @requires foundation.util.triggers
  3824. */
  3825. var Dropdown =
  3826. /*#__PURE__*/
  3827. function (_Positionable) {
  3828. _inherits(Dropdown, _Positionable);
  3829. function Dropdown() {
  3830. _classCallCheck(this, Dropdown);
  3831. return _possibleConstructorReturn(this, _getPrototypeOf(Dropdown).apply(this, arguments));
  3832. }
  3833. _createClass(Dropdown, [{
  3834. key: "_setup",
  3835. /**
  3836. * Creates a new instance of a dropdown.
  3837. * @class
  3838. * @name Dropdown
  3839. * @param {jQuery} element - jQuery object to make into a dropdown.
  3840. * Object should be of the dropdown panel, rather than its anchor.
  3841. * @param {Object} options - Overrides to the default plugin settings.
  3842. */
  3843. value: function _setup(element, options) {
  3844. this.$element = element;
  3845. this.options = $.extend({}, Dropdown.defaults, this.$element.data(), options);
  3846. this.className = 'Dropdown'; // ie9 back compat
  3847. // Triggers init is idempotent, just need to make sure it is initialized
  3848. Triggers.init($);
  3849. this._init();
  3850. Keyboard.register('Dropdown', {
  3851. 'ENTER': 'toggle',
  3852. 'SPACE': 'toggle',
  3853. 'ESCAPE': 'close'
  3854. });
  3855. }
  3856. /**
  3857. * Initializes the plugin by setting/checking options and attributes, adding helper variables, and saving the anchor.
  3858. * @function
  3859. * @private
  3860. */
  3861. }, {
  3862. key: "_init",
  3863. value: function _init() {
  3864. var $id = this.$element.attr('id');
  3865. this.$anchors = $("[data-toggle=\"".concat($id, "\"]")).length ? $("[data-toggle=\"".concat($id, "\"]")) : $("[data-open=\"".concat($id, "\"]"));
  3866. this.$anchors.attr({
  3867. 'aria-controls': $id,
  3868. 'data-is-focus': false,
  3869. 'data-yeti-box': $id,
  3870. 'aria-haspopup': true,
  3871. 'aria-expanded': false
  3872. });
  3873. this._setCurrentAnchor(this.$anchors.first());
  3874. if (this.options.parentClass) {
  3875. this.$parent = this.$element.parents('.' + this.options.parentClass);
  3876. } else {
  3877. this.$parent = null;
  3878. } // Set [aria-labelledby] on the Dropdown if it is not set
  3879. if (typeof this.$element.attr('aria-labelledby') === 'undefined') {
  3880. // Get the anchor ID or create one
  3881. if (typeof this.$currentAnchor.attr('id') === 'undefined') {
  3882. this.$currentAnchor.attr('id', GetYoDigits(6, 'dd-anchor'));
  3883. }
  3884. this.$element.attr('aria-labelledby', this.$currentAnchor.attr('id'));
  3885. }
  3886. this.$element.attr({
  3887. 'aria-hidden': 'true',
  3888. 'data-yeti-box': $id,
  3889. 'data-resize': $id
  3890. });
  3891. _get(_getPrototypeOf(Dropdown.prototype), "_init", this).call(this);
  3892. this._events();
  3893. }
  3894. }, {
  3895. key: "_getDefaultPosition",
  3896. value: function _getDefaultPosition() {
  3897. // handle legacy classnames
  3898. var position = this.$element[0].className.match(/(top|left|right|bottom)/g);
  3899. if (position) {
  3900. return position[0];
  3901. } else {
  3902. return 'bottom';
  3903. }
  3904. }
  3905. }, {
  3906. key: "_getDefaultAlignment",
  3907. value: function _getDefaultAlignment() {
  3908. // handle legacy float approach
  3909. var horizontalPosition = /float-(\S+)/.exec(this.$currentAnchor.attr('class'));
  3910. if (horizontalPosition) {
  3911. return horizontalPosition[1];
  3912. }
  3913. return _get(_getPrototypeOf(Dropdown.prototype), "_getDefaultAlignment", this).call(this);
  3914. }
  3915. /**
  3916. * Sets the position and orientation of the dropdown pane, checks for collisions if allow-overlap is not true.
  3917. * Recursively calls itself if a collision is detected, with a new position class.
  3918. * @function
  3919. * @private
  3920. */
  3921. }, {
  3922. key: "_setPosition",
  3923. value: function _setPosition() {
  3924. this.$element.removeClass("has-position-".concat(this.position, " has-alignment-").concat(this.alignment));
  3925. _get(_getPrototypeOf(Dropdown.prototype), "_setPosition", this).call(this, this.$currentAnchor, this.$element, this.$parent);
  3926. this.$element.addClass("has-position-".concat(this.position, " has-alignment-").concat(this.alignment));
  3927. }
  3928. /**
  3929. * Make it a current anchor.
  3930. * Current anchor as the reference for the position of Dropdown panes.
  3931. * @param {HTML} el - DOM element of the anchor.
  3932. * @function
  3933. * @private
  3934. */
  3935. }, {
  3936. key: "_setCurrentAnchor",
  3937. value: function _setCurrentAnchor(el) {
  3938. this.$currentAnchor = $(el);
  3939. }
  3940. /**
  3941. * Adds event listeners to the element utilizing the triggers utility library.
  3942. * @function
  3943. * @private
  3944. */
  3945. }, {
  3946. key: "_events",
  3947. value: function _events() {
  3948. var _this = this;
  3949. this.$element.on({
  3950. 'open.zf.trigger': this.open.bind(this),
  3951. 'close.zf.trigger': this.close.bind(this),
  3952. 'toggle.zf.trigger': this.toggle.bind(this),
  3953. 'resizeme.zf.trigger': this._setPosition.bind(this)
  3954. });
  3955. this.$anchors.off('click.zf.trigger').on('click.zf.trigger', function () {
  3956. _this._setCurrentAnchor(this);
  3957. });
  3958. if (this.options.hover) {
  3959. this.$anchors.off('mouseenter.zf.dropdown mouseleave.zf.dropdown').on('mouseenter.zf.dropdown', function () {
  3960. _this._setCurrentAnchor(this);
  3961. var bodyData = $('body').data();
  3962. if (typeof bodyData.whatinput === 'undefined' || bodyData.whatinput === 'mouse') {
  3963. clearTimeout(_this.timeout);
  3964. _this.timeout = setTimeout(function () {
  3965. _this.open();
  3966. _this.$anchors.data('hover', true);
  3967. }, _this.options.hoverDelay);
  3968. }
  3969. }).on('mouseleave.zf.dropdown', ignoreMousedisappear(function () {
  3970. clearTimeout(_this.timeout);
  3971. _this.timeout = setTimeout(function () {
  3972. _this.close();
  3973. _this.$anchors.data('hover', false);
  3974. }, _this.options.hoverDelay);
  3975. }));
  3976. if (this.options.hoverPane) {
  3977. this.$element.off('mouseenter.zf.dropdown mouseleave.zf.dropdown').on('mouseenter.zf.dropdown', function () {
  3978. clearTimeout(_this.timeout);
  3979. }).on('mouseleave.zf.dropdown', ignoreMousedisappear(function () {
  3980. clearTimeout(_this.timeout);
  3981. _this.timeout = setTimeout(function () {
  3982. _this.close();
  3983. _this.$anchors.data('hover', false);
  3984. }, _this.options.hoverDelay);
  3985. }));
  3986. }
  3987. }
  3988. this.$anchors.add(this.$element).on('keydown.zf.dropdown', function (e) {
  3989. var $target = $(this),
  3990. visibleFocusableElements = Keyboard.findFocusable(_this.$element);
  3991. Keyboard.handleKey(e, 'Dropdown', {
  3992. open: function open() {
  3993. if ($target.is(_this.$anchors) && !$target.is('input, textarea')) {
  3994. _this.open();
  3995. _this.$element.attr('tabindex', -1).focus();
  3996. e.preventDefault();
  3997. }
  3998. },
  3999. close: function close() {
  4000. _this.close();
  4001. _this.$anchors.focus();
  4002. }
  4003. });
  4004. });
  4005. }
  4006. /**
  4007. * Adds an event handler to the body to close any dropdowns on a click.
  4008. * @function
  4009. * @private
  4010. */
  4011. }, {
  4012. key: "_addBodyHandler",
  4013. value: function _addBodyHandler() {
  4014. var $body = $(document.body).not(this.$element),
  4015. _this = this;
  4016. $body.off('click.zf.dropdown').on('click.zf.dropdown', function (e) {
  4017. if (_this.$anchors.is(e.target) || _this.$anchors.find(e.target).length) {
  4018. return;
  4019. }
  4020. if (_this.$element.is(e.target) || _this.$element.find(e.target).length) {
  4021. return;
  4022. }
  4023. _this.close();
  4024. $body.off('click.zf.dropdown');
  4025. });
  4026. }
  4027. /**
  4028. * Opens the dropdown pane, and fires a bubbling event to close other dropdowns.
  4029. * @function
  4030. * @fires Dropdown#closeme
  4031. * @fires Dropdown#show
  4032. */
  4033. }, {
  4034. key: "open",
  4035. value: function open() {
  4036. // var _this = this;
  4037. /**
  4038. * Fires to close other open dropdowns, typically when dropdown is opening
  4039. * @event Dropdown#closeme
  4040. */
  4041. this.$element.trigger('closeme.zf.dropdown', this.$element.attr('id'));
  4042. this.$anchors.addClass('hover').attr({
  4043. 'aria-expanded': true
  4044. }); // this.$element/*.show()*/;
  4045. this.$element.addClass('is-opening');
  4046. this._setPosition();
  4047. this.$element.removeClass('is-opening').addClass('is-open').attr({
  4048. 'aria-hidden': false
  4049. });
  4050. if (this.options.autoFocus) {
  4051. var $focusable = Keyboard.findFocusable(this.$element);
  4052. if ($focusable.length) {
  4053. $focusable.eq(0).focus();
  4054. }
  4055. }
  4056. if (this.options.closeOnClick) {
  4057. this._addBodyHandler();
  4058. }
  4059. if (this.options.trapFocus) {
  4060. Keyboard.trapFocus(this.$element);
  4061. }
  4062. /**
  4063. * Fires once the dropdown is visible.
  4064. * @event Dropdown#show
  4065. */
  4066. this.$element.trigger('show.zf.dropdown', [this.$element]);
  4067. }
  4068. /**
  4069. * Closes the open dropdown pane.
  4070. * @function
  4071. * @fires Dropdown#hide
  4072. */
  4073. }, {
  4074. key: "close",
  4075. value: function close() {
  4076. if (!this.$element.hasClass('is-open')) {
  4077. return false;
  4078. }
  4079. this.$element.removeClass('is-open').attr({
  4080. 'aria-hidden': true
  4081. });
  4082. this.$anchors.removeClass('hover').attr('aria-expanded', false);
  4083. /**
  4084. * Fires once the dropdown is no longer visible.
  4085. * @event Dropdown#hide
  4086. */
  4087. this.$element.trigger('hide.zf.dropdown', [this.$element]);
  4088. if (this.options.trapFocus) {
  4089. Keyboard.releaseFocus(this.$element);
  4090. }
  4091. }
  4092. /**
  4093. * Toggles the dropdown pane's visibility.
  4094. * @function
  4095. */
  4096. }, {
  4097. key: "toggle",
  4098. value: function toggle() {
  4099. if (this.$element.hasClass('is-open')) {
  4100. if (this.$anchors.data('hover')) return;
  4101. this.close();
  4102. } else {
  4103. this.open();
  4104. }
  4105. }
  4106. /**
  4107. * Destroys the dropdown.
  4108. * @function
  4109. */
  4110. }, {
  4111. key: "_destroy",
  4112. value: function _destroy() {
  4113. this.$element.off('.zf.trigger').hide();
  4114. this.$anchors.off('.zf.dropdown');
  4115. $(document.body).off('click.zf.dropdown');
  4116. }
  4117. }]);
  4118. return Dropdown;
  4119. }(Positionable);
  4120. Dropdown.defaults = {
  4121. /**
  4122. * Class that designates bounding container of Dropdown (default: window)
  4123. * @option
  4124. * @type {?string}
  4125. * @default null
  4126. */
  4127. parentClass: null,
  4128. /**
  4129. * Amount of time to delay opening a submenu on hover event.
  4130. * @option
  4131. * @type {number}
  4132. * @default 250
  4133. */
  4134. hoverDelay: 250,
  4135. /**
  4136. * Allow submenus to open on hover events
  4137. * @option
  4138. * @type {boolean}
  4139. * @default false
  4140. */
  4141. hover: false,
  4142. /**
  4143. * Don't close dropdown when hovering over dropdown pane
  4144. * @option
  4145. * @type {boolean}
  4146. * @default false
  4147. */
  4148. hoverPane: false,
  4149. /**
  4150. * Number of pixels between the dropdown pane and the triggering element on open.
  4151. * @option
  4152. * @type {number}
  4153. * @default 0
  4154. */
  4155. vOffset: 0,
  4156. /**
  4157. * Number of pixels between the dropdown pane and the triggering element on open.
  4158. * @option
  4159. * @type {number}
  4160. * @default 0
  4161. */
  4162. hOffset: 0,
  4163. /**
  4164. * Position of dropdown. Can be left, right, bottom, top, or auto.
  4165. * @option
  4166. * @type {string}
  4167. * @default 'auto'
  4168. */
  4169. position: 'auto',
  4170. /**
  4171. * Alignment of dropdown relative to anchor. Can be left, right, bottom, top, center, or auto.
  4172. * @option
  4173. * @type {string}
  4174. * @default 'auto'
  4175. */
  4176. alignment: 'auto',
  4177. /**
  4178. * 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.
  4179. * @option
  4180. * @type {boolean}
  4181. * @default false
  4182. */
  4183. allowOverlap: false,
  4184. /**
  4185. * Allow overlap of only the bottom of the container. This is the most common
  4186. * behavior for dropdowns, allowing the dropdown to extend the bottom of the
  4187. * screen but not otherwise influence or break out of the container.
  4188. * @option
  4189. * @type {boolean}
  4190. * @default true
  4191. */
  4192. allowBottomOverlap: true,
  4193. /**
  4194. * Allow the plugin to trap focus to the dropdown pane if opened with keyboard commands.
  4195. * @option
  4196. * @type {boolean}
  4197. * @default false
  4198. */
  4199. trapFocus: false,
  4200. /**
  4201. * Allow the plugin to set focus to the first focusable element within the pane, regardless of method of opening.
  4202. * @option
  4203. * @type {boolean}
  4204. * @default false
  4205. */
  4206. autoFocus: false,
  4207. /**
  4208. * Allows a click on the body to close the dropdown.
  4209. * @option
  4210. * @type {boolean}
  4211. * @default false
  4212. */
  4213. closeOnClick: false
  4214. };
  4215. /**
  4216. * DropdownMenu module.
  4217. * @module foundation.dropdown-menu
  4218. * @requires foundation.util.keyboard
  4219. * @requires foundation.util.box
  4220. * @requires foundation.util.nest
  4221. */
  4222. var DropdownMenu =
  4223. /*#__PURE__*/
  4224. function (_Plugin) {
  4225. _inherits(DropdownMenu, _Plugin);
  4226. function DropdownMenu() {
  4227. _classCallCheck(this, DropdownMenu);
  4228. return _possibleConstructorReturn(this, _getPrototypeOf(DropdownMenu).apply(this, arguments));
  4229. }
  4230. _createClass(DropdownMenu, [{
  4231. key: "_setup",
  4232. /**
  4233. * Creates a new instance of DropdownMenu.
  4234. * @class
  4235. * @name DropdownMenu
  4236. * @fires DropdownMenu#init
  4237. * @param {jQuery} element - jQuery object to make into a dropdown menu.
  4238. * @param {Object} options - Overrides to the default plugin settings.
  4239. */
  4240. value: function _setup(element, options) {
  4241. this.$element = element;
  4242. this.options = $.extend({}, DropdownMenu.defaults, this.$element.data(), options);
  4243. this.className = 'DropdownMenu'; // ie9 back compat
  4244. this._init();
  4245. Keyboard.register('DropdownMenu', {
  4246. 'ENTER': 'open',
  4247. 'SPACE': 'open',
  4248. 'ARROW_RIGHT': 'next',
  4249. 'ARROW_UP': 'up',
  4250. 'ARROW_DOWN': 'down',
  4251. 'ARROW_LEFT': 'previous',
  4252. 'ESCAPE': 'close'
  4253. });
  4254. }
  4255. /**
  4256. * Initializes the plugin, and calls _prepareMenu
  4257. * @private
  4258. * @function
  4259. */
  4260. }, {
  4261. key: "_init",
  4262. value: function _init() {
  4263. Nest.Feather(this.$element, 'dropdown');
  4264. var subs = this.$element.find('li.is-dropdown-submenu-parent');
  4265. this.$element.children('.is-dropdown-submenu-parent').children('.is-dropdown-submenu').addClass('first-sub');
  4266. this.$menuItems = this.$element.find('[role="menuitem"]');
  4267. this.$tabs = this.$element.children('[role="menuitem"]');
  4268. this.$tabs.find('ul.is-dropdown-submenu').addClass(this.options.verticalClass);
  4269. if (this.options.alignment === 'auto') {
  4270. if (this.$element.hasClass(this.options.rightClass) || rtl() || this.$element.parents('.top-bar-right').is('*')) {
  4271. this.options.alignment = 'right';
  4272. subs.addClass('opens-left');
  4273. } else {
  4274. this.options.alignment = 'left';
  4275. subs.addClass('opens-right');
  4276. }
  4277. } else {
  4278. if (this.options.alignment === 'right') {
  4279. subs.addClass('opens-left');
  4280. } else {
  4281. subs.addClass('opens-right');
  4282. }
  4283. }
  4284. this.changed = false;
  4285. this._events();
  4286. }
  4287. }, {
  4288. key: "_isVertical",
  4289. value: function _isVertical() {
  4290. return this.$tabs.css('display') === 'block' || this.$element.css('flex-direction') === 'column';
  4291. }
  4292. }, {
  4293. key: "_isRtl",
  4294. value: function _isRtl() {
  4295. return this.$element.hasClass('align-right') || rtl() && !this.$element.hasClass('align-left');
  4296. }
  4297. /**
  4298. * Adds event listeners to elements within the menu
  4299. * @private
  4300. * @function
  4301. */
  4302. }, {
  4303. key: "_events",
  4304. value: function _events() {
  4305. var _this = this,
  4306. hasTouch = 'ontouchstart' in window || typeof window.ontouchstart !== 'undefined',
  4307. parClass = 'is-dropdown-submenu-parent'; // used for onClick and in the keyboard handlers
  4308. var handleClickFn = function handleClickFn(e) {
  4309. var $elem = $(e.target).parentsUntil('ul', ".".concat(parClass)),
  4310. hasSub = $elem.hasClass(parClass),
  4311. hasClicked = $elem.attr('data-is-click') === 'true',
  4312. $sub = $elem.children('.is-dropdown-submenu');
  4313. if (hasSub) {
  4314. if (hasClicked) {
  4315. if (!_this.options.closeOnClick || !_this.options.clickOpen && !hasTouch || _this.options.forceFollow && hasTouch) {
  4316. return;
  4317. } else {
  4318. e.stopImmediatePropagation();
  4319. e.preventDefault();
  4320. _this._hide($elem);
  4321. }
  4322. } else {
  4323. e.preventDefault();
  4324. e.stopImmediatePropagation();
  4325. _this._show($sub);
  4326. $elem.add($elem.parentsUntil(_this.$element, ".".concat(parClass))).attr('data-is-click', true);
  4327. }
  4328. }
  4329. };
  4330. if (this.options.clickOpen || hasTouch) {
  4331. this.$menuItems.on('click.zf.dropdownmenu touchstart.zf.dropdownmenu', handleClickFn);
  4332. } // Handle Leaf element Clicks
  4333. if (_this.options.closeOnClickInside) {
  4334. this.$menuItems.on('click.zf.dropdownmenu', function (e) {
  4335. var $elem = $(this),
  4336. hasSub = $elem.hasClass(parClass);
  4337. if (!hasSub) {
  4338. _this._hide();
  4339. }
  4340. });
  4341. }
  4342. if (!this.options.disableHover) {
  4343. this.$menuItems.on('mouseenter.zf.dropdownmenu', function (e) {
  4344. var $elem = $(this),
  4345. hasSub = $elem.hasClass(parClass);
  4346. if (hasSub) {
  4347. clearTimeout($elem.data('_delay'));
  4348. $elem.data('_delay', setTimeout(function () {
  4349. _this._show($elem.children('.is-dropdown-submenu'));
  4350. }, _this.options.hoverDelay));
  4351. }
  4352. }).on('mouseleave.zf.dropdownMenu', ignoreMousedisappear(function (e) {
  4353. var $elem = $(this),
  4354. hasSub = $elem.hasClass(parClass);
  4355. if (hasSub && _this.options.autoclose) {
  4356. if ($elem.attr('data-is-click') === 'true' && _this.options.clickOpen) {
  4357. return false;
  4358. }
  4359. clearTimeout($elem.data('_delay'));
  4360. $elem.data('_delay', setTimeout(function () {
  4361. _this._hide($elem);
  4362. }, _this.options.closingTime));
  4363. }
  4364. }));
  4365. }
  4366. this.$menuItems.on('keydown.zf.dropdownmenu', function (e) {
  4367. var $element = $(e.target).parentsUntil('ul', '[role="menuitem"]'),
  4368. isTab = _this.$tabs.index($element) > -1,
  4369. $elements = isTab ? _this.$tabs : $element.siblings('li').add($element),
  4370. $prevElement,
  4371. $nextElement;
  4372. $elements.each(function (i) {
  4373. if ($(this).is($element)) {
  4374. $prevElement = $elements.eq(i - 1);
  4375. $nextElement = $elements.eq(i + 1);
  4376. return;
  4377. }
  4378. });
  4379. var nextSibling = function nextSibling() {
  4380. $nextElement.children('a:first').focus();
  4381. e.preventDefault();
  4382. },
  4383. prevSibling = function prevSibling() {
  4384. $prevElement.children('a:first').focus();
  4385. e.preventDefault();
  4386. },
  4387. openSub = function openSub() {
  4388. var $sub = $element.children('ul.is-dropdown-submenu');
  4389. if ($sub.length) {
  4390. _this._show($sub);
  4391. $element.find('li > a:first').focus();
  4392. e.preventDefault();
  4393. } else {
  4394. return;
  4395. }
  4396. },
  4397. closeSub = function closeSub() {
  4398. //if ($element.is(':first-child')) {
  4399. var close = $element.parent('ul').parent('li');
  4400. close.children('a:first').focus();
  4401. _this._hide(close);
  4402. e.preventDefault(); //}
  4403. };
  4404. var functions = {
  4405. open: openSub,
  4406. close: function close() {
  4407. _this._hide(_this.$element);
  4408. _this.$menuItems.eq(0).children('a').focus(); // focus to first element
  4409. e.preventDefault();
  4410. },
  4411. handled: function handled() {
  4412. e.stopImmediatePropagation();
  4413. }
  4414. };
  4415. if (isTab) {
  4416. if (_this._isVertical()) {
  4417. // vertical menu
  4418. if (_this._isRtl()) {
  4419. // right aligned
  4420. $.extend(functions, {
  4421. down: nextSibling,
  4422. up: prevSibling,
  4423. next: closeSub,
  4424. previous: openSub
  4425. });
  4426. } else {
  4427. // left aligned
  4428. $.extend(functions, {
  4429. down: nextSibling,
  4430. up: prevSibling,
  4431. next: openSub,
  4432. previous: closeSub
  4433. });
  4434. }
  4435. } else {
  4436. // horizontal menu
  4437. if (_this._isRtl()) {
  4438. // right aligned
  4439. $.extend(functions, {
  4440. next: prevSibling,
  4441. previous: nextSibling,
  4442. down: openSub,
  4443. up: closeSub
  4444. });
  4445. } else {
  4446. // left aligned
  4447. $.extend(functions, {
  4448. next: nextSibling,
  4449. previous: prevSibling,
  4450. down: openSub,
  4451. up: closeSub
  4452. });
  4453. }
  4454. }
  4455. } else {
  4456. // not tabs -> one sub
  4457. if (_this._isRtl()) {
  4458. // right aligned
  4459. $.extend(functions, {
  4460. next: closeSub,
  4461. previous: openSub,
  4462. down: nextSibling,
  4463. up: prevSibling
  4464. });
  4465. } else {
  4466. // left aligned
  4467. $.extend(functions, {
  4468. next: openSub,
  4469. previous: closeSub,
  4470. down: nextSibling,
  4471. up: prevSibling
  4472. });
  4473. }
  4474. }
  4475. Keyboard.handleKey(e, 'DropdownMenu', functions);
  4476. });
  4477. }
  4478. /**
  4479. * Adds an event handler to the body to close any dropdowns on a click.
  4480. * @function
  4481. * @private
  4482. */
  4483. }, {
  4484. key: "_addBodyHandler",
  4485. value: function _addBodyHandler() {
  4486. var $body = $(document.body),
  4487. _this = this;
  4488. $body.off('mouseup.zf.dropdownmenu touchend.zf.dropdownmenu').on('mouseup.zf.dropdownmenu touchend.zf.dropdownmenu', function (e) {
  4489. var $link = _this.$element.find(e.target);
  4490. if ($link.length) {
  4491. return;
  4492. }
  4493. _this._hide();
  4494. $body.off('mouseup.zf.dropdownmenu touchend.zf.dropdownmenu');
  4495. });
  4496. }
  4497. /**
  4498. * Opens a dropdown pane, and checks for collisions first.
  4499. * @param {jQuery} $sub - ul element that is a submenu to show
  4500. * @function
  4501. * @private
  4502. * @fires Dropdownmenu#show
  4503. */
  4504. }, {
  4505. key: "_show",
  4506. value: function _show($sub) {
  4507. var idx = this.$tabs.index(this.$tabs.filter(function (i, el) {
  4508. return $(el).find($sub).length > 0;
  4509. }));
  4510. var $sibs = $sub.parent('li.is-dropdown-submenu-parent').siblings('li.is-dropdown-submenu-parent');
  4511. this._hide($sibs, idx);
  4512. $sub.css('visibility', 'hidden').addClass('js-dropdown-active').parent('li.is-dropdown-submenu-parent').addClass('is-active');
  4513. var clear = Box.ImNotTouchingYou($sub, null, true);
  4514. if (!clear) {
  4515. var oldClass = this.options.alignment === 'left' ? '-right' : '-left',
  4516. $parentLi = $sub.parent('.is-dropdown-submenu-parent');
  4517. $parentLi.removeClass("opens".concat(oldClass)).addClass("opens-".concat(this.options.alignment));
  4518. clear = Box.ImNotTouchingYou($sub, null, true);
  4519. if (!clear) {
  4520. $parentLi.removeClass("opens-".concat(this.options.alignment)).addClass('opens-inner');
  4521. }
  4522. this.changed = true;
  4523. }
  4524. $sub.css('visibility', '');
  4525. if (this.options.closeOnClick) {
  4526. this._addBodyHandler();
  4527. }
  4528. /**
  4529. * Fires when the new dropdown pane is visible.
  4530. * @event Dropdownmenu#show
  4531. */
  4532. this.$element.trigger('show.zf.dropdownmenu', [$sub]);
  4533. }
  4534. /**
  4535. * Hides a single, currently open dropdown pane, if passed a parameter, otherwise, hides everything.
  4536. * @function
  4537. * @param {jQuery} $elem - element with a submenu to hide
  4538. * @param {Number} idx - index of the $tabs collection to hide
  4539. * @private
  4540. */
  4541. }, {
  4542. key: "_hide",
  4543. value: function _hide($elem, idx) {
  4544. var $toClose;
  4545. if ($elem && $elem.length) {
  4546. $toClose = $elem;
  4547. } else if (typeof idx !== 'undefined') {
  4548. $toClose = this.$tabs.not(function (i, el) {
  4549. return i === idx;
  4550. });
  4551. } else {
  4552. $toClose = this.$element;
  4553. }
  4554. var somethingToClose = $toClose.hasClass('is-active') || $toClose.find('.is-active').length > 0;
  4555. if (somethingToClose) {
  4556. $toClose.find('li.is-active').add($toClose).attr({
  4557. 'data-is-click': false
  4558. }).removeClass('is-active');
  4559. $toClose.find('ul.js-dropdown-active').removeClass('js-dropdown-active');
  4560. if (this.changed || $toClose.find('opens-inner').length) {
  4561. var oldClass = this.options.alignment === 'left' ? 'right' : 'left';
  4562. $toClose.find('li.is-dropdown-submenu-parent').add($toClose).removeClass("opens-inner opens-".concat(this.options.alignment)).addClass("opens-".concat(oldClass));
  4563. this.changed = false;
  4564. }
  4565. /**
  4566. * Fires when the open menus are closed.
  4567. * @event Dropdownmenu#hide
  4568. */
  4569. this.$element.trigger('hide.zf.dropdownmenu', [$toClose]);
  4570. }
  4571. }
  4572. /**
  4573. * Destroys the plugin.
  4574. * @function
  4575. */
  4576. }, {
  4577. key: "_destroy",
  4578. value: function _destroy() {
  4579. 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');
  4580. $(document.body).off('.zf.dropdownmenu');
  4581. Nest.Burn(this.$element, 'dropdown');
  4582. }
  4583. }]);
  4584. return DropdownMenu;
  4585. }(Plugin);
  4586. /**
  4587. * Default settings for plugin
  4588. */
  4589. DropdownMenu.defaults = {
  4590. /**
  4591. * Disallows hover events from opening submenus
  4592. * @option
  4593. * @type {boolean}
  4594. * @default false
  4595. */
  4596. disableHover: false,
  4597. /**
  4598. * Allow a submenu to automatically close on a mouseleave event, if not clicked open.
  4599. * @option
  4600. * @type {boolean}
  4601. * @default true
  4602. */
  4603. autoclose: true,
  4604. /**
  4605. * Amount of time to delay opening a submenu on hover event.
  4606. * @option
  4607. * @type {number}
  4608. * @default 50
  4609. */
  4610. hoverDelay: 50,
  4611. /**
  4612. * Allow a submenu to open/remain open on parent click event. Allows cursor to move away from menu.
  4613. * @option
  4614. * @type {boolean}
  4615. * @default false
  4616. */
  4617. clickOpen: false,
  4618. /**
  4619. * Amount of time to delay closing a submenu on a mouseleave event.
  4620. * @option
  4621. * @type {number}
  4622. * @default 500
  4623. */
  4624. closingTime: 500,
  4625. /**
  4626. * Position of the menu relative to what direction the submenus should open. Handled by JS. Can be `'auto'`, `'left'` or `'right'`.
  4627. * @option
  4628. * @type {string}
  4629. * @default 'auto'
  4630. */
  4631. alignment: 'auto',
  4632. /**
  4633. * Allow clicks on the body to close any open submenus.
  4634. * @option
  4635. * @type {boolean}
  4636. * @default true
  4637. */
  4638. closeOnClick: true,
  4639. /**
  4640. * Allow clicks on leaf anchor links to close any open submenus.
  4641. * @option
  4642. * @type {boolean}
  4643. * @default true
  4644. */
  4645. closeOnClickInside: true,
  4646. /**
  4647. * Class applied to vertical oriented menus, Foundation default is `vertical`. Update this if using your own class.
  4648. * @option
  4649. * @type {string}
  4650. * @default 'vertical'
  4651. */
  4652. verticalClass: 'vertical',
  4653. /**
  4654. * Class applied to right-side oriented menus, Foundation default is `align-right`. Update this if using your own class.
  4655. * @option
  4656. * @type {string}
  4657. * @default 'align-right'
  4658. */
  4659. rightClass: 'align-right',
  4660. /**
  4661. * Boolean to force overide the clicking of links to perform default action, on second touch event for mobile.
  4662. * @option
  4663. * @type {boolean}
  4664. * @default true
  4665. */
  4666. forceFollow: true
  4667. };
  4668. /**
  4669. * Equalizer module.
  4670. * @module foundation.equalizer
  4671. * @requires foundation.util.mediaQuery
  4672. * @requires foundation.util.imageLoader if equalizer contains images
  4673. */
  4674. var Equalizer =
  4675. /*#__PURE__*/
  4676. function (_Plugin) {
  4677. _inherits(Equalizer, _Plugin);
  4678. function Equalizer() {
  4679. _classCallCheck(this, Equalizer);
  4680. return _possibleConstructorReturn(this, _getPrototypeOf(Equalizer).apply(this, arguments));
  4681. }
  4682. _createClass(Equalizer, [{
  4683. key: "_setup",
  4684. /**
  4685. * Creates a new instance of Equalizer.
  4686. * @class
  4687. * @name Equalizer
  4688. * @fires Equalizer#init
  4689. * @param {Object} element - jQuery object to add the trigger to.
  4690. * @param {Object} options - Overrides to the default plugin settings.
  4691. */
  4692. value: function _setup(element, options) {
  4693. this.$element = element;
  4694. this.options = $.extend({}, Equalizer.defaults, this.$element.data(), options);
  4695. this.className = 'Equalizer'; // ie9 back compat
  4696. this._init();
  4697. }
  4698. /**
  4699. * Initializes the Equalizer plugin and calls functions to get equalizer functioning on load.
  4700. * @private
  4701. */
  4702. }, {
  4703. key: "_init",
  4704. value: function _init() {
  4705. var eqId = this.$element.attr('data-equalizer') || '';
  4706. var $watched = this.$element.find("[data-equalizer-watch=\"".concat(eqId, "\"]"));
  4707. MediaQuery._init();
  4708. this.$watched = $watched.length ? $watched : this.$element.find('[data-equalizer-watch]');
  4709. this.$element.attr('data-resize', eqId || GetYoDigits(6, 'eq'));
  4710. this.$element.attr('data-mutate', eqId || GetYoDigits(6, 'eq'));
  4711. this.hasNested = this.$element.find('[data-equalizer]').length > 0;
  4712. this.isNested = this.$element.parentsUntil(document.body, '[data-equalizer]').length > 0;
  4713. this.isOn = false;
  4714. this._bindHandler = {
  4715. onResizeMeBound: this._onResizeMe.bind(this),
  4716. onPostEqualizedBound: this._onPostEqualized.bind(this)
  4717. };
  4718. var imgs = this.$element.find('img');
  4719. var tooSmall;
  4720. if (this.options.equalizeOn) {
  4721. tooSmall = this._checkMQ();
  4722. $(window).on('changed.zf.mediaquery', this._checkMQ.bind(this));
  4723. } else {
  4724. this._events();
  4725. }
  4726. if (typeof tooSmall !== 'undefined' && tooSmall === false || typeof tooSmall === 'undefined') {
  4727. if (imgs.length) {
  4728. onImagesLoaded(imgs, this._reflow.bind(this));
  4729. } else {
  4730. this._reflow();
  4731. }
  4732. }
  4733. }
  4734. /**
  4735. * Removes event listeners if the breakpoint is too small.
  4736. * @private
  4737. */
  4738. }, {
  4739. key: "_pauseEvents",
  4740. value: function _pauseEvents() {
  4741. this.isOn = false;
  4742. this.$element.off({
  4743. '.zf.equalizer': this._bindHandler.onPostEqualizedBound,
  4744. 'resizeme.zf.trigger': this._bindHandler.onResizeMeBound,
  4745. 'mutateme.zf.trigger': this._bindHandler.onResizeMeBound
  4746. });
  4747. }
  4748. /**
  4749. * function to handle $elements resizeme.zf.trigger, with bound this on _bindHandler.onResizeMeBound
  4750. * @private
  4751. */
  4752. }, {
  4753. key: "_onResizeMe",
  4754. value: function _onResizeMe(e) {
  4755. this._reflow();
  4756. }
  4757. /**
  4758. * function to handle $elements postequalized.zf.equalizer, with bound this on _bindHandler.onPostEqualizedBound
  4759. * @private
  4760. */
  4761. }, {
  4762. key: "_onPostEqualized",
  4763. value: function _onPostEqualized(e) {
  4764. if (e.target !== this.$element[0]) {
  4765. this._reflow();
  4766. }
  4767. }
  4768. /**
  4769. * Initializes events for Equalizer.
  4770. * @private
  4771. */
  4772. }, {
  4773. key: "_events",
  4774. value: function _events() {
  4775. this._pauseEvents();
  4776. if (this.hasNested) {
  4777. this.$element.on('postequalized.zf.equalizer', this._bindHandler.onPostEqualizedBound);
  4778. } else {
  4779. this.$element.on('resizeme.zf.trigger', this._bindHandler.onResizeMeBound);
  4780. this.$element.on('mutateme.zf.trigger', this._bindHandler.onResizeMeBound);
  4781. }
  4782. this.isOn = true;
  4783. }
  4784. /**
  4785. * Checks the current breakpoint to the minimum required size.
  4786. * @private
  4787. */
  4788. }, {
  4789. key: "_checkMQ",
  4790. value: function _checkMQ() {
  4791. var tooSmall = !MediaQuery.is(this.options.equalizeOn);
  4792. if (tooSmall) {
  4793. if (this.isOn) {
  4794. this._pauseEvents();
  4795. this.$watched.css('height', 'auto');
  4796. }
  4797. } else {
  4798. if (!this.isOn) {
  4799. this._events();
  4800. }
  4801. }
  4802. return tooSmall;
  4803. }
  4804. /**
  4805. * A noop version for the plugin
  4806. * @private
  4807. */
  4808. }, {
  4809. key: "_killswitch",
  4810. value: function _killswitch() {
  4811. return;
  4812. }
  4813. /**
  4814. * Calls necessary functions to update Equalizer upon DOM change
  4815. * @private
  4816. */
  4817. }, {
  4818. key: "_reflow",
  4819. value: function _reflow() {
  4820. if (!this.options.equalizeOnStack) {
  4821. if (this._isStacked()) {
  4822. this.$watched.css('height', 'auto');
  4823. return false;
  4824. }
  4825. }
  4826. if (this.options.equalizeByRow) {
  4827. this.getHeightsByRow(this.applyHeightByRow.bind(this));
  4828. } else {
  4829. this.getHeights(this.applyHeight.bind(this));
  4830. }
  4831. }
  4832. /**
  4833. * Manually determines if the first 2 elements are *NOT* stacked.
  4834. * @private
  4835. */
  4836. }, {
  4837. key: "_isStacked",
  4838. value: function _isStacked() {
  4839. if (!this.$watched[0] || !this.$watched[1]) {
  4840. return true;
  4841. }
  4842. return this.$watched[0].getBoundingClientRect().top !== this.$watched[1].getBoundingClientRect().top;
  4843. }
  4844. /**
  4845. * Finds the outer heights of children contained within an Equalizer parent and returns them in an array
  4846. * @param {Function} cb - A non-optional callback to return the heights array to.
  4847. * @returns {Array} heights - An array of heights of children within Equalizer container
  4848. */
  4849. }, {
  4850. key: "getHeights",
  4851. value: function getHeights(cb) {
  4852. var heights = [];
  4853. for (var i = 0, len = this.$watched.length; i < len; i++) {
  4854. this.$watched[i].style.height = 'auto';
  4855. heights.push(this.$watched[i].offsetHeight);
  4856. }
  4857. cb(heights);
  4858. }
  4859. /**
  4860. * Finds the outer heights of children contained within an Equalizer parent and returns them in an array
  4861. * @param {Function} cb - A non-optional callback to return the heights array to.
  4862. * @returns {Array} groups - An array of heights of children within Equalizer container grouped by row with element,height and max as last child
  4863. */
  4864. }, {
  4865. key: "getHeightsByRow",
  4866. value: function getHeightsByRow(cb) {
  4867. var lastElTopOffset = this.$watched.length ? this.$watched.first().offset().top : 0,
  4868. groups = [],
  4869. group = 0; //group by Row
  4870. groups[group] = [];
  4871. for (var i = 0, len = this.$watched.length; i < len; i++) {
  4872. this.$watched[i].style.height = 'auto'; //maybe could use this.$watched[i].offsetTop
  4873. var elOffsetTop = $(this.$watched[i]).offset().top;
  4874. if (elOffsetTop != lastElTopOffset) {
  4875. group++;
  4876. groups[group] = [];
  4877. lastElTopOffset = elOffsetTop;
  4878. }
  4879. groups[group].push([this.$watched[i], this.$watched[i].offsetHeight]);
  4880. }
  4881. for (var j = 0, ln = groups.length; j < ln; j++) {
  4882. var heights = $(groups[j]).map(function () {
  4883. return this[1];
  4884. }).get();
  4885. var max = Math.max.apply(null, heights);
  4886. groups[j].push(max);
  4887. }
  4888. cb(groups);
  4889. }
  4890. /**
  4891. * Changes the CSS height property of each child in an Equalizer parent to match the tallest
  4892. * @param {array} heights - An array of heights of children within Equalizer container
  4893. * @fires Equalizer#preequalized
  4894. * @fires Equalizer#postequalized
  4895. */
  4896. }, {
  4897. key: "applyHeight",
  4898. value: function applyHeight(heights) {
  4899. var max = Math.max.apply(null, heights);
  4900. /**
  4901. * Fires before the heights are applied
  4902. * @event Equalizer#preequalized
  4903. */
  4904. this.$element.trigger('preequalized.zf.equalizer');
  4905. this.$watched.css('height', max);
  4906. /**
  4907. * Fires when the heights have been applied
  4908. * @event Equalizer#postequalized
  4909. */
  4910. this.$element.trigger('postequalized.zf.equalizer');
  4911. }
  4912. /**
  4913. * Changes the CSS height property of each child in an Equalizer parent to match the tallest by row
  4914. * @param {array} groups - An array of heights of children within Equalizer container grouped by row with element,height and max as last child
  4915. * @fires Equalizer#preequalized
  4916. * @fires Equalizer#preequalizedrow
  4917. * @fires Equalizer#postequalizedrow
  4918. * @fires Equalizer#postequalized
  4919. */
  4920. }, {
  4921. key: "applyHeightByRow",
  4922. value: function applyHeightByRow(groups) {
  4923. /**
  4924. * Fires before the heights are applied
  4925. */
  4926. this.$element.trigger('preequalized.zf.equalizer');
  4927. for (var i = 0, len = groups.length; i < len; i++) {
  4928. var groupsILength = groups[i].length,
  4929. max = groups[i][groupsILength - 1];
  4930. if (groupsILength <= 2) {
  4931. $(groups[i][0][0]).css({
  4932. 'height': 'auto'
  4933. });
  4934. continue;
  4935. }
  4936. /**
  4937. * Fires before the heights per row are applied
  4938. * @event Equalizer#preequalizedrow
  4939. */
  4940. this.$element.trigger('preequalizedrow.zf.equalizer');
  4941. for (var j = 0, lenJ = groupsILength - 1; j < lenJ; j++) {
  4942. $(groups[i][j][0]).css({
  4943. 'height': max
  4944. });
  4945. }
  4946. /**
  4947. * Fires when the heights per row have been applied
  4948. * @event Equalizer#postequalizedrow
  4949. */
  4950. this.$element.trigger('postequalizedrow.zf.equalizer');
  4951. }
  4952. /**
  4953. * Fires when the heights have been applied
  4954. */
  4955. this.$element.trigger('postequalized.zf.equalizer');
  4956. }
  4957. /**
  4958. * Destroys an instance of Equalizer.
  4959. * @function
  4960. */
  4961. }, {
  4962. key: "_destroy",
  4963. value: function _destroy() {
  4964. this._pauseEvents();
  4965. this.$watched.css('height', 'auto');
  4966. }
  4967. }]);
  4968. return Equalizer;
  4969. }(Plugin);
  4970. /**
  4971. * Default settings for plugin
  4972. */
  4973. Equalizer.defaults = {
  4974. /**
  4975. * Enable height equalization when stacked on smaller screens.
  4976. * @option
  4977. * @type {boolean}
  4978. * @default false
  4979. */
  4980. equalizeOnStack: false,
  4981. /**
  4982. * Enable height equalization row by row.
  4983. * @option
  4984. * @type {boolean}
  4985. * @default false
  4986. */
  4987. equalizeByRow: false,
  4988. /**
  4989. * String representing the minimum breakpoint size the plugin should equalize heights on.
  4990. * @option
  4991. * @type {string}
  4992. * @default ''
  4993. */
  4994. equalizeOn: ''
  4995. };
  4996. /**
  4997. * Interchange module.
  4998. * @module foundation.interchange
  4999. * @requires foundation.util.mediaQuery
  5000. */
  5001. var Interchange =
  5002. /*#__PURE__*/
  5003. function (_Plugin) {
  5004. _inherits(Interchange, _Plugin);
  5005. function Interchange() {
  5006. _classCallCheck(this, Interchange);
  5007. return _possibleConstructorReturn(this, _getPrototypeOf(Interchange).apply(this, arguments));
  5008. }
  5009. _createClass(Interchange, [{
  5010. key: "_setup",
  5011. /**
  5012. * Creates a new instance of Interchange.
  5013. * @class
  5014. * @name Interchange
  5015. * @fires Interchange#init
  5016. * @param {Object} element - jQuery object to add the trigger to.
  5017. * @param {Object} options - Overrides to the default plugin settings.
  5018. */
  5019. value: function _setup(element, options) {
  5020. this.$element = element;
  5021. this.options = $.extend({}, Interchange.defaults, options);
  5022. this.rules = [];
  5023. this.currentPath = '';
  5024. this.className = 'Interchange'; // ie9 back compat
  5025. this._init();
  5026. this._events();
  5027. }
  5028. /**
  5029. * Initializes the Interchange plugin and calls functions to get interchange functioning on load.
  5030. * @function
  5031. * @private
  5032. */
  5033. }, {
  5034. key: "_init",
  5035. value: function _init() {
  5036. MediaQuery._init();
  5037. var id = this.$element[0].id || GetYoDigits(6, 'interchange');
  5038. this.$element.attr({
  5039. 'data-resize': id,
  5040. 'id': id
  5041. });
  5042. this._addBreakpoints();
  5043. this._generateRules();
  5044. this._reflow();
  5045. }
  5046. /**
  5047. * Initializes events for Interchange.
  5048. * @function
  5049. * @private
  5050. */
  5051. }, {
  5052. key: "_events",
  5053. value: function _events() {
  5054. var _this2 = this;
  5055. this.$element.off('resizeme.zf.trigger').on('resizeme.zf.trigger', function () {
  5056. return _this2._reflow();
  5057. });
  5058. }
  5059. /**
  5060. * Calls necessary functions to update Interchange upon DOM change
  5061. * @function
  5062. * @private
  5063. */
  5064. }, {
  5065. key: "_reflow",
  5066. value: function _reflow() {
  5067. var match; // Iterate through each rule, but only save the last match
  5068. for (var i in this.rules) {
  5069. if (this.rules.hasOwnProperty(i)) {
  5070. var rule = this.rules[i];
  5071. if (window.matchMedia(rule.query).matches) {
  5072. match = rule;
  5073. }
  5074. }
  5075. }
  5076. if (match) {
  5077. this.replace(match.path);
  5078. }
  5079. }
  5080. /**
  5081. * Gets the Foundation breakpoints and adds them to the Interchange.SPECIAL_QUERIES object.
  5082. * @function
  5083. * @private
  5084. */
  5085. }, {
  5086. key: "_addBreakpoints",
  5087. value: function _addBreakpoints() {
  5088. for (var i in MediaQuery.queries) {
  5089. if (MediaQuery.queries.hasOwnProperty(i)) {
  5090. var query = MediaQuery.queries[i];
  5091. Interchange.SPECIAL_QUERIES[query.name] = query.value;
  5092. }
  5093. }
  5094. }
  5095. /**
  5096. * Checks the Interchange element for the provided media query + content pairings
  5097. * @function
  5098. * @private
  5099. * @param {Object} element - jQuery object that is an Interchange instance
  5100. * @returns {Array} scenarios - Array of objects that have 'mq' and 'path' keys with corresponding keys
  5101. */
  5102. }, {
  5103. key: "_generateRules",
  5104. value: function _generateRules(element) {
  5105. var rulesList = [];
  5106. var rules;
  5107. if (this.options.rules) {
  5108. rules = this.options.rules;
  5109. } else {
  5110. rules = this.$element.data('interchange');
  5111. }
  5112. rules = typeof rules === 'string' ? rules.match(/\[.*?, .*?\]/g) : rules;
  5113. for (var i in rules) {
  5114. if (rules.hasOwnProperty(i)) {
  5115. var rule = rules[i].slice(1, -1).split(', ');
  5116. var path = rule.slice(0, -1).join('');
  5117. var query = rule[rule.length - 1];
  5118. if (Interchange.SPECIAL_QUERIES[query]) {
  5119. query = Interchange.SPECIAL_QUERIES[query];
  5120. }
  5121. rulesList.push({
  5122. path: path,
  5123. query: query
  5124. });
  5125. }
  5126. }
  5127. this.rules = rulesList;
  5128. }
  5129. /**
  5130. * Update the `src` property of an image, or change the HTML of a container, to the specified path.
  5131. * @function
  5132. * @param {String} path - Path to the image or HTML partial.
  5133. * @fires Interchange#replaced
  5134. */
  5135. }, {
  5136. key: "replace",
  5137. value: function replace(path) {
  5138. if (this.currentPath === path) return;
  5139. var _this = this,
  5140. trigger = 'replaced.zf.interchange'; // Replacing images
  5141. if (this.$element[0].nodeName === 'IMG') {
  5142. this.$element.attr('src', path).on('load', function () {
  5143. _this.currentPath = path;
  5144. }).trigger(trigger);
  5145. } // Replacing background images
  5146. else if (path.match(/\.(gif|jpg|jpeg|png|svg|tiff)([?#].*)?/i)) {
  5147. path = path.replace(/\(/g, '%28').replace(/\)/g, '%29');
  5148. this.$element.css({
  5149. 'background-image': 'url(' + path + ')'
  5150. }).trigger(trigger);
  5151. } // Replacing HTML
  5152. else {
  5153. $.get(path, function (response) {
  5154. _this.$element.html(response).trigger(trigger);
  5155. $(response).foundation();
  5156. _this.currentPath = path;
  5157. });
  5158. }
  5159. /**
  5160. * Fires when content in an Interchange element is done being loaded.
  5161. * @event Interchange#replaced
  5162. */
  5163. // this.$element.trigger('replaced.zf.interchange');
  5164. }
  5165. /**
  5166. * Destroys an instance of interchange.
  5167. * @function
  5168. */
  5169. }, {
  5170. key: "_destroy",
  5171. value: function _destroy() {
  5172. this.$element.off('resizeme.zf.trigger');
  5173. }
  5174. }]);
  5175. return Interchange;
  5176. }(Plugin);
  5177. /**
  5178. * Default settings for plugin
  5179. */
  5180. Interchange.defaults = {
  5181. /**
  5182. * Rules to be applied to Interchange elements. Set with the `data-interchange` array notation.
  5183. * @option
  5184. * @type {?array}
  5185. * @default null
  5186. */
  5187. rules: null
  5188. };
  5189. Interchange.SPECIAL_QUERIES = {
  5190. 'landscape': 'screen and (orientation: landscape)',
  5191. 'portrait': 'screen and (orientation: portrait)',
  5192. '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)'
  5193. };
  5194. /**
  5195. * SmoothScroll module.
  5196. * @module foundation.smooth-scroll
  5197. */
  5198. var SmoothScroll =
  5199. /*#__PURE__*/
  5200. function (_Plugin) {
  5201. _inherits(SmoothScroll, _Plugin);
  5202. function SmoothScroll() {
  5203. _classCallCheck(this, SmoothScroll);
  5204. return _possibleConstructorReturn(this, _getPrototypeOf(SmoothScroll).apply(this, arguments));
  5205. }
  5206. _createClass(SmoothScroll, [{
  5207. key: "_setup",
  5208. /**
  5209. * Creates a new instance of SmoothScroll.
  5210. * @class
  5211. * @name SmoothScroll
  5212. * @fires SmoothScroll#init
  5213. * @param {Object} element - jQuery object to add the trigger to.
  5214. * @param {Object} options - Overrides to the default plugin settings.
  5215. */
  5216. value: function _setup(element, options) {
  5217. this.$element = element;
  5218. this.options = $.extend({}, SmoothScroll.defaults, this.$element.data(), options);
  5219. this.className = 'SmoothScroll'; // ie9 back compat
  5220. this._init();
  5221. }
  5222. /**
  5223. * Initialize the SmoothScroll plugin
  5224. * @private
  5225. */
  5226. }, {
  5227. key: "_init",
  5228. value: function _init() {
  5229. var id = this.$element[0].id || GetYoDigits(6, 'smooth-scroll');
  5230. this.$element.attr({
  5231. id: id
  5232. });
  5233. this._events();
  5234. }
  5235. /**
  5236. * Initializes events for SmoothScroll.
  5237. * @private
  5238. */
  5239. }, {
  5240. key: "_events",
  5241. value: function _events() {
  5242. this._linkClickListener = this._handleLinkClick.bind(this);
  5243. this.$element.on('click.zf.smoothScroll', this._linkClickListener);
  5244. this.$element.on('click.zf.smoothScroll', 'a[href^="#"]', this._linkClickListener);
  5245. }
  5246. /**
  5247. * Handle the given event to smoothly scroll to the anchor pointed by the event target.
  5248. * @param {*} e - event
  5249. * @function
  5250. * @private
  5251. */
  5252. }, {
  5253. key: "_handleLinkClick",
  5254. value: function _handleLinkClick(e) {
  5255. var _this = this;
  5256. // Follow the link if it does not point to an anchor.
  5257. if (!$(e.currentTarget).is('a[href^="#"]')) return;
  5258. var arrival = e.currentTarget.getAttribute('href');
  5259. this._inTransition = true;
  5260. SmoothScroll.scrollToLoc(arrival, this.options, function () {
  5261. _this._inTransition = false;
  5262. });
  5263. e.preventDefault();
  5264. }
  5265. }, {
  5266. key: "_destroy",
  5267. /**
  5268. * Destroys the SmoothScroll instance.
  5269. * @function
  5270. */
  5271. value: function _destroy() {
  5272. this.$element.off('click.zf.smoothScroll', this._linkClickListener);
  5273. this.$element.off('click.zf.smoothScroll', 'a[href^="#"]', this._linkClickListener);
  5274. }
  5275. }], [{
  5276. key: "scrollToLoc",
  5277. /**
  5278. * Function to scroll to a given location on the page.
  5279. * @param {String} loc - A properly formatted jQuery id selector. Example: '#foo'
  5280. * @param {Object} options - The options to use.
  5281. * @param {Function} callback - The callback function.
  5282. * @static
  5283. * @function
  5284. */
  5285. value: function scrollToLoc(loc) {
  5286. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : SmoothScroll.defaults;
  5287. var callback = arguments.length > 2 ? arguments[2] : undefined;
  5288. var $loc = $(loc); // Do nothing if target does not exist to prevent errors
  5289. if (!$loc.length) return false;
  5290. var scrollPos = Math.round($loc.offset().top - options.threshold / 2 - options.offset);
  5291. $('html, body').stop(true).animate({
  5292. scrollTop: scrollPos
  5293. }, options.animationDuration, options.animationEasing, function () {
  5294. if (typeof callback === 'function') {
  5295. callback();
  5296. }
  5297. });
  5298. }
  5299. }]);
  5300. return SmoothScroll;
  5301. }(Plugin);
  5302. /**
  5303. * Default settings for plugin.
  5304. */
  5305. SmoothScroll.defaults = {
  5306. /**
  5307. * Amount of time, in ms, the animated scrolling should take between locations.
  5308. * @option
  5309. * @type {number}
  5310. * @default 500
  5311. */
  5312. animationDuration: 500,
  5313. /**
  5314. * Animation style to use when scrolling between locations. Can be `'swing'` or `'linear'`.
  5315. * @option
  5316. * @type {string}
  5317. * @default 'linear'
  5318. * @see {@link https://api.jquery.com/animate|Jquery animate}
  5319. */
  5320. animationEasing: 'linear',
  5321. /**
  5322. * Number of pixels to use as a marker for location changes.
  5323. * @option
  5324. * @type {number}
  5325. * @default 50
  5326. */
  5327. threshold: 50,
  5328. /**
  5329. * Number of pixels to offset the scroll of the page on item click if using a sticky nav bar.
  5330. * @option
  5331. * @type {number}
  5332. * @default 0
  5333. */
  5334. offset: 0
  5335. };
  5336. /**
  5337. * Magellan module.
  5338. * @module foundation.magellan
  5339. * @requires foundation.smoothScroll
  5340. */
  5341. var Magellan =
  5342. /*#__PURE__*/
  5343. function (_Plugin) {
  5344. _inherits(Magellan, _Plugin);
  5345. function Magellan() {
  5346. _classCallCheck(this, Magellan);
  5347. return _possibleConstructorReturn(this, _getPrototypeOf(Magellan).apply(this, arguments));
  5348. }
  5349. _createClass(Magellan, [{
  5350. key: "_setup",
  5351. /**
  5352. * Creates a new instance of Magellan.
  5353. * @class
  5354. * @name Magellan
  5355. * @fires Magellan#init
  5356. * @param {Object} element - jQuery object to add the trigger to.
  5357. * @param {Object} options - Overrides to the default plugin settings.
  5358. */
  5359. value: function _setup(element, options) {
  5360. this.$element = element;
  5361. this.options = $.extend({}, Magellan.defaults, this.$element.data(), options);
  5362. this.className = 'Magellan'; // ie9 back compat
  5363. this._init();
  5364. this.calcPoints();
  5365. }
  5366. /**
  5367. * Initializes the Magellan plugin and calls functions to get equalizer functioning on load.
  5368. * @private
  5369. */
  5370. }, {
  5371. key: "_init",
  5372. value: function _init() {
  5373. var id = this.$element[0].id || GetYoDigits(6, 'magellan');
  5374. this.$targets = $('[data-magellan-target]');
  5375. this.$links = this.$element.find('a');
  5376. this.$element.attr({
  5377. 'data-resize': id,
  5378. 'data-scroll': id,
  5379. 'id': id
  5380. });
  5381. this.$active = $();
  5382. this.scrollPos = parseInt(window.pageYOffset, 10);
  5383. this._events();
  5384. }
  5385. /**
  5386. * Calculates an array of pixel values that are the demarcation lines between locations on the page.
  5387. * Can be invoked if new elements are added or the size of a location changes.
  5388. * @function
  5389. */
  5390. }, {
  5391. key: "calcPoints",
  5392. value: function calcPoints() {
  5393. var _this = this,
  5394. body = document.body,
  5395. html = document.documentElement;
  5396. this.points = [];
  5397. this.winHeight = Math.round(Math.max(window.innerHeight, html.clientHeight));
  5398. this.docHeight = Math.round(Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight));
  5399. this.$targets.each(function () {
  5400. var $tar = $(this),
  5401. pt = Math.round($tar.offset().top - _this.options.threshold);
  5402. $tar.targetPoint = pt;
  5403. _this.points.push(pt);
  5404. });
  5405. }
  5406. /**
  5407. * Initializes events for Magellan.
  5408. * @private
  5409. */
  5410. }, {
  5411. key: "_events",
  5412. value: function _events() {
  5413. var _this = this,
  5414. $body = $('html, body'),
  5415. opts = {
  5416. duration: _this.options.animationDuration,
  5417. easing: _this.options.animationEasing
  5418. };
  5419. $(window).one('load', function () {
  5420. if (_this.options.deepLinking) {
  5421. if (location.hash) {
  5422. _this.scrollToLoc(location.hash);
  5423. }
  5424. }
  5425. _this.calcPoints();
  5426. _this._updateActive();
  5427. });
  5428. _this.onLoadListener = onLoad($(window), function () {
  5429. _this.$element.on({
  5430. 'resizeme.zf.trigger': _this.reflow.bind(_this),
  5431. 'scrollme.zf.trigger': _this._updateActive.bind(_this)
  5432. }).on('click.zf.magellan', 'a[href^="#"]', function (e) {
  5433. e.preventDefault();
  5434. var arrival = this.getAttribute('href');
  5435. _this.scrollToLoc(arrival);
  5436. });
  5437. });
  5438. this._deepLinkScroll = function (e) {
  5439. if (_this.options.deepLinking) {
  5440. _this.scrollToLoc(window.location.hash);
  5441. }
  5442. };
  5443. $(window).on('hashchange', this._deepLinkScroll);
  5444. }
  5445. /**
  5446. * Function to scroll to a given location on the page.
  5447. * @param {String} loc - a properly formatted jQuery id selector. Example: '#foo'
  5448. * @function
  5449. */
  5450. }, {
  5451. key: "scrollToLoc",
  5452. value: function scrollToLoc(loc) {
  5453. this._inTransition = true;
  5454. var _this = this;
  5455. var options = {
  5456. animationEasing: this.options.animationEasing,
  5457. animationDuration: this.options.animationDuration,
  5458. threshold: this.options.threshold,
  5459. offset: this.options.offset
  5460. };
  5461. SmoothScroll.scrollToLoc(loc, options, function () {
  5462. _this._inTransition = false;
  5463. });
  5464. }
  5465. /**
  5466. * Calls necessary functions to update Magellan upon DOM change
  5467. * @function
  5468. */
  5469. }, {
  5470. key: "reflow",
  5471. value: function reflow() {
  5472. this.calcPoints();
  5473. this._updateActive();
  5474. }
  5475. /**
  5476. * Updates the visibility of an active location link, and updates the url hash for the page, if deepLinking enabled.
  5477. * @private
  5478. * @function
  5479. * @fires Magellan#update
  5480. */
  5481. }, {
  5482. key: "_updateActive",
  5483. value: function _updateActive()
  5484. /*evt, elem, scrollPos*/
  5485. {
  5486. var _this2 = this;
  5487. if (this._inTransition) return;
  5488. var newScrollPos = parseInt(window.pageYOffset, 10);
  5489. var isScrollingUp = this.scrollPos > newScrollPos;
  5490. this.scrollPos = newScrollPos;
  5491. var activeIdx; // Before the first point: no link
  5492. if (newScrollPos < this.points[0]) ;
  5493. /* do nothing */
  5494. // At the bottom of the page: last link
  5495. else if (newScrollPos + this.winHeight === this.docHeight) {
  5496. activeIdx = this.points.length - 1;
  5497. } // Otherwhise, use the last visible link
  5498. else {
  5499. var visibleLinks = this.points.filter(function (p, i) {
  5500. return p - _this2.options.offset - (isScrollingUp ? _this2.options.threshold : 0) <= newScrollPos;
  5501. });
  5502. activeIdx = visibleLinks.length ? visibleLinks.length - 1 : 0;
  5503. } // Get the new active link
  5504. var $oldActive = this.$active;
  5505. var activeHash = '';
  5506. if (typeof activeIdx !== 'undefined') {
  5507. this.$active = this.$links.filter('[href="#' + this.$targets.eq(activeIdx).data('magellan-target') + '"]');
  5508. if (this.$active.length) activeHash = this.$active[0].getAttribute('href');
  5509. } else {
  5510. this.$active = $();
  5511. }
  5512. var isNewActive = !(!this.$active.length && !$oldActive.length) && !this.$active.is($oldActive);
  5513. var isNewHash = activeHash !== window.location.hash; // Update the active link element
  5514. if (isNewActive) {
  5515. $oldActive.removeClass(this.options.activeClass);
  5516. this.$active.addClass(this.options.activeClass);
  5517. } // Update the hash (it may have changed with the same active link)
  5518. if (this.options.deepLinking && isNewHash) {
  5519. if (window.history.pushState) {
  5520. // Set or remove the hash (see: https://stackoverflow.com/a/5298684/4317384
  5521. var url = activeHash ? activeHash : window.location.pathname + window.location.search;
  5522. window.history.pushState(null, null, url);
  5523. } else {
  5524. window.location.hash = activeHash;
  5525. }
  5526. }
  5527. if (isNewActive) {
  5528. /**
  5529. * Fires when magellan is finished updating to the new active element.
  5530. * @event Magellan#update
  5531. */
  5532. this.$element.trigger('update.zf.magellan', [this.$active]);
  5533. }
  5534. }
  5535. /**
  5536. * Destroys an instance of Magellan and resets the url of the window.
  5537. * @function
  5538. */
  5539. }, {
  5540. key: "_destroy",
  5541. value: function _destroy() {
  5542. this.$element.off('.zf.trigger .zf.magellan').find(".".concat(this.options.activeClass)).removeClass(this.options.activeClass);
  5543. if (this.options.deepLinking) {
  5544. var hash = this.$active[0].getAttribute('href');
  5545. window.location.hash.replace(hash, '');
  5546. }
  5547. $(window).off('hashchange', this._deepLinkScroll);
  5548. if (this.onLoadListener) $(window).off(this.onLoadListener);
  5549. }
  5550. }]);
  5551. return Magellan;
  5552. }(Plugin);
  5553. /**
  5554. * Default settings for plugin
  5555. */
  5556. Magellan.defaults = {
  5557. /**
  5558. * Amount of time, in ms, the animated scrolling should take between locations.
  5559. * @option
  5560. * @type {number}
  5561. * @default 500
  5562. */
  5563. animationDuration: 500,
  5564. /**
  5565. * Animation style to use when scrolling between locations. Can be `'swing'` or `'linear'`.
  5566. * @option
  5567. * @type {string}
  5568. * @default 'linear'
  5569. * @see {@link https://api.jquery.com/animate|Jquery animate}
  5570. */
  5571. animationEasing: 'linear',
  5572. /**
  5573. * Number of pixels to use as a marker for location changes.
  5574. * @option
  5575. * @type {number}
  5576. * @default 50
  5577. */
  5578. threshold: 50,
  5579. /**
  5580. * Class applied to the active locations link on the magellan container.
  5581. * @option
  5582. * @type {string}
  5583. * @default 'is-active'
  5584. */
  5585. activeClass: 'is-active',
  5586. /**
  5587. * Allows the script to manipulate the url of the current page, and if supported, alter the history.
  5588. * @option
  5589. * @type {boolean}
  5590. * @default false
  5591. */
  5592. deepLinking: false,
  5593. /**
  5594. * Number of pixels to offset the scroll of the page on item click if using a sticky nav bar.
  5595. * @option
  5596. * @type {number}
  5597. * @default 0
  5598. */
  5599. offset: 0
  5600. };
  5601. /**
  5602. * OffCanvas module.
  5603. * @module foundation.offcanvas
  5604. * @requires foundation.util.keyboard
  5605. * @requires foundation.util.mediaQuery
  5606. * @requires foundation.util.triggers
  5607. */
  5608. var OffCanvas =
  5609. /*#__PURE__*/
  5610. function (_Plugin) {
  5611. _inherits(OffCanvas, _Plugin);
  5612. function OffCanvas() {
  5613. _classCallCheck(this, OffCanvas);
  5614. return _possibleConstructorReturn(this, _getPrototypeOf(OffCanvas).apply(this, arguments));
  5615. }
  5616. _createClass(OffCanvas, [{
  5617. key: "_setup",
  5618. /**
  5619. * Creates a new instance of an off-canvas wrapper.
  5620. * @class
  5621. * @name OffCanvas
  5622. * @fires OffCanvas#init
  5623. * @param {Object} element - jQuery object to initialize.
  5624. * @param {Object} options - Overrides to the default plugin settings.
  5625. */
  5626. value: function _setup(element, options) {
  5627. var _this2 = this;
  5628. this.className = 'OffCanvas'; // ie9 back compat
  5629. this.$element = element;
  5630. this.options = $.extend({}, OffCanvas.defaults, this.$element.data(), options);
  5631. this.contentClasses = {
  5632. base: [],
  5633. reveal: []
  5634. };
  5635. this.$lastTrigger = $();
  5636. this.$triggers = $();
  5637. this.position = 'left';
  5638. this.$content = $();
  5639. this.nested = !!this.options.nested; // Defines the CSS transition/position classes of the off-canvas content container.
  5640. $(['push', 'overlap']).each(function (index, val) {
  5641. _this2.contentClasses.base.push('has-transition-' + val);
  5642. });
  5643. $(['left', 'right', 'top', 'bottom']).each(function (index, val) {
  5644. _this2.contentClasses.base.push('has-position-' + val);
  5645. _this2.contentClasses.reveal.push('has-reveal-' + val);
  5646. }); // Triggers init is idempotent, just need to make sure it is initialized
  5647. Triggers.init($);
  5648. MediaQuery._init();
  5649. this._init();
  5650. this._events();
  5651. Keyboard.register('OffCanvas', {
  5652. 'ESCAPE': 'close'
  5653. });
  5654. }
  5655. /**
  5656. * Initializes the off-canvas wrapper by adding the exit overlay (if needed).
  5657. * @function
  5658. * @private
  5659. */
  5660. }, {
  5661. key: "_init",
  5662. value: function _init() {
  5663. var id = this.$element.attr('id');
  5664. this.$element.attr('aria-hidden', 'true'); // Find off-canvas content, either by ID (if specified), by siblings or by closest selector (fallback)
  5665. if (this.options.contentId) {
  5666. this.$content = $('#' + this.options.contentId);
  5667. } else if (this.$element.siblings('[data-off-canvas-content]').length) {
  5668. this.$content = this.$element.siblings('[data-off-canvas-content]').first();
  5669. } else {
  5670. this.$content = this.$element.closest('[data-off-canvas-content]').first();
  5671. }
  5672. if (!this.options.contentId) {
  5673. // Assume that the off-canvas element is nested if it isn't a sibling of the content
  5674. this.nested = this.$element.siblings('[data-off-canvas-content]').length === 0;
  5675. } else if (this.options.contentId && this.options.nested === null) {
  5676. // Warning if using content ID without setting the nested option
  5677. // Once the element is nested it is required to work properly in this case
  5678. console.warn('Remember to use the nested option if using the content ID option!');
  5679. }
  5680. if (this.nested === true) {
  5681. // Force transition overlap if nested
  5682. this.options.transition = 'overlap'; // Remove appropriate classes if already assigned in markup
  5683. this.$element.removeClass('is-transition-push');
  5684. }
  5685. this.$element.addClass("is-transition-".concat(this.options.transition, " is-closed")); // Find triggers that affect this element and add aria-expanded to them
  5686. 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
  5687. 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
  5688. if (this.options.contentOverlay === true) {
  5689. var overlay = document.createElement('div');
  5690. var overlayPosition = $(this.$element).css("position") === 'fixed' ? 'is-overlay-fixed' : 'is-overlay-absolute';
  5691. overlay.setAttribute('class', 'js-off-canvas-overlay ' + overlayPosition);
  5692. this.$overlay = $(overlay);
  5693. if (overlayPosition === 'is-overlay-fixed') {
  5694. $(this.$overlay).insertAfter(this.$element);
  5695. } else {
  5696. this.$content.append(this.$overlay);
  5697. }
  5698. } // Get the revealOn option from the class.
  5699. var revealOnRegExp = new RegExp(RegExpEscape(this.options.revealClass) + '([^\\s]+)', 'g');
  5700. var revealOnClass = revealOnRegExp.exec(this.$element[0].className);
  5701. if (revealOnClass) {
  5702. this.options.isRevealed = true;
  5703. this.options.revealOn = this.options.revealOn || revealOnClass[1];
  5704. } // Ensure the `reveal-on-*` class is set.
  5705. if (this.options.isRevealed === true && this.options.revealOn) {
  5706. this.$element.first().addClass("".concat(this.options.revealClass).concat(this.options.revealOn));
  5707. this._setMQChecker();
  5708. }
  5709. if (this.options.transitionTime) {
  5710. this.$element.css('transition-duration', this.options.transitionTime);
  5711. } // Initally remove all transition/position CSS classes from off-canvas content container.
  5712. this._removeContentClasses();
  5713. }
  5714. /**
  5715. * Adds event handlers to the off-canvas wrapper and the exit overlay.
  5716. * @function
  5717. * @private
  5718. */
  5719. }, {
  5720. key: "_events",
  5721. value: function _events() {
  5722. this.$element.off('.zf.trigger .zf.offcanvas').on({
  5723. 'open.zf.trigger': this.open.bind(this),
  5724. 'close.zf.trigger': this.close.bind(this),
  5725. 'toggle.zf.trigger': this.toggle.bind(this),
  5726. 'keydown.zf.offcanvas': this._handleKeyboard.bind(this)
  5727. });
  5728. if (this.options.closeOnClick === true) {
  5729. var $target = this.options.contentOverlay ? this.$overlay : this.$content;
  5730. $target.on({
  5731. 'click.zf.offcanvas': this.close.bind(this)
  5732. });
  5733. }
  5734. }
  5735. /**
  5736. * Applies event listener for elements that will reveal at certain breakpoints.
  5737. * @private
  5738. */
  5739. }, {
  5740. key: "_setMQChecker",
  5741. value: function _setMQChecker() {
  5742. var _this = this;
  5743. this.onLoadListener = onLoad($(window), function () {
  5744. if (MediaQuery.atLeast(_this.options.revealOn)) {
  5745. _this.reveal(true);
  5746. }
  5747. });
  5748. $(window).on('changed.zf.mediaquery', function () {
  5749. if (MediaQuery.atLeast(_this.options.revealOn)) {
  5750. _this.reveal(true);
  5751. } else {
  5752. _this.reveal(false);
  5753. }
  5754. });
  5755. }
  5756. /**
  5757. * Removes the CSS transition/position classes of the off-canvas content container.
  5758. * Removing the classes is important when another off-canvas gets opened that uses the same content container.
  5759. * @param {Boolean} hasReveal - true if related off-canvas element is revealed.
  5760. * @private
  5761. */
  5762. }, {
  5763. key: "_removeContentClasses",
  5764. value: function _removeContentClasses(hasReveal) {
  5765. if (typeof hasReveal !== 'boolean') {
  5766. this.$content.removeClass(this.contentClasses.base.join(' '));
  5767. } else if (hasReveal === false) {
  5768. this.$content.removeClass("has-reveal-".concat(this.position));
  5769. }
  5770. }
  5771. /**
  5772. * Adds the CSS transition/position classes of the off-canvas content container, based on the opening off-canvas element.
  5773. * Beforehand any transition/position class gets removed.
  5774. * @param {Boolean} hasReveal - true if related off-canvas element is revealed.
  5775. * @private
  5776. */
  5777. }, {
  5778. key: "_addContentClasses",
  5779. value: function _addContentClasses(hasReveal) {
  5780. this._removeContentClasses(hasReveal);
  5781. if (typeof hasReveal !== 'boolean') {
  5782. this.$content.addClass("has-transition-".concat(this.options.transition, " has-position-").concat(this.position));
  5783. } else if (hasReveal === true) {
  5784. this.$content.addClass("has-reveal-".concat(this.position));
  5785. }
  5786. }
  5787. /**
  5788. * Handles the revealing/hiding the off-canvas at breakpoints, not the same as open.
  5789. * @param {Boolean} isRevealed - true if element should be revealed.
  5790. * @function
  5791. */
  5792. }, {
  5793. key: "reveal",
  5794. value: function reveal(isRevealed) {
  5795. if (isRevealed) {
  5796. this.close();
  5797. this.isRevealed = true;
  5798. this.$element.attr('aria-hidden', 'false');
  5799. this.$element.off('open.zf.trigger toggle.zf.trigger');
  5800. this.$element.removeClass('is-closed');
  5801. } else {
  5802. this.isRevealed = false;
  5803. this.$element.attr('aria-hidden', 'true');
  5804. this.$element.off('open.zf.trigger toggle.zf.trigger').on({
  5805. 'open.zf.trigger': this.open.bind(this),
  5806. 'toggle.zf.trigger': this.toggle.bind(this)
  5807. });
  5808. this.$element.addClass('is-closed');
  5809. }
  5810. this._addContentClasses(isRevealed);
  5811. }
  5812. /**
  5813. * Stops scrolling of the body when offcanvas is open on mobile Safari and other troublesome browsers.
  5814. * @private
  5815. */
  5816. }, {
  5817. key: "_stopScrolling",
  5818. value: function _stopScrolling(event) {
  5819. return false;
  5820. } // Taken and adapted from http://stackoverflow.com/questions/16889447/prevent-full-page-scrolling-ios
  5821. // Only really works for y, not sure how to extend to x or if we need to.
  5822. }, {
  5823. key: "_recordScrollable",
  5824. value: function _recordScrollable(event) {
  5825. var elem = this; // called from event handler context with this as elem
  5826. // If the element is scrollable (content overflows), then...
  5827. if (elem.scrollHeight !== elem.clientHeight) {
  5828. // If we're at the top, scroll down one pixel to allow scrolling up
  5829. if (elem.scrollTop === 0) {
  5830. elem.scrollTop = 1;
  5831. } // If we're at the bottom, scroll up one pixel to allow scrolling down
  5832. if (elem.scrollTop === elem.scrollHeight - elem.clientHeight) {
  5833. elem.scrollTop = elem.scrollHeight - elem.clientHeight - 1;
  5834. }
  5835. }
  5836. elem.allowUp = elem.scrollTop > 0;
  5837. elem.allowDown = elem.scrollTop < elem.scrollHeight - elem.clientHeight;
  5838. elem.lastY = event.originalEvent.pageY;
  5839. }
  5840. }, {
  5841. key: "_stopScrollPropagation",
  5842. value: function _stopScrollPropagation(event) {
  5843. var elem = this; // called from event handler context with this as elem
  5844. var up = event.pageY < elem.lastY;
  5845. var down = !up;
  5846. elem.lastY = event.pageY;
  5847. if (up && elem.allowUp || down && elem.allowDown) {
  5848. event.stopPropagation();
  5849. } else {
  5850. event.preventDefault();
  5851. }
  5852. }
  5853. /**
  5854. * Opens the off-canvas menu.
  5855. * @function
  5856. * @param {Object} event - Event object passed from listener.
  5857. * @param {jQuery} trigger - element that triggered the off-canvas to open.
  5858. * @fires Offcanvas#opened
  5859. * @todo also trigger 'open' event?
  5860. */
  5861. }, {
  5862. key: "open",
  5863. value: function open(event, trigger) {
  5864. if (this.$element.hasClass('is-open') || this.isRevealed) {
  5865. return;
  5866. }
  5867. var _this = this;
  5868. if (trigger) {
  5869. this.$lastTrigger = trigger;
  5870. }
  5871. if (this.options.forceTo === 'top') {
  5872. window.scrollTo(0, 0);
  5873. } else if (this.options.forceTo === 'bottom') {
  5874. window.scrollTo(0, document.body.scrollHeight);
  5875. }
  5876. if (this.options.transitionTime && this.options.transition !== 'overlap') {
  5877. this.$element.siblings('[data-off-canvas-content]').css('transition-duration', this.options.transitionTime);
  5878. } else {
  5879. this.$element.siblings('[data-off-canvas-content]').css('transition-duration', '');
  5880. }
  5881. this.$element.addClass('is-open').removeClass('is-closed');
  5882. this.$triggers.attr('aria-expanded', 'true');
  5883. this.$element.attr('aria-hidden', 'false');
  5884. this.$content.addClass('is-open-' + this.position); // If `contentScroll` is set to false, add class and disable scrolling on touch devices.
  5885. if (this.options.contentScroll === false) {
  5886. $('body').addClass('is-off-canvas-open').on('touchmove', this._stopScrolling);
  5887. this.$element.on('touchstart', this._recordScrollable);
  5888. this.$element.on('touchmove', this._stopScrollPropagation);
  5889. }
  5890. if (this.options.contentOverlay === true) {
  5891. this.$overlay.addClass('is-visible');
  5892. }
  5893. if (this.options.closeOnClick === true && this.options.contentOverlay === true) {
  5894. this.$overlay.addClass('is-closable');
  5895. }
  5896. if (this.options.autoFocus === true) {
  5897. this.$element.one(transitionend(this.$element), function () {
  5898. if (!_this.$element.hasClass('is-open')) {
  5899. return; // exit if prematurely closed
  5900. }
  5901. var canvasFocus = _this.$element.find('[data-autofocus]');
  5902. if (canvasFocus.length) {
  5903. canvasFocus.eq(0).focus();
  5904. } else {
  5905. _this.$element.find('a, button').eq(0).focus();
  5906. }
  5907. });
  5908. }
  5909. if (this.options.trapFocus === true) {
  5910. this.$content.attr('tabindex', '-1');
  5911. Keyboard.trapFocus(this.$element);
  5912. }
  5913. this._addContentClasses();
  5914. /**
  5915. * Fires when the off-canvas menu opens.
  5916. * @event Offcanvas#opened
  5917. */
  5918. this.$element.trigger('opened.zf.offcanvas');
  5919. }
  5920. /**
  5921. * Closes the off-canvas menu.
  5922. * @function
  5923. * @param {Function} cb - optional cb to fire after closure.
  5924. * @fires Offcanvas#closed
  5925. */
  5926. }, {
  5927. key: "close",
  5928. value: function close(cb) {
  5929. if (!this.$element.hasClass('is-open') || this.isRevealed) {
  5930. return;
  5931. }
  5932. var _this = this;
  5933. this.$element.removeClass('is-open');
  5934. this.$element.attr('aria-hidden', 'true')
  5935. /**
  5936. * Fires when the off-canvas menu opens.
  5937. * @event Offcanvas#closed
  5938. */
  5939. .trigger('closed.zf.offcanvas');
  5940. 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.
  5941. if (this.options.contentScroll === false) {
  5942. $('body').removeClass('is-off-canvas-open').off('touchmove', this._stopScrolling);
  5943. this.$element.off('touchstart', this._recordScrollable);
  5944. this.$element.off('touchmove', this._stopScrollPropagation);
  5945. }
  5946. if (this.options.contentOverlay === true) {
  5947. this.$overlay.removeClass('is-visible');
  5948. }
  5949. if (this.options.closeOnClick === true && this.options.contentOverlay === true) {
  5950. this.$overlay.removeClass('is-closable');
  5951. }
  5952. this.$triggers.attr('aria-expanded', 'false');
  5953. if (this.options.trapFocus === true) {
  5954. this.$content.removeAttr('tabindex');
  5955. Keyboard.releaseFocus(this.$element);
  5956. } // Listen to transitionEnd and add class when done.
  5957. this.$element.one(transitionend(this.$element), function (e) {
  5958. _this.$element.addClass('is-closed');
  5959. _this._removeContentClasses();
  5960. });
  5961. }
  5962. /**
  5963. * Toggles the off-canvas menu open or closed.
  5964. * @function
  5965. * @param {Object} event - Event object passed from listener.
  5966. * @param {jQuery} trigger - element that triggered the off-canvas to open.
  5967. */
  5968. }, {
  5969. key: "toggle",
  5970. value: function toggle(event, trigger) {
  5971. if (this.$element.hasClass('is-open')) {
  5972. this.close(event, trigger);
  5973. } else {
  5974. this.open(event, trigger);
  5975. }
  5976. }
  5977. /**
  5978. * 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.
  5979. * @function
  5980. * @private
  5981. */
  5982. }, {
  5983. key: "_handleKeyboard",
  5984. value: function _handleKeyboard(e) {
  5985. var _this3 = this;
  5986. Keyboard.handleKey(e, 'OffCanvas', {
  5987. close: function close() {
  5988. _this3.close();
  5989. _this3.$lastTrigger.focus();
  5990. return true;
  5991. },
  5992. handled: function handled() {
  5993. e.stopPropagation();
  5994. e.preventDefault();
  5995. }
  5996. });
  5997. }
  5998. /**
  5999. * Destroys the offcanvas plugin.
  6000. * @function
  6001. */
  6002. }, {
  6003. key: "_destroy",
  6004. value: function _destroy() {
  6005. this.close();
  6006. this.$element.off('.zf.trigger .zf.offcanvas');
  6007. this.$overlay.off('.zf.offcanvas');
  6008. if (this.onLoadListener) $(window).off(this.onLoadListener);
  6009. }
  6010. }]);
  6011. return OffCanvas;
  6012. }(Plugin);
  6013. OffCanvas.defaults = {
  6014. /**
  6015. * Allow the user to click outside of the menu to close it.
  6016. * @option
  6017. * @type {boolean}
  6018. * @default true
  6019. */
  6020. closeOnClick: true,
  6021. /**
  6022. * Adds an overlay on top of `[data-off-canvas-content]`.
  6023. * @option
  6024. * @type {boolean}
  6025. * @default true
  6026. */
  6027. contentOverlay: true,
  6028. /**
  6029. * Target an off-canvas content container by ID that may be placed anywhere. If null the closest content container will be taken.
  6030. * @option
  6031. * @type {?string}
  6032. * @default null
  6033. */
  6034. contentId: null,
  6035. /**
  6036. * Define the off-canvas element is nested in an off-canvas content. This is required when using the contentId option for a nested element.
  6037. * @option
  6038. * @type {boolean}
  6039. * @default null
  6040. */
  6041. nested: null,
  6042. /**
  6043. * Enable/disable scrolling of the main content when an off canvas panel is open.
  6044. * @option
  6045. * @type {boolean}
  6046. * @default true
  6047. */
  6048. contentScroll: true,
  6049. /**
  6050. * Amount of time in ms the open and close transition requires. If none selected, pulls from body style.
  6051. * @option
  6052. * @type {number}
  6053. * @default null
  6054. */
  6055. transitionTime: null,
  6056. /**
  6057. * Type of transition for the offcanvas menu. Options are 'push', 'detached' or 'slide'.
  6058. * @option
  6059. * @type {string}
  6060. * @default push
  6061. */
  6062. transition: 'push',
  6063. /**
  6064. * Force the page to scroll to top or bottom on open.
  6065. * @option
  6066. * @type {?string}
  6067. * @default null
  6068. */
  6069. forceTo: null,
  6070. /**
  6071. * Allow the offcanvas to remain open for certain breakpoints.
  6072. * @option
  6073. * @type {boolean}
  6074. * @default false
  6075. */
  6076. isRevealed: false,
  6077. /**
  6078. * Breakpoint at which to reveal. JS will use a RegExp to target standard classes, if changing classnames, pass your class with the `revealClass` option.
  6079. * @option
  6080. * @type {?string}
  6081. * @default null
  6082. */
  6083. revealOn: null,
  6084. /**
  6085. * Force focus to the offcanvas on open. If true, will focus the opening trigger on close.
  6086. * @option
  6087. * @type {boolean}
  6088. * @default true
  6089. */
  6090. autoFocus: true,
  6091. /**
  6092. * Class used to force an offcanvas to remain open. Foundation defaults for this are `reveal-for-large` & `reveal-for-medium`.
  6093. * @option
  6094. * @type {string}
  6095. * @default reveal-for-
  6096. * @todo improve the regex testing for this.
  6097. */
  6098. revealClass: 'reveal-for-',
  6099. /**
  6100. * Triggers optional focus trapping when opening an offcanvas. Sets tabindex of [data-off-canvas-content] to -1 for accessibility purposes.
  6101. * @option
  6102. * @type {boolean}
  6103. * @default false
  6104. */
  6105. trapFocus: false
  6106. };
  6107. /**
  6108. * Orbit module.
  6109. * @module foundation.orbit
  6110. * @requires foundation.util.keyboard
  6111. * @requires foundation.util.motion
  6112. * @requires foundation.util.timer
  6113. * @requires foundation.util.imageLoader
  6114. * @requires foundation.util.touch
  6115. */
  6116. var Orbit =
  6117. /*#__PURE__*/
  6118. function (_Plugin) {
  6119. _inherits(Orbit, _Plugin);
  6120. function Orbit() {
  6121. _classCallCheck(this, Orbit);
  6122. return _possibleConstructorReturn(this, _getPrototypeOf(Orbit).apply(this, arguments));
  6123. }
  6124. _createClass(Orbit, [{
  6125. key: "_setup",
  6126. /**
  6127. * Creates a new instance of an orbit carousel.
  6128. * @class
  6129. * @name Orbit
  6130. * @param {jQuery} element - jQuery object to make into an Orbit Carousel.
  6131. * @param {Object} options - Overrides to the default plugin settings.
  6132. */
  6133. value: function _setup(element, options) {
  6134. this.$element = element;
  6135. this.options = $.extend({}, Orbit.defaults, this.$element.data(), options);
  6136. this.className = 'Orbit'; // ie9 back compat
  6137. Touch.init($); // Touch init is idempotent, we just need to make sure it's initialied.
  6138. this._init();
  6139. Keyboard.register('Orbit', {
  6140. 'ltr': {
  6141. 'ARROW_RIGHT': 'next',
  6142. 'ARROW_LEFT': 'previous'
  6143. },
  6144. 'rtl': {
  6145. 'ARROW_LEFT': 'next',
  6146. 'ARROW_RIGHT': 'previous'
  6147. }
  6148. });
  6149. }
  6150. /**
  6151. * Initializes the plugin by creating jQuery collections, setting attributes, and starting the animation.
  6152. * @function
  6153. * @private
  6154. */
  6155. }, {
  6156. key: "_init",
  6157. value: function _init() {
  6158. // @TODO: consider discussion on PR #9278 about DOM pollution by changeSlide
  6159. this._reset();
  6160. this.$wrapper = this.$element.find(".".concat(this.options.containerClass));
  6161. this.$slides = this.$element.find(".".concat(this.options.slideClass));
  6162. var $images = this.$element.find('img'),
  6163. initActive = this.$slides.filter('.is-active'),
  6164. id = this.$element[0].id || GetYoDigits(6, 'orbit');
  6165. this.$element.attr({
  6166. 'data-resize': id,
  6167. 'id': id
  6168. });
  6169. if (!initActive.length) {
  6170. this.$slides.eq(0).addClass('is-active');
  6171. }
  6172. if (!this.options.useMUI) {
  6173. this.$slides.addClass('no-motionui');
  6174. }
  6175. if ($images.length) {
  6176. onImagesLoaded($images, this._prepareForOrbit.bind(this));
  6177. } else {
  6178. this._prepareForOrbit(); //hehe
  6179. }
  6180. if (this.options.bullets) {
  6181. this._loadBullets();
  6182. }
  6183. this._events();
  6184. if (this.options.autoPlay && this.$slides.length > 1) {
  6185. this.geoSync();
  6186. }
  6187. if (this.options.accessible) {
  6188. // allow wrapper to be focusable to enable arrow navigation
  6189. this.$wrapper.attr('tabindex', 0);
  6190. }
  6191. }
  6192. /**
  6193. * Creates a jQuery collection of bullets, if they are being used.
  6194. * @function
  6195. * @private
  6196. */
  6197. }, {
  6198. key: "_loadBullets",
  6199. value: function _loadBullets() {
  6200. this.$bullets = this.$element.find(".".concat(this.options.boxOfBullets)).find('button');
  6201. }
  6202. /**
  6203. * Sets a `timer` object on the orbit, and starts the counter for the next slide.
  6204. * @function
  6205. */
  6206. }, {
  6207. key: "geoSync",
  6208. value: function geoSync() {
  6209. var _this = this;
  6210. this.timer = new Timer(this.$element, {
  6211. duration: this.options.timerDelay,
  6212. infinite: false
  6213. }, function () {
  6214. _this.changeSlide(true);
  6215. });
  6216. this.timer.start();
  6217. }
  6218. /**
  6219. * Sets wrapper and slide heights for the orbit.
  6220. * @function
  6221. * @private
  6222. */
  6223. }, {
  6224. key: "_prepareForOrbit",
  6225. value: function _prepareForOrbit() {
  6226. this._setWrapperHeight();
  6227. }
  6228. /**
  6229. * Calulates the height of each slide in the collection, and uses the tallest one for the wrapper height.
  6230. * @function
  6231. * @private
  6232. * @param {Function} cb - a callback function to fire when complete.
  6233. */
  6234. }, {
  6235. key: "_setWrapperHeight",
  6236. value: function _setWrapperHeight(cb) {
  6237. //rewrite this to `for` loop
  6238. var max = 0,
  6239. temp,
  6240. counter = 0,
  6241. _this = this;
  6242. this.$slides.each(function () {
  6243. temp = this.getBoundingClientRect().height;
  6244. $(this).attr('data-slide', counter); // hide all slides but the active one
  6245. if (!/mui/g.test($(this)[0].className) && _this.$slides.filter('.is-active')[0] !== _this.$slides.eq(counter)[0]) {
  6246. $(this).css({
  6247. 'display': 'none'
  6248. });
  6249. }
  6250. max = temp > max ? temp : max;
  6251. counter++;
  6252. });
  6253. if (counter === this.$slides.length) {
  6254. this.$wrapper.css({
  6255. 'height': max
  6256. }); //only change the wrapper height property once.
  6257. if (cb) {
  6258. cb(max);
  6259. } //fire callback with max height dimension.
  6260. }
  6261. }
  6262. /**
  6263. * Sets the max-height of each slide.
  6264. * @function
  6265. * @private
  6266. */
  6267. }, {
  6268. key: "_setSlideHeight",
  6269. value: function _setSlideHeight(height) {
  6270. this.$slides.each(function () {
  6271. $(this).css('max-height', height);
  6272. });
  6273. }
  6274. /**
  6275. * Adds event listeners to basically everything within the element.
  6276. * @function
  6277. * @private
  6278. */
  6279. }, {
  6280. key: "_events",
  6281. value: function _events() {
  6282. var _this = this; //***************************************
  6283. //**Now using custom event - thanks to:**
  6284. //** Yohai Ararat of Toronto **
  6285. //***************************************
  6286. //
  6287. this.$element.off('.resizeme.zf.trigger').on({
  6288. 'resizeme.zf.trigger': this._prepareForOrbit.bind(this)
  6289. });
  6290. if (this.$slides.length > 1) {
  6291. if (this.options.swipe) {
  6292. this.$slides.off('swipeleft.zf.orbit swiperight.zf.orbit').on('swipeleft.zf.orbit', function (e) {
  6293. e.preventDefault();
  6294. _this.changeSlide(true);
  6295. }).on('swiperight.zf.orbit', function (e) {
  6296. e.preventDefault();
  6297. _this.changeSlide(false);
  6298. });
  6299. } //***************************************
  6300. if (this.options.autoPlay) {
  6301. this.$slides.on('click.zf.orbit', function () {
  6302. _this.$element.data('clickedOn', _this.$element.data('clickedOn') ? false : true);
  6303. _this.timer[_this.$element.data('clickedOn') ? 'pause' : 'start']();
  6304. });
  6305. if (this.options.pauseOnHover) {
  6306. this.$element.on('mouseenter.zf.orbit', function () {
  6307. _this.timer.pause();
  6308. }).on('mouseleave.zf.orbit', function () {
  6309. if (!_this.$element.data('clickedOn')) {
  6310. _this.timer.start();
  6311. }
  6312. });
  6313. }
  6314. }
  6315. if (this.options.navButtons) {
  6316. var $controls = this.$element.find(".".concat(this.options.nextClass, ", .").concat(this.options.prevClass));
  6317. $controls.attr('tabindex', 0) //also need to handle enter/return and spacebar key presses
  6318. .on('click.zf.orbit touchend.zf.orbit', function (e) {
  6319. e.preventDefault();
  6320. _this.changeSlide($(this).hasClass(_this.options.nextClass));
  6321. });
  6322. }
  6323. if (this.options.bullets) {
  6324. this.$bullets.on('click.zf.orbit touchend.zf.orbit', function () {
  6325. if (/is-active/g.test(this.className)) {
  6326. return false;
  6327. } //if this is active, kick out of function.
  6328. var idx = $(this).data('slide'),
  6329. ltr = idx > _this.$slides.filter('.is-active').data('slide'),
  6330. $slide = _this.$slides.eq(idx);
  6331. _this.changeSlide(ltr, $slide, idx);
  6332. });
  6333. }
  6334. if (this.options.accessible) {
  6335. this.$wrapper.add(this.$bullets).on('keydown.zf.orbit', function (e) {
  6336. // handle keyboard event with keyboard util
  6337. Keyboard.handleKey(e, 'Orbit', {
  6338. next: function next() {
  6339. _this.changeSlide(true);
  6340. },
  6341. previous: function previous() {
  6342. _this.changeSlide(false);
  6343. },
  6344. handled: function handled() {
  6345. // if bullet is focused, make sure focus moves
  6346. if ($(e.target).is(_this.$bullets)) {
  6347. _this.$bullets.filter('.is-active').focus();
  6348. }
  6349. }
  6350. });
  6351. });
  6352. }
  6353. }
  6354. }
  6355. /**
  6356. * Resets Orbit so it can be reinitialized
  6357. */
  6358. }, {
  6359. key: "_reset",
  6360. value: function _reset() {
  6361. // Don't do anything if there are no slides (first run)
  6362. if (typeof this.$slides == 'undefined') {
  6363. return;
  6364. }
  6365. if (this.$slides.length > 1) {
  6366. // Remove old events
  6367. this.$element.off('.zf.orbit').find('*').off('.zf.orbit'); // Restart timer if autoPlay is enabled
  6368. if (this.options.autoPlay) {
  6369. this.timer.restart();
  6370. } // Reset all sliddes
  6371. this.$slides.each(function (el) {
  6372. $(el).removeClass('is-active is-active is-in').removeAttr('aria-live').hide();
  6373. }); // Show the first slide
  6374. this.$slides.first().addClass('is-active').show(); // Triggers when the slide has finished animating
  6375. this.$element.trigger('slidechange.zf.orbit', [this.$slides.first()]); // Select first bullet if bullets are present
  6376. if (this.options.bullets) {
  6377. this._updateBullets(0);
  6378. }
  6379. }
  6380. }
  6381. /**
  6382. * Changes the current slide to a new one.
  6383. * @function
  6384. * @param {Boolean} isLTR - if true the slide moves from right to left, if false the slide moves from left to right.
  6385. * @param {jQuery} chosenSlide - the jQuery element of the slide to show next, if one is selected.
  6386. * @param {Number} idx - the index of the new slide in its collection, if one chosen.
  6387. * @fires Orbit#slidechange
  6388. */
  6389. }, {
  6390. key: "changeSlide",
  6391. value: function changeSlide(isLTR, chosenSlide, idx) {
  6392. if (!this.$slides) {
  6393. return;
  6394. } // Don't freak out if we're in the middle of cleanup
  6395. var $curSlide = this.$slides.filter('.is-active').eq(0);
  6396. if (/mui/g.test($curSlide[0].className)) {
  6397. return false;
  6398. } //if the slide is currently animating, kick out of the function
  6399. var $firstSlide = this.$slides.first(),
  6400. $lastSlide = this.$slides.last(),
  6401. dirIn = isLTR ? 'Right' : 'Left',
  6402. dirOut = isLTR ? 'Left' : 'Right',
  6403. _this = this,
  6404. $newSlide;
  6405. if (!chosenSlide) {
  6406. //most of the time, this will be auto played or clicked from the navButtons.
  6407. $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!!!!!
  6408. 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
  6409. 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
  6410. } else {
  6411. $newSlide = chosenSlide;
  6412. }
  6413. if ($newSlide.length) {
  6414. /**
  6415. * Triggers before the next slide starts animating in and only if a next slide has been found.
  6416. * @event Orbit#beforeslidechange
  6417. */
  6418. this.$element.trigger('beforeslidechange.zf.orbit', [$curSlide, $newSlide]);
  6419. if (this.options.bullets) {
  6420. idx = idx || this.$slides.index($newSlide); //grab index to update bullets
  6421. this._updateBullets(idx);
  6422. }
  6423. if (this.options.useMUI && !this.$element.is(':hidden')) {
  6424. Motion.animateIn($newSlide.addClass('is-active'), this.options["animInFrom".concat(dirIn)], function () {
  6425. $newSlide.css({
  6426. 'display': 'block'
  6427. }).attr('aria-live', 'polite');
  6428. });
  6429. Motion.animateOut($curSlide.removeClass('is-active'), this.options["animOutTo".concat(dirOut)], function () {
  6430. $curSlide.removeAttr('aria-live');
  6431. if (_this.options.autoPlay && !_this.timer.isPaused) {
  6432. _this.timer.restart();
  6433. } //do stuff?
  6434. });
  6435. } else {
  6436. $curSlide.removeClass('is-active is-in').removeAttr('aria-live').hide();
  6437. $newSlide.addClass('is-active is-in').attr('aria-live', 'polite').show();
  6438. if (this.options.autoPlay && !this.timer.isPaused) {
  6439. this.timer.restart();
  6440. }
  6441. }
  6442. /**
  6443. * Triggers when the slide has finished animating in.
  6444. * @event Orbit#slidechange
  6445. */
  6446. this.$element.trigger('slidechange.zf.orbit', [$newSlide]);
  6447. }
  6448. }
  6449. /**
  6450. * Updates the active state of the bullets, if displayed.
  6451. * @function
  6452. * @private
  6453. * @param {Number} idx - the index of the current slide.
  6454. */
  6455. }, {
  6456. key: "_updateBullets",
  6457. value: function _updateBullets(idx) {
  6458. var $oldBullet = this.$element.find(".".concat(this.options.boxOfBullets)).find('.is-active').removeClass('is-active').blur(),
  6459. span = $oldBullet.find('span:last').detach(),
  6460. $newBullet = this.$bullets.eq(idx).addClass('is-active').append(span);
  6461. }
  6462. /**
  6463. * Destroys the carousel and hides the element.
  6464. * @function
  6465. */
  6466. }, {
  6467. key: "_destroy",
  6468. value: function _destroy() {
  6469. this.$element.off('.zf.orbit').find('*').off('.zf.orbit').end().hide();
  6470. }
  6471. }]);
  6472. return Orbit;
  6473. }(Plugin);
  6474. Orbit.defaults = {
  6475. /**
  6476. * Tells the JS to look for and loadBullets.
  6477. * @option
  6478. * @type {boolean}
  6479. * @default true
  6480. */
  6481. bullets: true,
  6482. /**
  6483. * Tells the JS to apply event listeners to nav buttons
  6484. * @option
  6485. * @type {boolean}
  6486. * @default true
  6487. */
  6488. navButtons: true,
  6489. /**
  6490. * motion-ui animation class to apply
  6491. * @option
  6492. * @type {string}
  6493. * @default 'slide-in-right'
  6494. */
  6495. animInFromRight: 'slide-in-right',
  6496. /**
  6497. * motion-ui animation class to apply
  6498. * @option
  6499. * @type {string}
  6500. * @default 'slide-out-right'
  6501. */
  6502. animOutToRight: 'slide-out-right',
  6503. /**
  6504. * motion-ui animation class to apply
  6505. * @option
  6506. * @type {string}
  6507. * @default 'slide-in-left'
  6508. *
  6509. */
  6510. animInFromLeft: 'slide-in-left',
  6511. /**
  6512. * motion-ui animation class to apply
  6513. * @option
  6514. * @type {string}
  6515. * @default 'slide-out-left'
  6516. */
  6517. animOutToLeft: 'slide-out-left',
  6518. /**
  6519. * Allows Orbit to automatically animate on page load.
  6520. * @option
  6521. * @type {boolean}
  6522. * @default true
  6523. */
  6524. autoPlay: true,
  6525. /**
  6526. * Amount of time, in ms, between slide transitions
  6527. * @option
  6528. * @type {number}
  6529. * @default 5000
  6530. */
  6531. timerDelay: 5000,
  6532. /**
  6533. * Allows Orbit to infinitely loop through the slides
  6534. * @option
  6535. * @type {boolean}
  6536. * @default true
  6537. */
  6538. infiniteWrap: true,
  6539. /**
  6540. * Allows the Orbit slides to bind to swipe events for mobile, requires an additional util library
  6541. * @option
  6542. * @type {boolean}
  6543. * @default true
  6544. */
  6545. swipe: true,
  6546. /**
  6547. * Allows the timing function to pause animation on hover.
  6548. * @option
  6549. * @type {boolean}
  6550. * @default true
  6551. */
  6552. pauseOnHover: true,
  6553. /**
  6554. * Allows Orbit to bind keyboard events to the slider, to animate frames with arrow keys
  6555. * @option
  6556. * @type {boolean}
  6557. * @default true
  6558. */
  6559. accessible: true,
  6560. /**
  6561. * Class applied to the container of Orbit
  6562. * @option
  6563. * @type {string}
  6564. * @default 'orbit-container'
  6565. */
  6566. containerClass: 'orbit-container',
  6567. /**
  6568. * Class applied to individual slides.
  6569. * @option
  6570. * @type {string}
  6571. * @default 'orbit-slide'
  6572. */
  6573. slideClass: 'orbit-slide',
  6574. /**
  6575. * Class applied to the bullet container. You're welcome.
  6576. * @option
  6577. * @type {string}
  6578. * @default 'orbit-bullets'
  6579. */
  6580. boxOfBullets: 'orbit-bullets',
  6581. /**
  6582. * Class applied to the `next` navigation button.
  6583. * @option
  6584. * @type {string}
  6585. * @default 'orbit-next'
  6586. */
  6587. nextClass: 'orbit-next',
  6588. /**
  6589. * Class applied to the `previous` navigation button.
  6590. * @option
  6591. * @type {string}
  6592. * @default 'orbit-previous'
  6593. */
  6594. prevClass: 'orbit-previous',
  6595. /**
  6596. * Boolean to flag the js to use motion ui classes or not. Default to true for backwards compatibility.
  6597. * @option
  6598. * @type {boolean}
  6599. * @default true
  6600. */
  6601. useMUI: true
  6602. };
  6603. var MenuPlugins = {
  6604. dropdown: {
  6605. cssClass: 'dropdown',
  6606. plugin: DropdownMenu
  6607. },
  6608. drilldown: {
  6609. cssClass: 'drilldown',
  6610. plugin: Drilldown
  6611. },
  6612. accordion: {
  6613. cssClass: 'accordion-menu',
  6614. plugin: AccordionMenu
  6615. }
  6616. }; // import "foundation.util.triggers.js";
  6617. /**
  6618. * ResponsiveMenu module.
  6619. * @module foundation.responsiveMenu
  6620. * @requires foundation.util.triggers
  6621. * @requires foundation.util.mediaQuery
  6622. */
  6623. var ResponsiveMenu =
  6624. /*#__PURE__*/
  6625. function (_Plugin) {
  6626. _inherits(ResponsiveMenu, _Plugin);
  6627. function ResponsiveMenu() {
  6628. _classCallCheck(this, ResponsiveMenu);
  6629. return _possibleConstructorReturn(this, _getPrototypeOf(ResponsiveMenu).apply(this, arguments));
  6630. }
  6631. _createClass(ResponsiveMenu, [{
  6632. key: "_setup",
  6633. /**
  6634. * Creates a new instance of a responsive menu.
  6635. * @class
  6636. * @name ResponsiveMenu
  6637. * @fires ResponsiveMenu#init
  6638. * @param {jQuery} element - jQuery object to make into a dropdown menu.
  6639. * @param {Object} options - Overrides to the default plugin settings.
  6640. */
  6641. value: function _setup(element, options) {
  6642. this.$element = $(element);
  6643. this.rules = this.$element.data('responsive-menu');
  6644. this.currentMq = null;
  6645. this.currentPlugin = null;
  6646. this.className = 'ResponsiveMenu'; // ie9 back compat
  6647. this._init();
  6648. this._events();
  6649. }
  6650. /**
  6651. * Initializes the Menu by parsing the classes from the 'data-ResponsiveMenu' attribute on the element.
  6652. * @function
  6653. * @private
  6654. */
  6655. }, {
  6656. key: "_init",
  6657. value: function _init() {
  6658. MediaQuery._init(); // The first time an Interchange plugin is initialized, this.rules is converted from a string of "classes" to an object of rules
  6659. if (typeof this.rules === 'string') {
  6660. var rulesTree = {}; // Parse rules from "classes" pulled from data attribute
  6661. var rules = this.rules.split(' '); // Iterate through every rule found
  6662. for (var i = 0; i < rules.length; i++) {
  6663. var rule = rules[i].split('-');
  6664. var ruleSize = rule.length > 1 ? rule[0] : 'small';
  6665. var rulePlugin = rule.length > 1 ? rule[1] : rule[0];
  6666. if (MenuPlugins[rulePlugin] !== null) {
  6667. rulesTree[ruleSize] = MenuPlugins[rulePlugin];
  6668. }
  6669. }
  6670. this.rules = rulesTree;
  6671. }
  6672. if (!$.isEmptyObject(this.rules)) {
  6673. this._checkMediaQueries();
  6674. } // Add data-mutate since children may need it.
  6675. this.$element.attr('data-mutate', this.$element.attr('data-mutate') || GetYoDigits(6, 'responsive-menu'));
  6676. }
  6677. /**
  6678. * Initializes events for the Menu.
  6679. * @function
  6680. * @private
  6681. */
  6682. }, {
  6683. key: "_events",
  6684. value: function _events() {
  6685. var _this = this;
  6686. $(window).on('changed.zf.mediaquery', function () {
  6687. _this._checkMediaQueries();
  6688. }); // $(window).on('resize.zf.ResponsiveMenu', function() {
  6689. // _this._checkMediaQueries();
  6690. // });
  6691. }
  6692. /**
  6693. * 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.
  6694. * @function
  6695. * @private
  6696. */
  6697. }, {
  6698. key: "_checkMediaQueries",
  6699. value: function _checkMediaQueries() {
  6700. var matchedMq,
  6701. _this = this; // Iterate through each rule and find the last matching rule
  6702. $.each(this.rules, function (key) {
  6703. if (MediaQuery.atLeast(key)) {
  6704. matchedMq = key;
  6705. }
  6706. }); // No match? No dice
  6707. if (!matchedMq) return; // Plugin already initialized? We good
  6708. if (this.currentPlugin instanceof this.rules[matchedMq].plugin) return; // Remove existing plugin-specific CSS classes
  6709. $.each(MenuPlugins, function (key, value) {
  6710. _this.$element.removeClass(value.cssClass);
  6711. }); // Add the CSS class for the new plugin
  6712. this.$element.addClass(this.rules[matchedMq].cssClass); // Create an instance of the new plugin
  6713. if (this.currentPlugin) this.currentPlugin.destroy();
  6714. this.currentPlugin = new this.rules[matchedMq].plugin(this.$element, {});
  6715. }
  6716. /**
  6717. * Destroys the instance of the current plugin on this element, as well as the window resize handler that switches the plugins out.
  6718. * @function
  6719. */
  6720. }, {
  6721. key: "_destroy",
  6722. value: function _destroy() {
  6723. this.currentPlugin.destroy();
  6724. $(window).off('.zf.ResponsiveMenu');
  6725. }
  6726. }]);
  6727. return ResponsiveMenu;
  6728. }(Plugin);
  6729. ResponsiveMenu.defaults = {};
  6730. /**
  6731. * ResponsiveToggle module.
  6732. * @module foundation.responsiveToggle
  6733. * @requires foundation.util.mediaQuery
  6734. * @requires foundation.util.motion
  6735. */
  6736. var ResponsiveToggle =
  6737. /*#__PURE__*/
  6738. function (_Plugin) {
  6739. _inherits(ResponsiveToggle, _Plugin);
  6740. function ResponsiveToggle() {
  6741. _classCallCheck(this, ResponsiveToggle);
  6742. return _possibleConstructorReturn(this, _getPrototypeOf(ResponsiveToggle).apply(this, arguments));
  6743. }
  6744. _createClass(ResponsiveToggle, [{
  6745. key: "_setup",
  6746. /**
  6747. * Creates a new instance of Tab Bar.
  6748. * @class
  6749. * @name ResponsiveToggle
  6750. * @fires ResponsiveToggle#init
  6751. * @param {jQuery} element - jQuery object to attach tab bar functionality to.
  6752. * @param {Object} options - Overrides to the default plugin settings.
  6753. */
  6754. value: function _setup(element, options) {
  6755. this.$element = $(element);
  6756. this.options = $.extend({}, ResponsiveToggle.defaults, this.$element.data(), options);
  6757. this.className = 'ResponsiveToggle'; // ie9 back compat
  6758. this._init();
  6759. this._events();
  6760. }
  6761. /**
  6762. * Initializes the tab bar by finding the target element, toggling element, and running update().
  6763. * @function
  6764. * @private
  6765. */
  6766. }, {
  6767. key: "_init",
  6768. value: function _init() {
  6769. MediaQuery._init();
  6770. var targetID = this.$element.data('responsive-toggle');
  6771. if (!targetID) {
  6772. console.error('Your tab bar needs an ID of a Menu as the value of data-tab-bar.');
  6773. }
  6774. this.$targetMenu = $("#".concat(targetID));
  6775. this.$toggler = this.$element.find('[data-toggle]').filter(function () {
  6776. var target = $(this).data('toggle');
  6777. return target === targetID || target === "";
  6778. });
  6779. this.options = $.extend({}, this.options, this.$targetMenu.data()); // If they were set, parse the animation classes
  6780. if (this.options.animate) {
  6781. var input = this.options.animate.split(' ');
  6782. this.animationIn = input[0];
  6783. this.animationOut = input[1] || null;
  6784. }
  6785. this._update();
  6786. }
  6787. /**
  6788. * Adds necessary event handlers for the tab bar to work.
  6789. * @function
  6790. * @private
  6791. */
  6792. }, {
  6793. key: "_events",
  6794. value: function _events() {
  6795. this._updateMqHandler = this._update.bind(this);
  6796. $(window).on('changed.zf.mediaquery', this._updateMqHandler);
  6797. this.$toggler.on('click.zf.responsiveToggle', this.toggleMenu.bind(this));
  6798. }
  6799. /**
  6800. * Checks the current media query to determine if the tab bar should be visible or hidden.
  6801. * @function
  6802. * @private
  6803. */
  6804. }, {
  6805. key: "_update",
  6806. value: function _update() {
  6807. // Mobile
  6808. if (!MediaQuery.atLeast(this.options.hideFor)) {
  6809. this.$element.show();
  6810. this.$targetMenu.hide();
  6811. } // Desktop
  6812. else {
  6813. this.$element.hide();
  6814. this.$targetMenu.show();
  6815. }
  6816. }
  6817. /**
  6818. * Toggles the element attached to the tab bar. The toggle only happens if the screen is small enough to allow it.
  6819. * @function
  6820. * @fires ResponsiveToggle#toggled
  6821. */
  6822. }, {
  6823. key: "toggleMenu",
  6824. value: function toggleMenu() {
  6825. var _this2 = this;
  6826. if (!MediaQuery.atLeast(this.options.hideFor)) {
  6827. /**
  6828. * Fires when the element attached to the tab bar toggles.
  6829. * @event ResponsiveToggle#toggled
  6830. */
  6831. if (this.options.animate) {
  6832. if (this.$targetMenu.is(':hidden')) {
  6833. Motion.animateIn(this.$targetMenu, this.animationIn, function () {
  6834. _this2.$element.trigger('toggled.zf.responsiveToggle');
  6835. _this2.$targetMenu.find('[data-mutate]').triggerHandler('mutateme.zf.trigger');
  6836. });
  6837. } else {
  6838. Motion.animateOut(this.$targetMenu, this.animationOut, function () {
  6839. _this2.$element.trigger('toggled.zf.responsiveToggle');
  6840. });
  6841. }
  6842. } else {
  6843. this.$targetMenu.toggle(0);
  6844. this.$targetMenu.find('[data-mutate]').trigger('mutateme.zf.trigger');
  6845. this.$element.trigger('toggled.zf.responsiveToggle');
  6846. }
  6847. }
  6848. }
  6849. }, {
  6850. key: "_destroy",
  6851. value: function _destroy() {
  6852. this.$element.off('.zf.responsiveToggle');
  6853. this.$toggler.off('.zf.responsiveToggle');
  6854. $(window).off('changed.zf.mediaquery', this._updateMqHandler);
  6855. }
  6856. }]);
  6857. return ResponsiveToggle;
  6858. }(Plugin);
  6859. ResponsiveToggle.defaults = {
  6860. /**
  6861. * The breakpoint after which the menu is always shown, and the tab bar is hidden.
  6862. * @option
  6863. * @type {string}
  6864. * @default 'medium'
  6865. */
  6866. hideFor: 'medium',
  6867. /**
  6868. * To decide if the toggle should be animated or not.
  6869. * @option
  6870. * @type {boolean}
  6871. * @default false
  6872. */
  6873. animate: false
  6874. };
  6875. /**
  6876. * Reveal module.
  6877. * @module foundation.reveal
  6878. * @requires foundation.util.keyboard
  6879. * @requires foundation.util.triggers
  6880. * @requires foundation.util.mediaQuery
  6881. * @requires foundation.util.motion if using animations
  6882. */
  6883. var Reveal =
  6884. /*#__PURE__*/
  6885. function (_Plugin) {
  6886. _inherits(Reveal, _Plugin);
  6887. function Reveal() {
  6888. _classCallCheck(this, Reveal);
  6889. return _possibleConstructorReturn(this, _getPrototypeOf(Reveal).apply(this, arguments));
  6890. }
  6891. _createClass(Reveal, [{
  6892. key: "_setup",
  6893. /**
  6894. * Creates a new instance of Reveal.
  6895. * @class
  6896. * @name Reveal
  6897. * @param {jQuery} element - jQuery object to use for the modal.
  6898. * @param {Object} options - optional parameters.
  6899. */
  6900. value: function _setup(element, options) {
  6901. this.$element = element;
  6902. this.options = $.extend({}, Reveal.defaults, this.$element.data(), options);
  6903. this.className = 'Reveal'; // ie9 back compat
  6904. this._init(); // Triggers init is idempotent, just need to make sure it is initialized
  6905. Triggers.init($);
  6906. Keyboard.register('Reveal', {
  6907. 'ESCAPE': 'close'
  6908. });
  6909. }
  6910. /**
  6911. * Initializes the modal by adding the overlay and close buttons, (if selected).
  6912. * @private
  6913. */
  6914. }, {
  6915. key: "_init",
  6916. value: function _init() {
  6917. var _this2 = this;
  6918. MediaQuery._init();
  6919. this.id = this.$element.attr('id');
  6920. this.isActive = false;
  6921. this.cached = {
  6922. mq: MediaQuery.current
  6923. };
  6924. this.$anchor = $("[data-open=\"".concat(this.id, "\"]")).length ? $("[data-open=\"".concat(this.id, "\"]")) : $("[data-toggle=\"".concat(this.id, "\"]"));
  6925. this.$anchor.attr({
  6926. 'aria-controls': this.id,
  6927. 'aria-haspopup': true,
  6928. 'tabindex': 0
  6929. });
  6930. if (this.options.fullScreen || this.$element.hasClass('full')) {
  6931. this.options.fullScreen = true;
  6932. this.options.overlay = false;
  6933. }
  6934. if (this.options.overlay && !this.$overlay) {
  6935. this.$overlay = this._makeOverlay(this.id);
  6936. }
  6937. this.$element.attr({
  6938. 'role': 'dialog',
  6939. 'aria-hidden': true,
  6940. 'data-yeti-box': this.id,
  6941. 'data-resize': this.id
  6942. });
  6943. if (this.$overlay) {
  6944. this.$element.detach().appendTo(this.$overlay);
  6945. } else {
  6946. this.$element.detach().appendTo($(this.options.appendTo));
  6947. this.$element.addClass('without-overlay');
  6948. }
  6949. this._events();
  6950. if (this.options.deepLink && window.location.hash === "#".concat(this.id)) {
  6951. this.onLoadListener = onLoad($(window), function () {
  6952. return _this2.open();
  6953. });
  6954. }
  6955. }
  6956. /**
  6957. * Creates an overlay div to display behind the modal.
  6958. * @private
  6959. */
  6960. }, {
  6961. key: "_makeOverlay",
  6962. value: function _makeOverlay() {
  6963. var additionalOverlayClasses = '';
  6964. if (this.options.additionalOverlayClasses) {
  6965. additionalOverlayClasses = ' ' + this.options.additionalOverlayClasses;
  6966. }
  6967. return $('<div></div>').addClass('reveal-overlay' + additionalOverlayClasses).appendTo(this.options.appendTo);
  6968. }
  6969. /**
  6970. * Updates position of modal
  6971. * TODO: Figure out if we actually need to cache these values or if it doesn't matter
  6972. * @private
  6973. */
  6974. }, {
  6975. key: "_updatePosition",
  6976. value: function _updatePosition() {
  6977. var width = this.$element.outerWidth();
  6978. var outerWidth = $(window).width();
  6979. var height = this.$element.outerHeight();
  6980. var outerHeight = $(window).height();
  6981. var left,
  6982. top = null;
  6983. if (this.options.hOffset === 'auto') {
  6984. left = parseInt((outerWidth - width) / 2, 10);
  6985. } else {
  6986. left = parseInt(this.options.hOffset, 10);
  6987. }
  6988. if (this.options.vOffset === 'auto') {
  6989. if (height > outerHeight) {
  6990. top = parseInt(Math.min(100, outerHeight / 10), 10);
  6991. } else {
  6992. top = parseInt((outerHeight - height) / 4, 10);
  6993. }
  6994. } else if (this.options.vOffset !== null) {
  6995. top = parseInt(this.options.vOffset, 10);
  6996. }
  6997. if (top !== null) {
  6998. this.$element.css({
  6999. top: top + 'px'
  7000. });
  7001. } // only worry about left if we don't have an overlay or we have a horizontal offset,
  7002. // otherwise we're perfectly in the middle
  7003. if (!this.$overlay || this.options.hOffset !== 'auto') {
  7004. this.$element.css({
  7005. left: left + 'px'
  7006. });
  7007. this.$element.css({
  7008. margin: '0px'
  7009. });
  7010. }
  7011. }
  7012. /**
  7013. * Adds event handlers for the modal.
  7014. * @private
  7015. */
  7016. }, {
  7017. key: "_events",
  7018. value: function _events() {
  7019. var _this3 = this;
  7020. var _this = this;
  7021. this.$element.on({
  7022. 'open.zf.trigger': this.open.bind(this),
  7023. 'close.zf.trigger': function closeZfTrigger(event, $element) {
  7024. if (event.target === _this.$element[0] || $(event.target).parents('[data-closable]')[0] === $element) {
  7025. // only close reveal when it's explicitly called
  7026. return _this3.close.apply(_this3);
  7027. }
  7028. },
  7029. 'toggle.zf.trigger': this.toggle.bind(this),
  7030. 'resizeme.zf.trigger': function resizemeZfTrigger() {
  7031. _this._updatePosition();
  7032. }
  7033. });
  7034. if (this.options.closeOnClick && this.options.overlay) {
  7035. this.$overlay.off('.zf.reveal').on('click.zf.reveal', function (e) {
  7036. if (e.target === _this.$element[0] || $.contains(_this.$element[0], e.target) || !$.contains(document, e.target)) {
  7037. return;
  7038. }
  7039. _this.close();
  7040. });
  7041. }
  7042. if (this.options.deepLink) {
  7043. $(window).on("hashchange.zf.reveal:".concat(this.id), this._handleState.bind(this));
  7044. }
  7045. }
  7046. /**
  7047. * Handles modal methods on back/forward button clicks or any other event that triggers hashchange.
  7048. * @private
  7049. */
  7050. }, {
  7051. key: "_handleState",
  7052. value: function _handleState(e) {
  7053. if (window.location.hash === '#' + this.id && !this.isActive) {
  7054. this.open();
  7055. } else {
  7056. this.close();
  7057. }
  7058. }
  7059. /**
  7060. * Disables the scroll when Reveal is shown to prevent the background from shifting
  7061. * @param {number} scrollTop - Scroll to visually apply, window current scroll by default
  7062. */
  7063. }, {
  7064. key: "_disableScroll",
  7065. value: function _disableScroll(scrollTop) {
  7066. scrollTop = scrollTop || $(window).scrollTop();
  7067. if ($(document).height() > $(window).height()) {
  7068. $("html").css("top", -scrollTop);
  7069. }
  7070. }
  7071. /**
  7072. * Reenables the scroll when Reveal closes
  7073. * @param {number} scrollTop - Scroll to restore, html "top" property by default (as set by `_disableScroll`)
  7074. */
  7075. }, {
  7076. key: "_enableScroll",
  7077. value: function _enableScroll(scrollTop) {
  7078. scrollTop = scrollTop || parseInt($("html").css("top"));
  7079. if ($(document).height() > $(window).height()) {
  7080. $("html").css("top", "");
  7081. $(window).scrollTop(-scrollTop);
  7082. }
  7083. }
  7084. /**
  7085. * Opens the modal controlled by `this.$anchor`, and closes all others by default.
  7086. * @function
  7087. * @fires Reveal#closeme
  7088. * @fires Reveal#open
  7089. */
  7090. }, {
  7091. key: "open",
  7092. value: function open() {
  7093. var _this4 = this;
  7094. // either update or replace browser history
  7095. var hash = "#".concat(this.id);
  7096. if (this.options.deepLink && window.location.hash !== hash) {
  7097. if (window.history.pushState) {
  7098. if (this.options.updateHistory) {
  7099. window.history.pushState({}, '', hash);
  7100. } else {
  7101. window.history.replaceState({}, '', hash);
  7102. }
  7103. } else {
  7104. window.location.hash = hash;
  7105. }
  7106. } // Remember anchor that opened it to set focus back later, have general anchors as fallback
  7107. this.$activeAnchor = $(document.activeElement).is(this.$anchor) ? $(document.activeElement) : this.$anchor;
  7108. this.isActive = true; // Make elements invisible, but remove display: none so we can get size and positioning
  7109. this.$element.css({
  7110. 'visibility': 'hidden'
  7111. }).show().scrollTop(0);
  7112. if (this.options.overlay) {
  7113. this.$overlay.css({
  7114. 'visibility': 'hidden'
  7115. }).show();
  7116. }
  7117. this._updatePosition();
  7118. this.$element.hide().css({
  7119. 'visibility': ''
  7120. });
  7121. if (this.$overlay) {
  7122. this.$overlay.css({
  7123. 'visibility': ''
  7124. }).hide();
  7125. if (this.$element.hasClass('fast')) {
  7126. this.$overlay.addClass('fast');
  7127. } else if (this.$element.hasClass('slow')) {
  7128. this.$overlay.addClass('slow');
  7129. }
  7130. }
  7131. if (!this.options.multipleOpened) {
  7132. /**
  7133. * Fires immediately before the modal opens.
  7134. * Closes any other modals that are currently open
  7135. * @event Reveal#closeme
  7136. */
  7137. this.$element.trigger('closeme.zf.reveal', this.id);
  7138. }
  7139. this._disableScroll();
  7140. var _this = this; // Motion UI method of reveal
  7141. if (this.options.animationIn) {
  7142. var afterAnimation = function afterAnimation() {
  7143. _this.$element.attr({
  7144. 'aria-hidden': false,
  7145. 'tabindex': -1
  7146. }).focus();
  7147. _this._addGlobalClasses();
  7148. Keyboard.trapFocus(_this.$element);
  7149. };
  7150. if (this.options.overlay) {
  7151. Motion.animateIn(this.$overlay, 'fade-in');
  7152. }
  7153. Motion.animateIn(this.$element, this.options.animationIn, function () {
  7154. if (_this4.$element) {
  7155. // protect against object having been removed
  7156. _this4.focusableElements = Keyboard.findFocusable(_this4.$element);
  7157. afterAnimation();
  7158. }
  7159. });
  7160. } // jQuery method of reveal
  7161. else {
  7162. if (this.options.overlay) {
  7163. this.$overlay.show(0);
  7164. }
  7165. this.$element.show(this.options.showDelay);
  7166. } // handle accessibility
  7167. this.$element.attr({
  7168. 'aria-hidden': false,
  7169. 'tabindex': -1
  7170. }).focus();
  7171. Keyboard.trapFocus(this.$element);
  7172. this._addGlobalClasses();
  7173. this._addGlobalListeners();
  7174. /**
  7175. * Fires when the modal has successfully opened.
  7176. * @event Reveal#open
  7177. */
  7178. this.$element.trigger('open.zf.reveal');
  7179. }
  7180. /**
  7181. * Adds classes and listeners on document required by open modals.
  7182. *
  7183. * The following classes are added and updated:
  7184. * - `.is-reveal-open` - Prevents the scroll on document
  7185. * - `.zf-has-scroll` - Displays a disabled scrollbar on document if required like if the
  7186. * scroll was not disabled. This prevent a "shift" of the page content due
  7187. * the scrollbar disappearing when the modal opens.
  7188. *
  7189. * @private
  7190. */
  7191. }, {
  7192. key: "_addGlobalClasses",
  7193. value: function _addGlobalClasses() {
  7194. var updateScrollbarClass = function updateScrollbarClass() {
  7195. $('html').toggleClass('zf-has-scroll', !!($(document).height() > $(window).height()));
  7196. };
  7197. this.$element.on('resizeme.zf.trigger.revealScrollbarListener', function () {
  7198. return updateScrollbarClass();
  7199. });
  7200. updateScrollbarClass();
  7201. $('html').addClass('is-reveal-open');
  7202. }
  7203. /**
  7204. * Removes classes and listeners on document that were required by open modals.
  7205. * @private
  7206. */
  7207. }, {
  7208. key: "_removeGlobalClasses",
  7209. value: function _removeGlobalClasses() {
  7210. this.$element.off('resizeme.zf.trigger.revealScrollbarListener');
  7211. $('html').removeClass('is-reveal-open');
  7212. $('html').removeClass('zf-has-scroll');
  7213. }
  7214. /**
  7215. * Adds extra event handlers for the body and window if necessary.
  7216. * @private
  7217. */
  7218. }, {
  7219. key: "_addGlobalListeners",
  7220. value: function _addGlobalListeners() {
  7221. var _this = this;
  7222. if (!this.$element) {
  7223. return;
  7224. } // If we're in the middle of cleanup, don't freak out
  7225. this.focusableElements = Keyboard.findFocusable(this.$element);
  7226. if (!this.options.overlay && this.options.closeOnClick && !this.options.fullScreen) {
  7227. $('body').on('click.zf.reveal', function (e) {
  7228. if (e.target === _this.$element[0] || $.contains(_this.$element[0], e.target) || !$.contains(document, e.target)) {
  7229. return;
  7230. }
  7231. _this.close();
  7232. });
  7233. }
  7234. if (this.options.closeOnEsc) {
  7235. $(window).on('keydown.zf.reveal', function (e) {
  7236. Keyboard.handleKey(e, 'Reveal', {
  7237. close: function close() {
  7238. if (_this.options.closeOnEsc) {
  7239. _this.close();
  7240. }
  7241. }
  7242. });
  7243. });
  7244. }
  7245. }
  7246. /**
  7247. * Closes the modal.
  7248. * @function
  7249. * @fires Reveal#closed
  7250. */
  7251. }, {
  7252. key: "close",
  7253. value: function close() {
  7254. if (!this.isActive || !this.$element.is(':visible')) {
  7255. return false;
  7256. }
  7257. var _this = this; // Motion UI method of hiding
  7258. if (this.options.animationOut) {
  7259. if (this.options.overlay) {
  7260. Motion.animateOut(this.$overlay, 'fade-out');
  7261. }
  7262. Motion.animateOut(this.$element, this.options.animationOut, finishUp);
  7263. } // jQuery method of hiding
  7264. else {
  7265. this.$element.hide(this.options.hideDelay);
  7266. if (this.options.overlay) {
  7267. this.$overlay.hide(0, finishUp);
  7268. } else {
  7269. finishUp();
  7270. }
  7271. } // Conditionals to remove extra event listeners added on open
  7272. if (this.options.closeOnEsc) {
  7273. $(window).off('keydown.zf.reveal');
  7274. }
  7275. if (!this.options.overlay && this.options.closeOnClick) {
  7276. $('body').off('click.zf.reveal');
  7277. }
  7278. this.$element.off('keydown.zf.reveal');
  7279. function finishUp() {
  7280. // Get the current top before the modal is closed and restore the scroll after.
  7281. // TODO: use component properties instead of HTML properties
  7282. // See https://github.com/zurb/foundation-sites/pull/10786
  7283. var scrollTop = parseInt($("html").css("top"));
  7284. if ($('.reveal:visible').length === 0) {
  7285. _this._removeGlobalClasses(); // also remove .is-reveal-open from the html element when there is no opened reveal
  7286. }
  7287. Keyboard.releaseFocus(_this.$element);
  7288. _this.$element.attr('aria-hidden', true);
  7289. _this._enableScroll(scrollTop);
  7290. /**
  7291. * Fires when the modal is done closing.
  7292. * @event Reveal#closed
  7293. */
  7294. _this.$element.trigger('closed.zf.reveal');
  7295. }
  7296. /**
  7297. * Resets the modal content
  7298. * This prevents a running video to keep going in the background
  7299. */
  7300. if (this.options.resetOnClose) {
  7301. this.$element.html(this.$element.html());
  7302. }
  7303. this.isActive = false; // If deepLink and we did not switched to an other modal...
  7304. if (_this.options.deepLink && window.location.hash === "#".concat(this.id)) {
  7305. // Remove the history hash
  7306. if (window.history.replaceState) {
  7307. var urlWithoutHash = window.location.pathname + window.location.search;
  7308. if (this.options.updateHistory) {
  7309. window.history.pushState({}, '', urlWithoutHash); // remove the hash
  7310. } else {
  7311. window.history.replaceState('', document.title, urlWithoutHash);
  7312. }
  7313. } else {
  7314. window.location.hash = '';
  7315. }
  7316. }
  7317. this.$activeAnchor.focus();
  7318. }
  7319. /**
  7320. * Toggles the open/closed state of a modal.
  7321. * @function
  7322. */
  7323. }, {
  7324. key: "toggle",
  7325. value: function toggle() {
  7326. if (this.isActive) {
  7327. this.close();
  7328. } else {
  7329. this.open();
  7330. }
  7331. }
  7332. }, {
  7333. key: "_destroy",
  7334. /**
  7335. * Destroys an instance of a modal.
  7336. * @function
  7337. */
  7338. value: function _destroy() {
  7339. if (this.options.overlay) {
  7340. this.$element.appendTo($(this.options.appendTo)); // move $element outside of $overlay to prevent error unregisterPlugin()
  7341. this.$overlay.hide().off().remove();
  7342. }
  7343. this.$element.hide().off();
  7344. this.$anchor.off('.zf');
  7345. $(window).off(".zf.reveal:".concat(this.id));
  7346. if (this.onLoadListener) $(window).off(this.onLoadListener);
  7347. if ($('.reveal:visible').length === 0) {
  7348. this._removeGlobalClasses(); // also remove .is-reveal-open from the html element when there is no opened reveal
  7349. }
  7350. }
  7351. }]);
  7352. return Reveal;
  7353. }(Plugin);
  7354. Reveal.defaults = {
  7355. /**
  7356. * Motion-UI class to use for animated elements. If none used, defaults to simple show/hide.
  7357. * @option
  7358. * @type {string}
  7359. * @default ''
  7360. */
  7361. animationIn: '',
  7362. /**
  7363. * Motion-UI class to use for animated elements. If none used, defaults to simple show/hide.
  7364. * @option
  7365. * @type {string}
  7366. * @default ''
  7367. */
  7368. animationOut: '',
  7369. /**
  7370. * Time, in ms, to delay the opening of a modal after a click if no animation used.
  7371. * @option
  7372. * @type {number}
  7373. * @default 0
  7374. */
  7375. showDelay: 0,
  7376. /**
  7377. * Time, in ms, to delay the closing of a modal after a click if no animation used.
  7378. * @option
  7379. * @type {number}
  7380. * @default 0
  7381. */
  7382. hideDelay: 0,
  7383. /**
  7384. * Allows a click on the body/overlay to close the modal.
  7385. * @option
  7386. * @type {boolean}
  7387. * @default true
  7388. */
  7389. closeOnClick: true,
  7390. /**
  7391. * Allows the modal to close if the user presses the `ESCAPE` key.
  7392. * @option
  7393. * @type {boolean}
  7394. * @default true
  7395. */
  7396. closeOnEsc: true,
  7397. /**
  7398. * If true, allows multiple modals to be displayed at once.
  7399. * @option
  7400. * @type {boolean}
  7401. * @default false
  7402. */
  7403. multipleOpened: false,
  7404. /**
  7405. * Distance, in pixels, the modal should push down from the top of the screen.
  7406. * @option
  7407. * @type {number|string}
  7408. * @default auto
  7409. */
  7410. vOffset: 'auto',
  7411. /**
  7412. * Distance, in pixels, the modal should push in from the side of the screen.
  7413. * @option
  7414. * @type {number|string}
  7415. * @default auto
  7416. */
  7417. hOffset: 'auto',
  7418. /**
  7419. * Allows the modal to be fullscreen, completely blocking out the rest of the view. JS checks for this as well.
  7420. * @option
  7421. * @type {boolean}
  7422. * @default false
  7423. */
  7424. fullScreen: false,
  7425. /**
  7426. * Allows the modal to generate an overlay div, which will cover the view when modal opens.
  7427. * @option
  7428. * @type {boolean}
  7429. * @default true
  7430. */
  7431. overlay: true,
  7432. /**
  7433. * 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.
  7434. * @option
  7435. * @type {boolean}
  7436. * @default false
  7437. */
  7438. resetOnClose: false,
  7439. /**
  7440. * Link the location hash to the modal.
  7441. * Set the location hash when the modal is opened/closed, and open/close the modal when the location changes.
  7442. * @option
  7443. * @type {boolean}
  7444. * @default false
  7445. */
  7446. deepLink: false,
  7447. /**
  7448. * If `deepLink` is enabled, update the browser history with the open modal
  7449. * @option
  7450. * @default false
  7451. */
  7452. updateHistory: false,
  7453. /**
  7454. * Allows the modal to append to custom div.
  7455. * @option
  7456. * @type {string}
  7457. * @default "body"
  7458. */
  7459. appendTo: "body",
  7460. /**
  7461. * Allows adding additional class names to the reveal overlay.
  7462. * @option
  7463. * @type {string}
  7464. * @default ''
  7465. */
  7466. additionalOverlayClasses: ''
  7467. };
  7468. /**
  7469. * Slider module.
  7470. * @module foundation.slider
  7471. * @requires foundation.util.motion
  7472. * @requires foundation.util.triggers
  7473. * @requires foundation.util.keyboard
  7474. * @requires foundation.util.touch
  7475. */
  7476. var Slider =
  7477. /*#__PURE__*/
  7478. function (_Plugin) {
  7479. _inherits(Slider, _Plugin);
  7480. function Slider() {
  7481. _classCallCheck(this, Slider);
  7482. return _possibleConstructorReturn(this, _getPrototypeOf(Slider).apply(this, arguments));
  7483. }
  7484. _createClass(Slider, [{
  7485. key: "_setup",
  7486. /**
  7487. * Creates a new instance of a slider control.
  7488. * @class
  7489. * @name Slider
  7490. * @param {jQuery} element - jQuery object to make into a slider control.
  7491. * @param {Object} options - Overrides to the default plugin settings.
  7492. */
  7493. value: function _setup(element, options) {
  7494. this.$element = element;
  7495. this.options = $.extend({}, Slider.defaults, this.$element.data(), options);
  7496. this.className = 'Slider'; // ie9 back compat
  7497. // Touch and Triggers inits are idempotent, we just need to make sure it's initialied.
  7498. Touch.init($);
  7499. Triggers.init($);
  7500. this._init();
  7501. Keyboard.register('Slider', {
  7502. 'ltr': {
  7503. 'ARROW_RIGHT': 'increase',
  7504. 'ARROW_UP': 'increase',
  7505. 'ARROW_DOWN': 'decrease',
  7506. 'ARROW_LEFT': 'decrease',
  7507. 'SHIFT_ARROW_RIGHT': 'increase_fast',
  7508. 'SHIFT_ARROW_UP': 'increase_fast',
  7509. 'SHIFT_ARROW_DOWN': 'decrease_fast',
  7510. 'SHIFT_ARROW_LEFT': 'decrease_fast',
  7511. 'HOME': 'min',
  7512. 'END': 'max'
  7513. },
  7514. 'rtl': {
  7515. 'ARROW_LEFT': 'increase',
  7516. 'ARROW_RIGHT': 'decrease',
  7517. 'SHIFT_ARROW_LEFT': 'increase_fast',
  7518. 'SHIFT_ARROW_RIGHT': 'decrease_fast'
  7519. }
  7520. });
  7521. }
  7522. /**
  7523. * Initilizes the plugin by reading/setting attributes, creating collections and setting the initial position of the handle(s).
  7524. * @function
  7525. * @private
  7526. */
  7527. }, {
  7528. key: "_init",
  7529. value: function _init() {
  7530. this.inputs = this.$element.find('input');
  7531. this.handles = this.$element.find('[data-slider-handle]');
  7532. this.$handle = this.handles.eq(0);
  7533. this.$input = this.inputs.length ? this.inputs.eq(0) : $("#".concat(this.$handle.attr('aria-controls')));
  7534. this.$fill = this.$element.find('[data-slider-fill]').css(this.options.vertical ? 'height' : 'width', 0);
  7535. if (this.options.disabled || this.$element.hasClass(this.options.disabledClass)) {
  7536. this.options.disabled = true;
  7537. this.$element.addClass(this.options.disabledClass);
  7538. }
  7539. if (!this.inputs.length) {
  7540. this.inputs = $().add(this.$input);
  7541. this.options.binding = true;
  7542. }
  7543. this._setInitAttr(0);
  7544. if (this.handles[1]) {
  7545. this.options.doubleSided = true;
  7546. this.$handle2 = this.handles.eq(1);
  7547. this.$input2 = this.inputs.length > 1 ? this.inputs.eq(1) : $("#".concat(this.$handle2.attr('aria-controls')));
  7548. if (!this.inputs[1]) {
  7549. this.inputs = this.inputs.add(this.$input2);
  7550. }
  7551. this._setInitAttr(1);
  7552. } // Set handle positions
  7553. this.setHandles();
  7554. this._events();
  7555. }
  7556. }, {
  7557. key: "setHandles",
  7558. value: function setHandles() {
  7559. var _this2 = this;
  7560. if (this.handles[1]) {
  7561. this._setHandlePos(this.$handle, this.inputs.eq(0).val(), true, function () {
  7562. _this2._setHandlePos(_this2.$handle2, _this2.inputs.eq(1).val(), true);
  7563. });
  7564. } else {
  7565. this._setHandlePos(this.$handle, this.inputs.eq(0).val(), true);
  7566. }
  7567. }
  7568. }, {
  7569. key: "_reflow",
  7570. value: function _reflow() {
  7571. this.setHandles();
  7572. }
  7573. /**
  7574. * @function
  7575. * @private
  7576. * @param {Number} value - floating point (the value) to be transformed using to a relative position on the slider (the inverse of _value)
  7577. */
  7578. }, {
  7579. key: "_pctOfBar",
  7580. value: function _pctOfBar(value) {
  7581. var pctOfBar = percent(value - this.options.start, this.options.end - this.options.start);
  7582. switch (this.options.positionValueFunction) {
  7583. case "pow":
  7584. pctOfBar = this._logTransform(pctOfBar);
  7585. break;
  7586. case "log":
  7587. pctOfBar = this._powTransform(pctOfBar);
  7588. break;
  7589. }
  7590. return pctOfBar.toFixed(2);
  7591. }
  7592. /**
  7593. * @function
  7594. * @private
  7595. * @param {Number} pctOfBar - floating point, the relative position of the slider (typically between 0-1) to be transformed to a value
  7596. */
  7597. }, {
  7598. key: "_value",
  7599. value: function _value(pctOfBar) {
  7600. switch (this.options.positionValueFunction) {
  7601. case "pow":
  7602. pctOfBar = this._powTransform(pctOfBar);
  7603. break;
  7604. case "log":
  7605. pctOfBar = this._logTransform(pctOfBar);
  7606. break;
  7607. }
  7608. var value = (this.options.end - this.options.start) * pctOfBar + parseFloat(this.options.start);
  7609. return value;
  7610. }
  7611. /**
  7612. * @function
  7613. * @private
  7614. * @param {Number} value - floating point (typically between 0-1) to be transformed using the log function
  7615. */
  7616. }, {
  7617. key: "_logTransform",
  7618. value: function _logTransform(value) {
  7619. return baseLog(this.options.nonLinearBase, value * (this.options.nonLinearBase - 1) + 1);
  7620. }
  7621. /**
  7622. * @function
  7623. * @private
  7624. * @param {Number} value - floating point (typically between 0-1) to be transformed using the power function
  7625. */
  7626. }, {
  7627. key: "_powTransform",
  7628. value: function _powTransform(value) {
  7629. return (Math.pow(this.options.nonLinearBase, value) - 1) / (this.options.nonLinearBase - 1);
  7630. }
  7631. /**
  7632. * Sets the position of the selected handle and fill bar.
  7633. * @function
  7634. * @private
  7635. * @param {jQuery} $hndl - the selected handle to move.
  7636. * @param {Number} location - floating point between the start and end values of the slider bar.
  7637. * @param {Function} cb - callback function to fire on completion.
  7638. * @fires Slider#moved
  7639. * @fires Slider#changed
  7640. */
  7641. }, {
  7642. key: "_setHandlePos",
  7643. value: function _setHandlePos($hndl, location, noInvert, cb) {
  7644. // don't move if the slider has been disabled since its initialization
  7645. if (this.$element.hasClass(this.options.disabledClass)) {
  7646. return;
  7647. } //might need to alter that slightly for bars that will have odd number selections.
  7648. location = parseFloat(location); //on input change events, convert string to number...grumble.
  7649. // prevent slider from running out of bounds, if value exceeds the limits set through options, override the value to min/max
  7650. if (location < this.options.start) {
  7651. location = this.options.start;
  7652. } else if (location > this.options.end) {
  7653. location = this.options.end;
  7654. }
  7655. var isDbl = this.options.doubleSided; //this is for single-handled vertical sliders, it adjusts the value to account for the slider being "upside-down"
  7656. //for click and drag events, it's weird due to the scale(-1, 1) css property
  7657. if (this.options.vertical && !noInvert) {
  7658. location = this.options.end - location;
  7659. }
  7660. if (isDbl) {
  7661. //this block is to prevent 2 handles from crossing eachother. Could/should be improved.
  7662. if (this.handles.index($hndl) === 0) {
  7663. var h2Val = parseFloat(this.$handle2.attr('aria-valuenow'));
  7664. location = location >= h2Val ? h2Val - this.options.step : location;
  7665. } else {
  7666. var h1Val = parseFloat(this.$handle.attr('aria-valuenow'));
  7667. location = location <= h1Val ? h1Val + this.options.step : location;
  7668. }
  7669. }
  7670. var _this = this,
  7671. vert = this.options.vertical,
  7672. hOrW = vert ? 'height' : 'width',
  7673. lOrT = vert ? 'top' : 'left',
  7674. handleDim = $hndl[0].getBoundingClientRect()[hOrW],
  7675. elemDim = this.$element[0].getBoundingClientRect()[hOrW],
  7676. //percentage of bar min/max value based on click or drag point
  7677. pctOfBar = this._pctOfBar(location),
  7678. //number of actual pixels to shift the handle, based on the percentage obtained above
  7679. pxToMove = (elemDim - handleDim) * pctOfBar,
  7680. //percentage of bar to shift the handle
  7681. 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
  7682. location = parseFloat(location.toFixed(this.options.decimal)); // declare empty object for css adjustments, only used with 2 handled-sliders
  7683. var css = {};
  7684. this._setValues($hndl, location); // TODO update to calculate based on values set to respective inputs??
  7685. if (isDbl) {
  7686. var isLeftHndl = this.handles.index($hndl) === 0,
  7687. //empty variable, will be used for min-height/width for fill bar
  7688. dim,
  7689. //percentage w/h of the handle compared to the slider bar
  7690. 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
  7691. if (isLeftHndl) {
  7692. //left or top percentage value to apply to the fill bar.
  7693. css[lOrT] = "".concat(movement, "%"); //calculate the new min-height/width for the fill bar.
  7694. 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
  7695. //plus, it means we don't care if 'dim' isNaN on init, it won't be in the future.
  7696. if (cb && typeof cb === 'function') {
  7697. cb();
  7698. } //this is only needed for the initialization of 2 handled sliders
  7699. } else {
  7700. //just caching the value of the left/bottom handle's left/top property
  7701. 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
  7702. //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
  7703. dim = movement - (isNaN(handlePos) ? (this.options.initialStart - this.options.start) / ((this.options.end - this.options.start) / 100) : handlePos) + handlePct;
  7704. } // assign the min-height/width to our css object
  7705. css["min-".concat(hOrW)] = "".concat(dim, "%");
  7706. }
  7707. this.$element.one('finished.zf.animate', function () {
  7708. /**
  7709. * Fires when the handle is done moving.
  7710. * @event Slider#moved
  7711. */
  7712. _this.$element.trigger('moved.zf.slider', [$hndl]);
  7713. }); //because we don't know exactly how the handle will be moved, check the amount of time it should take to move.
  7714. var moveTime = this.$element.data('dragging') ? 1000 / 60 : this.options.moveTime;
  7715. Move(moveTime, $hndl, function () {
  7716. // adjusting the left/top property of the handle, based on the percentage calculated above
  7717. // if movement isNaN, that is because the slider is hidden and we cannot determine handle width,
  7718. // fall back to next best guess.
  7719. if (isNaN(movement)) {
  7720. $hndl.css(lOrT, "".concat(pctOfBar * 100, "%"));
  7721. } else {
  7722. $hndl.css(lOrT, "".concat(movement, "%"));
  7723. }
  7724. if (!_this.options.doubleSided) {
  7725. //if single-handled, a simple method to expand the fill bar
  7726. _this.$fill.css(hOrW, "".concat(pctOfBar * 100, "%"));
  7727. } else {
  7728. //otherwise, use the css object we created above
  7729. _this.$fill.css(css);
  7730. }
  7731. });
  7732. /**
  7733. * Fires when the value has not been change for a given time.
  7734. * @event Slider#changed
  7735. */
  7736. clearTimeout(_this.timeout);
  7737. _this.timeout = setTimeout(function () {
  7738. _this.$element.trigger('changed.zf.slider', [$hndl]);
  7739. }, _this.options.changedDelay);
  7740. }
  7741. /**
  7742. * Sets the initial attribute for the slider element.
  7743. * @function
  7744. * @private
  7745. * @param {Number} idx - index of the current handle/input to use.
  7746. */
  7747. }, {
  7748. key: "_setInitAttr",
  7749. value: function _setInitAttr(idx) {
  7750. var initVal = idx === 0 ? this.options.initialStart : this.options.initialEnd;
  7751. var id = this.inputs.eq(idx).attr('id') || GetYoDigits(6, 'slider');
  7752. this.inputs.eq(idx).attr({
  7753. 'id': id,
  7754. 'max': this.options.end,
  7755. 'min': this.options.start,
  7756. 'step': this.options.step
  7757. });
  7758. this.inputs.eq(idx).val(initVal);
  7759. this.handles.eq(idx).attr({
  7760. 'role': 'slider',
  7761. 'aria-controls': id,
  7762. 'aria-valuemax': this.options.end,
  7763. 'aria-valuemin': this.options.start,
  7764. 'aria-valuenow': initVal,
  7765. 'aria-orientation': this.options.vertical ? 'vertical' : 'horizontal',
  7766. 'tabindex': 0
  7767. });
  7768. }
  7769. /**
  7770. * Sets the input and `aria-valuenow` values for the slider element.
  7771. * @function
  7772. * @private
  7773. * @param {jQuery} $handle - the currently selected handle.
  7774. * @param {Number} val - floating point of the new value.
  7775. */
  7776. }, {
  7777. key: "_setValues",
  7778. value: function _setValues($handle, val) {
  7779. var idx = this.options.doubleSided ? this.handles.index($handle) : 0;
  7780. this.inputs.eq(idx).val(val);
  7781. $handle.attr('aria-valuenow', val);
  7782. }
  7783. /**
  7784. * Handles events on the slider element.
  7785. * Calculates the new location of the current handle.
  7786. * If there are two handles and the bar was clicked, it determines which handle to move.
  7787. * @function
  7788. * @private
  7789. * @param {Object} e - the `event` object passed from the listener.
  7790. * @param {jQuery} $handle - the current handle to calculate for, if selected.
  7791. * @param {Number} val - floating point number for the new value of the slider.
  7792. * TODO clean this up, there's a lot of repeated code between this and the _setHandlePos fn.
  7793. */
  7794. }, {
  7795. key: "_handleEvent",
  7796. value: function _handleEvent(e, $handle, val) {
  7797. var value, hasVal;
  7798. if (!val) {
  7799. //click or drag events
  7800. e.preventDefault();
  7801. var _this = this,
  7802. vertical = this.options.vertical,
  7803. param = vertical ? 'height' : 'width',
  7804. direction = vertical ? 'top' : 'left',
  7805. eventOffset = vertical ? e.pageY : e.pageX,
  7806. halfOfHandle = this.$handle[0].getBoundingClientRect()[param] / 2,
  7807. barDim = this.$element[0].getBoundingClientRect()[param],
  7808. windowScroll = vertical ? $(window).scrollTop() : $(window).scrollLeft();
  7809. var elemOffset = this.$element.offset()[direction]; // touch events emulated by the touch util give position relative to screen, add window.scroll to event coordinates...
  7810. // best way to guess this is simulated is if clientY == pageY
  7811. if (e.clientY === e.pageY) {
  7812. eventOffset = eventOffset + windowScroll;
  7813. }
  7814. var eventFromBar = eventOffset - elemOffset;
  7815. var barXY;
  7816. if (eventFromBar < 0) {
  7817. barXY = 0;
  7818. } else if (eventFromBar > barDim) {
  7819. barXY = barDim;
  7820. } else {
  7821. barXY = eventFromBar;
  7822. }
  7823. var offsetPct = percent(barXY, barDim);
  7824. value = this._value(offsetPct); // turn everything around for RTL, yay math!
  7825. if (rtl() && !this.options.vertical) {
  7826. value = this.options.end - value;
  7827. }
  7828. value = _this._adjustValue(null, value); //boolean flag for the setHandlePos fn, specifically for vertical sliders
  7829. hasVal = false;
  7830. if (!$handle) {
  7831. //figure out which handle it is, pass it to the next function.
  7832. var firstHndlPos = absPosition(this.$handle, direction, barXY, param),
  7833. secndHndlPos = absPosition(this.$handle2, direction, barXY, param);
  7834. $handle = firstHndlPos <= secndHndlPos ? this.$handle : this.$handle2;
  7835. }
  7836. } else {
  7837. //change event on input
  7838. value = this._adjustValue(null, val);
  7839. hasVal = true;
  7840. }
  7841. this._setHandlePos($handle, value, hasVal);
  7842. }
  7843. /**
  7844. * Adjustes value for handle in regard to step value. returns adjusted value
  7845. * @function
  7846. * @private
  7847. * @param {jQuery} $handle - the selected handle.
  7848. * @param {Number} value - value to adjust. used if $handle is falsy
  7849. */
  7850. }, {
  7851. key: "_adjustValue",
  7852. value: function _adjustValue($handle, value) {
  7853. var val,
  7854. step = this.options.step,
  7855. div = parseFloat(step / 2),
  7856. left,
  7857. prev_val,
  7858. next_val;
  7859. if (!!$handle) {
  7860. val = parseFloat($handle.attr('aria-valuenow'));
  7861. } else {
  7862. val = value;
  7863. }
  7864. if (val >= 0) {
  7865. left = val % step;
  7866. } else {
  7867. left = step + val % step;
  7868. }
  7869. prev_val = val - left;
  7870. next_val = prev_val + step;
  7871. if (left === 0) {
  7872. return val;
  7873. }
  7874. val = val >= prev_val + div ? next_val : prev_val;
  7875. return val;
  7876. }
  7877. /**
  7878. * Adds event listeners to the slider elements.
  7879. * @function
  7880. * @private
  7881. */
  7882. }, {
  7883. key: "_events",
  7884. value: function _events() {
  7885. this._eventsForHandle(this.$handle);
  7886. if (this.handles[1]) {
  7887. this._eventsForHandle(this.$handle2);
  7888. }
  7889. }
  7890. /**
  7891. * Adds event listeners a particular handle
  7892. * @function
  7893. * @private
  7894. * @param {jQuery} $handle - the current handle to apply listeners to.
  7895. */
  7896. }, {
  7897. key: "_eventsForHandle",
  7898. value: function _eventsForHandle($handle) {
  7899. var _this = this,
  7900. curHandle;
  7901. var handleChangeEvent = function handleChangeEvent(e) {
  7902. var idx = _this.inputs.index($(this));
  7903. _this._handleEvent(e, _this.handles.eq(idx), $(this).val());
  7904. }; // IE only triggers the change event when the input loses focus which strictly follows the HTML specification
  7905. // listen for the enter key and trigger a change
  7906. // @see https://html.spec.whatwg.org/multipage/input.html#common-input-element-events
  7907. this.inputs.off('keyup.zf.slider').on('keyup.zf.slider', function (e) {
  7908. if (e.keyCode == 13) handleChangeEvent.call(this, e);
  7909. });
  7910. this.inputs.off('change.zf.slider').on('change.zf.slider', handleChangeEvent);
  7911. if (this.options.clickSelect) {
  7912. this.$element.off('click.zf.slider').on('click.zf.slider', function (e) {
  7913. if (_this.$element.data('dragging')) {
  7914. return false;
  7915. }
  7916. if (!$(e.target).is('[data-slider-handle]')) {
  7917. if (_this.options.doubleSided) {
  7918. _this._handleEvent(e);
  7919. } else {
  7920. _this._handleEvent(e, _this.$handle);
  7921. }
  7922. }
  7923. });
  7924. }
  7925. if (this.options.draggable) {
  7926. this.handles.addTouch();
  7927. var $body = $('body');
  7928. $handle.off('mousedown.zf.slider').on('mousedown.zf.slider', function (e) {
  7929. $handle.addClass('is-dragging');
  7930. _this.$fill.addClass('is-dragging'); //
  7931. _this.$element.data('dragging', true);
  7932. curHandle = $(e.currentTarget);
  7933. $body.on('mousemove.zf.slider', function (e) {
  7934. e.preventDefault();
  7935. _this._handleEvent(e, curHandle);
  7936. }).on('mouseup.zf.slider', function (e) {
  7937. _this._handleEvent(e, curHandle);
  7938. $handle.removeClass('is-dragging');
  7939. _this.$fill.removeClass('is-dragging');
  7940. _this.$element.data('dragging', false);
  7941. $body.off('mousemove.zf.slider mouseup.zf.slider');
  7942. });
  7943. }) // prevent events triggered by touch
  7944. .on('selectstart.zf.slider touchmove.zf.slider', function (e) {
  7945. e.preventDefault();
  7946. });
  7947. }
  7948. $handle.off('keydown.zf.slider').on('keydown.zf.slider', function (e) {
  7949. var _$handle = $(this),
  7950. idx = _this.options.doubleSided ? _this.handles.index(_$handle) : 0,
  7951. oldValue = parseFloat(_this.inputs.eq(idx).val()),
  7952. newValue; // handle keyboard event with keyboard util
  7953. Keyboard.handleKey(e, 'Slider', {
  7954. decrease: function decrease() {
  7955. newValue = oldValue - _this.options.step;
  7956. },
  7957. increase: function increase() {
  7958. newValue = oldValue + _this.options.step;
  7959. },
  7960. decrease_fast: function decrease_fast() {
  7961. newValue = oldValue - _this.options.step * 10;
  7962. },
  7963. increase_fast: function increase_fast() {
  7964. newValue = oldValue + _this.options.step * 10;
  7965. },
  7966. min: function min() {
  7967. newValue = _this.options.start;
  7968. },
  7969. max: function max() {
  7970. newValue = _this.options.end;
  7971. },
  7972. handled: function handled() {
  7973. // only set handle pos when event was handled specially
  7974. e.preventDefault();
  7975. _this._setHandlePos(_$handle, newValue, true);
  7976. }
  7977. });
  7978. /*if (newValue) { // if pressed key has special function, update value
  7979. e.preventDefault();
  7980. _this._setHandlePos(_$handle, newValue);
  7981. }*/
  7982. });
  7983. }
  7984. /**
  7985. * Destroys the slider plugin.
  7986. */
  7987. }, {
  7988. key: "_destroy",
  7989. value: function _destroy() {
  7990. this.handles.off('.zf.slider');
  7991. this.inputs.off('.zf.slider');
  7992. this.$element.off('.zf.slider');
  7993. clearTimeout(this.timeout);
  7994. }
  7995. }]);
  7996. return Slider;
  7997. }(Plugin);
  7998. Slider.defaults = {
  7999. /**
  8000. * Minimum value for the slider scale.
  8001. * @option
  8002. * @type {number}
  8003. * @default 0
  8004. */
  8005. start: 0,
  8006. /**
  8007. * Maximum value for the slider scale.
  8008. * @option
  8009. * @type {number}
  8010. * @default 100
  8011. */
  8012. end: 100,
  8013. /**
  8014. * Minimum value change per change event.
  8015. * @option
  8016. * @type {number}
  8017. * @default 1
  8018. */
  8019. step: 1,
  8020. /**
  8021. * Value at which the handle/input *(left handle/first input)* should be set to on initialization.
  8022. * @option
  8023. * @type {number}
  8024. * @default 0
  8025. */
  8026. initialStart: 0,
  8027. /**
  8028. * Value at which the right handle/second input should be set to on initialization.
  8029. * @option
  8030. * @type {number}
  8031. * @default 100
  8032. */
  8033. initialEnd: 100,
  8034. /**
  8035. * Allows the input to be located outside the container and visible. Set to by the JS
  8036. * @option
  8037. * @type {boolean}
  8038. * @default false
  8039. */
  8040. binding: false,
  8041. /**
  8042. * Allows the user to click/tap on the slider bar to select a value.
  8043. * @option
  8044. * @type {boolean}
  8045. * @default true
  8046. */
  8047. clickSelect: true,
  8048. /**
  8049. * Set to true and use the `vertical` class to change alignment to vertical.
  8050. * @option
  8051. * @type {boolean}
  8052. * @default false
  8053. */
  8054. vertical: false,
  8055. /**
  8056. * Allows the user to drag the slider handle(s) to select a value.
  8057. * @option
  8058. * @type {boolean}
  8059. * @default true
  8060. */
  8061. draggable: true,
  8062. /**
  8063. * Disables the slider and prevents event listeners from being applied. Double checked by JS with `disabledClass`.
  8064. * @option
  8065. * @type {boolean}
  8066. * @default false
  8067. */
  8068. disabled: false,
  8069. /**
  8070. * Allows the use of two handles. Double checked by the JS. Changes some logic handling.
  8071. * @option
  8072. * @type {boolean}
  8073. * @default false
  8074. */
  8075. doubleSided: false,
  8076. /**
  8077. * Potential future feature.
  8078. */
  8079. // steps: 100,
  8080. /**
  8081. * Number of decimal places the plugin should go to for floating point precision.
  8082. * @option
  8083. * @type {number}
  8084. * @default 2
  8085. */
  8086. decimal: 2,
  8087. /**
  8088. * Time delay for dragged elements.
  8089. */
  8090. // dragDelay: 0,
  8091. /**
  8092. * 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.
  8093. * @option
  8094. * @type {number}
  8095. * @default 200
  8096. */
  8097. moveTime: 200,
  8098. //update this if changing the transition time in the sass
  8099. /**
  8100. * Class applied to disabled sliders.
  8101. * @option
  8102. * @type {string}
  8103. * @default 'disabled'
  8104. */
  8105. disabledClass: 'disabled',
  8106. /**
  8107. * Will invert the default layout for a vertical<span data-tooltip title="who would do this???"> </span>slider.
  8108. * @option
  8109. * @type {boolean}
  8110. * @default false
  8111. */
  8112. invertVertical: false,
  8113. /**
  8114. * Milliseconds before the `changed.zf-slider` event is triggered after value change.
  8115. * @option
  8116. * @type {number}
  8117. * @default 500
  8118. */
  8119. changedDelay: 500,
  8120. /**
  8121. * Basevalue for non-linear sliders
  8122. * @option
  8123. * @type {number}
  8124. * @default 5
  8125. */
  8126. nonLinearBase: 5,
  8127. /**
  8128. * Basevalue for non-linear sliders, possible values are: `'linear'`, `'pow'` & `'log'`. Pow and Log use the nonLinearBase setting.
  8129. * @option
  8130. * @type {string}
  8131. * @default 'linear'
  8132. */
  8133. positionValueFunction: 'linear'
  8134. };
  8135. function percent(frac, num) {
  8136. return frac / num;
  8137. }
  8138. function absPosition($handle, dir, clickPos, param) {
  8139. return Math.abs($handle.position()[dir] + $handle[param]() / 2 - clickPos);
  8140. }
  8141. function baseLog(base, value) {
  8142. return Math.log(value) / Math.log(base);
  8143. }
  8144. /**
  8145. * Sticky module.
  8146. * @module foundation.sticky
  8147. * @requires foundation.util.triggers
  8148. * @requires foundation.util.mediaQuery
  8149. */
  8150. var Sticky =
  8151. /*#__PURE__*/
  8152. function (_Plugin) {
  8153. _inherits(Sticky, _Plugin);
  8154. function Sticky() {
  8155. _classCallCheck(this, Sticky);
  8156. return _possibleConstructorReturn(this, _getPrototypeOf(Sticky).apply(this, arguments));
  8157. }
  8158. _createClass(Sticky, [{
  8159. key: "_setup",
  8160. /**
  8161. * Creates a new instance of a sticky thing.
  8162. * @class
  8163. * @name Sticky
  8164. * @param {jQuery} element - jQuery object to make sticky.
  8165. * @param {Object} options - options object passed when creating the element programmatically.
  8166. */
  8167. value: function _setup(element, options) {
  8168. this.$element = element;
  8169. this.options = $.extend({}, Sticky.defaults, this.$element.data(), options);
  8170. this.className = 'Sticky'; // ie9 back compat
  8171. // Triggers init is idempotent, just need to make sure it is initialized
  8172. Triggers.init($);
  8173. this._init();
  8174. }
  8175. /**
  8176. * Initializes the sticky element by adding classes, getting/setting dimensions, breakpoints and attributes
  8177. * @function
  8178. * @private
  8179. */
  8180. }, {
  8181. key: "_init",
  8182. value: function _init() {
  8183. MediaQuery._init();
  8184. var $parent = this.$element.parent('[data-sticky-container]'),
  8185. id = this.$element[0].id || GetYoDigits(6, 'sticky'),
  8186. _this = this;
  8187. if ($parent.length) {
  8188. this.$container = $parent;
  8189. } else {
  8190. this.wasWrapped = true;
  8191. this.$element.wrap(this.options.container);
  8192. this.$container = this.$element.parent();
  8193. }
  8194. this.$container.addClass(this.options.containerClass);
  8195. this.$element.addClass(this.options.stickyClass).attr({
  8196. 'data-resize': id,
  8197. 'data-mutate': id
  8198. });
  8199. if (this.options.anchor !== '') {
  8200. $('#' + _this.options.anchor).attr({
  8201. 'data-mutate': id
  8202. });
  8203. }
  8204. this.scrollCount = this.options.checkEvery;
  8205. this.isStuck = false;
  8206. this.onLoadListener = onLoad($(window), function () {
  8207. //We calculate the container height to have correct values for anchor points offset calculation.
  8208. _this.containerHeight = _this.$element.css("display") == "none" ? 0 : _this.$element[0].getBoundingClientRect().height;
  8209. _this.$container.css('height', _this.containerHeight);
  8210. _this.elemHeight = _this.containerHeight;
  8211. if (_this.options.anchor !== '') {
  8212. _this.$anchor = $('#' + _this.options.anchor);
  8213. } else {
  8214. _this._parsePoints();
  8215. }
  8216. _this._setSizes(function () {
  8217. var scroll = window.pageYOffset;
  8218. _this._calc(false, scroll); //Unstick the element will ensure that proper classes are set.
  8219. if (!_this.isStuck) {
  8220. _this._removeSticky(scroll >= _this.topPoint ? false : true);
  8221. }
  8222. });
  8223. _this._events(id.split('-').reverse().join('-'));
  8224. });
  8225. }
  8226. /**
  8227. * If using multiple elements as anchors, calculates the top and bottom pixel values the sticky thing should stick and unstick on.
  8228. * @function
  8229. * @private
  8230. */
  8231. }, {
  8232. key: "_parsePoints",
  8233. value: function _parsePoints() {
  8234. var top = this.options.topAnchor == "" ? 1 : this.options.topAnchor,
  8235. btm = this.options.btmAnchor == "" ? document.documentElement.scrollHeight : this.options.btmAnchor,
  8236. pts = [top, btm],
  8237. breaks = {};
  8238. for (var i = 0, len = pts.length; i < len && pts[i]; i++) {
  8239. var pt;
  8240. if (typeof pts[i] === 'number') {
  8241. pt = pts[i];
  8242. } else {
  8243. var place = pts[i].split(':'),
  8244. anchor = $("#".concat(place[0]));
  8245. pt = anchor.offset().top;
  8246. if (place[1] && place[1].toLowerCase() === 'bottom') {
  8247. pt += anchor[0].getBoundingClientRect().height;
  8248. }
  8249. }
  8250. breaks[i] = pt;
  8251. }
  8252. this.points = breaks;
  8253. return;
  8254. }
  8255. /**
  8256. * Adds event handlers for the scrolling element.
  8257. * @private
  8258. * @param {String} id - pseudo-random id for unique scroll event listener.
  8259. */
  8260. }, {
  8261. key: "_events",
  8262. value: function _events(id) {
  8263. var _this = this,
  8264. scrollListener = this.scrollListener = "scroll.zf.".concat(id);
  8265. if (this.isOn) {
  8266. return;
  8267. }
  8268. if (this.canStick) {
  8269. this.isOn = true;
  8270. $(window).off(scrollListener).on(scrollListener, function (e) {
  8271. if (_this.scrollCount === 0) {
  8272. _this.scrollCount = _this.options.checkEvery;
  8273. _this._setSizes(function () {
  8274. _this._calc(false, window.pageYOffset);
  8275. });
  8276. } else {
  8277. _this.scrollCount--;
  8278. _this._calc(false, window.pageYOffset);
  8279. }
  8280. });
  8281. }
  8282. this.$element.off('resizeme.zf.trigger').on('resizeme.zf.trigger', function (e, el) {
  8283. _this._eventsHandler(id);
  8284. });
  8285. this.$element.on('mutateme.zf.trigger', function (e, el) {
  8286. _this._eventsHandler(id);
  8287. });
  8288. if (this.$anchor) {
  8289. this.$anchor.on('mutateme.zf.trigger', function (e, el) {
  8290. _this._eventsHandler(id);
  8291. });
  8292. }
  8293. }
  8294. /**
  8295. * Handler for events.
  8296. * @private
  8297. * @param {String} id - pseudo-random id for unique scroll event listener.
  8298. */
  8299. }, {
  8300. key: "_eventsHandler",
  8301. value: function _eventsHandler(id) {
  8302. var _this = this,
  8303. scrollListener = this.scrollListener = "scroll.zf.".concat(id);
  8304. _this._setSizes(function () {
  8305. _this._calc(false);
  8306. if (_this.canStick) {
  8307. if (!_this.isOn) {
  8308. _this._events(id);
  8309. }
  8310. } else if (_this.isOn) {
  8311. _this._pauseListeners(scrollListener);
  8312. }
  8313. });
  8314. }
  8315. /**
  8316. * Removes event handlers for scroll and change events on anchor.
  8317. * @fires Sticky#pause
  8318. * @param {String} scrollListener - unique, namespaced scroll listener attached to `window`
  8319. */
  8320. }, {
  8321. key: "_pauseListeners",
  8322. value: function _pauseListeners(scrollListener) {
  8323. this.isOn = false;
  8324. $(window).off(scrollListener);
  8325. /**
  8326. * Fires when the plugin is paused due to resize event shrinking the view.
  8327. * @event Sticky#pause
  8328. * @private
  8329. */
  8330. this.$element.trigger('pause.zf.sticky');
  8331. }
  8332. /**
  8333. * Called on every `scroll` event and on `_init`
  8334. * fires functions based on booleans and cached values
  8335. * @param {Boolean} checkSizes - true if plugin should recalculate sizes and breakpoints.
  8336. * @param {Number} scroll - current scroll position passed from scroll event cb function. If not passed, defaults to `window.pageYOffset`.
  8337. */
  8338. }, {
  8339. key: "_calc",
  8340. value: function _calc(checkSizes, scroll) {
  8341. if (checkSizes) {
  8342. this._setSizes();
  8343. }
  8344. if (!this.canStick) {
  8345. if (this.isStuck) {
  8346. this._removeSticky(true);
  8347. }
  8348. return false;
  8349. }
  8350. if (!scroll) {
  8351. scroll = window.pageYOffset;
  8352. }
  8353. if (scroll >= this.topPoint) {
  8354. if (scroll <= this.bottomPoint) {
  8355. if (!this.isStuck) {
  8356. this._setSticky();
  8357. }
  8358. } else {
  8359. if (this.isStuck) {
  8360. this._removeSticky(false);
  8361. }
  8362. }
  8363. } else {
  8364. if (this.isStuck) {
  8365. this._removeSticky(true);
  8366. }
  8367. }
  8368. }
  8369. /**
  8370. * Causes the $element to become stuck.
  8371. * Adds `position: fixed;`, and helper classes.
  8372. * @fires Sticky#stuckto
  8373. * @function
  8374. * @private
  8375. */
  8376. }, {
  8377. key: "_setSticky",
  8378. value: function _setSticky() {
  8379. var _this = this,
  8380. stickTo = this.options.stickTo,
  8381. mrgn = stickTo === 'top' ? 'marginTop' : 'marginBottom',
  8382. notStuckTo = stickTo === 'top' ? 'bottom' : 'top',
  8383. css = {};
  8384. css[mrgn] = "".concat(this.options[mrgn], "em");
  8385. css[stickTo] = 0;
  8386. css[notStuckTo] = 'auto';
  8387. this.isStuck = true;
  8388. this.$element.removeClass("is-anchored is-at-".concat(notStuckTo)).addClass("is-stuck is-at-".concat(stickTo)).css(css)
  8389. /**
  8390. * Fires when the $element has become `position: fixed;`
  8391. * Namespaced to `top` or `bottom`, e.g. `sticky.zf.stuckto:top`
  8392. * @event Sticky#stuckto
  8393. */
  8394. .trigger("sticky.zf.stuckto:".concat(stickTo));
  8395. this.$element.on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", function () {
  8396. _this._setSizes();
  8397. });
  8398. }
  8399. /**
  8400. * Causes the $element to become unstuck.
  8401. * Removes `position: fixed;`, and helper classes.
  8402. * Adds other helper classes.
  8403. * @param {Boolean} isTop - tells the function if the $element should anchor to the top or bottom of its $anchor element.
  8404. * @fires Sticky#unstuckfrom
  8405. * @private
  8406. */
  8407. }, {
  8408. key: "_removeSticky",
  8409. value: function _removeSticky(isTop) {
  8410. var stickTo = this.options.stickTo,
  8411. stickToTop = stickTo === 'top',
  8412. css = {},
  8413. anchorPt = (this.points ? this.points[1] - this.points[0] : this.anchorHeight) - this.elemHeight,
  8414. mrgn = stickToTop ? 'marginTop' : 'marginBottom',
  8415. topOrBottom = isTop ? 'top' : 'bottom';
  8416. css[mrgn] = 0;
  8417. css['bottom'] = 'auto';
  8418. if (isTop) {
  8419. css['top'] = 0;
  8420. } else {
  8421. css['top'] = anchorPt;
  8422. }
  8423. this.isStuck = false;
  8424. this.$element.removeClass("is-stuck is-at-".concat(stickTo)).addClass("is-anchored is-at-".concat(topOrBottom)).css(css)
  8425. /**
  8426. * Fires when the $element has become anchored.
  8427. * Namespaced to `top` or `bottom`, e.g. `sticky.zf.unstuckfrom:bottom`
  8428. * @event Sticky#unstuckfrom
  8429. */
  8430. .trigger("sticky.zf.unstuckfrom:".concat(topOrBottom));
  8431. }
  8432. /**
  8433. * Sets the $element and $container sizes for plugin.
  8434. * Calls `_setBreakPoints`.
  8435. * @param {Function} cb - optional callback function to fire on completion of `_setBreakPoints`.
  8436. * @private
  8437. */
  8438. }, {
  8439. key: "_setSizes",
  8440. value: function _setSizes(cb) {
  8441. this.canStick = MediaQuery.is(this.options.stickyOn);
  8442. if (!this.canStick) {
  8443. if (cb && typeof cb === 'function') {
  8444. cb();
  8445. }
  8446. }
  8447. var newElemWidth = this.$container[0].getBoundingClientRect().width,
  8448. comp = window.getComputedStyle(this.$container[0]),
  8449. pdngl = parseInt(comp['padding-left'], 10),
  8450. pdngr = parseInt(comp['padding-right'], 10);
  8451. if (this.$anchor && this.$anchor.length) {
  8452. this.anchorHeight = this.$anchor[0].getBoundingClientRect().height;
  8453. } else {
  8454. this._parsePoints();
  8455. }
  8456. this.$element.css({
  8457. 'max-width': "".concat(newElemWidth - pdngl - pdngr, "px")
  8458. });
  8459. var newContainerHeight = this.$element[0].getBoundingClientRect().height || this.containerHeight;
  8460. if (this.$element.css("display") == "none") {
  8461. newContainerHeight = 0;
  8462. }
  8463. this.containerHeight = newContainerHeight;
  8464. this.$container.css({
  8465. height: newContainerHeight
  8466. });
  8467. this.elemHeight = newContainerHeight;
  8468. if (!this.isStuck) {
  8469. if (this.$element.hasClass('is-at-bottom')) {
  8470. var anchorPt = (this.points ? this.points[1] - this.$container.offset().top : this.anchorHeight) - this.elemHeight;
  8471. this.$element.css('top', anchorPt);
  8472. }
  8473. }
  8474. this._setBreakPoints(newContainerHeight, function () {
  8475. if (cb && typeof cb === 'function') {
  8476. cb();
  8477. }
  8478. });
  8479. }
  8480. /**
  8481. * Sets the upper and lower breakpoints for the element to become sticky/unsticky.
  8482. * @param {Number} elemHeight - px value for sticky.$element height, calculated by `_setSizes`.
  8483. * @param {Function} cb - optional callback function to be called on completion.
  8484. * @private
  8485. */
  8486. }, {
  8487. key: "_setBreakPoints",
  8488. value: function _setBreakPoints(elemHeight, cb) {
  8489. if (!this.canStick) {
  8490. if (cb && typeof cb === 'function') {
  8491. cb();
  8492. } else {
  8493. return false;
  8494. }
  8495. }
  8496. var mTop = emCalc(this.options.marginTop),
  8497. mBtm = emCalc(this.options.marginBottom),
  8498. topPoint = this.points ? this.points[0] : this.$anchor.offset().top,
  8499. bottomPoint = this.points ? this.points[1] : topPoint + this.anchorHeight,
  8500. // topPoint = this.$anchor.offset().top || this.points[0],
  8501. // bottomPoint = topPoint + this.anchorHeight || this.points[1],
  8502. winHeight = window.innerHeight;
  8503. if (this.options.stickTo === 'top') {
  8504. topPoint -= mTop;
  8505. bottomPoint -= elemHeight + mTop;
  8506. } else if (this.options.stickTo === 'bottom') {
  8507. topPoint -= winHeight - (elemHeight + mBtm);
  8508. bottomPoint -= winHeight - mBtm;
  8509. }
  8510. this.topPoint = topPoint;
  8511. this.bottomPoint = bottomPoint;
  8512. if (cb && typeof cb === 'function') {
  8513. cb();
  8514. }
  8515. }
  8516. /**
  8517. * Destroys the current sticky element.
  8518. * Resets the element to the top position first.
  8519. * Removes event listeners, JS-added css properties and classes, and unwraps the $element if the JS added the $container.
  8520. * @function
  8521. */
  8522. }, {
  8523. key: "_destroy",
  8524. value: function _destroy() {
  8525. this._removeSticky(true);
  8526. this.$element.removeClass("".concat(this.options.stickyClass, " is-anchored is-at-top")).css({
  8527. height: '',
  8528. top: '',
  8529. bottom: '',
  8530. 'max-width': ''
  8531. }).off('resizeme.zf.trigger').off('mutateme.zf.trigger');
  8532. if (this.$anchor && this.$anchor.length) {
  8533. this.$anchor.off('change.zf.sticky');
  8534. }
  8535. if (this.scrollListener) $(window).off(this.scrollListener);
  8536. if (this.onLoadListener) $(window).off(this.onLoadListener);
  8537. if (this.wasWrapped) {
  8538. this.$element.unwrap();
  8539. } else {
  8540. this.$container.removeClass(this.options.containerClass).css({
  8541. height: ''
  8542. });
  8543. }
  8544. }
  8545. }]);
  8546. return Sticky;
  8547. }(Plugin);
  8548. Sticky.defaults = {
  8549. /**
  8550. * Customizable container template. Add your own classes for styling and sizing.
  8551. * @option
  8552. * @type {string}
  8553. * @default '&lt;div data-sticky-container&gt;&lt;/div&gt;'
  8554. */
  8555. container: '<div data-sticky-container></div>',
  8556. /**
  8557. * Location in the view the element sticks to. Can be `'top'` or `'bottom'`.
  8558. * @option
  8559. * @type {string}
  8560. * @default 'top'
  8561. */
  8562. stickTo: 'top',
  8563. /**
  8564. * If anchored to a single element, the id of that element.
  8565. * @option
  8566. * @type {string}
  8567. * @default ''
  8568. */
  8569. anchor: '',
  8570. /**
  8571. * If using more than one element as anchor points, the id of the top anchor.
  8572. * @option
  8573. * @type {string}
  8574. * @default ''
  8575. */
  8576. topAnchor: '',
  8577. /**
  8578. * If using more than one element as anchor points, the id of the bottom anchor.
  8579. * @option
  8580. * @type {string}
  8581. * @default ''
  8582. */
  8583. btmAnchor: '',
  8584. /**
  8585. * Margin, in `em`'s to apply to the top of the element when it becomes sticky.
  8586. * @option
  8587. * @type {number}
  8588. * @default 1
  8589. */
  8590. marginTop: 1,
  8591. /**
  8592. * Margin, in `em`'s to apply to the bottom of the element when it becomes sticky.
  8593. * @option
  8594. * @type {number}
  8595. * @default 1
  8596. */
  8597. marginBottom: 1,
  8598. /**
  8599. * Breakpoint string that is the minimum screen size an element should become sticky.
  8600. * @option
  8601. * @type {string}
  8602. * @default 'medium'
  8603. */
  8604. stickyOn: 'medium',
  8605. /**
  8606. * Class applied to sticky element, and removed on destruction. Foundation defaults to `sticky`.
  8607. * @option
  8608. * @type {string}
  8609. * @default 'sticky'
  8610. */
  8611. stickyClass: 'sticky',
  8612. /**
  8613. * Class applied to sticky container. Foundation defaults to `sticky-container`.
  8614. * @option
  8615. * @type {string}
  8616. * @default 'sticky-container'
  8617. */
  8618. containerClass: 'sticky-container',
  8619. /**
  8620. * 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.
  8621. * @option
  8622. * @type {number}
  8623. * @default -1
  8624. */
  8625. checkEvery: -1
  8626. };
  8627. /**
  8628. * Helper function to calculate em values
  8629. * @param Number {em} - number of em's to calculate into pixels
  8630. */
  8631. function emCalc(em) {
  8632. return parseInt(window.getComputedStyle(document.body, null).fontSize, 10) * em;
  8633. }
  8634. /**
  8635. * Tabs module.
  8636. * @module foundation.tabs
  8637. * @requires foundation.util.keyboard
  8638. * @requires foundation.util.imageLoader if tabs contain images
  8639. */
  8640. var Tabs =
  8641. /*#__PURE__*/
  8642. function (_Plugin) {
  8643. _inherits(Tabs, _Plugin);
  8644. function Tabs() {
  8645. _classCallCheck(this, Tabs);
  8646. return _possibleConstructorReturn(this, _getPrototypeOf(Tabs).apply(this, arguments));
  8647. }
  8648. _createClass(Tabs, [{
  8649. key: "_setup",
  8650. /**
  8651. * Creates a new instance of tabs.
  8652. * @class
  8653. * @name Tabs
  8654. * @fires Tabs#init
  8655. * @param {jQuery} element - jQuery object to make into tabs.
  8656. * @param {Object} options - Overrides to the default plugin settings.
  8657. */
  8658. value: function _setup(element, options) {
  8659. this.$element = element;
  8660. this.options = $.extend({}, Tabs.defaults, this.$element.data(), options);
  8661. this.className = 'Tabs'; // ie9 back compat
  8662. this._init();
  8663. Keyboard.register('Tabs', {
  8664. 'ENTER': 'open',
  8665. 'SPACE': 'open',
  8666. 'ARROW_RIGHT': 'next',
  8667. 'ARROW_UP': 'previous',
  8668. 'ARROW_DOWN': 'next',
  8669. 'ARROW_LEFT': 'previous' // 'TAB': 'next',
  8670. // 'SHIFT_TAB': 'previous'
  8671. });
  8672. }
  8673. /**
  8674. * Initializes the tabs by showing and focusing (if autoFocus=true) the preset active tab.
  8675. * @private
  8676. */
  8677. }, {
  8678. key: "_init",
  8679. value: function _init() {
  8680. var _this2 = this;
  8681. var _this = this;
  8682. this._isInitializing = true;
  8683. this.$element.attr({
  8684. 'role': 'tablist'
  8685. });
  8686. this.$tabTitles = this.$element.find(".".concat(this.options.linkClass));
  8687. this.$tabContent = $("[data-tabs-content=\"".concat(this.$element[0].id, "\"]"));
  8688. this.$tabTitles.each(function () {
  8689. var $elem = $(this),
  8690. $link = $elem.find('a'),
  8691. isActive = $elem.hasClass("".concat(_this.options.linkActiveClass)),
  8692. hash = $link.attr('data-tabs-target') || $link[0].hash.slice(1),
  8693. linkId = $link[0].id ? $link[0].id : "".concat(hash, "-label"),
  8694. $tabContent = $("#".concat(hash));
  8695. $elem.attr({
  8696. 'role': 'presentation'
  8697. });
  8698. $link.attr({
  8699. 'role': 'tab',
  8700. 'aria-controls': hash,
  8701. 'aria-selected': isActive,
  8702. 'id': linkId,
  8703. 'tabindex': isActive ? '0' : '-1'
  8704. });
  8705. $tabContent.attr({
  8706. 'role': 'tabpanel',
  8707. 'aria-labelledby': linkId
  8708. }); // Save up the initial hash to return to it later when going back in history
  8709. if (isActive) {
  8710. _this._initialAnchor = "#".concat(hash);
  8711. }
  8712. if (!isActive) {
  8713. $tabContent.attr('aria-hidden', 'true');
  8714. }
  8715. if (isActive && _this.options.autoFocus) {
  8716. _this.onLoadListener = onLoad($(window), function () {
  8717. $('html, body').animate({
  8718. scrollTop: $elem.offset().top
  8719. }, _this.options.deepLinkSmudgeDelay, function () {
  8720. $link.focus();
  8721. });
  8722. });
  8723. }
  8724. });
  8725. if (this.options.matchHeight) {
  8726. var $images = this.$tabContent.find('img');
  8727. if ($images.length) {
  8728. onImagesLoaded($images, this._setHeight.bind(this));
  8729. } else {
  8730. this._setHeight();
  8731. }
  8732. } // Current context-bound function to open tabs on page load or history hashchange
  8733. this._checkDeepLink = function () {
  8734. var anchor = window.location.hash;
  8735. if (!anchor.length) {
  8736. // If we are still initializing and there is no anchor, then there is nothing to do
  8737. if (_this2._isInitializing) return; // Otherwise, move to the initial anchor
  8738. if (_this2._initialAnchor) anchor = _this2._initialAnchor;
  8739. }
  8740. var $anchor = anchor && $(anchor);
  8741. var $link = anchor && _this2.$element.find('[href$="' + anchor + '"]'); // Whether the anchor element that has been found is part of this element
  8742. var isOwnAnchor = !!($anchor.length && $link.length); // If there is an anchor for the hash, select it
  8743. if ($anchor && $anchor.length && $link && $link.length) {
  8744. _this2.selectTab($anchor, true);
  8745. } // Otherwise, collapse everything
  8746. else {
  8747. _this2._collapse();
  8748. }
  8749. if (isOwnAnchor) {
  8750. // Roll up a little to show the titles
  8751. if (_this2.options.deepLinkSmudge) {
  8752. var offset = _this2.$element.offset();
  8753. $('html, body').animate({
  8754. scrollTop: offset.top
  8755. }, _this2.options.deepLinkSmudgeDelay);
  8756. }
  8757. /**
  8758. * Fires when the plugin has deeplinked at pageload
  8759. * @event Tabs#deeplink
  8760. */
  8761. _this2.$element.trigger('deeplink.zf.tabs', [$link, $anchor]);
  8762. }
  8763. }; //use browser to open a tab, if it exists in this tabset
  8764. if (this.options.deepLink) {
  8765. this._checkDeepLink();
  8766. }
  8767. this._events();
  8768. this._isInitializing = false;
  8769. }
  8770. /**
  8771. * Adds event handlers for items within the tabs.
  8772. * @private
  8773. */
  8774. }, {
  8775. key: "_events",
  8776. value: function _events() {
  8777. this._addKeyHandler();
  8778. this._addClickHandler();
  8779. this._setHeightMqHandler = null;
  8780. if (this.options.matchHeight) {
  8781. this._setHeightMqHandler = this._setHeight.bind(this);
  8782. $(window).on('changed.zf.mediaquery', this._setHeightMqHandler);
  8783. }
  8784. if (this.options.deepLink) {
  8785. $(window).on('hashchange', this._checkDeepLink);
  8786. }
  8787. }
  8788. /**
  8789. * Adds click handlers for items within the tabs.
  8790. * @private
  8791. */
  8792. }, {
  8793. key: "_addClickHandler",
  8794. value: function _addClickHandler() {
  8795. var _this = this;
  8796. this.$element.off('click.zf.tabs').on('click.zf.tabs', ".".concat(this.options.linkClass), function (e) {
  8797. e.preventDefault();
  8798. e.stopPropagation();
  8799. _this._handleTabChange($(this));
  8800. });
  8801. }
  8802. /**
  8803. * Adds keyboard event handlers for items within the tabs.
  8804. * @private
  8805. */
  8806. }, {
  8807. key: "_addKeyHandler",
  8808. value: function _addKeyHandler() {
  8809. var _this = this;
  8810. this.$tabTitles.off('keydown.zf.tabs').on('keydown.zf.tabs', function (e) {
  8811. if (e.which === 9) return;
  8812. var $element = $(this),
  8813. $elements = $element.parent('ul').children('li'),
  8814. $prevElement,
  8815. $nextElement;
  8816. $elements.each(function (i) {
  8817. if ($(this).is($element)) {
  8818. if (_this.options.wrapOnKeys) {
  8819. $prevElement = i === 0 ? $elements.last() : $elements.eq(i - 1);
  8820. $nextElement = i === $elements.length - 1 ? $elements.first() : $elements.eq(i + 1);
  8821. } else {
  8822. $prevElement = $elements.eq(Math.max(0, i - 1));
  8823. $nextElement = $elements.eq(Math.min(i + 1, $elements.length - 1));
  8824. }
  8825. return;
  8826. }
  8827. }); // handle keyboard event with keyboard util
  8828. Keyboard.handleKey(e, 'Tabs', {
  8829. open: function open() {
  8830. $element.find('[role="tab"]').focus();
  8831. _this._handleTabChange($element);
  8832. },
  8833. previous: function previous() {
  8834. $prevElement.find('[role="tab"]').focus();
  8835. _this._handleTabChange($prevElement);
  8836. },
  8837. next: function next() {
  8838. $nextElement.find('[role="tab"]').focus();
  8839. _this._handleTabChange($nextElement);
  8840. },
  8841. handled: function handled() {
  8842. e.stopPropagation();
  8843. e.preventDefault();
  8844. }
  8845. });
  8846. });
  8847. }
  8848. /**
  8849. * Opens the tab `$targetContent` defined by `$target`. Collapses active tab.
  8850. * @param {jQuery} $target - Tab to open.
  8851. * @param {boolean} historyHandled - browser has already handled a history update
  8852. * @fires Tabs#change
  8853. * @function
  8854. */
  8855. }, {
  8856. key: "_handleTabChange",
  8857. value: function _handleTabChange($target, historyHandled) {
  8858. // With `activeCollapse`, if the target is the active Tab, collapse it.
  8859. if ($target.hasClass("".concat(this.options.linkActiveClass))) {
  8860. if (this.options.activeCollapse) {
  8861. this._collapse();
  8862. }
  8863. return;
  8864. }
  8865. var $oldTab = this.$element.find(".".concat(this.options.linkClass, ".").concat(this.options.linkActiveClass)),
  8866. $tabLink = $target.find('[role="tab"]'),
  8867. target = $tabLink.attr('data-tabs-target'),
  8868. anchor = target && target.length ? "#".concat(target) : $tabLink[0].hash,
  8869. $targetContent = this.$tabContent.find(anchor); //close old tab
  8870. this._collapseTab($oldTab); //open new tab
  8871. this._openTab($target); //either replace or update browser history
  8872. if (this.options.deepLink && !historyHandled) {
  8873. if (this.options.updateHistory) {
  8874. history.pushState({}, '', anchor);
  8875. } else {
  8876. history.replaceState({}, '', anchor);
  8877. }
  8878. }
  8879. /**
  8880. * Fires when the plugin has successfully changed tabs.
  8881. * @event Tabs#change
  8882. */
  8883. this.$element.trigger('change.zf.tabs', [$target, $targetContent]); //fire to children a mutation event
  8884. $targetContent.find("[data-mutate]").trigger("mutateme.zf.trigger");
  8885. }
  8886. /**
  8887. * Opens the tab `$targetContent` defined by `$target`.
  8888. * @param {jQuery} $target - Tab to open.
  8889. * @function
  8890. */
  8891. }, {
  8892. key: "_openTab",
  8893. value: function _openTab($target) {
  8894. var $tabLink = $target.find('[role="tab"]'),
  8895. hash = $tabLink.attr('data-tabs-target') || $tabLink[0].hash.slice(1),
  8896. $targetContent = this.$tabContent.find("#".concat(hash));
  8897. $target.addClass("".concat(this.options.linkActiveClass));
  8898. $tabLink.attr({
  8899. 'aria-selected': 'true',
  8900. 'tabindex': '0'
  8901. });
  8902. $targetContent.addClass("".concat(this.options.panelActiveClass)).removeAttr('aria-hidden');
  8903. }
  8904. /**
  8905. * Collapses `$targetContent` defined by `$target`.
  8906. * @param {jQuery} $target - Tab to collapse.
  8907. * @function
  8908. */
  8909. }, {
  8910. key: "_collapseTab",
  8911. value: function _collapseTab($target) {
  8912. var $target_anchor = $target.removeClass("".concat(this.options.linkActiveClass)).find('[role="tab"]').attr({
  8913. 'aria-selected': 'false',
  8914. 'tabindex': -1
  8915. });
  8916. $("#".concat($target_anchor.attr('aria-controls'))).removeClass("".concat(this.options.panelActiveClass)).attr({
  8917. 'aria-hidden': 'true'
  8918. });
  8919. }
  8920. /**
  8921. * Collapses the active Tab.
  8922. * @fires Tabs#collapse
  8923. * @function
  8924. */
  8925. }, {
  8926. key: "_collapse",
  8927. value: function _collapse() {
  8928. var $activeTab = this.$element.find(".".concat(this.options.linkClass, ".").concat(this.options.linkActiveClass));
  8929. if ($activeTab.length) {
  8930. this._collapseTab($activeTab);
  8931. /**
  8932. * Fires when the plugin has successfully collapsed tabs.
  8933. * @event Tabs#collapse
  8934. */
  8935. this.$element.trigger('collapse.zf.tabs', [$activeTab]);
  8936. }
  8937. }
  8938. /**
  8939. * Public method for selecting a content pane to display.
  8940. * @param {jQuery | String} elem - jQuery object or string of the id of the pane to display.
  8941. * @param {boolean} historyHandled - browser has already handled a history update
  8942. * @function
  8943. */
  8944. }, {
  8945. key: "selectTab",
  8946. value: function selectTab(elem, historyHandled) {
  8947. var idStr;
  8948. if (_typeof(elem) === 'object') {
  8949. idStr = elem[0].id;
  8950. } else {
  8951. idStr = elem;
  8952. }
  8953. if (idStr.indexOf('#') < 0) {
  8954. idStr = "#".concat(idStr);
  8955. }
  8956. var $target = this.$tabTitles.has("[href$=\"".concat(idStr, "\"]"));
  8957. this._handleTabChange($target, historyHandled);
  8958. }
  8959. }, {
  8960. key: "_setHeight",
  8961. /**
  8962. * Sets the height of each panel to the height of the tallest panel.
  8963. * If enabled in options, gets called on media query change.
  8964. * If loading content via external source, can be called directly or with _reflow.
  8965. * If enabled with `data-match-height="true"`, tabs sets to equal height
  8966. * @function
  8967. * @private
  8968. */
  8969. value: function _setHeight() {
  8970. var max = 0,
  8971. _this = this; // Lock down the `this` value for the root tabs object
  8972. this.$tabContent.find(".".concat(this.options.panelClass)).css('height', '').each(function () {
  8973. var panel = $(this),
  8974. isActive = panel.hasClass("".concat(_this.options.panelActiveClass)); // get the options from the parent instead of trying to get them from the child
  8975. if (!isActive) {
  8976. panel.css({
  8977. 'visibility': 'hidden',
  8978. 'display': 'block'
  8979. });
  8980. }
  8981. var temp = this.getBoundingClientRect().height;
  8982. if (!isActive) {
  8983. panel.css({
  8984. 'visibility': '',
  8985. 'display': ''
  8986. });
  8987. }
  8988. max = temp > max ? temp : max;
  8989. }).css('height', "".concat(max, "px"));
  8990. }
  8991. /**
  8992. * Destroys an instance of tabs.
  8993. * @fires Tabs#destroyed
  8994. */
  8995. }, {
  8996. key: "_destroy",
  8997. value: function _destroy() {
  8998. this.$element.find(".".concat(this.options.linkClass)).off('.zf.tabs').hide().end().find(".".concat(this.options.panelClass)).hide();
  8999. if (this.options.matchHeight) {
  9000. if (this._setHeightMqHandler != null) {
  9001. $(window).off('changed.zf.mediaquery', this._setHeightMqHandler);
  9002. }
  9003. }
  9004. if (this.options.deepLink) {
  9005. $(window).off('hashchange', this._checkDeepLink);
  9006. }
  9007. if (this.onLoadListener) {
  9008. $(window).off(this.onLoadListener);
  9009. }
  9010. }
  9011. }]);
  9012. return Tabs;
  9013. }(Plugin);
  9014. Tabs.defaults = {
  9015. /**
  9016. * Link the location hash to the active pane.
  9017. * Set the location hash when the active pane changes, and open the corresponding pane when the location changes.
  9018. * @option
  9019. * @type {boolean}
  9020. * @default false
  9021. */
  9022. deepLink: false,
  9023. /**
  9024. * If `deepLink` is enabled, adjust the deep link scroll to make sure the top of the tab panel is visible
  9025. * @option
  9026. * @type {boolean}
  9027. * @default false
  9028. */
  9029. deepLinkSmudge: false,
  9030. /**
  9031. * If `deepLinkSmudge` is enabled, animation time (ms) for the deep link adjustment
  9032. * @option
  9033. * @type {number}
  9034. * @default 300
  9035. */
  9036. deepLinkSmudgeDelay: 300,
  9037. /**
  9038. * If `deepLink` is enabled, update the browser history with the open tab
  9039. * @option
  9040. * @type {boolean}
  9041. * @default false
  9042. */
  9043. updateHistory: false,
  9044. /**
  9045. * Allows the window to scroll to content of active pane on load.
  9046. * Not recommended if more than one tab panel per page.
  9047. * @option
  9048. * @type {boolean}
  9049. * @default false
  9050. */
  9051. autoFocus: false,
  9052. /**
  9053. * Allows keyboard input to 'wrap' around the tab links.
  9054. * @option
  9055. * @type {boolean}
  9056. * @default true
  9057. */
  9058. wrapOnKeys: true,
  9059. /**
  9060. * Allows the tab content panes to match heights if set to true.
  9061. * @option
  9062. * @type {boolean}
  9063. * @default false
  9064. */
  9065. matchHeight: false,
  9066. /**
  9067. * Allows active tabs to collapse when clicked.
  9068. * @option
  9069. * @type {boolean}
  9070. * @default false
  9071. */
  9072. activeCollapse: false,
  9073. /**
  9074. * Class applied to `li`'s in tab link list.
  9075. * @option
  9076. * @type {string}
  9077. * @default 'tabs-title'
  9078. */
  9079. linkClass: 'tabs-title',
  9080. /**
  9081. * Class applied to the active `li` in tab link list.
  9082. * @option
  9083. * @type {string}
  9084. * @default 'is-active'
  9085. */
  9086. linkActiveClass: 'is-active',
  9087. /**
  9088. * Class applied to the content containers.
  9089. * @option
  9090. * @type {string}
  9091. * @default 'tabs-panel'
  9092. */
  9093. panelClass: 'tabs-panel',
  9094. /**
  9095. * Class applied to the active content container.
  9096. * @option
  9097. * @type {string}
  9098. * @default 'is-active'
  9099. */
  9100. panelActiveClass: 'is-active'
  9101. };
  9102. /**
  9103. * Toggler module.
  9104. * @module foundation.toggler
  9105. * @requires foundation.util.motion
  9106. * @requires foundation.util.triggers
  9107. */
  9108. var Toggler =
  9109. /*#__PURE__*/
  9110. function (_Plugin) {
  9111. _inherits(Toggler, _Plugin);
  9112. function Toggler() {
  9113. _classCallCheck(this, Toggler);
  9114. return _possibleConstructorReturn(this, _getPrototypeOf(Toggler).apply(this, arguments));
  9115. }
  9116. _createClass(Toggler, [{
  9117. key: "_setup",
  9118. /**
  9119. * Creates a new instance of Toggler.
  9120. * @class
  9121. * @name Toggler
  9122. * @fires Toggler#init
  9123. * @param {Object} element - jQuery object to add the trigger to.
  9124. * @param {Object} options - Overrides to the default plugin settings.
  9125. */
  9126. value: function _setup(element, options) {
  9127. this.$element = element;
  9128. this.options = $.extend({}, Toggler.defaults, element.data(), options);
  9129. this.className = '';
  9130. this.className = 'Toggler'; // ie9 back compat
  9131. // Triggers init is idempotent, just need to make sure it is initialized
  9132. Triggers.init($);
  9133. this._init();
  9134. this._events();
  9135. }
  9136. /**
  9137. * Initializes the Toggler plugin by parsing the toggle class from data-toggler, or animation classes from data-animate.
  9138. * @function
  9139. * @private
  9140. */
  9141. }, {
  9142. key: "_init",
  9143. value: function _init() {
  9144. var input; // Parse animation classes if they were set
  9145. if (this.options.animate) {
  9146. input = this.options.animate.split(' ');
  9147. this.animationIn = input[0];
  9148. this.animationOut = input[1] || null;
  9149. } // Otherwise, parse toggle class
  9150. else {
  9151. input = this.$element.data('toggler'); // Allow for a . at the beginning of the string
  9152. this.className = input[0] === '.' ? input.slice(1) : input;
  9153. } // Add ARIA attributes to triggers:
  9154. var id = this.$element[0].id,
  9155. $triggers = $("[data-open~=\"".concat(id, "\"], [data-close~=\"").concat(id, "\"], [data-toggle~=\"").concat(id, "\"]")); // - aria-expanded: according to the element visibility.
  9156. $triggers.attr('aria-expanded', !this.$element.is(':hidden')); // - aria-controls: adding the element id to it if not already in it.
  9157. $triggers.each(function (index, trigger) {
  9158. var $trigger = $(trigger);
  9159. var controls = $trigger.attr('aria-controls') || '';
  9160. var containsId = new RegExp("\\b".concat(RegExpEscape(id), "\\b")).test(controls);
  9161. if (!containsId) $trigger.attr('aria-controls', controls ? "".concat(controls, " ").concat(id) : id);
  9162. });
  9163. }
  9164. /**
  9165. * Initializes events for the toggle trigger.
  9166. * @function
  9167. * @private
  9168. */
  9169. }, {
  9170. key: "_events",
  9171. value: function _events() {
  9172. this.$element.off('toggle.zf.trigger').on('toggle.zf.trigger', this.toggle.bind(this));
  9173. }
  9174. /**
  9175. * 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".
  9176. * @function
  9177. * @fires Toggler#on
  9178. * @fires Toggler#off
  9179. */
  9180. }, {
  9181. key: "toggle",
  9182. value: function toggle() {
  9183. this[this.options.animate ? '_toggleAnimate' : '_toggleClass']();
  9184. }
  9185. }, {
  9186. key: "_toggleClass",
  9187. value: function _toggleClass() {
  9188. this.$element.toggleClass(this.className);
  9189. var isOn = this.$element.hasClass(this.className);
  9190. if (isOn) {
  9191. /**
  9192. * Fires if the target element has the class after a toggle.
  9193. * @event Toggler#on
  9194. */
  9195. this.$element.trigger('on.zf.toggler');
  9196. } else {
  9197. /**
  9198. * Fires if the target element does not have the class after a toggle.
  9199. * @event Toggler#off
  9200. */
  9201. this.$element.trigger('off.zf.toggler');
  9202. }
  9203. this._updateARIA(isOn);
  9204. this.$element.find('[data-mutate]').trigger('mutateme.zf.trigger');
  9205. }
  9206. }, {
  9207. key: "_toggleAnimate",
  9208. value: function _toggleAnimate() {
  9209. var _this = this;
  9210. if (this.$element.is(':hidden')) {
  9211. Motion.animateIn(this.$element, this.animationIn, function () {
  9212. _this._updateARIA(true);
  9213. this.trigger('on.zf.toggler');
  9214. this.find('[data-mutate]').trigger('mutateme.zf.trigger');
  9215. });
  9216. } else {
  9217. Motion.animateOut(this.$element, this.animationOut, function () {
  9218. _this._updateARIA(false);
  9219. this.trigger('off.zf.toggler');
  9220. this.find('[data-mutate]').trigger('mutateme.zf.trigger');
  9221. });
  9222. }
  9223. }
  9224. }, {
  9225. key: "_updateARIA",
  9226. value: function _updateARIA(isOn) {
  9227. var id = this.$element[0].id;
  9228. $("[data-open=\"".concat(id, "\"], [data-close=\"").concat(id, "\"], [data-toggle=\"").concat(id, "\"]")).attr({
  9229. 'aria-expanded': isOn ? true : false
  9230. });
  9231. }
  9232. /**
  9233. * Destroys the instance of Toggler on the element.
  9234. * @function
  9235. */
  9236. }, {
  9237. key: "_destroy",
  9238. value: function _destroy() {
  9239. this.$element.off('.zf.toggler');
  9240. }
  9241. }]);
  9242. return Toggler;
  9243. }(Plugin);
  9244. Toggler.defaults = {
  9245. /**
  9246. * Tells the plugin if the element should animated when toggled.
  9247. * @option
  9248. * @type {boolean}
  9249. * @default false
  9250. */
  9251. animate: false
  9252. };
  9253. /**
  9254. * Tooltip module.
  9255. * @module foundation.tooltip
  9256. * @requires foundation.util.box
  9257. * @requires foundation.util.mediaQuery
  9258. * @requires foundation.util.triggers
  9259. */
  9260. var Tooltip =
  9261. /*#__PURE__*/
  9262. function (_Positionable) {
  9263. _inherits(Tooltip, _Positionable);
  9264. function Tooltip() {
  9265. _classCallCheck(this, Tooltip);
  9266. return _possibleConstructorReturn(this, _getPrototypeOf(Tooltip).apply(this, arguments));
  9267. }
  9268. _createClass(Tooltip, [{
  9269. key: "_setup",
  9270. /**
  9271. * Creates a new instance of a Tooltip.
  9272. * @class
  9273. * @name Tooltip
  9274. * @fires Tooltip#init
  9275. * @param {jQuery} element - jQuery object to attach a tooltip to.
  9276. * @param {Object} options - object to extend the default configuration.
  9277. */
  9278. value: function _setup(element, options) {
  9279. this.$element = element;
  9280. this.options = $.extend({}, Tooltip.defaults, this.$element.data(), options);
  9281. this.className = 'Tooltip'; // ie9 back compat
  9282. this.isActive = false;
  9283. this.isClick = false; // Triggers init is idempotent, just need to make sure it is initialized
  9284. Triggers.init($);
  9285. this._init();
  9286. }
  9287. /**
  9288. * Initializes the tooltip by setting the creating the tip element, adding it's text, setting private variables and setting attributes on the anchor.
  9289. * @private
  9290. */
  9291. }, {
  9292. key: "_init",
  9293. value: function _init() {
  9294. MediaQuery._init();
  9295. var elemId = this.$element.attr('aria-describedby') || GetYoDigits(6, 'tooltip');
  9296. this.options.tipText = this.options.tipText || this.$element.attr('title');
  9297. this.template = this.options.template ? $(this.options.template) : this._buildTemplate(elemId);
  9298. if (this.options.allowHtml) {
  9299. this.template.appendTo(document.body).html(this.options.tipText).hide();
  9300. } else {
  9301. this.template.appendTo(document.body).text(this.options.tipText).hide();
  9302. }
  9303. this.$element.attr({
  9304. 'title': '',
  9305. 'aria-describedby': elemId,
  9306. 'data-yeti-box': elemId,
  9307. 'data-toggle': elemId,
  9308. 'data-resize': elemId
  9309. }).addClass(this.options.triggerClass);
  9310. _get(_getPrototypeOf(Tooltip.prototype), "_init", this).call(this);
  9311. this._events();
  9312. }
  9313. }, {
  9314. key: "_getDefaultPosition",
  9315. value: function _getDefaultPosition() {
  9316. // handle legacy classnames
  9317. var position = this.$element[0].className.match(/\b(top|left|right|bottom)\b/g);
  9318. return position ? position[0] : 'top';
  9319. }
  9320. }, {
  9321. key: "_getDefaultAlignment",
  9322. value: function _getDefaultAlignment() {
  9323. return 'center';
  9324. }
  9325. }, {
  9326. key: "_getHOffset",
  9327. value: function _getHOffset() {
  9328. if (this.position === 'left' || this.position === 'right') {
  9329. return this.options.hOffset + this.options.tooltipWidth;
  9330. } else {
  9331. return this.options.hOffset;
  9332. }
  9333. }
  9334. }, {
  9335. key: "_getVOffset",
  9336. value: function _getVOffset() {
  9337. if (this.position === 'top' || this.position === 'bottom') {
  9338. return this.options.vOffset + this.options.tooltipHeight;
  9339. } else {
  9340. return this.options.vOffset;
  9341. }
  9342. }
  9343. /**
  9344. * builds the tooltip element, adds attributes, and returns the template.
  9345. * @private
  9346. */
  9347. }, {
  9348. key: "_buildTemplate",
  9349. value: function _buildTemplate(id) {
  9350. var templateClasses = "".concat(this.options.tooltipClass, " ").concat(this.options.templateClasses).trim();
  9351. var $template = $('<div></div>').addClass(templateClasses).attr({
  9352. 'role': 'tooltip',
  9353. 'aria-hidden': true,
  9354. 'data-is-active': false,
  9355. 'data-is-focus': false,
  9356. 'id': id
  9357. });
  9358. return $template;
  9359. }
  9360. /**
  9361. * 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.
  9362. * if the tooltip is larger than the screen width, default to full width - any user selected margin
  9363. * @private
  9364. */
  9365. }, {
  9366. key: "_setPosition",
  9367. value: function _setPosition() {
  9368. _get(_getPrototypeOf(Tooltip.prototype), "_setPosition", this).call(this, this.$element, this.template);
  9369. }
  9370. /**
  9371. * reveals the tooltip, and fires an event to close any other open tooltips on the page
  9372. * @fires Tooltip#closeme
  9373. * @fires Tooltip#show
  9374. * @function
  9375. */
  9376. }, {
  9377. key: "show",
  9378. value: function show() {
  9379. if (this.options.showOn !== 'all' && !MediaQuery.is(this.options.showOn)) {
  9380. // console.error('The screen is too small to display this tooltip');
  9381. return false;
  9382. }
  9383. var _this = this;
  9384. this.template.css('visibility', 'hidden').show();
  9385. this._setPosition();
  9386. this.template.removeClass('top bottom left right').addClass(this.position);
  9387. this.template.removeClass('align-top align-bottom align-left align-right align-center').addClass('align-' + this.alignment);
  9388. /**
  9389. * Fires to close all other open tooltips on the page
  9390. * @event Closeme#tooltip
  9391. */
  9392. this.$element.trigger('closeme.zf.tooltip', this.template.attr('id'));
  9393. this.template.attr({
  9394. 'data-is-active': true,
  9395. 'aria-hidden': false
  9396. });
  9397. _this.isActive = true; // console.log(this.template);
  9398. this.template.stop().hide().css('visibility', '').fadeIn(this.options.fadeInDuration, function () {//maybe do stuff?
  9399. });
  9400. /**
  9401. * Fires when the tooltip is shown
  9402. * @event Tooltip#show
  9403. */
  9404. this.$element.trigger('show.zf.tooltip');
  9405. }
  9406. /**
  9407. * Hides the current tooltip, and resets the positioning class if it was changed due to collision
  9408. * @fires Tooltip#hide
  9409. * @function
  9410. */
  9411. }, {
  9412. key: "hide",
  9413. value: function hide() {
  9414. // console.log('hiding', this.$element.data('yeti-box'));
  9415. var _this = this;
  9416. this.template.stop().attr({
  9417. 'aria-hidden': true,
  9418. 'data-is-active': false
  9419. }).fadeOut(this.options.fadeOutDuration, function () {
  9420. _this.isActive = false;
  9421. _this.isClick = false;
  9422. });
  9423. /**
  9424. * fires when the tooltip is hidden
  9425. * @event Tooltip#hide
  9426. */
  9427. this.$element.trigger('hide.zf.tooltip');
  9428. }
  9429. /**
  9430. * adds event listeners for the tooltip and its anchor
  9431. * TODO combine some of the listeners like focus and mouseenter, etc.
  9432. * @private
  9433. */
  9434. }, {
  9435. key: "_events",
  9436. value: function _events() {
  9437. var _this = this;
  9438. var $template = this.template;
  9439. var isFocus = false;
  9440. if (!this.options.disableHover) {
  9441. this.$element.on('mouseenter.zf.tooltip', function (e) {
  9442. if (!_this.isActive) {
  9443. _this.timeout = setTimeout(function () {
  9444. _this.show();
  9445. }, _this.options.hoverDelay);
  9446. }
  9447. }).on('mouseleave.zf.tooltip', ignoreMousedisappear(function (e) {
  9448. clearTimeout(_this.timeout);
  9449. if (!isFocus || _this.isClick && !_this.options.clickOpen) {
  9450. _this.hide();
  9451. }
  9452. }));
  9453. }
  9454. if (this.options.clickOpen) {
  9455. this.$element.on('mousedown.zf.tooltip', function (e) {
  9456. e.stopImmediatePropagation();
  9457. if (_this.isClick) ; else {
  9458. _this.isClick = true;
  9459. if ((_this.options.disableHover || !_this.$element.attr('tabindex')) && !_this.isActive) {
  9460. _this.show();
  9461. }
  9462. }
  9463. });
  9464. } else {
  9465. this.$element.on('mousedown.zf.tooltip', function (e) {
  9466. e.stopImmediatePropagation();
  9467. _this.isClick = true;
  9468. });
  9469. }
  9470. if (!this.options.disableForTouch) {
  9471. this.$element.on('tap.zf.tooltip touchend.zf.tooltip', function (e) {
  9472. _this.isActive ? _this.hide() : _this.show();
  9473. });
  9474. }
  9475. this.$element.on({
  9476. // 'toggle.zf.trigger': this.toggle.bind(this),
  9477. // 'close.zf.trigger': this.hide.bind(this)
  9478. 'close.zf.trigger': this.hide.bind(this)
  9479. });
  9480. this.$element.on('focus.zf.tooltip', function (e) {
  9481. isFocus = true;
  9482. if (_this.isClick) {
  9483. // If we're not showing open on clicks, we need to pretend a click-launched focus isn't
  9484. // a real focus, otherwise on hover and come back we get bad behavior
  9485. if (!_this.options.clickOpen) {
  9486. isFocus = false;
  9487. }
  9488. return false;
  9489. } else {
  9490. _this.show();
  9491. }
  9492. }).on('focusout.zf.tooltip', function (e) {
  9493. isFocus = false;
  9494. _this.isClick = false;
  9495. _this.hide();
  9496. }).on('resizeme.zf.trigger', function () {
  9497. if (_this.isActive) {
  9498. _this._setPosition();
  9499. }
  9500. });
  9501. }
  9502. /**
  9503. * adds a toggle method, in addition to the static show() & hide() functions
  9504. * @function
  9505. */
  9506. }, {
  9507. key: "toggle",
  9508. value: function toggle() {
  9509. if (this.isActive) {
  9510. this.hide();
  9511. } else {
  9512. this.show();
  9513. }
  9514. }
  9515. /**
  9516. * Destroys an instance of tooltip, removes template element from the view.
  9517. * @function
  9518. */
  9519. }, {
  9520. key: "_destroy",
  9521. value: function _destroy() {
  9522. 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');
  9523. this.template.remove();
  9524. }
  9525. }]);
  9526. return Tooltip;
  9527. }(Positionable);
  9528. Tooltip.defaults = {
  9529. disableForTouch: false,
  9530. /**
  9531. * Time, in ms, before a tooltip should open on hover.
  9532. * @option
  9533. * @type {number}
  9534. * @default 200
  9535. */
  9536. hoverDelay: 200,
  9537. /**
  9538. * Time, in ms, a tooltip should take to fade into view.
  9539. * @option
  9540. * @type {number}
  9541. * @default 150
  9542. */
  9543. fadeInDuration: 150,
  9544. /**
  9545. * Time, in ms, a tooltip should take to fade out of view.
  9546. * @option
  9547. * @type {number}
  9548. * @default 150
  9549. */
  9550. fadeOutDuration: 150,
  9551. /**
  9552. * Disables hover events from opening the tooltip if set to true
  9553. * @option
  9554. * @type {boolean}
  9555. * @default false
  9556. */
  9557. disableHover: false,
  9558. /**
  9559. * Optional addtional classes to apply to the tooltip template on init.
  9560. * @option
  9561. * @type {string}
  9562. * @default ''
  9563. */
  9564. templateClasses: '',
  9565. /**
  9566. * Non-optional class added to tooltip templates. Foundation default is 'tooltip'.
  9567. * @option
  9568. * @type {string}
  9569. * @default 'tooltip'
  9570. */
  9571. tooltipClass: 'tooltip',
  9572. /**
  9573. * Class applied to the tooltip anchor element.
  9574. * @option
  9575. * @type {string}
  9576. * @default 'has-tip'
  9577. */
  9578. triggerClass: 'has-tip',
  9579. /**
  9580. * Minimum breakpoint size at which to open the tooltip.
  9581. * @option
  9582. * @type {string}
  9583. * @default 'small'
  9584. */
  9585. showOn: 'small',
  9586. /**
  9587. * Custom template to be used to generate markup for tooltip.
  9588. * @option
  9589. * @type {string}
  9590. * @default ''
  9591. */
  9592. template: '',
  9593. /**
  9594. * Text displayed in the tooltip template on open.
  9595. * @option
  9596. * @type {string}
  9597. * @default ''
  9598. */
  9599. tipText: '',
  9600. touchCloseText: 'Tap to close.',
  9601. /**
  9602. * Allows the tooltip to remain open if triggered with a click or touch event.
  9603. * @option
  9604. * @type {boolean}
  9605. * @default true
  9606. */
  9607. clickOpen: true,
  9608. /**
  9609. * Position of tooltip. Can be left, right, bottom, top, or auto.
  9610. * @option
  9611. * @type {string}
  9612. * @default 'auto'
  9613. */
  9614. position: 'auto',
  9615. /**
  9616. * Alignment of tooltip relative to anchor. Can be left, right, bottom, top, center, or auto.
  9617. * @option
  9618. * @type {string}
  9619. * @default 'auto'
  9620. */
  9621. alignment: 'auto',
  9622. /**
  9623. * Allow overlap of container/window. If false, tooltip will first try to
  9624. * position as defined by data-position and data-alignment, but reposition if
  9625. * it would cause an overflow. @option
  9626. * @type {boolean}
  9627. * @default false
  9628. */
  9629. allowOverlap: false,
  9630. /**
  9631. * Allow overlap of only the bottom of the container. This is the most common
  9632. * behavior for dropdowns, allowing the dropdown to extend the bottom of the
  9633. * screen but not otherwise influence or break out of the container.
  9634. * Less common for tooltips.
  9635. * @option
  9636. * @type {boolean}
  9637. * @default false
  9638. */
  9639. allowBottomOverlap: false,
  9640. /**
  9641. * Distance, in pixels, the template should push away from the anchor on the Y axis.
  9642. * @option
  9643. * @type {number}
  9644. * @default 0
  9645. */
  9646. vOffset: 0,
  9647. /**
  9648. * Distance, in pixels, the template should push away from the anchor on the X axis
  9649. * @option
  9650. * @type {number}
  9651. * @default 0
  9652. */
  9653. hOffset: 0,
  9654. /**
  9655. * Distance, in pixels, the template spacing auto-adjust for a vertical tooltip
  9656. * @option
  9657. * @type {number}
  9658. * @default 14
  9659. */
  9660. tooltipHeight: 14,
  9661. /**
  9662. * Distance, in pixels, the template spacing auto-adjust for a horizontal tooltip
  9663. * @option
  9664. * @type {number}
  9665. * @default 12
  9666. */
  9667. tooltipWidth: 12,
  9668. /**
  9669. * Allow HTML in tooltip. Warning: If you are loading user-generated content into tooltips,
  9670. * allowing HTML may open yourself up to XSS attacks.
  9671. * @option
  9672. * @type {boolean}
  9673. * @default false
  9674. */
  9675. allowHtml: false
  9676. };
  9677. var MenuPlugins$1 = {
  9678. tabs: {
  9679. cssClass: 'tabs',
  9680. plugin: Tabs
  9681. },
  9682. accordion: {
  9683. cssClass: 'accordion',
  9684. plugin: Accordion
  9685. }
  9686. };
  9687. /**
  9688. * ResponsiveAccordionTabs module.
  9689. * @module foundation.responsiveAccordionTabs
  9690. * @requires foundation.util.motion
  9691. * @requires foundation.accordion
  9692. * @requires foundation.tabs
  9693. */
  9694. var ResponsiveAccordionTabs =
  9695. /*#__PURE__*/
  9696. function (_Plugin) {
  9697. _inherits(ResponsiveAccordionTabs, _Plugin);
  9698. function ResponsiveAccordionTabs() {
  9699. _classCallCheck(this, ResponsiveAccordionTabs);
  9700. return _possibleConstructorReturn(this, _getPrototypeOf(ResponsiveAccordionTabs).apply(this, arguments));
  9701. }
  9702. _createClass(ResponsiveAccordionTabs, [{
  9703. key: "_setup",
  9704. /**
  9705. * Creates a new instance of a responsive accordion tabs.
  9706. * @class
  9707. * @name ResponsiveAccordionTabs
  9708. * @fires ResponsiveAccordionTabs#init
  9709. * @param {jQuery} element - jQuery object to make into Responsive Accordion Tabs.
  9710. * @param {Object} options - Overrides to the default plugin settings.
  9711. */
  9712. value: function _setup(element, options) {
  9713. this.$element = $(element);
  9714. this.options = $.extend({}, this.$element.data(), options);
  9715. this.rules = this.$element.data('responsive-accordion-tabs');
  9716. this.currentMq = null;
  9717. this.currentPlugin = null;
  9718. this.className = 'ResponsiveAccordionTabs'; // ie9 back compat
  9719. if (!this.$element.attr('id')) {
  9720. this.$element.attr('id', GetYoDigits(6, 'responsiveaccordiontabs'));
  9721. }
  9722. this._init();
  9723. this._events();
  9724. }
  9725. /**
  9726. * Initializes the Menu by parsing the classes from the 'data-responsive-accordion-tabs' attribute on the element.
  9727. * @function
  9728. * @private
  9729. */
  9730. }, {
  9731. key: "_init",
  9732. value: function _init() {
  9733. MediaQuery._init(); // The first time an Interchange plugin is initialized, this.rules is converted from a string of "classes" to an object of rules
  9734. if (typeof this.rules === 'string') {
  9735. var rulesTree = {}; // Parse rules from "classes" pulled from data attribute
  9736. var rules = this.rules.split(' '); // Iterate through every rule found
  9737. for (var i = 0; i < rules.length; i++) {
  9738. var rule = rules[i].split('-');
  9739. var ruleSize = rule.length > 1 ? rule[0] : 'small';
  9740. var rulePlugin = rule.length > 1 ? rule[1] : rule[0];
  9741. if (MenuPlugins$1[rulePlugin] !== null) {
  9742. rulesTree[ruleSize] = MenuPlugins$1[rulePlugin];
  9743. }
  9744. }
  9745. this.rules = rulesTree;
  9746. }
  9747. this._getAllOptions();
  9748. if (!$.isEmptyObject(this.rules)) {
  9749. this._checkMediaQueries();
  9750. }
  9751. }
  9752. }, {
  9753. key: "_getAllOptions",
  9754. value: function _getAllOptions() {
  9755. //get all defaults and options
  9756. var _this = this;
  9757. _this.allOptions = {};
  9758. for (var key in MenuPlugins$1) {
  9759. if (MenuPlugins$1.hasOwnProperty(key)) {
  9760. var obj = MenuPlugins$1[key];
  9761. try {
  9762. var dummyPlugin = $('<ul></ul>');
  9763. var tmpPlugin = new obj.plugin(dummyPlugin, _this.options);
  9764. for (var keyKey in tmpPlugin.options) {
  9765. if (tmpPlugin.options.hasOwnProperty(keyKey) && keyKey !== 'zfPlugin') {
  9766. var objObj = tmpPlugin.options[keyKey];
  9767. _this.allOptions[keyKey] = objObj;
  9768. }
  9769. }
  9770. tmpPlugin.destroy();
  9771. } catch (e) {}
  9772. }
  9773. }
  9774. }
  9775. /**
  9776. * Initializes events for the Menu.
  9777. * @function
  9778. * @private
  9779. */
  9780. }, {
  9781. key: "_events",
  9782. value: function _events() {
  9783. this._changedZfMediaQueryHandler = this._checkMediaQueries.bind(this);
  9784. $(window).on('changed.zf.mediaquery', this._changedZfMediaQueryHandler);
  9785. }
  9786. /**
  9787. * 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.
  9788. * @function
  9789. * @private
  9790. */
  9791. }, {
  9792. key: "_checkMediaQueries",
  9793. value: function _checkMediaQueries() {
  9794. var matchedMq,
  9795. _this = this; // Iterate through each rule and find the last matching rule
  9796. $.each(this.rules, function (key) {
  9797. if (MediaQuery.atLeast(key)) {
  9798. matchedMq = key;
  9799. }
  9800. }); // No match? No dice
  9801. if (!matchedMq) return; // Plugin already initialized? We good
  9802. if (this.currentPlugin instanceof this.rules[matchedMq].plugin) return; // Remove existing plugin-specific CSS classes
  9803. $.each(MenuPlugins$1, function (key, value) {
  9804. _this.$element.removeClass(value.cssClass);
  9805. }); // Add the CSS class for the new plugin
  9806. this.$element.addClass(this.rules[matchedMq].cssClass); // Create an instance of the new plugin
  9807. if (this.currentPlugin) {
  9808. //don't know why but on nested elements data zfPlugin get's lost
  9809. if (!this.currentPlugin.$element.data('zfPlugin') && this.storezfData) this.currentPlugin.$element.data('zfPlugin', this.storezfData);
  9810. this.currentPlugin.destroy();
  9811. }
  9812. this._handleMarkup(this.rules[matchedMq].cssClass);
  9813. this.currentPlugin = new this.rules[matchedMq].plugin(this.$element, {});
  9814. this.storezfData = this.currentPlugin.$element.data('zfPlugin');
  9815. }
  9816. }, {
  9817. key: "_handleMarkup",
  9818. value: function _handleMarkup(toSet) {
  9819. var _this = this,
  9820. fromString = 'accordion';
  9821. var $panels = $('[data-tabs-content=' + this.$element.attr('id') + ']');
  9822. if ($panels.length) fromString = 'tabs';
  9823. if (fromString === toSet) {
  9824. return;
  9825. }
  9826. var tabsTitle = _this.allOptions.linkClass ? _this.allOptions.linkClass : 'tabs-title';
  9827. var tabsPanel = _this.allOptions.panelClass ? _this.allOptions.panelClass : 'tabs-panel';
  9828. this.$element.removeAttr('role');
  9829. var $liHeads = this.$element.children('.' + tabsTitle + ',[data-accordion-item]').removeClass(tabsTitle).removeClass('accordion-item').removeAttr('data-accordion-item');
  9830. var $liHeadsA = $liHeads.children('a').removeClass('accordion-title');
  9831. if (fromString === 'tabs') {
  9832. $panels = $panels.children('.' + tabsPanel).removeClass(tabsPanel).removeAttr('role').removeAttr('aria-hidden').removeAttr('aria-labelledby');
  9833. $panels.children('a').removeAttr('role').removeAttr('aria-controls').removeAttr('aria-selected');
  9834. } else {
  9835. $panels = $liHeads.children('[data-tab-content]').removeClass('accordion-content');
  9836. }
  9837. $panels.css({
  9838. display: '',
  9839. visibility: ''
  9840. });
  9841. $liHeads.css({
  9842. display: '',
  9843. visibility: ''
  9844. });
  9845. if (toSet === 'accordion') {
  9846. $panels.each(function (key, value) {
  9847. $(value).appendTo($liHeads.get(key)).addClass('accordion-content').attr('data-tab-content', '').removeClass('is-active').css({
  9848. height: ''
  9849. });
  9850. $('[data-tabs-content=' + _this.$element.attr('id') + ']').after('<div id="tabs-placeholder-' + _this.$element.attr('id') + '"></div>').detach();
  9851. $liHeads.addClass('accordion-item').attr('data-accordion-item', '');
  9852. $liHeadsA.addClass('accordion-title');
  9853. });
  9854. } else if (toSet === 'tabs') {
  9855. var $tabsContent = $('[data-tabs-content=' + _this.$element.attr('id') + ']');
  9856. var $placeholder = $('#tabs-placeholder-' + _this.$element.attr('id'));
  9857. if ($placeholder.length) {
  9858. $tabsContent = $('<div class="tabs-content"></div>').insertAfter($placeholder).attr('data-tabs-content', _this.$element.attr('id'));
  9859. $placeholder.remove();
  9860. } else {
  9861. $tabsContent = $('<div class="tabs-content"></div>').insertAfter(_this.$element).attr('data-tabs-content', _this.$element.attr('id'));
  9862. }
  9863. $panels.each(function (key, value) {
  9864. var tempValue = $(value).appendTo($tabsContent).addClass(tabsPanel);
  9865. var hash = $liHeadsA.get(key).hash.slice(1);
  9866. var id = $(value).attr('id') || GetYoDigits(6, 'accordion');
  9867. if (hash !== id) {
  9868. if (hash !== '') {
  9869. $(value).attr('id', hash);
  9870. } else {
  9871. hash = id;
  9872. $(value).attr('id', hash);
  9873. $($liHeadsA.get(key)).attr('href', $($liHeadsA.get(key)).attr('href').replace('#', '') + '#' + hash);
  9874. }
  9875. }
  9876. var isActive = $($liHeads.get(key)).hasClass('is-active');
  9877. if (isActive) {
  9878. tempValue.addClass('is-active');
  9879. }
  9880. });
  9881. $liHeads.addClass(tabsTitle);
  9882. }
  9883. }
  9884. /**
  9885. * Destroys the instance of the current plugin on this element, as well as the window resize handler that switches the plugins out.
  9886. * @function
  9887. */
  9888. }, {
  9889. key: "_destroy",
  9890. value: function _destroy() {
  9891. if (this.currentPlugin) this.currentPlugin.destroy();
  9892. $(window).off('changed.zf.mediaquery', this._changedZfMediaQueryHandler);
  9893. }
  9894. }]);
  9895. return ResponsiveAccordionTabs;
  9896. }(Plugin);
  9897. ResponsiveAccordionTabs.defaults = {};
  9898. Foundation.addToJquery($); // Add Foundation Utils to Foundation global namespace for backwards
  9899. // compatibility.
  9900. Foundation.rtl = rtl;
  9901. Foundation.GetYoDigits = GetYoDigits;
  9902. Foundation.transitionend = transitionend;
  9903. Foundation.RegExpEscape = RegExpEscape;
  9904. Foundation.onLoad = onLoad;
  9905. Foundation.Box = Box;
  9906. Foundation.onImagesLoaded = onImagesLoaded;
  9907. Foundation.Keyboard = Keyboard;
  9908. Foundation.MediaQuery = MediaQuery;
  9909. Foundation.Motion = Motion;
  9910. Foundation.Move = Move;
  9911. Foundation.Nest = Nest;
  9912. Foundation.Timer = Timer; // Touch and Triggers previously were almost purely sede effect driven,
  9913. // so no need to add it to Foundation, just init them.
  9914. Touch.init($);
  9915. Triggers.init($, Foundation);
  9916. MediaQuery._init();
  9917. Foundation.plugin(Abide, 'Abide');
  9918. Foundation.plugin(Accordion, 'Accordion');
  9919. Foundation.plugin(AccordionMenu, 'AccordionMenu');
  9920. Foundation.plugin(Drilldown, 'Drilldown');
  9921. Foundation.plugin(Dropdown, 'Dropdown');
  9922. Foundation.plugin(DropdownMenu, 'DropdownMenu');
  9923. Foundation.plugin(Equalizer, 'Equalizer');
  9924. Foundation.plugin(Interchange, 'Interchange');
  9925. Foundation.plugin(Magellan, 'Magellan');
  9926. Foundation.plugin(OffCanvas, 'OffCanvas');
  9927. Foundation.plugin(Orbit, 'Orbit');
  9928. Foundation.plugin(ResponsiveMenu, 'ResponsiveMenu');
  9929. Foundation.plugin(ResponsiveToggle, 'ResponsiveToggle');
  9930. Foundation.plugin(Reveal, 'Reveal');
  9931. Foundation.plugin(Slider, 'Slider');
  9932. Foundation.plugin(SmoothScroll, 'SmoothScroll');
  9933. Foundation.plugin(Sticky, 'Sticky');
  9934. Foundation.plugin(Tabs, 'Tabs');
  9935. Foundation.plugin(Toggler, 'Toggler');
  9936. Foundation.plugin(Tooltip, 'Tooltip');
  9937. Foundation.plugin(ResponsiveAccordionTabs, 'ResponsiveAccordionTabs');
  9938. export default Foundation;
  9939. export { foundation_core_utils as CoreUtils, Foundation as Core, Foundation, Box, onImagesLoaded, Keyboard, MediaQuery, Motion, Move, Nest, Timer, Touch, Triggers, Abide, Accordion, AccordionMenu, Drilldown, Dropdown, DropdownMenu, Equalizer, Interchange, Magellan, OffCanvas, Orbit, ResponsiveMenu, ResponsiveToggle, Reveal, Slider, SmoothScroll, Sticky, Tabs, Toggler, Tooltip, ResponsiveAccordionTabs };
  9940. //# sourceMappingURL=foundation.esm.js.map