amazeui.js 460 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800
  1. /*! Amaze UI v2.7.2 | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-12-16T16:25:57+0800 */
  2. (function webpackUniversalModuleDefinition(root, factory) {
  3. if(typeof exports === 'object' && typeof module === 'object')
  4. module.exports = factory(require("jquery"));
  5. else if(typeof define === 'function' && define.amd)
  6. define(["jquery"], factory);
  7. else if(typeof exports === 'object')
  8. exports["AMUI"] = factory(require("jquery"));
  9. else
  10. root["AMUI"] = factory(root["jQuery"]);
  11. })(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {
  12. return /******/ (function(modules) { // webpackBootstrap
  13. /******/ // The module cache
  14. /******/ var installedModules = {};
  15. /******/ // The require function
  16. /******/ function __webpack_require__(moduleId) {
  17. /******/ // Check if module is in cache
  18. /******/ if(installedModules[moduleId])
  19. /******/ return installedModules[moduleId].exports;
  20. /******/ // Create a new module (and put it into the cache)
  21. /******/ var module = installedModules[moduleId] = {
  22. /******/ exports: {},
  23. /******/ id: moduleId,
  24. /******/ loaded: false
  25. /******/ };
  26. /******/ // Execute the module function
  27. /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  28. /******/ // Flag the module as loaded
  29. /******/ module.loaded = true;
  30. /******/ // Return the exports of the module
  31. /******/ return module.exports;
  32. /******/ }
  33. /******/ // expose the modules object (__webpack_modules__)
  34. /******/ __webpack_require__.m = modules;
  35. /******/ // expose the module cache
  36. /******/ __webpack_require__.c = installedModules;
  37. /******/ // __webpack_public_path__
  38. /******/ __webpack_require__.p = "";
  39. /******/ // Load entry module and return exports
  40. /******/ return __webpack_require__(0);
  41. /******/ })
  42. /************************************************************************/
  43. /******/ ([
  44. /* 0 */
  45. /***/ function(module, exports, __webpack_require__) {
  46. 'use strict';
  47. var $ = __webpack_require__(1);
  48. var UI = __webpack_require__(2);
  49. __webpack_require__(3);
  50. __webpack_require__(4);
  51. __webpack_require__(5);
  52. __webpack_require__(6);
  53. __webpack_require__(7);
  54. __webpack_require__(8);
  55. __webpack_require__(9);
  56. __webpack_require__(10);
  57. __webpack_require__(11);
  58. __webpack_require__(14);
  59. __webpack_require__(15);
  60. __webpack_require__(16);
  61. __webpack_require__(17);
  62. __webpack_require__(18);
  63. __webpack_require__(19);
  64. __webpack_require__(20);
  65. __webpack_require__(21);
  66. __webpack_require__(22);
  67. __webpack_require__(24);
  68. __webpack_require__(25);
  69. __webpack_require__(23);
  70. __webpack_require__(27);
  71. __webpack_require__(28);
  72. __webpack_require__(29);
  73. __webpack_require__(30);
  74. __webpack_require__(31);
  75. __webpack_require__(32);
  76. __webpack_require__(33);
  77. __webpack_require__(26);
  78. __webpack_require__(34);
  79. __webpack_require__(35);
  80. __webpack_require__(36);
  81. __webpack_require__(37);
  82. __webpack_require__(38);
  83. __webpack_require__(39);
  84. __webpack_require__(40);
  85. __webpack_require__(41);
  86. __webpack_require__(42);
  87. __webpack_require__(43);
  88. __webpack_require__(44);
  89. __webpack_require__(45);
  90. __webpack_require__(46);
  91. __webpack_require__(47);
  92. __webpack_require__(48);
  93. __webpack_require__(49);
  94. __webpack_require__(50);
  95. __webpack_require__(51);
  96. __webpack_require__(52);
  97. __webpack_require__(53);
  98. __webpack_require__(54);
  99. module.exports = $.AMUI = UI;
  100. /***/ },
  101. /* 1 */
  102. /***/ function(module, exports) {
  103. module.exports = __WEBPACK_EXTERNAL_MODULE_1__;
  104. /***/ },
  105. /* 2 */
  106. /***/ function(module, exports, __webpack_require__) {
  107. 'use strict';
  108. var $ = __webpack_require__(1);
  109. if (typeof $ === 'undefined') {
  110. throw new Error('Amaze UI 2.x requires jQuery :-(\n' +
  111. '\u7231\u4e0a\u4e00\u5339\u91ce\u9a6c\uff0c\u53ef\u4f60' +
  112. '\u7684\u5bb6\u91cc\u6ca1\u6709\u8349\u539f\u2026');
  113. }
  114. var UI = $.AMUI || {};
  115. var $win = $(window);
  116. var doc = window.document;
  117. var $html = $('html');
  118. UI.VERSION = '2.7.2';
  119. UI.support = {};
  120. UI.support.transition = (function() {
  121. var transitionEnd = (function() {
  122. // https://developer.mozilla.org/en-US/docs/Web/Events/transitionend#Browser_compatibility
  123. var element = doc.body || doc.documentElement;
  124. var transEndEventNames = {
  125. WebkitTransition: 'webkitTransitionEnd',
  126. MozTransition: 'transitionend',
  127. OTransition: 'oTransitionEnd otransitionend',
  128. transition: 'transitionend'
  129. };
  130. for (var name in transEndEventNames) {
  131. if (element.style[name] !== undefined) {
  132. return transEndEventNames[name];
  133. }
  134. }
  135. })();
  136. return transitionEnd && {end: transitionEnd};
  137. })();
  138. UI.support.animation = (function() {
  139. var animationEnd = (function() {
  140. var element = doc.body || doc.documentElement;
  141. var animEndEventNames = {
  142. WebkitAnimation: 'webkitAnimationEnd',
  143. MozAnimation: 'animationend',
  144. OAnimation: 'oAnimationEnd oanimationend',
  145. animation: 'animationend'
  146. };
  147. for (var name in animEndEventNames) {
  148. if (element.style[name] !== undefined) {
  149. return animEndEventNames[name];
  150. }
  151. }
  152. })();
  153. return animationEnd && {end: animationEnd};
  154. })();
  155. /* eslint-disable dot-notation */
  156. UI.support.touch = (
  157. ('ontouchstart' in window &&
  158. navigator.userAgent.toLowerCase().match(/mobile|tablet/)) ||
  159. (window.DocumentTouch && document instanceof window.DocumentTouch) ||
  160. (window.navigator['msPointerEnabled'] &&
  161. window.navigator['msMaxTouchPoints'] > 0) || // IE 10
  162. (window.navigator['pointerEnabled'] &&
  163. window.navigator['maxTouchPoints'] > 0) || // IE >=11
  164. false);
  165. /* eslint-enable dot-notation */
  166. // https://developer.mozilla.org/zh-CN/docs/DOM/MutationObserver
  167. UI.support.mutationobserver = (window.MutationObserver ||
  168. window.WebKitMutationObserver || null);
  169. // https://github.com/Modernizr/Modernizr/blob/924c7611c170ef2dc502582e5079507aff61e388/feature-detects/forms/validation.js#L20
  170. UI.support.formValidation = (typeof document.createElement('form').
  171. checkValidity === 'function');
  172. UI.utils = {};
  173. /**
  174. * Debounce function
  175. *
  176. * @param {function} func Function to be debounced
  177. * @param {number} wait Function execution threshold in milliseconds
  178. * @param {bool} immediate Whether the function should be called at
  179. * the beginning of the delay instead of the
  180. * end. Default is false.
  181. * @description Executes a function when it stops being invoked for n seconds
  182. * @see _.debounce() http://underscorejs.org
  183. */
  184. UI.utils.debounce = function(func, wait, immediate) {
  185. var timeout;
  186. return function() {
  187. var context = this;
  188. var args = arguments;
  189. var later = function() {
  190. timeout = null;
  191. if (!immediate) {
  192. func.apply(context, args);
  193. }
  194. };
  195. var callNow = immediate && !timeout;
  196. clearTimeout(timeout);
  197. timeout = setTimeout(later, wait);
  198. if (callNow) {
  199. func.apply(context, args);
  200. }
  201. };
  202. };
  203. UI.utils.isInView = function(element, options) {
  204. var $element = $(element);
  205. var visible = !!($element.width() || $element.height()) &&
  206. $element.css('display') !== 'none';
  207. if (!visible) {
  208. return false;
  209. }
  210. var windowLeft = $win.scrollLeft();
  211. var windowTop = $win.scrollTop();
  212. var offset = $element.offset();
  213. var left = offset.left;
  214. var top = offset.top;
  215. options = $.extend({topOffset: 0, leftOffset: 0}, options);
  216. return (top + $element.height() >= windowTop &&
  217. top - options.topOffset <= windowTop + $win.height() &&
  218. left + $element.width() >= windowLeft &&
  219. left - options.leftOffset <= windowLeft + $win.width());
  220. };
  221. UI.utils.parseOptions = UI.utils.options = function(string) {
  222. if ($.isPlainObject(string)) {
  223. return string;
  224. }
  225. var start = (string ? string.indexOf('{') : -1);
  226. var options = {};
  227. if (start != -1) {
  228. try {
  229. options = (new Function('',
  230. 'var json = ' + string.substr(start) +
  231. '; return JSON.parse(JSON.stringify(json));'))();
  232. } catch (e) {
  233. }
  234. }
  235. return options;
  236. };
  237. UI.utils.generateGUID = function(namespace) {
  238. var uid = namespace + '-' || 'am-';
  239. do {
  240. uid += Math.random().toString(36).substring(2, 7);
  241. } while (document.getElementById(uid));
  242. return uid;
  243. };
  244. // @see https://davidwalsh.name/get-absolute-url
  245. UI.utils.getAbsoluteUrl = (function() {
  246. var a;
  247. return function(url) {
  248. if (!a) {
  249. a = document.createElement('a');
  250. }
  251. a.href = url;
  252. return a.href;
  253. };
  254. })();
  255. /**
  256. * Plugin AMUI Component to jQuery
  257. *
  258. * @param {String} name - plugin name
  259. * @param {Function} Component - plugin constructor
  260. * @param {Object} [pluginOption]
  261. * @param {String} pluginOption.dataOptions
  262. * @param {Function} pluginOption.methodCall - custom method call
  263. * @param {Function} pluginOption.before
  264. * @param {Function} pluginOption.after
  265. * @since v2.4.1
  266. */
  267. UI.plugin = function UIPlugin(name, Component, pluginOption) {
  268. var old = $.fn[name];
  269. pluginOption = pluginOption || {};
  270. $.fn[name] = function(option) {
  271. var allArgs = Array.prototype.slice.call(arguments, 0);
  272. var args = allArgs.slice(1);
  273. var propReturn;
  274. var $set = this.each(function() {
  275. var $this = $(this);
  276. var dataName = 'amui.' + name;
  277. var dataOptionsName = pluginOption.dataOptions || ('data-am-' + name);
  278. var instance = $this.data(dataName);
  279. var options = $.extend({},
  280. UI.utils.parseOptions($this.attr(dataOptionsName)),
  281. typeof option === 'object' && option);
  282. if (!instance && option === 'destroy') {
  283. return;
  284. }
  285. if (!instance) {
  286. $this.data(dataName, (instance = new Component(this, options)));
  287. }
  288. // custom method call
  289. if (pluginOption.methodCall) {
  290. pluginOption.methodCall.call($this, allArgs, instance);
  291. } else {
  292. // before method call
  293. pluginOption.before &&
  294. pluginOption.before.call($this, allArgs, instance);
  295. if (typeof option === 'string') {
  296. propReturn = typeof instance[option] === 'function' ?
  297. instance[option].apply(instance, args) : instance[option];
  298. }
  299. // after method call
  300. pluginOption.after && pluginOption.after.call($this, allArgs, instance);
  301. }
  302. });
  303. return (propReturn === undefined) ? $set : propReturn;
  304. };
  305. $.fn[name].Constructor = Component;
  306. // no conflict
  307. $.fn[name].noConflict = function() {
  308. $.fn[name] = old;
  309. return this;
  310. };
  311. UI[name] = Component;
  312. };
  313. // http://blog.alexmaccaw.com/css-transitions
  314. $.fn.emulateTransitionEnd = function(duration) {
  315. var called = false;
  316. var $el = this;
  317. $(this).one(UI.support.transition.end, function() {
  318. called = true;
  319. });
  320. var callback = function() {
  321. if (!called) {
  322. $($el).trigger(UI.support.transition.end);
  323. }
  324. $el.transitionEndTimmer = undefined;
  325. };
  326. this.transitionEndTimmer = setTimeout(callback, duration);
  327. return this;
  328. };
  329. $.fn.redraw = function() {
  330. return this.each(function() {
  331. /* eslint-disable */
  332. var redraw = this.offsetHeight;
  333. /* eslint-enable */
  334. });
  335. };
  336. $.fn.transitionEnd = function(callback) {
  337. var endEvent = UI.support.transition.end;
  338. var dom = this;
  339. function fireCallBack(e) {
  340. callback.call(this, e);
  341. endEvent && dom.off(endEvent, fireCallBack);
  342. }
  343. if (callback && endEvent) {
  344. dom.on(endEvent, fireCallBack);
  345. }
  346. return this;
  347. };
  348. $.fn.removeClassRegEx = function() {
  349. return this.each(function(regex) {
  350. var classes = $(this).attr('class');
  351. if (!classes || !regex) {
  352. return false;
  353. }
  354. var classArray = [];
  355. classes = classes.split(' ');
  356. for (var i = 0, len = classes.length; i < len; i++) {
  357. if (!classes[i].match(regex)) {
  358. classArray.push(classes[i]);
  359. }
  360. }
  361. $(this).attr('class', classArray.join(' '));
  362. });
  363. };
  364. //
  365. $.fn.alterClass = function(removals, additions) {
  366. var self = this;
  367. if (removals.indexOf('*') === -1) {
  368. // Use native jQuery methods if there is no wildcard matching
  369. self.removeClass(removals);
  370. return !additions ? self : self.addClass(additions);
  371. }
  372. var classPattern = new RegExp('\\s' +
  373. removals.
  374. replace(/\*/g, '[A-Za-z0-9-_]+').
  375. split(' ').
  376. join('\\s|\\s') +
  377. '\\s', 'g');
  378. self.each(function(i, it) {
  379. var cn = ' ' + it.className + ' ';
  380. while (classPattern.test(cn)) {
  381. cn = cn.replace(classPattern, ' ');
  382. }
  383. it.className = $.trim(cn);
  384. });
  385. return !additions ? self : self.addClass(additions);
  386. };
  387. // handle multiple browsers for requestAnimationFrame()
  388. // http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
  389. // https://github.com/gnarf/jquery-requestAnimationFrame
  390. UI.utils.rAF = (function() {
  391. return window.requestAnimationFrame ||
  392. window.webkitRequestAnimationFrame ||
  393. window.mozRequestAnimationFrame ||
  394. window.oRequestAnimationFrame ||
  395. // if all else fails, use setTimeout
  396. function(callback) {
  397. return window.setTimeout(callback, 1000 / 60); // shoot for 60 fps
  398. };
  399. })();
  400. // handle multiple browsers for cancelAnimationFrame()
  401. UI.utils.cancelAF = (function() {
  402. return window.cancelAnimationFrame ||
  403. window.webkitCancelAnimationFrame ||
  404. window.mozCancelAnimationFrame ||
  405. window.oCancelAnimationFrame ||
  406. function(id) {
  407. window.clearTimeout(id);
  408. };
  409. })();
  410. // via http://davidwalsh.name/detect-scrollbar-width
  411. UI.utils.measureScrollbar = function() {
  412. if (document.body.clientWidth >= window.innerWidth) {
  413. return 0;
  414. }
  415. // if ($html.width() >= window.innerWidth) return;
  416. // var scrollbarWidth = window.innerWidth - $html.width();
  417. var $measure = $('<div ' +
  418. 'style="width: 100px;height: 100px;overflow: scroll;' +
  419. 'position: absolute;top: -9999px;"></div>');
  420. $(document.body).append($measure);
  421. var scrollbarWidth = $measure[0].offsetWidth - $measure[0].clientWidth;
  422. $measure.remove();
  423. return scrollbarWidth;
  424. };
  425. UI.utils.imageLoader = function($image, callback) {
  426. function loaded() {
  427. callback($image[0]);
  428. }
  429. function bindLoad() {
  430. this.one('load', loaded);
  431. if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) {
  432. var src = this.attr('src');
  433. var param = src.match(/\?/) ? '&' : '?';
  434. param += 'random=' + (new Date()).getTime();
  435. this.attr('src', src + param);
  436. }
  437. }
  438. if (!$image.attr('src')) {
  439. loaded();
  440. return;
  441. }
  442. if ($image[0].complete || $image[0].readyState === 4) {
  443. loaded();
  444. } else {
  445. bindLoad.call($image);
  446. }
  447. };
  448. /**
  449. * @see https://github.com/cho45/micro-template.js
  450. * (c) cho45 http://cho45.github.com/mit-license
  451. */
  452. UI.template = function(id, data) {
  453. var me = UI.template;
  454. if (!me.cache[id]) {
  455. me.cache[id] = (function() {
  456. var name = id;
  457. var string = /^[\w\-]+$/.test(id) ?
  458. me.get(id) : (name = 'template(string)', id); // no warnings
  459. var line = 1;
  460. /* eslint-disable max-len, quotes */
  461. var body = ('try { ' + (me.variable ?
  462. 'var ' + me.variable + ' = this.stash;' : 'with (this.stash) { ') +
  463. "this.ret += '" +
  464. string.
  465. replace(/<%/g, '\x11').replace(/%>/g, '\x13'). // if you want other tag, just edit this line
  466. replace(/'(?![^\x11\x13]+?\x13)/g, '\\x27').
  467. replace(/^\s*|\s*$/g, '').
  468. replace(/\n/g, function() {
  469. return "';\nthis.line = " + (++line) + "; this.ret += '\\n";
  470. }).
  471. replace(/\x11-(.+?)\x13/g, "' + ($1) + '").
  472. replace(/\x11=(.+?)\x13/g, "' + this.escapeHTML($1) + '").
  473. replace(/\x11(.+?)\x13/g, "'; $1; this.ret += '") +
  474. "'; " + (me.variable ? "" : "}") + "return this.ret;" +
  475. "} catch (e) { throw 'TemplateError: ' + e + ' (on " + name +
  476. "' + ' line ' + this.line + ')'; } " +
  477. "//@ sourceURL=" + name + "\n" // source map
  478. ).replace(/this\.ret \+= '';/g, '');
  479. /* eslint-enable max-len, quotes */
  480. var func = new Function(body);
  481. var map = {
  482. '&': '&amp;',
  483. '<': '&lt;',
  484. '>': '&gt;',
  485. '\x22': '&#x22;',
  486. '\x27': '&#x27;'
  487. };
  488. var escapeHTML = function(string) {
  489. return ('' + string).replace(/[&<>\'\"]/g, function(_) {
  490. return map[_];
  491. });
  492. };
  493. return function(stash) {
  494. return func.call(me.context = {
  495. escapeHTML: escapeHTML,
  496. line: 1,
  497. ret: '',
  498. stash: stash
  499. });
  500. };
  501. })();
  502. }
  503. return data ? me.cache[id](data) : me.cache[id];
  504. };
  505. UI.template.cache = {};
  506. UI.template.get = function(id) {
  507. if (id) {
  508. var element = document.getElementById(id);
  509. return element && element.innerHTML || '';
  510. }
  511. };
  512. // Dom mutation watchers
  513. UI.DOMWatchers = [];
  514. UI.DOMReady = false;
  515. UI.ready = function(callback) {
  516. UI.DOMWatchers.push(callback);
  517. if (UI.DOMReady) {
  518. // console.log('Ready call');
  519. callback(document);
  520. }
  521. };
  522. UI.DOMObserve = function(elements, options, callback) {
  523. var Observer = UI.support.mutationobserver;
  524. if (!Observer) {
  525. return;
  526. }
  527. options = $.isPlainObject(options) ?
  528. options : {childList: true, subtree: true};
  529. callback = typeof callback === 'function' && callback || function() {
  530. };
  531. $(elements).each(function() {
  532. var element = this;
  533. var $element = $(element);
  534. if ($element.data('am.observer')) {
  535. return;
  536. }
  537. try {
  538. var observer = new Observer(UI.utils.debounce(
  539. function(mutations, instance) {
  540. callback.call(element, mutations, instance);
  541. // trigger this event manually if MutationObserver not supported
  542. $element.trigger('changed.dom.amui');
  543. }, 50));
  544. observer.observe(element, options);
  545. $element.data('am.observer', observer);
  546. } catch (e) {
  547. }
  548. });
  549. };
  550. $.fn.DOMObserve = function(options, callback) {
  551. return this.each(function() {
  552. /* eslint-disable new-cap */
  553. UI.DOMObserve(this, options, callback);
  554. /* eslint-enable new-cap */
  555. });
  556. };
  557. if (UI.support.touch) {
  558. $html.addClass('am-touch');
  559. }
  560. $(document).on('changed.dom.amui', function(e) {
  561. var element = e.target;
  562. // TODO: just call changed element's watcher
  563. // every watcher callback should have a key
  564. // use like this: <div data-am-observe='key1, key2'>
  565. // get keys via $(element).data('amObserve')
  566. // call functions store with these keys
  567. $.each(UI.DOMWatchers, function(i, watcher) {
  568. watcher(element);
  569. });
  570. });
  571. $(function() {
  572. var $body = $(document.body);
  573. UI.DOMReady = true;
  574. // Run default init
  575. $.each(UI.DOMWatchers, function(i, watcher) {
  576. watcher(document);
  577. });
  578. // watches DOM
  579. /* eslint-disable new-cap */
  580. UI.DOMObserve('[data-am-observe]');
  581. /* eslint-enable */
  582. $html.removeClass('no-js').addClass('js');
  583. UI.support.animation && $html.addClass('cssanimations');
  584. // iOS standalone mode
  585. if (window.navigator.standalone) {
  586. $html.addClass('am-standalone');
  587. }
  588. $('.am-topbar-fixed-top').length &&
  589. $body.addClass('am-with-topbar-fixed-top');
  590. $('.am-topbar-fixed-bottom').length &&
  591. $body.addClass('am-with-topbar-fixed-bottom');
  592. // Remove responsive classes in .am-layout
  593. var $layout = $('.am-layout');
  594. $layout.find('[class*="md-block-grid"]').alterClass('md-block-grid-*');
  595. $layout.find('[class*="lg-block-grid"]').alterClass('lg-block-grid');
  596. // widgets not in .am-layout
  597. $('[data-am-widget]').each(function() {
  598. var $widget = $(this);
  599. // console.log($widget.parents('.am-layout').length)
  600. if ($widget.parents('.am-layout').length === 0) {
  601. $widget.addClass('am-no-layout');
  602. }
  603. });
  604. });
  605. module.exports = UI;
  606. /***/ },
  607. /* 3 */
  608. /***/ function(module, exports, __webpack_require__) {
  609. /*! Hammer.JS - v2.0.8 - 2016-04-22
  610. * http://hammerjs.github.io/
  611. *
  612. * Copyright (c) 2016 Jorik Tangelder;
  613. * Licensed under the MIT license */
  614. 'use strict';
  615. var $ = __webpack_require__(1);
  616. var UI = __webpack_require__(2);
  617. var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
  618. var TEST_ELEMENT = document.createElement('div');
  619. var TYPE_FUNCTION = 'function';
  620. var round = Math.round;
  621. var abs = Math.abs;
  622. var now = Date.now;
  623. /**
  624. * set a timeout with a given scope
  625. * @param {Function} fn
  626. * @param {Number} timeout
  627. * @param {Object} context
  628. * @returns {number}
  629. */
  630. function setTimeoutContext(fn, timeout, context) {
  631. return setTimeout(bindFn(fn, context), timeout);
  632. }
  633. /**
  634. * if the argument is an array, we want to execute the fn on each entry
  635. * if it aint an array we don't want to do a thing.
  636. * this is used by all the methods that accept a single and array argument.
  637. * @param {*|Array} arg
  638. * @param {String} fn
  639. * @param {Object} [context]
  640. * @returns {Boolean}
  641. */
  642. function invokeArrayArg(arg, fn, context) {
  643. if (Array.isArray(arg)) {
  644. each(arg, context[fn], context);
  645. return true;
  646. }
  647. return false;
  648. }
  649. /**
  650. * walk objects and arrays
  651. * @param {Object} obj
  652. * @param {Function} iterator
  653. * @param {Object} context
  654. */
  655. function each(obj, iterator, context) {
  656. var i;
  657. if (!obj) {
  658. return;
  659. }
  660. if (obj.forEach) {
  661. obj.forEach(iterator, context);
  662. } else if (obj.length !== undefined) {
  663. i = 0;
  664. while (i < obj.length) {
  665. iterator.call(context, obj[i], i, obj);
  666. i++;
  667. }
  668. } else {
  669. for (i in obj) {
  670. obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
  671. }
  672. }
  673. }
  674. /**
  675. * wrap a method with a deprecation warning and stack trace
  676. * @param {Function} method
  677. * @param {String} name
  678. * @param {String} message
  679. * @returns {Function} A new function wrapping the supplied method.
  680. */
  681. function deprecate(method, name, message) {
  682. var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n';
  683. return function() {
  684. var e = new Error('get-stack-trace');
  685. var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '')
  686. .replace(/^\s+at\s+/gm, '')
  687. .replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';
  688. var log = window.console && (window.console.warn || window.console.log);
  689. if (log) {
  690. log.call(window.console, deprecationMessage, stack);
  691. }
  692. return method.apply(this, arguments);
  693. };
  694. }
  695. /**
  696. * extend object.
  697. * means that properties in dest will be overwritten by the ones in src.
  698. * @param {Object} target
  699. * @param {...Object} objects_to_assign
  700. * @returns {Object} target
  701. */
  702. var assign;
  703. if (typeof Object.assign !== 'function') {
  704. assign = function assign(target) {
  705. if (target === undefined || target === null) {
  706. throw new TypeError('Cannot convert undefined or null to object');
  707. }
  708. var output = Object(target);
  709. for (var index = 1; index < arguments.length; index++) {
  710. var source = arguments[index];
  711. if (source !== undefined && source !== null) {
  712. for (var nextKey in source) {
  713. if (source.hasOwnProperty(nextKey)) {
  714. output[nextKey] = source[nextKey];
  715. }
  716. }
  717. }
  718. }
  719. return output;
  720. };
  721. } else {
  722. assign = Object.assign;
  723. }
  724. /**
  725. * extend object.
  726. * means that properties in dest will be overwritten by the ones in src.
  727. * @param {Object} dest
  728. * @param {Object} src
  729. * @param {Boolean} [merge=false]
  730. * @returns {Object} dest
  731. */
  732. var extend = deprecate(function extend(dest, src, merge) {
  733. var keys = Object.keys(src);
  734. var i = 0;
  735. while (i < keys.length) {
  736. if (!merge || (merge && dest[keys[i]] === undefined)) {
  737. dest[keys[i]] = src[keys[i]];
  738. }
  739. i++;
  740. }
  741. return dest;
  742. }, 'extend', 'Use `assign`.');
  743. /**
  744. * merge the values from src in the dest.
  745. * means that properties that exist in dest will not be overwritten by src
  746. * @param {Object} dest
  747. * @param {Object} src
  748. * @returns {Object} dest
  749. */
  750. var merge = deprecate(function merge(dest, src) {
  751. return extend(dest, src, true);
  752. }, 'merge', 'Use `assign`.');
  753. /**
  754. * simple class inheritance
  755. * @param {Function} child
  756. * @param {Function} base
  757. * @param {Object} [properties]
  758. */
  759. function inherit(child, base, properties) {
  760. var baseP = base.prototype,
  761. childP;
  762. childP = child.prototype = Object.create(baseP);
  763. childP.constructor = child;
  764. childP._super = baseP;
  765. if (properties) {
  766. assign(childP, properties);
  767. }
  768. }
  769. /**
  770. * simple function bind
  771. * @param {Function} fn
  772. * @param {Object} context
  773. * @returns {Function}
  774. */
  775. function bindFn(fn, context) {
  776. return function boundFn() {
  777. return fn.apply(context, arguments);
  778. };
  779. }
  780. /**
  781. * let a boolean value also be a function that must return a boolean
  782. * this first item in args will be used as the context
  783. * @param {Boolean|Function} val
  784. * @param {Array} [args]
  785. * @returns {Boolean}
  786. */
  787. function boolOrFn(val, args) {
  788. if (typeof val == TYPE_FUNCTION) {
  789. return val.apply(args ? args[0] || undefined : undefined, args);
  790. }
  791. return val;
  792. }
  793. /**
  794. * use the val2 when val1 is undefined
  795. * @param {*} val1
  796. * @param {*} val2
  797. * @returns {*}
  798. */
  799. function ifUndefined(val1, val2) {
  800. return (val1 === undefined) ? val2 : val1;
  801. }
  802. /**
  803. * addEventListener with multiple events at once
  804. * @param {EventTarget} target
  805. * @param {String} types
  806. * @param {Function} handler
  807. */
  808. function addEventListeners(target, types, handler) {
  809. each(splitStr(types), function(type) {
  810. target.addEventListener(type, handler, false);
  811. });
  812. }
  813. /**
  814. * removeEventListener with multiple events at once
  815. * @param {EventTarget} target
  816. * @param {String} types
  817. * @param {Function} handler
  818. */
  819. function removeEventListeners(target, types, handler) {
  820. each(splitStr(types), function(type) {
  821. target.removeEventListener(type, handler, false);
  822. });
  823. }
  824. /**
  825. * find if a node is in the given parent
  826. * @method hasParent
  827. * @param {HTMLElement} node
  828. * @param {HTMLElement} parent
  829. * @return {Boolean} found
  830. */
  831. function hasParent(node, parent) {
  832. while (node) {
  833. if (node == parent) {
  834. return true;
  835. }
  836. node = node.parentNode;
  837. }
  838. return false;
  839. }
  840. /**
  841. * small indexOf wrapper
  842. * @param {String} str
  843. * @param {String} find
  844. * @returns {Boolean} found
  845. */
  846. function inStr(str, find) {
  847. return str.indexOf(find) > -1;
  848. }
  849. /**
  850. * split string on whitespace
  851. * @param {String} str
  852. * @returns {Array} words
  853. */
  854. function splitStr(str) {
  855. return str.trim().split(/\s+/g);
  856. }
  857. /**
  858. * find if a array contains the object using indexOf or a simple polyFill
  859. * @param {Array} src
  860. * @param {String} find
  861. * @param {String} [findByKey]
  862. * @return {Boolean|Number} false when not found, or the index
  863. */
  864. function inArray(src, find, findByKey) {
  865. if (src.indexOf && !findByKey) {
  866. return src.indexOf(find);
  867. } else {
  868. var i = 0;
  869. while (i < src.length) {
  870. if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {
  871. return i;
  872. }
  873. i++;
  874. }
  875. return -1;
  876. }
  877. }
  878. /**
  879. * convert array-like objects to real arrays
  880. * @param {Object} obj
  881. * @returns {Array}
  882. */
  883. function toArray(obj) {
  884. return Array.prototype.slice.call(obj, 0);
  885. }
  886. /**
  887. * unique array with objects based on a key (like 'id') or just by the array's value
  888. * @param {Array} src [{id:1},{id:2},{id:1}]
  889. * @param {String} [key]
  890. * @param {Boolean} [sort=False]
  891. * @returns {Array} [{id:1},{id:2}]
  892. */
  893. function uniqueArray(src, key, sort) {
  894. var results = [];
  895. var values = [];
  896. var i = 0;
  897. while (i < src.length) {
  898. var val = key ? src[i][key] : src[i];
  899. if (inArray(values, val) < 0) {
  900. results.push(src[i]);
  901. }
  902. values[i] = val;
  903. i++;
  904. }
  905. if (sort) {
  906. if (!key) {
  907. results = results.sort();
  908. } else {
  909. results = results.sort(function sortUniqueArray(a, b) {
  910. return a[key] > b[key];
  911. });
  912. }
  913. }
  914. return results;
  915. }
  916. /**
  917. * get the prefixed property
  918. * @param {Object} obj
  919. * @param {String} property
  920. * @returns {String|Undefined} prefixed
  921. */
  922. function prefixed(obj, property) {
  923. var prefix, prop;
  924. var camelProp = property[0].toUpperCase() + property.slice(1);
  925. var i = 0;
  926. while (i < VENDOR_PREFIXES.length) {
  927. prefix = VENDOR_PREFIXES[i];
  928. prop = (prefix) ? prefix + camelProp : property;
  929. if (prop in obj) {
  930. return prop;
  931. }
  932. i++;
  933. }
  934. return undefined;
  935. }
  936. /**
  937. * get a unique id
  938. * @returns {number} uniqueId
  939. */
  940. var _uniqueId = 1;
  941. function uniqueId() {
  942. return _uniqueId++;
  943. }
  944. /**
  945. * get the window object of an element
  946. * @param {HTMLElement} element
  947. * @returns {DocumentView|Window}
  948. */
  949. function getWindowForElement(element) {
  950. var doc = element.ownerDocument || element;
  951. return (doc.defaultView || doc.parentWindow || window);
  952. }
  953. var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
  954. var SUPPORT_TOUCH = ('ontouchstart' in window);
  955. var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined;
  956. var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
  957. var INPUT_TYPE_TOUCH = 'touch';
  958. var INPUT_TYPE_PEN = 'pen';
  959. var INPUT_TYPE_MOUSE = 'mouse';
  960. var INPUT_TYPE_KINECT = 'kinect';
  961. var COMPUTE_INTERVAL = 25;
  962. var INPUT_START = 1;
  963. var INPUT_MOVE = 2;
  964. var INPUT_END = 4;
  965. var INPUT_CANCEL = 8;
  966. var DIRECTION_NONE = 1;
  967. var DIRECTION_LEFT = 2;
  968. var DIRECTION_RIGHT = 4;
  969. var DIRECTION_UP = 8;
  970. var DIRECTION_DOWN = 16;
  971. var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
  972. var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
  973. var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
  974. var PROPS_XY = ['x', 'y'];
  975. var PROPS_CLIENT_XY = ['clientX', 'clientY'];
  976. /**
  977. * create new input type manager
  978. * @param {Manager} manager
  979. * @param {Function} callback
  980. * @returns {Input}
  981. * @constructor
  982. */
  983. function Input(manager, callback) {
  984. var self = this;
  985. this.manager = manager;
  986. this.callback = callback;
  987. this.element = manager.element;
  988. this.target = manager.options.inputTarget;
  989. // smaller wrapper around the handler, for the scope and the enabled state of the manager,
  990. // so when disabled the input events are completely bypassed.
  991. this.domHandler = function(ev) {
  992. if (boolOrFn(manager.options.enable, [manager])) {
  993. self.handler(ev);
  994. }
  995. };
  996. this.init();
  997. }
  998. Input.prototype = {
  999. /**
  1000. * should handle the inputEvent data and trigger the callback
  1001. * @virtual
  1002. */
  1003. handler: function() { },
  1004. /**
  1005. * bind the events
  1006. */
  1007. init: function() {
  1008. this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
  1009. this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
  1010. this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
  1011. },
  1012. /**
  1013. * unbind the events
  1014. */
  1015. destroy: function() {
  1016. this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
  1017. this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
  1018. this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
  1019. }
  1020. };
  1021. /**
  1022. * create new input type manager
  1023. * called by the Manager constructor
  1024. * @param {Hammer} manager
  1025. * @returns {Input}
  1026. */
  1027. function createInputInstance(manager) {
  1028. var Type;
  1029. var inputClass = manager.options.inputClass;
  1030. if (inputClass) {
  1031. Type = inputClass;
  1032. } else if (SUPPORT_POINTER_EVENTS) {
  1033. Type = PointerEventInput;
  1034. } else if (SUPPORT_ONLY_TOUCH) {
  1035. Type = TouchInput;
  1036. } else if (!SUPPORT_TOUCH) {
  1037. Type = MouseInput;
  1038. } else {
  1039. Type = TouchMouseInput;
  1040. }
  1041. return new (Type)(manager, inputHandler);
  1042. }
  1043. /**
  1044. * handle input events
  1045. * @param {Manager} manager
  1046. * @param {String} eventType
  1047. * @param {Object} input
  1048. */
  1049. function inputHandler(manager, eventType, input) {
  1050. var pointersLen = input.pointers.length;
  1051. var changedPointersLen = input.changedPointers.length;
  1052. var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0));
  1053. var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0));
  1054. input.isFirst = !!isFirst;
  1055. input.isFinal = !!isFinal;
  1056. if (isFirst) {
  1057. manager.session = {};
  1058. }
  1059. // source event is the normalized value of the domEvents
  1060. // like 'touchstart, mouseup, pointerdown'
  1061. input.eventType = eventType;
  1062. // compute scale, rotation etc
  1063. computeInputData(manager, input);
  1064. // emit secret event
  1065. manager.emit('hammer.input', input);
  1066. manager.recognize(input);
  1067. manager.session.prevInput = input;
  1068. }
  1069. /**
  1070. * extend the data with some usable properties like scale, rotate, velocity etc
  1071. * @param {Object} manager
  1072. * @param {Object} input
  1073. */
  1074. function computeInputData(manager, input) {
  1075. var session = manager.session;
  1076. var pointers = input.pointers;
  1077. var pointersLength = pointers.length;
  1078. // store the first input to calculate the distance and direction
  1079. if (!session.firstInput) {
  1080. session.firstInput = simpleCloneInputData(input);
  1081. }
  1082. // to compute scale and rotation we need to store the multiple touches
  1083. if (pointersLength > 1 && !session.firstMultiple) {
  1084. session.firstMultiple = simpleCloneInputData(input);
  1085. } else if (pointersLength === 1) {
  1086. session.firstMultiple = false;
  1087. }
  1088. var firstInput = session.firstInput;
  1089. var firstMultiple = session.firstMultiple;
  1090. var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;
  1091. var center = input.center = getCenter(pointers);
  1092. input.timeStamp = now();
  1093. input.deltaTime = input.timeStamp - firstInput.timeStamp;
  1094. input.angle = getAngle(offsetCenter, center);
  1095. input.distance = getDistance(offsetCenter, center);
  1096. computeDeltaXY(session, input);
  1097. input.offsetDirection = getDirection(input.deltaX, input.deltaY);
  1098. var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);
  1099. input.overallVelocityX = overallVelocity.x;
  1100. input.overallVelocityY = overallVelocity.y;
  1101. input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y;
  1102. input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
  1103. input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;
  1104. input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length >
  1105. session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers);
  1106. computeIntervalInputData(session, input);
  1107. // find the correct target
  1108. var target = manager.element;
  1109. if (hasParent(input.srcEvent.target, target)) {
  1110. target = input.srcEvent.target;
  1111. }
  1112. input.target = target;
  1113. }
  1114. function computeDeltaXY(session, input) {
  1115. var center = input.center;
  1116. var offset = session.offsetDelta || {};
  1117. var prevDelta = session.prevDelta || {};
  1118. var prevInput = session.prevInput || {};
  1119. if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
  1120. prevDelta = session.prevDelta = {
  1121. x: prevInput.deltaX || 0,
  1122. y: prevInput.deltaY || 0
  1123. };
  1124. offset = session.offsetDelta = {
  1125. x: center.x,
  1126. y: center.y
  1127. };
  1128. }
  1129. input.deltaX = prevDelta.x + (center.x - offset.x);
  1130. input.deltaY = prevDelta.y + (center.y - offset.y);
  1131. }
  1132. /**
  1133. * velocity is calculated every x ms
  1134. * @param {Object} session
  1135. * @param {Object} input
  1136. */
  1137. function computeIntervalInputData(session, input) {
  1138. var last = session.lastInterval || input,
  1139. deltaTime = input.timeStamp - last.timeStamp,
  1140. velocity, velocityX, velocityY, direction;
  1141. if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {
  1142. var deltaX = input.deltaX - last.deltaX;
  1143. var deltaY = input.deltaY - last.deltaY;
  1144. var v = getVelocity(deltaTime, deltaX, deltaY);
  1145. velocityX = v.x;
  1146. velocityY = v.y;
  1147. velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;
  1148. direction = getDirection(deltaX, deltaY);
  1149. session.lastInterval = input;
  1150. } else {
  1151. // use latest velocity info if it doesn't overtake a minimum period
  1152. velocity = last.velocity;
  1153. velocityX = last.velocityX;
  1154. velocityY = last.velocityY;
  1155. direction = last.direction;
  1156. }
  1157. input.velocity = velocity;
  1158. input.velocityX = velocityX;
  1159. input.velocityY = velocityY;
  1160. input.direction = direction;
  1161. }
  1162. /**
  1163. * create a simple clone from the input used for storage of firstInput and firstMultiple
  1164. * @param {Object} input
  1165. * @returns {Object} clonedInputData
  1166. */
  1167. function simpleCloneInputData(input) {
  1168. // make a simple copy of the pointers because we will get a reference if we don't
  1169. // we only need clientXY for the calculations
  1170. var pointers = [];
  1171. var i = 0;
  1172. while (i < input.pointers.length) {
  1173. pointers[i] = {
  1174. clientX: round(input.pointers[i].clientX),
  1175. clientY: round(input.pointers[i].clientY)
  1176. };
  1177. i++;
  1178. }
  1179. return {
  1180. timeStamp: now(),
  1181. pointers: pointers,
  1182. center: getCenter(pointers),
  1183. deltaX: input.deltaX,
  1184. deltaY: input.deltaY
  1185. };
  1186. }
  1187. /**
  1188. * get the center of all the pointers
  1189. * @param {Array} pointers
  1190. * @return {Object} center contains `x` and `y` properties
  1191. */
  1192. function getCenter(pointers) {
  1193. var pointersLength = pointers.length;
  1194. // no need to loop when only one touch
  1195. if (pointersLength === 1) {
  1196. return {
  1197. x: round(pointers[0].clientX),
  1198. y: round(pointers[0].clientY)
  1199. };
  1200. }
  1201. var x = 0, y = 0, i = 0;
  1202. while (i < pointersLength) {
  1203. x += pointers[i].clientX;
  1204. y += pointers[i].clientY;
  1205. i++;
  1206. }
  1207. return {
  1208. x: round(x / pointersLength),
  1209. y: round(y / pointersLength)
  1210. };
  1211. }
  1212. /**
  1213. * calculate the velocity between two points. unit is in px per ms.
  1214. * @param {Number} deltaTime
  1215. * @param {Number} x
  1216. * @param {Number} y
  1217. * @return {Object} velocity `x` and `y`
  1218. */
  1219. function getVelocity(deltaTime, x, y) {
  1220. return {
  1221. x: x / deltaTime || 0,
  1222. y: y / deltaTime || 0
  1223. };
  1224. }
  1225. /**
  1226. * get the direction between two points
  1227. * @param {Number} x
  1228. * @param {Number} y
  1229. * @return {Number} direction
  1230. */
  1231. function getDirection(x, y) {
  1232. if (x === y) {
  1233. return DIRECTION_NONE;
  1234. }
  1235. if (abs(x) >= abs(y)) {
  1236. return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
  1237. }
  1238. return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
  1239. }
  1240. /**
  1241. * calculate the absolute distance between two points
  1242. * @param {Object} p1 {x, y}
  1243. * @param {Object} p2 {x, y}
  1244. * @param {Array} [props] containing x and y keys
  1245. * @return {Number} distance
  1246. */
  1247. function getDistance(p1, p2, props) {
  1248. if (!props) {
  1249. props = PROPS_XY;
  1250. }
  1251. var x = p2[props[0]] - p1[props[0]],
  1252. y = p2[props[1]] - p1[props[1]];
  1253. return Math.sqrt((x * x) + (y * y));
  1254. }
  1255. /**
  1256. * calculate the angle between two coordinates
  1257. * @param {Object} p1
  1258. * @param {Object} p2
  1259. * @param {Array} [props] containing x and y keys
  1260. * @return {Number} angle
  1261. */
  1262. function getAngle(p1, p2, props) {
  1263. if (!props) {
  1264. props = PROPS_XY;
  1265. }
  1266. var x = p2[props[0]] - p1[props[0]],
  1267. y = p2[props[1]] - p1[props[1]];
  1268. return Math.atan2(y, x) * 180 / Math.PI;
  1269. }
  1270. /**
  1271. * calculate the rotation degrees between two pointersets
  1272. * @param {Array} start array of pointers
  1273. * @param {Array} end array of pointers
  1274. * @return {Number} rotation
  1275. */
  1276. function getRotation(start, end) {
  1277. return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);
  1278. }
  1279. /**
  1280. * calculate the scale factor between two pointersets
  1281. * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
  1282. * @param {Array} start array of pointers
  1283. * @param {Array} end array of pointers
  1284. * @return {Number} scale
  1285. */
  1286. function getScale(start, end) {
  1287. return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
  1288. }
  1289. var MOUSE_INPUT_MAP = {
  1290. mousedown: INPUT_START,
  1291. mousemove: INPUT_MOVE,
  1292. mouseup: INPUT_END
  1293. };
  1294. var MOUSE_ELEMENT_EVENTS = 'mousedown';
  1295. var MOUSE_WINDOW_EVENTS = 'mousemove mouseup';
  1296. /**
  1297. * Mouse events input
  1298. * @constructor
  1299. * @extends Input
  1300. */
  1301. function MouseInput() {
  1302. this.evEl = MOUSE_ELEMENT_EVENTS;
  1303. this.evWin = MOUSE_WINDOW_EVENTS;
  1304. this.pressed = false; // mousedown state
  1305. Input.apply(this, arguments);
  1306. }
  1307. inherit(MouseInput, Input, {
  1308. /**
  1309. * handle mouse events
  1310. * @param {Object} ev
  1311. */
  1312. handler: function MEhandler(ev) {
  1313. var eventType = MOUSE_INPUT_MAP[ev.type];
  1314. // on start we want to have the left mouse button down
  1315. if (eventType & INPUT_START && ev.button === 0) {
  1316. this.pressed = true;
  1317. }
  1318. if (eventType & INPUT_MOVE && ev.which !== 1) {
  1319. eventType = INPUT_END;
  1320. }
  1321. // mouse must be down
  1322. if (!this.pressed) {
  1323. return;
  1324. }
  1325. if (eventType & INPUT_END) {
  1326. this.pressed = false;
  1327. }
  1328. this.callback(this.manager, eventType, {
  1329. pointers: [ev],
  1330. changedPointers: [ev],
  1331. pointerType: INPUT_TYPE_MOUSE,
  1332. srcEvent: ev
  1333. });
  1334. }
  1335. });
  1336. var POINTER_INPUT_MAP = {
  1337. pointerdown: INPUT_START,
  1338. pointermove: INPUT_MOVE,
  1339. pointerup: INPUT_END,
  1340. pointercancel: INPUT_CANCEL,
  1341. pointerout: INPUT_CANCEL
  1342. };
  1343. // in IE10 the pointer types is defined as an enum
  1344. var IE10_POINTER_TYPE_ENUM = {
  1345. 2: INPUT_TYPE_TOUCH,
  1346. 3: INPUT_TYPE_PEN,
  1347. 4: INPUT_TYPE_MOUSE,
  1348. 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816
  1349. };
  1350. var POINTER_ELEMENT_EVENTS = 'pointerdown';
  1351. var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel';
  1352. // IE10 has prefixed support, and case-sensitive
  1353. if (window.MSPointerEvent && !window.PointerEvent) {
  1354. POINTER_ELEMENT_EVENTS = 'MSPointerDown';
  1355. POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';
  1356. }
  1357. /**
  1358. * Pointer events input
  1359. * @constructor
  1360. * @extends Input
  1361. */
  1362. function PointerEventInput() {
  1363. this.evEl = POINTER_ELEMENT_EVENTS;
  1364. this.evWin = POINTER_WINDOW_EVENTS;
  1365. Input.apply(this, arguments);
  1366. this.store = (this.manager.session.pointerEvents = []);
  1367. }
  1368. inherit(PointerEventInput, Input, {
  1369. /**
  1370. * handle mouse events
  1371. * @param {Object} ev
  1372. */
  1373. handler: function PEhandler(ev) {
  1374. var store = this.store;
  1375. var removePointer = false;
  1376. var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
  1377. var eventType = POINTER_INPUT_MAP[eventTypeNormalized];
  1378. var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;
  1379. var isTouch = (pointerType == INPUT_TYPE_TOUCH);
  1380. // get index of the event in the store
  1381. var storeIndex = inArray(store, ev.pointerId, 'pointerId');
  1382. // start and mouse must be down
  1383. if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {
  1384. if (storeIndex < 0) {
  1385. store.push(ev);
  1386. storeIndex = store.length - 1;
  1387. }
  1388. } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
  1389. removePointer = true;
  1390. }
  1391. // it not found, so the pointer hasn't been down (so it's probably a hover)
  1392. if (storeIndex < 0) {
  1393. return;
  1394. }
  1395. // update the event in the store
  1396. store[storeIndex] = ev;
  1397. this.callback(this.manager, eventType, {
  1398. pointers: store,
  1399. changedPointers: [ev],
  1400. pointerType: pointerType,
  1401. srcEvent: ev
  1402. });
  1403. if (removePointer) {
  1404. // remove from the store
  1405. store.splice(storeIndex, 1);
  1406. }
  1407. }
  1408. });
  1409. var SINGLE_TOUCH_INPUT_MAP = {
  1410. touchstart: INPUT_START,
  1411. touchmove: INPUT_MOVE,
  1412. touchend: INPUT_END,
  1413. touchcancel: INPUT_CANCEL
  1414. };
  1415. var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';
  1416. var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';
  1417. /**
  1418. * Touch events input
  1419. * @constructor
  1420. * @extends Input
  1421. */
  1422. function SingleTouchInput() {
  1423. this.evTarget = SINGLE_TOUCH_TARGET_EVENTS;
  1424. this.evWin = SINGLE_TOUCH_WINDOW_EVENTS;
  1425. this.started = false;
  1426. Input.apply(this, arguments);
  1427. }
  1428. inherit(SingleTouchInput, Input, {
  1429. handler: function TEhandler(ev) {
  1430. var type = SINGLE_TOUCH_INPUT_MAP[ev.type];
  1431. // should we handle the touch events?
  1432. if (type === INPUT_START) {
  1433. this.started = true;
  1434. }
  1435. if (!this.started) {
  1436. return;
  1437. }
  1438. var touches = normalizeSingleTouches.call(this, ev, type);
  1439. // when done, reset the started state
  1440. if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {
  1441. this.started = false;
  1442. }
  1443. this.callback(this.manager, type, {
  1444. pointers: touches[0],
  1445. changedPointers: touches[1],
  1446. pointerType: INPUT_TYPE_TOUCH,
  1447. srcEvent: ev
  1448. });
  1449. }
  1450. });
  1451. /**
  1452. * @this {TouchInput}
  1453. * @param {Object} ev
  1454. * @param {Number} type flag
  1455. * @returns {undefined|Array} [all, changed]
  1456. */
  1457. function normalizeSingleTouches(ev, type) {
  1458. var all = toArray(ev.touches);
  1459. var changed = toArray(ev.changedTouches);
  1460. if (type & (INPUT_END | INPUT_CANCEL)) {
  1461. all = uniqueArray(all.concat(changed), 'identifier', true);
  1462. }
  1463. return [all, changed];
  1464. }
  1465. var TOUCH_INPUT_MAP = {
  1466. touchstart: INPUT_START,
  1467. touchmove: INPUT_MOVE,
  1468. touchend: INPUT_END,
  1469. touchcancel: INPUT_CANCEL
  1470. };
  1471. var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
  1472. /**
  1473. * Multi-user touch events input
  1474. * @constructor
  1475. * @extends Input
  1476. */
  1477. function TouchInput() {
  1478. this.evTarget = TOUCH_TARGET_EVENTS;
  1479. this.targetIds = {};
  1480. Input.apply(this, arguments);
  1481. }
  1482. inherit(TouchInput, Input, {
  1483. handler: function MTEhandler(ev) {
  1484. var type = TOUCH_INPUT_MAP[ev.type];
  1485. var touches = getTouches.call(this, ev, type);
  1486. if (!touches) {
  1487. return;
  1488. }
  1489. this.callback(this.manager, type, {
  1490. pointers: touches[0],
  1491. changedPointers: touches[1],
  1492. pointerType: INPUT_TYPE_TOUCH,
  1493. srcEvent: ev
  1494. });
  1495. }
  1496. });
  1497. /**
  1498. * @this {TouchInput}
  1499. * @param {Object} ev
  1500. * @param {Number} type flag
  1501. * @returns {undefined|Array} [all, changed]
  1502. */
  1503. function getTouches(ev, type) {
  1504. var allTouches = toArray(ev.touches);
  1505. var targetIds = this.targetIds;
  1506. // when there is only one touch, the process can be simplified
  1507. if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {
  1508. targetIds[allTouches[0].identifier] = true;
  1509. return [allTouches, allTouches];
  1510. }
  1511. var i,
  1512. targetTouches,
  1513. changedTouches = toArray(ev.changedTouches),
  1514. changedTargetTouches = [],
  1515. target = this.target;
  1516. // get target touches from touches
  1517. targetTouches = allTouches.filter(function(touch) {
  1518. return hasParent(touch.target, target);
  1519. });
  1520. // collect touches
  1521. if (type === INPUT_START) {
  1522. i = 0;
  1523. while (i < targetTouches.length) {
  1524. targetIds[targetTouches[i].identifier] = true;
  1525. i++;
  1526. }
  1527. }
  1528. // filter changed touches to only contain touches that exist in the collected target ids
  1529. i = 0;
  1530. while (i < changedTouches.length) {
  1531. if (targetIds[changedTouches[i].identifier]) {
  1532. changedTargetTouches.push(changedTouches[i]);
  1533. }
  1534. // cleanup removed touches
  1535. if (type & (INPUT_END | INPUT_CANCEL)) {
  1536. delete targetIds[changedTouches[i].identifier];
  1537. }
  1538. i++;
  1539. }
  1540. if (!changedTargetTouches.length) {
  1541. return;
  1542. }
  1543. return [
  1544. // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
  1545. uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true),
  1546. changedTargetTouches
  1547. ];
  1548. }
  1549. /**
  1550. * Combined touch and mouse input
  1551. *
  1552. * Touch has a higher priority then mouse, and while touching no mouse events are allowed.
  1553. * This because touch devices also emit mouse events while doing a touch.
  1554. *
  1555. * @constructor
  1556. * @extends Input
  1557. */
  1558. var DEDUP_TIMEOUT = 2500;
  1559. var DEDUP_DISTANCE = 25;
  1560. function TouchMouseInput() {
  1561. Input.apply(this, arguments);
  1562. var handler = bindFn(this.handler, this);
  1563. this.touch = new TouchInput(this.manager, handler);
  1564. this.mouse = new MouseInput(this.manager, handler);
  1565. this.primaryTouch = null;
  1566. this.lastTouches = [];
  1567. }
  1568. inherit(TouchMouseInput, Input, {
  1569. /**
  1570. * handle mouse and touch events
  1571. * @param {Hammer} manager
  1572. * @param {String} inputEvent
  1573. * @param {Object} inputData
  1574. */
  1575. handler: function TMEhandler(manager, inputEvent, inputData) {
  1576. var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH),
  1577. isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE);
  1578. if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) {
  1579. return;
  1580. }
  1581. // when we're in a touch event, record touches to de-dupe synthetic mouse event
  1582. if (isTouch) {
  1583. recordTouches.call(this, inputEvent, inputData);
  1584. } else if (isMouse && isSyntheticEvent.call(this, inputData)) {
  1585. return;
  1586. }
  1587. this.callback(manager, inputEvent, inputData);
  1588. },
  1589. /**
  1590. * remove the event listeners
  1591. */
  1592. destroy: function destroy() {
  1593. this.touch.destroy();
  1594. this.mouse.destroy();
  1595. }
  1596. });
  1597. function recordTouches(eventType, eventData) {
  1598. if (eventType & INPUT_START) {
  1599. this.primaryTouch = eventData.changedPointers[0].identifier;
  1600. setLastTouch.call(this, eventData);
  1601. } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
  1602. setLastTouch.call(this, eventData);
  1603. }
  1604. }
  1605. function setLastTouch(eventData) {
  1606. var touch = eventData.changedPointers[0];
  1607. if (touch.identifier === this.primaryTouch) {
  1608. var lastTouch = {x: touch.clientX, y: touch.clientY};
  1609. this.lastTouches.push(lastTouch);
  1610. var lts = this.lastTouches;
  1611. var removeLastTouch = function() {
  1612. var i = lts.indexOf(lastTouch);
  1613. if (i > -1) {
  1614. lts.splice(i, 1);
  1615. }
  1616. };
  1617. setTimeout(removeLastTouch, DEDUP_TIMEOUT);
  1618. }
  1619. }
  1620. function isSyntheticEvent(eventData) {
  1621. var x = eventData.srcEvent.clientX, y = eventData.srcEvent.clientY;
  1622. for (var i = 0; i < this.lastTouches.length; i++) {
  1623. var t = this.lastTouches[i];
  1624. var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y);
  1625. if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) {
  1626. return true;
  1627. }
  1628. }
  1629. return false;
  1630. }
  1631. var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
  1632. var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;
  1633. // magical touchAction value
  1634. var TOUCH_ACTION_COMPUTE = 'compute';
  1635. var TOUCH_ACTION_AUTO = 'auto';
  1636. var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented
  1637. var TOUCH_ACTION_NONE = 'none';
  1638. var TOUCH_ACTION_PAN_X = 'pan-x';
  1639. var TOUCH_ACTION_PAN_Y = 'pan-y';
  1640. var TOUCH_ACTION_MAP = getTouchActionProps();
  1641. /**
  1642. * Touch Action
  1643. * sets the touchAction property or uses the js alternative
  1644. * @param {Manager} manager
  1645. * @param {String} value
  1646. * @constructor
  1647. */
  1648. function TouchAction(manager, value) {
  1649. this.manager = manager;
  1650. this.set(value);
  1651. }
  1652. TouchAction.prototype = {
  1653. /**
  1654. * set the touchAction value on the element or enable the polyfill
  1655. * @param {String} value
  1656. */
  1657. set: function(value) {
  1658. // find out the touch-action by the event handlers
  1659. if (value == TOUCH_ACTION_COMPUTE) {
  1660. value = this.compute();
  1661. }
  1662. if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) {
  1663. this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;
  1664. }
  1665. this.actions = value.toLowerCase().trim();
  1666. },
  1667. /**
  1668. * just re-set the touchAction value
  1669. */
  1670. update: function() {
  1671. this.set(this.manager.options.touchAction);
  1672. },
  1673. /**
  1674. * compute the value for the touchAction property based on the recognizer's settings
  1675. * @returns {String} value
  1676. */
  1677. compute: function() {
  1678. var actions = [];
  1679. each(this.manager.recognizers, function(recognizer) {
  1680. if (boolOrFn(recognizer.options.enable, [recognizer])) {
  1681. actions = actions.concat(recognizer.getTouchAction());
  1682. }
  1683. });
  1684. return cleanTouchActions(actions.join(' '));
  1685. },
  1686. /**
  1687. * this method is called on each input cycle and provides the preventing of the browser behavior
  1688. * @param {Object} input
  1689. */
  1690. preventDefaults: function(input) {
  1691. var srcEvent = input.srcEvent;
  1692. var direction = input.offsetDirection;
  1693. // if the touch action did prevented once this session
  1694. if (this.manager.session.prevented) {
  1695. srcEvent.preventDefault();
  1696. return;
  1697. }
  1698. var actions = this.actions;
  1699. var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE];
  1700. var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y];
  1701. var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X];
  1702. if (hasNone) {
  1703. //do not prevent defaults if this is a tap gesture
  1704. var isTapPointer = input.pointers.length === 1;
  1705. var isTapMovement = input.distance < 2;
  1706. var isTapTouchTime = input.deltaTime < 250;
  1707. if (isTapPointer && isTapMovement && isTapTouchTime) {
  1708. return;
  1709. }
  1710. }
  1711. if (hasPanX && hasPanY) {
  1712. // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent
  1713. return;
  1714. }
  1715. if (hasNone ||
  1716. (hasPanY && direction & DIRECTION_HORIZONTAL) ||
  1717. (hasPanX && direction & DIRECTION_VERTICAL)) {
  1718. return this.preventSrc(srcEvent);
  1719. }
  1720. },
  1721. /**
  1722. * call preventDefault to prevent the browser's default behavior (scrolling in most cases)
  1723. * @param {Object} srcEvent
  1724. */
  1725. preventSrc: function(srcEvent) {
  1726. this.manager.session.prevented = true;
  1727. srcEvent.preventDefault();
  1728. }
  1729. };
  1730. /**
  1731. * when the touchActions are collected they are not a valid value, so we need to clean things up. *
  1732. * @param {String} actions
  1733. * @returns {*}
  1734. */
  1735. function cleanTouchActions(actions) {
  1736. // none
  1737. if (inStr(actions, TOUCH_ACTION_NONE)) {
  1738. return TOUCH_ACTION_NONE;
  1739. }
  1740. var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
  1741. var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);
  1742. // if both pan-x and pan-y are set (different recognizers
  1743. // for different directions, e.g. horizontal pan but vertical swipe?)
  1744. // we need none (as otherwise with pan-x pan-y combined none of these
  1745. // recognizers will work, since the browser would handle all panning
  1746. if (hasPanX && hasPanY) {
  1747. return TOUCH_ACTION_NONE;
  1748. }
  1749. // pan-x OR pan-y
  1750. if (hasPanX || hasPanY) {
  1751. return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;
  1752. }
  1753. // manipulation
  1754. if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {
  1755. return TOUCH_ACTION_MANIPULATION;
  1756. }
  1757. return TOUCH_ACTION_AUTO;
  1758. }
  1759. function getTouchActionProps() {
  1760. if (!NATIVE_TOUCH_ACTION) {
  1761. return false;
  1762. }
  1763. var touchMap = {};
  1764. var cssSupports = window.CSS && window.CSS.supports;
  1765. ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) {
  1766. // If css.supports is not supported but there is native touch-action assume it supports
  1767. // all values. This is the case for IE 10 and 11.
  1768. touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true;
  1769. });
  1770. return touchMap;
  1771. }
  1772. /**
  1773. * Recognizer flow explained; *
  1774. * All recognizers have the initial state of POSSIBLE when a input session starts.
  1775. * The definition of a input session is from the first input until the last input, with all it's movement in it. *
  1776. * Example session for mouse-input: mousedown -> mousemove -> mouseup
  1777. *
  1778. * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed
  1779. * which determines with state it should be.
  1780. *
  1781. * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to
  1782. * POSSIBLE to give it another change on the next cycle.
  1783. *
  1784. * Possible
  1785. * |
  1786. * +-----+---------------+
  1787. * | |
  1788. * +-----+-----+ |
  1789. * | | |
  1790. * Failed Cancelled |
  1791. * +-------+------+
  1792. * | |
  1793. * Recognized Began
  1794. * |
  1795. * Changed
  1796. * |
  1797. * Ended/Recognized
  1798. */
  1799. var STATE_POSSIBLE = 1;
  1800. var STATE_BEGAN = 2;
  1801. var STATE_CHANGED = 4;
  1802. var STATE_ENDED = 8;
  1803. var STATE_RECOGNIZED = STATE_ENDED;
  1804. var STATE_CANCELLED = 16;
  1805. var STATE_FAILED = 32;
  1806. /**
  1807. * Recognizer
  1808. * Every recognizer needs to extend from this class.
  1809. * @constructor
  1810. * @param {Object} options
  1811. */
  1812. function Recognizer(options) {
  1813. this.options = assign({}, this.defaults, options || {});
  1814. this.id = uniqueId();
  1815. this.manager = null;
  1816. // default is enable true
  1817. this.options.enable = ifUndefined(this.options.enable, true);
  1818. this.state = STATE_POSSIBLE;
  1819. this.simultaneous = {};
  1820. this.requireFail = [];
  1821. }
  1822. Recognizer.prototype = {
  1823. /**
  1824. * @virtual
  1825. * @type {Object}
  1826. */
  1827. defaults: {},
  1828. /**
  1829. * set options
  1830. * @param {Object} options
  1831. * @return {Recognizer}
  1832. */
  1833. set: function(options) {
  1834. assign(this.options, options);
  1835. // also update the touchAction, in case something changed about the directions/enabled state
  1836. this.manager && this.manager.touchAction.update();
  1837. return this;
  1838. },
  1839. /**
  1840. * recognize simultaneous with an other recognizer.
  1841. * @param {Recognizer} otherRecognizer
  1842. * @returns {Recognizer} this
  1843. */
  1844. recognizeWith: function(otherRecognizer) {
  1845. if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {
  1846. return this;
  1847. }
  1848. var simultaneous = this.simultaneous;
  1849. otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
  1850. if (!simultaneous[otherRecognizer.id]) {
  1851. simultaneous[otherRecognizer.id] = otherRecognizer;
  1852. otherRecognizer.recognizeWith(this);
  1853. }
  1854. return this;
  1855. },
  1856. /**
  1857. * drop the simultaneous link. it doesnt remove the link on the other recognizer.
  1858. * @param {Recognizer} otherRecognizer
  1859. * @returns {Recognizer} this
  1860. */
  1861. dropRecognizeWith: function(otherRecognizer) {
  1862. if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {
  1863. return this;
  1864. }
  1865. otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
  1866. delete this.simultaneous[otherRecognizer.id];
  1867. return this;
  1868. },
  1869. /**
  1870. * recognizer can only run when an other is failing
  1871. * @param {Recognizer} otherRecognizer
  1872. * @returns {Recognizer} this
  1873. */
  1874. requireFailure: function(otherRecognizer) {
  1875. if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {
  1876. return this;
  1877. }
  1878. var requireFail = this.requireFail;
  1879. otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
  1880. if (inArray(requireFail, otherRecognizer) === -1) {
  1881. requireFail.push(otherRecognizer);
  1882. otherRecognizer.requireFailure(this);
  1883. }
  1884. return this;
  1885. },
  1886. /**
  1887. * drop the requireFailure link. it does not remove the link on the other recognizer.
  1888. * @param {Recognizer} otherRecognizer
  1889. * @returns {Recognizer} this
  1890. */
  1891. dropRequireFailure: function(otherRecognizer) {
  1892. if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {
  1893. return this;
  1894. }
  1895. otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
  1896. var index = inArray(this.requireFail, otherRecognizer);
  1897. if (index > -1) {
  1898. this.requireFail.splice(index, 1);
  1899. }
  1900. return this;
  1901. },
  1902. /**
  1903. * has require failures boolean
  1904. * @returns {boolean}
  1905. */
  1906. hasRequireFailures: function() {
  1907. return this.requireFail.length > 0;
  1908. },
  1909. /**
  1910. * if the recognizer can recognize simultaneous with an other recognizer
  1911. * @param {Recognizer} otherRecognizer
  1912. * @returns {Boolean}
  1913. */
  1914. canRecognizeWith: function(otherRecognizer) {
  1915. return !!this.simultaneous[otherRecognizer.id];
  1916. },
  1917. /**
  1918. * You should use `tryEmit` instead of `emit` directly to check
  1919. * that all the needed recognizers has failed before emitting.
  1920. * @param {Object} input
  1921. */
  1922. emit: function(input) {
  1923. var self = this;
  1924. var state = this.state;
  1925. function emit(event) {
  1926. self.manager.emit(event, input);
  1927. }
  1928. // 'panstart' and 'panmove'
  1929. if (state < STATE_ENDED) {
  1930. emit(self.options.event + stateStr(state));
  1931. }
  1932. emit(self.options.event); // simple 'eventName' events
  1933. if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...)
  1934. emit(input.additionalEvent);
  1935. }
  1936. // panend and pancancel
  1937. if (state >= STATE_ENDED) {
  1938. emit(self.options.event + stateStr(state));
  1939. }
  1940. },
  1941. /**
  1942. * Check that all the require failure recognizers has failed,
  1943. * if true, it emits a gesture event,
  1944. * otherwise, setup the state to FAILED.
  1945. * @param {Object} input
  1946. */
  1947. tryEmit: function(input) {
  1948. if (this.canEmit()) {
  1949. return this.emit(input);
  1950. }
  1951. // it's failing anyway
  1952. this.state = STATE_FAILED;
  1953. },
  1954. /**
  1955. * can we emit?
  1956. * @returns {boolean}
  1957. */
  1958. canEmit: function() {
  1959. var i = 0;
  1960. while (i < this.requireFail.length) {
  1961. if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {
  1962. return false;
  1963. }
  1964. i++;
  1965. }
  1966. return true;
  1967. },
  1968. /**
  1969. * update the recognizer
  1970. * @param {Object} inputData
  1971. */
  1972. recognize: function(inputData) {
  1973. // make a new copy of the inputData
  1974. // so we can change the inputData without messing up the other recognizers
  1975. var inputDataClone = assign({}, inputData);
  1976. // is is enabled and allow recognizing?
  1977. if (!boolOrFn(this.options.enable, [this, inputDataClone])) {
  1978. this.reset();
  1979. this.state = STATE_FAILED;
  1980. return;
  1981. }
  1982. // reset when we've reached the end
  1983. if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {
  1984. this.state = STATE_POSSIBLE;
  1985. }
  1986. this.state = this.process(inputDataClone);
  1987. // the recognizer has recognized a gesture
  1988. // so trigger an event
  1989. if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {
  1990. this.tryEmit(inputDataClone);
  1991. }
  1992. },
  1993. /**
  1994. * return the state of the recognizer
  1995. * the actual recognizing happens in this method
  1996. * @virtual
  1997. * @param {Object} inputData
  1998. * @returns {Const} STATE
  1999. */
  2000. process: function(inputData) { }, // jshint ignore:line
  2001. /**
  2002. * return the preferred touch-action
  2003. * @virtual
  2004. * @returns {Array}
  2005. */
  2006. getTouchAction: function() { },
  2007. /**
  2008. * called when the gesture isn't allowed to recognize
  2009. * like when another is being recognized or it is disabled
  2010. * @virtual
  2011. */
  2012. reset: function() { }
  2013. };
  2014. /**
  2015. * get a usable string, used as event postfix
  2016. * @param {Const} state
  2017. * @returns {String} state
  2018. */
  2019. function stateStr(state) {
  2020. if (state & STATE_CANCELLED) {
  2021. return 'cancel';
  2022. } else if (state & STATE_ENDED) {
  2023. return 'end';
  2024. } else if (state & STATE_CHANGED) {
  2025. return 'move';
  2026. } else if (state & STATE_BEGAN) {
  2027. return 'start';
  2028. }
  2029. return '';
  2030. }
  2031. /**
  2032. * direction cons to string
  2033. * @param {Const} direction
  2034. * @returns {String}
  2035. */
  2036. function directionStr(direction) {
  2037. if (direction == DIRECTION_DOWN) {
  2038. return 'down';
  2039. } else if (direction == DIRECTION_UP) {
  2040. return 'up';
  2041. } else if (direction == DIRECTION_LEFT) {
  2042. return 'left';
  2043. } else if (direction == DIRECTION_RIGHT) {
  2044. return 'right';
  2045. }
  2046. return '';
  2047. }
  2048. /**
  2049. * get a recognizer by name if it is bound to a manager
  2050. * @param {Recognizer|String} otherRecognizer
  2051. * @param {Recognizer} recognizer
  2052. * @returns {Recognizer}
  2053. */
  2054. function getRecognizerByNameIfManager(otherRecognizer, recognizer) {
  2055. var manager = recognizer.manager;
  2056. if (manager) {
  2057. return manager.get(otherRecognizer);
  2058. }
  2059. return otherRecognizer;
  2060. }
  2061. /**
  2062. * This recognizer is just used as a base for the simple attribute recognizers.
  2063. * @constructor
  2064. * @extends Recognizer
  2065. */
  2066. function AttrRecognizer() {
  2067. Recognizer.apply(this, arguments);
  2068. }
  2069. inherit(AttrRecognizer, Recognizer, {
  2070. /**
  2071. * @namespace
  2072. * @memberof AttrRecognizer
  2073. */
  2074. defaults: {
  2075. /**
  2076. * @type {Number}
  2077. * @default 1
  2078. */
  2079. pointers: 1
  2080. },
  2081. /**
  2082. * Used to check if it the recognizer receives valid input, like input.distance > 10.
  2083. * @memberof AttrRecognizer
  2084. * @param {Object} input
  2085. * @returns {Boolean} recognized
  2086. */
  2087. attrTest: function(input) {
  2088. var optionPointers = this.options.pointers;
  2089. return optionPointers === 0 || input.pointers.length === optionPointers;
  2090. },
  2091. /**
  2092. * Process the input and return the state for the recognizer
  2093. * @memberof AttrRecognizer
  2094. * @param {Object} input
  2095. * @returns {*} State
  2096. */
  2097. process: function(input) {
  2098. var state = this.state;
  2099. var eventType = input.eventType;
  2100. var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);
  2101. var isValid = this.attrTest(input);
  2102. // on cancel input and we've recognized before, return STATE_CANCELLED
  2103. if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {
  2104. return state | STATE_CANCELLED;
  2105. } else if (isRecognized || isValid) {
  2106. if (eventType & INPUT_END) {
  2107. return state | STATE_ENDED;
  2108. } else if (!(state & STATE_BEGAN)) {
  2109. return STATE_BEGAN;
  2110. }
  2111. return state | STATE_CHANGED;
  2112. }
  2113. return STATE_FAILED;
  2114. }
  2115. });
  2116. /**
  2117. * Pan
  2118. * Recognized when the pointer is down and moved in the allowed direction.
  2119. * @constructor
  2120. * @extends AttrRecognizer
  2121. */
  2122. function PanRecognizer() {
  2123. AttrRecognizer.apply(this, arguments);
  2124. this.pX = null;
  2125. this.pY = null;
  2126. }
  2127. inherit(PanRecognizer, AttrRecognizer, {
  2128. /**
  2129. * @namespace
  2130. * @memberof PanRecognizer
  2131. */
  2132. defaults: {
  2133. event: 'pan',
  2134. threshold: 10,
  2135. pointers: 1,
  2136. direction: DIRECTION_ALL
  2137. },
  2138. getTouchAction: function() {
  2139. var direction = this.options.direction;
  2140. var actions = [];
  2141. if (direction & DIRECTION_HORIZONTAL) {
  2142. actions.push(TOUCH_ACTION_PAN_Y);
  2143. }
  2144. if (direction & DIRECTION_VERTICAL) {
  2145. actions.push(TOUCH_ACTION_PAN_X);
  2146. }
  2147. return actions;
  2148. },
  2149. directionTest: function(input) {
  2150. var options = this.options;
  2151. var hasMoved = true;
  2152. var distance = input.distance;
  2153. var direction = input.direction;
  2154. var x = input.deltaX;
  2155. var y = input.deltaY;
  2156. // lock to axis?
  2157. if (!(direction & options.direction)) {
  2158. if (options.direction & DIRECTION_HORIZONTAL) {
  2159. direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT;
  2160. hasMoved = x != this.pX;
  2161. distance = Math.abs(input.deltaX);
  2162. } else {
  2163. direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN;
  2164. hasMoved = y != this.pY;
  2165. distance = Math.abs(input.deltaY);
  2166. }
  2167. }
  2168. input.direction = direction;
  2169. return hasMoved && distance > options.threshold && direction & options.direction;
  2170. },
  2171. attrTest: function(input) {
  2172. return AttrRecognizer.prototype.attrTest.call(this, input) &&
  2173. (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input)));
  2174. },
  2175. emit: function(input) {
  2176. this.pX = input.deltaX;
  2177. this.pY = input.deltaY;
  2178. var direction = directionStr(input.direction);
  2179. if (direction) {
  2180. input.additionalEvent = this.options.event + direction;
  2181. }
  2182. this._super.emit.call(this, input);
  2183. }
  2184. });
  2185. /**
  2186. * Pinch
  2187. * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).
  2188. * @constructor
  2189. * @extends AttrRecognizer
  2190. */
  2191. function PinchRecognizer() {
  2192. AttrRecognizer.apply(this, arguments);
  2193. }
  2194. inherit(PinchRecognizer, AttrRecognizer, {
  2195. /**
  2196. * @namespace
  2197. * @memberof PinchRecognizer
  2198. */
  2199. defaults: {
  2200. event: 'pinch',
  2201. threshold: 0,
  2202. pointers: 2
  2203. },
  2204. getTouchAction: function() {
  2205. return [TOUCH_ACTION_NONE];
  2206. },
  2207. attrTest: function(input) {
  2208. return this._super.attrTest.call(this, input) &&
  2209. (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);
  2210. },
  2211. emit: function(input) {
  2212. if (input.scale !== 1) {
  2213. var inOut = input.scale < 1 ? 'in' : 'out';
  2214. input.additionalEvent = this.options.event + inOut;
  2215. }
  2216. this._super.emit.call(this, input);
  2217. }
  2218. });
  2219. /**
  2220. * Press
  2221. * Recognized when the pointer is down for x ms without any movement.
  2222. * @constructor
  2223. * @extends Recognizer
  2224. */
  2225. function PressRecognizer() {
  2226. Recognizer.apply(this, arguments);
  2227. this._timer = null;
  2228. this._input = null;
  2229. }
  2230. inherit(PressRecognizer, Recognizer, {
  2231. /**
  2232. * @namespace
  2233. * @memberof PressRecognizer
  2234. */
  2235. defaults: {
  2236. event: 'press',
  2237. pointers: 1,
  2238. time: 251, // minimal time of the pointer to be pressed
  2239. threshold: 9 // a minimal movement is ok, but keep it low
  2240. },
  2241. getTouchAction: function() {
  2242. return [TOUCH_ACTION_AUTO];
  2243. },
  2244. process: function(input) {
  2245. var options = this.options;
  2246. var validPointers = input.pointers.length === options.pointers;
  2247. var validMovement = input.distance < options.threshold;
  2248. var validTime = input.deltaTime > options.time;
  2249. this._input = input;
  2250. // we only allow little movement
  2251. // and we've reached an end event, so a tap is possible
  2252. if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) {
  2253. this.reset();
  2254. } else if (input.eventType & INPUT_START) {
  2255. this.reset();
  2256. this._timer = setTimeoutContext(function() {
  2257. this.state = STATE_RECOGNIZED;
  2258. this.tryEmit();
  2259. }, options.time, this);
  2260. } else if (input.eventType & INPUT_END) {
  2261. return STATE_RECOGNIZED;
  2262. }
  2263. return STATE_FAILED;
  2264. },
  2265. reset: function() {
  2266. clearTimeout(this._timer);
  2267. },
  2268. emit: function(input) {
  2269. if (this.state !== STATE_RECOGNIZED) {
  2270. return;
  2271. }
  2272. if (input && (input.eventType & INPUT_END)) {
  2273. this.manager.emit(this.options.event + 'up', input);
  2274. } else {
  2275. this._input.timeStamp = now();
  2276. this.manager.emit(this.options.event, this._input);
  2277. }
  2278. }
  2279. });
  2280. /**
  2281. * Rotate
  2282. * Recognized when two or more pointer are moving in a circular motion.
  2283. * @constructor
  2284. * @extends AttrRecognizer
  2285. */
  2286. function RotateRecognizer() {
  2287. AttrRecognizer.apply(this, arguments);
  2288. }
  2289. inherit(RotateRecognizer, AttrRecognizer, {
  2290. /**
  2291. * @namespace
  2292. * @memberof RotateRecognizer
  2293. */
  2294. defaults: {
  2295. event: 'rotate',
  2296. threshold: 0,
  2297. pointers: 2
  2298. },
  2299. getTouchAction: function() {
  2300. return [TOUCH_ACTION_NONE];
  2301. },
  2302. attrTest: function(input) {
  2303. return this._super.attrTest.call(this, input) &&
  2304. (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);
  2305. }
  2306. });
  2307. /**
  2308. * Swipe
  2309. * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.
  2310. * @constructor
  2311. * @extends AttrRecognizer
  2312. */
  2313. function SwipeRecognizer() {
  2314. AttrRecognizer.apply(this, arguments);
  2315. }
  2316. inherit(SwipeRecognizer, AttrRecognizer, {
  2317. /**
  2318. * @namespace
  2319. * @memberof SwipeRecognizer
  2320. */
  2321. defaults: {
  2322. event: 'swipe',
  2323. threshold: 10,
  2324. velocity: 0.3,
  2325. direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,
  2326. pointers: 1
  2327. },
  2328. getTouchAction: function() {
  2329. return PanRecognizer.prototype.getTouchAction.call(this);
  2330. },
  2331. attrTest: function(input) {
  2332. var direction = this.options.direction;
  2333. var velocity;
  2334. if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {
  2335. velocity = input.overallVelocity;
  2336. } else if (direction & DIRECTION_HORIZONTAL) {
  2337. velocity = input.overallVelocityX;
  2338. } else if (direction & DIRECTION_VERTICAL) {
  2339. velocity = input.overallVelocityY;
  2340. }
  2341. return this._super.attrTest.call(this, input) &&
  2342. direction & input.offsetDirection &&
  2343. input.distance > this.options.threshold &&
  2344. input.maxPointers == this.options.pointers &&
  2345. abs(velocity) > this.options.velocity && input.eventType & INPUT_END;
  2346. },
  2347. emit: function(input) {
  2348. var direction = directionStr(input.offsetDirection);
  2349. if (direction) {
  2350. this.manager.emit(this.options.event + direction, input);
  2351. }
  2352. this.manager.emit(this.options.event, input);
  2353. }
  2354. });
  2355. /**
  2356. * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur
  2357. * between the given interval and position. The delay option can be used to recognize multi-taps without firing
  2358. * a single tap.
  2359. *
  2360. * The eventData from the emitted event contains the property `tapCount`, which contains the amount of
  2361. * multi-taps being recognized.
  2362. * @constructor
  2363. * @extends Recognizer
  2364. */
  2365. function TapRecognizer() {
  2366. Recognizer.apply(this, arguments);
  2367. // previous time and center,
  2368. // used for tap counting
  2369. this.pTime = false;
  2370. this.pCenter = false;
  2371. this._timer = null;
  2372. this._input = null;
  2373. this.count = 0;
  2374. }
  2375. inherit(TapRecognizer, Recognizer, {
  2376. /**
  2377. * @namespace
  2378. * @memberof PinchRecognizer
  2379. */
  2380. defaults: {
  2381. event: 'tap',
  2382. pointers: 1,
  2383. taps: 1,
  2384. interval: 300, // max time between the multi-tap taps
  2385. time: 250, // max time of the pointer to be down (like finger on the screen)
  2386. threshold: 9, // a minimal movement is ok, but keep it low
  2387. posThreshold: 10 // a multi-tap can be a bit off the initial position
  2388. },
  2389. getTouchAction: function() {
  2390. return [TOUCH_ACTION_MANIPULATION];
  2391. },
  2392. process: function(input) {
  2393. var options = this.options;
  2394. var validPointers = input.pointers.length === options.pointers;
  2395. var validMovement = input.distance < options.threshold;
  2396. var validTouchTime = input.deltaTime < options.time;
  2397. this.reset();
  2398. if ((input.eventType & INPUT_START) && (this.count === 0)) {
  2399. return this.failTimeout();
  2400. }
  2401. // we only allow little movement
  2402. // and we've reached an end event, so a tap is possible
  2403. if (validMovement && validTouchTime && validPointers) {
  2404. if (input.eventType != INPUT_END) {
  2405. return this.failTimeout();
  2406. }
  2407. var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true;
  2408. var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;
  2409. this.pTime = input.timeStamp;
  2410. this.pCenter = input.center;
  2411. if (!validMultiTap || !validInterval) {
  2412. this.count = 1;
  2413. } else {
  2414. this.count += 1;
  2415. }
  2416. this._input = input;
  2417. // if tap count matches we have recognized it,
  2418. // else it has began recognizing...
  2419. var tapCount = this.count % options.taps;
  2420. if (tapCount === 0) {
  2421. // no failing requirements, immediately trigger the tap event
  2422. // or wait as long as the multitap interval to trigger
  2423. if (!this.hasRequireFailures()) {
  2424. return STATE_RECOGNIZED;
  2425. } else {
  2426. this._timer = setTimeoutContext(function() {
  2427. this.state = STATE_RECOGNIZED;
  2428. this.tryEmit();
  2429. }, options.interval, this);
  2430. return STATE_BEGAN;
  2431. }
  2432. }
  2433. }
  2434. return STATE_FAILED;
  2435. },
  2436. failTimeout: function() {
  2437. this._timer = setTimeoutContext(function() {
  2438. this.state = STATE_FAILED;
  2439. }, this.options.interval, this);
  2440. return STATE_FAILED;
  2441. },
  2442. reset: function() {
  2443. clearTimeout(this._timer);
  2444. },
  2445. emit: function() {
  2446. if (this.state == STATE_RECOGNIZED) {
  2447. this._input.tapCount = this.count;
  2448. this.manager.emit(this.options.event, this._input);
  2449. }
  2450. }
  2451. });
  2452. /**
  2453. * Simple way to create a manager with a default set of recognizers.
  2454. * @param {HTMLElement} element
  2455. * @param {Object} [options]
  2456. * @constructor
  2457. */
  2458. function Hammer(element, options) {
  2459. options = options || {};
  2460. options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);
  2461. return new Manager(element, options);
  2462. }
  2463. /**
  2464. * @const {string}
  2465. */
  2466. Hammer.VERSION = '2.0.7';
  2467. /**
  2468. * default settings
  2469. * @namespace
  2470. */
  2471. Hammer.defaults = {
  2472. /**
  2473. * set if DOM events are being triggered.
  2474. * But this is slower and unused by simple implementations, so disabled by default.
  2475. * @type {Boolean}
  2476. * @default false
  2477. */
  2478. domEvents: false,
  2479. /**
  2480. * The value for the touchAction property/fallback.
  2481. * When set to `compute` it will magically set the correct value based on the added recognizers.
  2482. * @type {String}
  2483. * @default compute
  2484. */
  2485. touchAction: TOUCH_ACTION_COMPUTE,
  2486. /**
  2487. * @type {Boolean}
  2488. * @default true
  2489. */
  2490. enable: true,
  2491. /**
  2492. * EXPERIMENTAL FEATURE -- can be removed/changed
  2493. * Change the parent input target element.
  2494. * If Null, then it is being set the to main element.
  2495. * @type {Null|EventTarget}
  2496. * @default null
  2497. */
  2498. inputTarget: null,
  2499. /**
  2500. * force an input class
  2501. * @type {Null|Function}
  2502. * @default null
  2503. */
  2504. inputClass: null,
  2505. /**
  2506. * Default recognizer setup when calling `Hammer()`
  2507. * When creating a new Manager these will be skipped.
  2508. * @type {Array}
  2509. */
  2510. preset: [
  2511. // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]
  2512. [RotateRecognizer, {enable: false}],
  2513. [PinchRecognizer, {enable: false}, ['rotate']],
  2514. [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}],
  2515. [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']],
  2516. [TapRecognizer],
  2517. [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']],
  2518. [PressRecognizer]
  2519. ],
  2520. /**
  2521. * Some CSS properties can be used to improve the working of Hammer.
  2522. * Add them to this method and they will be set when creating a new Manager.
  2523. * @namespace
  2524. */
  2525. cssProps: {
  2526. /**
  2527. * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.
  2528. * @type {String}
  2529. * @default 'none'
  2530. */
  2531. userSelect: 'none',
  2532. /**
  2533. * Disable the Windows Phone grippers when pressing an element.
  2534. * @type {String}
  2535. * @default 'none'
  2536. */
  2537. touchSelect: 'none',
  2538. /**
  2539. * Disables the default callout shown when you touch and hold a touch target.
  2540. * On iOS, when you touch and hold a touch target such as a link, Safari displays
  2541. * a callout containing information about the link. This property allows you to disable that callout.
  2542. * @type {String}
  2543. * @default 'none'
  2544. */
  2545. touchCallout: 'none',
  2546. /**
  2547. * Specifies whether zooming is enabled. Used by IE10>
  2548. * @type {String}
  2549. * @default 'none'
  2550. */
  2551. contentZooming: 'none',
  2552. /**
  2553. * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.
  2554. * @type {String}
  2555. * @default 'none'
  2556. */
  2557. userDrag: 'none',
  2558. /**
  2559. * Overrides the highlight color shown when the user taps a link or a JavaScript
  2560. * clickable element in iOS. This property obeys the alpha value, if specified.
  2561. * @type {String}
  2562. * @default 'rgba(0,0,0,0)'
  2563. */
  2564. tapHighlightColor: 'rgba(0,0,0,0)'
  2565. }
  2566. };
  2567. var STOP = 1;
  2568. var FORCED_STOP = 2;
  2569. /**
  2570. * Manager
  2571. * @param {HTMLElement} element
  2572. * @param {Object} [options]
  2573. * @constructor
  2574. */
  2575. function Manager(element, options) {
  2576. this.options = assign({}, Hammer.defaults, options || {});
  2577. this.options.inputTarget = this.options.inputTarget || element;
  2578. this.handlers = {};
  2579. this.session = {};
  2580. this.recognizers = [];
  2581. this.oldCssProps = {};
  2582. this.element = element;
  2583. this.input = createInputInstance(this);
  2584. this.touchAction = new TouchAction(this, this.options.touchAction);
  2585. toggleCssProps(this, true);
  2586. each(this.options.recognizers, function(item) {
  2587. var recognizer = this.add(new (item[0])(item[1]));
  2588. item[2] && recognizer.recognizeWith(item[2]);
  2589. item[3] && recognizer.requireFailure(item[3]);
  2590. }, this);
  2591. }
  2592. Manager.prototype = {
  2593. /**
  2594. * set options
  2595. * @param {Object} options
  2596. * @returns {Manager}
  2597. */
  2598. set: function(options) {
  2599. assign(this.options, options);
  2600. // Options that need a little more setup
  2601. if (options.touchAction) {
  2602. this.touchAction.update();
  2603. }
  2604. if (options.inputTarget) {
  2605. // Clean up existing event listeners and reinitialize
  2606. this.input.destroy();
  2607. this.input.target = options.inputTarget;
  2608. this.input.init();
  2609. }
  2610. return this;
  2611. },
  2612. /**
  2613. * stop recognizing for this session.
  2614. * This session will be discarded, when a new [input]start event is fired.
  2615. * When forced, the recognizer cycle is stopped immediately.
  2616. * @param {Boolean} [force]
  2617. */
  2618. stop: function(force) {
  2619. this.session.stopped = force ? FORCED_STOP : STOP;
  2620. },
  2621. /**
  2622. * run the recognizers!
  2623. * called by the inputHandler function on every movement of the pointers (touches)
  2624. * it walks through all the recognizers and tries to detect the gesture that is being made
  2625. * @param {Object} inputData
  2626. */
  2627. recognize: function(inputData) {
  2628. var session = this.session;
  2629. if (session.stopped) {
  2630. return;
  2631. }
  2632. // run the touch-action polyfill
  2633. this.touchAction.preventDefaults(inputData);
  2634. var recognizer;
  2635. var recognizers = this.recognizers;
  2636. // this holds the recognizer that is being recognized.
  2637. // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED
  2638. // if no recognizer is detecting a thing, it is set to `null`
  2639. var curRecognizer = session.curRecognizer;
  2640. // reset when the last recognizer is recognized
  2641. // or when we're in a new session
  2642. if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) {
  2643. curRecognizer = session.curRecognizer = null;
  2644. }
  2645. var i = 0;
  2646. while (i < recognizers.length) {
  2647. recognizer = recognizers[i];
  2648. // find out if we are allowed try to recognize the input for this one.
  2649. // 1. allow if the session is NOT forced stopped (see the .stop() method)
  2650. // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one
  2651. // that is being recognized.
  2652. // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.
  2653. // this can be setup with the `recognizeWith()` method on the recognizer.
  2654. if (session.stopped !== FORCED_STOP && ( // 1
  2655. !curRecognizer || recognizer == curRecognizer || // 2
  2656. recognizer.canRecognizeWith(curRecognizer))) { // 3
  2657. recognizer.recognize(inputData);
  2658. } else {
  2659. recognizer.reset();
  2660. }
  2661. // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the
  2662. // current active recognizer. but only if we don't already have an active recognizer
  2663. if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {
  2664. curRecognizer = session.curRecognizer = recognizer;
  2665. }
  2666. i++;
  2667. }
  2668. },
  2669. /**
  2670. * get a recognizer by its event name.
  2671. * @param {Recognizer|String} recognizer
  2672. * @returns {Recognizer|Null}
  2673. */
  2674. get: function(recognizer) {
  2675. if (recognizer instanceof Recognizer) {
  2676. return recognizer;
  2677. }
  2678. var recognizers = this.recognizers;
  2679. for (var i = 0; i < recognizers.length; i++) {
  2680. if (recognizers[i].options.event == recognizer) {
  2681. return recognizers[i];
  2682. }
  2683. }
  2684. return null;
  2685. },
  2686. /**
  2687. * add a recognizer to the manager
  2688. * existing recognizers with the same event name will be removed
  2689. * @param {Recognizer} recognizer
  2690. * @returns {Recognizer|Manager}
  2691. */
  2692. add: function(recognizer) {
  2693. if (invokeArrayArg(recognizer, 'add', this)) {
  2694. return this;
  2695. }
  2696. // remove existing
  2697. var existing = this.get(recognizer.options.event);
  2698. if (existing) {
  2699. this.remove(existing);
  2700. }
  2701. this.recognizers.push(recognizer);
  2702. recognizer.manager = this;
  2703. this.touchAction.update();
  2704. return recognizer;
  2705. },
  2706. /**
  2707. * remove a recognizer by name or instance
  2708. * @param {Recognizer|String} recognizer
  2709. * @returns {Manager}
  2710. */
  2711. remove: function(recognizer) {
  2712. if (invokeArrayArg(recognizer, 'remove', this)) {
  2713. return this;
  2714. }
  2715. recognizer = this.get(recognizer);
  2716. // let's make sure this recognizer exists
  2717. if (recognizer) {
  2718. var recognizers = this.recognizers;
  2719. var index = inArray(recognizers, recognizer);
  2720. if (index !== -1) {
  2721. recognizers.splice(index, 1);
  2722. this.touchAction.update();
  2723. }
  2724. }
  2725. return this;
  2726. },
  2727. /**
  2728. * bind event
  2729. * @param {String} events
  2730. * @param {Function} handler
  2731. * @returns {EventEmitter} this
  2732. */
  2733. on: function(events, handler) {
  2734. if (events === undefined) {
  2735. return;
  2736. }
  2737. if (handler === undefined) {
  2738. return;
  2739. }
  2740. var handlers = this.handlers;
  2741. each(splitStr(events), function(event) {
  2742. handlers[event] = handlers[event] || [];
  2743. handlers[event].push(handler);
  2744. });
  2745. return this;
  2746. },
  2747. /**
  2748. * unbind event, leave emit blank to remove all handlers
  2749. * @param {String} events
  2750. * @param {Function} [handler]
  2751. * @returns {EventEmitter} this
  2752. */
  2753. off: function(events, handler) {
  2754. if (events === undefined) {
  2755. return;
  2756. }
  2757. var handlers = this.handlers;
  2758. each(splitStr(events), function(event) {
  2759. if (!handler) {
  2760. delete handlers[event];
  2761. } else {
  2762. handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);
  2763. }
  2764. });
  2765. return this;
  2766. },
  2767. /**
  2768. * emit event to the listeners
  2769. * @param {String} event
  2770. * @param {Object} data
  2771. */
  2772. emit: function(event, data) {
  2773. // we also want to trigger dom events
  2774. if (this.options.domEvents) {
  2775. triggerDomEvent(event, data);
  2776. }
  2777. // no handlers, so skip it all
  2778. var handlers = this.handlers[event] && this.handlers[event].slice();
  2779. if (!handlers || !handlers.length) {
  2780. return;
  2781. }
  2782. data.type = event;
  2783. data.preventDefault = function() {
  2784. data.srcEvent.preventDefault();
  2785. };
  2786. var i = 0;
  2787. while (i < handlers.length) {
  2788. handlers[i](data);
  2789. i++;
  2790. }
  2791. },
  2792. /**
  2793. * destroy the manager and unbinds all events
  2794. * it doesn't unbind dom events, that is the user own responsibility
  2795. */
  2796. destroy: function() {
  2797. this.element && toggleCssProps(this, false);
  2798. this.handlers = {};
  2799. this.session = {};
  2800. this.input.destroy();
  2801. this.element = null;
  2802. }
  2803. };
  2804. /**
  2805. * add/remove the css properties as defined in manager.options.cssProps
  2806. * @param {Manager} manager
  2807. * @param {Boolean} add
  2808. */
  2809. function toggleCssProps(manager, add) {
  2810. var element = manager.element;
  2811. if (!element.style) {
  2812. return;
  2813. }
  2814. var prop;
  2815. each(manager.options.cssProps, function(value, name) {
  2816. prop = prefixed(element.style, name);
  2817. if (add) {
  2818. manager.oldCssProps[prop] = element.style[prop];
  2819. element.style[prop] = value;
  2820. } else {
  2821. element.style[prop] = manager.oldCssProps[prop] || '';
  2822. }
  2823. });
  2824. if (!add) {
  2825. manager.oldCssProps = {};
  2826. }
  2827. }
  2828. /**
  2829. * trigger dom event
  2830. * @param {String} event
  2831. * @param {Object} data
  2832. */
  2833. function triggerDomEvent(event, data) {
  2834. var gestureEvent = document.createEvent('Event');
  2835. gestureEvent.initEvent(event, true, true);
  2836. gestureEvent.gesture = data;
  2837. data.target.dispatchEvent(gestureEvent);
  2838. }
  2839. assign(Hammer, {
  2840. INPUT_START: INPUT_START,
  2841. INPUT_MOVE: INPUT_MOVE,
  2842. INPUT_END: INPUT_END,
  2843. INPUT_CANCEL: INPUT_CANCEL,
  2844. STATE_POSSIBLE: STATE_POSSIBLE,
  2845. STATE_BEGAN: STATE_BEGAN,
  2846. STATE_CHANGED: STATE_CHANGED,
  2847. STATE_ENDED: STATE_ENDED,
  2848. STATE_RECOGNIZED: STATE_RECOGNIZED,
  2849. STATE_CANCELLED: STATE_CANCELLED,
  2850. STATE_FAILED: STATE_FAILED,
  2851. DIRECTION_NONE: DIRECTION_NONE,
  2852. DIRECTION_LEFT: DIRECTION_LEFT,
  2853. DIRECTION_RIGHT: DIRECTION_RIGHT,
  2854. DIRECTION_UP: DIRECTION_UP,
  2855. DIRECTION_DOWN: DIRECTION_DOWN,
  2856. DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL,
  2857. DIRECTION_VERTICAL: DIRECTION_VERTICAL,
  2858. DIRECTION_ALL: DIRECTION_ALL,
  2859. Manager: Manager,
  2860. Input: Input,
  2861. TouchAction: TouchAction,
  2862. TouchInput: TouchInput,
  2863. MouseInput: MouseInput,
  2864. PointerEventInput: PointerEventInput,
  2865. TouchMouseInput: TouchMouseInput,
  2866. SingleTouchInput: SingleTouchInput,
  2867. Recognizer: Recognizer,
  2868. AttrRecognizer: AttrRecognizer,
  2869. Tap: TapRecognizer,
  2870. Pan: PanRecognizer,
  2871. Swipe: SwipeRecognizer,
  2872. Pinch: PinchRecognizer,
  2873. Rotate: RotateRecognizer,
  2874. Press: PressRecognizer,
  2875. on: addEventListeners,
  2876. off: removeEventListeners,
  2877. each: each,
  2878. merge: merge,
  2879. extend: extend,
  2880. assign: assign,
  2881. inherit: inherit,
  2882. bindFn: bindFn,
  2883. prefixed: prefixed
  2884. });
  2885. // jquery.hammer.js
  2886. // This jQuery plugin is just a small wrapper around the Hammer() class.
  2887. // It also extends the Manager.emit method by triggering jQuery events.
  2888. // $(element).hammer(options).bind("pan", myPanHandler);
  2889. // The Hammer instance is stored at $element.data("hammer").
  2890. // https://github.com/hammerjs/jquery.hammer.js
  2891. (function($, Hammer) {
  2892. function hammerify(el, options) {
  2893. var $el = $(el);
  2894. if (!$el.data('hammer')) {
  2895. $el.data('hammer', new Hammer($el[0], options));
  2896. }
  2897. }
  2898. $.fn.hammer = function(options) {
  2899. return this.each(function() {
  2900. hammerify(this, options);
  2901. });
  2902. };
  2903. // extend the emit method to also trigger jQuery events
  2904. Hammer.Manager.prototype.emit = (function(originalEmit) {
  2905. return function(type, data) {
  2906. originalEmit.call(this, type, data);
  2907. $(this.element).trigger({
  2908. type: type,
  2909. gesture: data
  2910. });
  2911. };
  2912. })(Hammer.Manager.prototype.emit);
  2913. })($, Hammer);
  2914. module.exports = UI.Hammer = Hammer;
  2915. /***/ },
  2916. /* 4 */
  2917. /***/ function(module, exports, __webpack_require__) {
  2918. 'use strict';
  2919. var UI = __webpack_require__(2);
  2920. /**
  2921. * Add to Homescreen v3.2.2
  2922. * (c) 2015 Matteo Spinelli
  2923. * @license: http://cubiq.org/license
  2924. */
  2925. // Check for addEventListener browser support (prevent errors in IE<9)
  2926. var _eventListener = 'addEventListener' in window;
  2927. // Check if document is loaded, needed by autostart
  2928. var _DOMReady = false;
  2929. if (document.readyState === 'complete') {
  2930. _DOMReady = true;
  2931. } else if (_eventListener) {
  2932. window.addEventListener('load', loaded, false);
  2933. }
  2934. function loaded() {
  2935. window.removeEventListener('load', loaded, false);
  2936. _DOMReady = true;
  2937. }
  2938. // regex used to detect if app has been added to the homescreen
  2939. var _reSmartURL = /\/ath(\/)?$/;
  2940. var _reQueryString = /([\?&]ath=[^&]*$|&ath=[^&]*(&))/;
  2941. // singleton
  2942. var _instance;
  2943. function ath(options) {
  2944. _instance = _instance || new ath.Class(options);
  2945. return _instance;
  2946. }
  2947. // message in all supported languages
  2948. ath.intl = {
  2949. en_us: {
  2950. ios: 'To add this web app to the home screen: tap %icon and then <strong>Add to Home Screen</strong>.',
  2951. android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  2952. },
  2953. zh_cn: {
  2954. ios: '如要把应用程式加至主屏幕,请点击%icon, 然后<strong>加至主屏幕</strong>',
  2955. android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  2956. },
  2957. zh_tw: {
  2958. ios: '如要把應用程式加至主屏幕, 請點擊%icon, 然後<strong>加至主屏幕</strong>.',
  2959. android: 'To add this web app to the home screen open the browser option menu and tap on <strong>Add to homescreen</strong>. <small>The menu can be accessed by pressing the menu hardware button if your device has one, or by tapping the top right menu icon <span class="ath-action-icon">icon</span>.</small>'
  2960. }
  2961. };
  2962. // Add 2 characters language support (Android mostly)
  2963. for (var lang in ath.intl) {
  2964. ath.intl[lang.substr(0, 2)] = ath.intl[lang];
  2965. }
  2966. // default options
  2967. ath.defaults = {
  2968. appID: 'org.cubiq.addtohome', // local storage name (no need to change)
  2969. fontSize: 15, // base font size, used to properly resize the popup based on viewport scale factor
  2970. debug: false, // override browser checks
  2971. logging: false, // log reasons for showing or not showing to js console; defaults to true when debug is true
  2972. modal: false, // prevent further actions until the message is closed
  2973. mandatory: false, // you can't proceed if you don't add the app to the homescreen
  2974. autostart: true, // show the message automatically
  2975. skipFirstVisit: false, // show only to returning visitors (ie: skip the first time you visit)
  2976. startDelay: 1, // display the message after that many seconds from page load
  2977. lifespan: 15, // life of the message in seconds
  2978. displayPace: 1440, // minutes before the message is shown again (0: display every time, default 24 hours)
  2979. maxDisplayCount: 0, // absolute maximum number of times the message will be shown to the user (0: no limit)
  2980. icon: true, // add touch icon to the message
  2981. message: '', // the message can be customized
  2982. validLocation: [], // list of pages where the message will be shown (array of regexes)
  2983. onInit: null, // executed on instance creation
  2984. onShow: null, // executed when the message is shown
  2985. onRemove: null, // executed when the message is removed
  2986. onAdd: null, // when the application is launched the first time from the homescreen (guesstimate)
  2987. onPrivate: null, // executed if user is in private mode
  2988. privateModeOverride: false, // show the message even in private mode (very rude)
  2989. detectHomescreen: false // try to detect if the site has been added to the homescreen (false | true | 'hash' | 'queryString' | 'smartURL')
  2990. };
  2991. // browser info and capability
  2992. var _ua = window.navigator.userAgent;
  2993. var _nav = window.navigator;
  2994. _extend(ath, {
  2995. hasToken: document.location.hash == '#ath' || _reSmartURL.test(document.location.href) || _reQueryString.test(document.location.search),
  2996. isRetina: window.devicePixelRatio && window.devicePixelRatio > 1,
  2997. isIDevice: (/iphone|ipod|ipad/i).test(_ua),
  2998. isMobileChrome: _ua.indexOf('Android') > -1 && (/Chrome\/[.0-9]*/).test(_ua) && _ua.indexOf("Version") == -1,
  2999. isMobileIE: _ua.indexOf('Windows Phone') > -1,
  3000. language: _nav.language && _nav.language.toLowerCase().replace('-', '_') || ''
  3001. });
  3002. // falls back to en_us if language is unsupported
  3003. ath.language = ath.language && ath.language in ath.intl ? ath.language : 'en_us';
  3004. ath.isMobileSafari = ath.isIDevice && _ua.indexOf('Safari') > -1 && _ua.indexOf('CriOS') < 0;
  3005. ath.OS = ath.isIDevice ? 'ios' : ath.isMobileChrome ? 'android' : ath.isMobileIE ? 'windows' : 'unsupported';
  3006. ath.OSVersion = _ua.match(/(OS|Android) (\d+[_\.]\d+)/);
  3007. ath.OSVersion = ath.OSVersion && ath.OSVersion[2] ? +ath.OSVersion[2].replace('_', '.') : 0;
  3008. ath.isStandalone = 'standalone' in window.navigator && window.navigator.standalone;
  3009. ath.isTablet = (ath.isMobileSafari && _ua.indexOf('iPad') > -1) || (ath.isMobileChrome && _ua.indexOf('Mobile') < 0);
  3010. ath.isCompatible = (ath.isMobileSafari && ath.OSVersion >= 6) || ath.isMobileChrome; // TODO: add winphone
  3011. var _defaultSession = {
  3012. lastDisplayTime: 0, // last time we displayed the message
  3013. returningVisitor: false, // is this the first time you visit
  3014. displayCount: 0, // number of times the message has been shown
  3015. optedout: false, // has the user opted out
  3016. added: false // has been actually added to the homescreen
  3017. };
  3018. ath.removeSession = function(appID) {
  3019. try {
  3020. if (!localStorage) {
  3021. throw new Error('localStorage is not defined');
  3022. }
  3023. localStorage.removeItem(appID || ath.defaults.appID);
  3024. } catch (e) {
  3025. // we are most likely in private mode
  3026. }
  3027. };
  3028. ath.doLog = function(logStr) {
  3029. if (this.options.logging) {
  3030. console.log(logStr);
  3031. }
  3032. };
  3033. ath.Class = function(options) {
  3034. // class methods
  3035. this.doLog = ath.doLog;
  3036. // merge default options with user config
  3037. this.options = _extend({}, ath.defaults);
  3038. _extend(this.options, options);
  3039. // override defaults that are dependent on each other
  3040. if (this.options.debug) {
  3041. this.options.logging = true;
  3042. }
  3043. // IE<9 so exit (I hate you, really)
  3044. if (!_eventListener) {
  3045. return;
  3046. }
  3047. // normalize some options
  3048. this.options.mandatory = this.options.mandatory && ( 'standalone' in window.navigator || this.options.debug );
  3049. this.options.modal = this.options.modal || this.options.mandatory;
  3050. if (this.options.mandatory) {
  3051. this.options.startDelay = -0.5; // make the popup hasty
  3052. }
  3053. this.options.detectHomescreen = this.options.detectHomescreen === true ? 'hash' : this.options.detectHomescreen;
  3054. // setup the debug environment
  3055. if (this.options.debug) {
  3056. ath.isCompatible = true;
  3057. ath.OS = typeof this.options.debug == 'string' ? this.options.debug : ath.OS == 'unsupported' ? 'android' : ath.OS;
  3058. ath.OSVersion = ath.OS == 'ios' ? '8' : '4';
  3059. }
  3060. // the element the message will be appended to
  3061. this.container = document.documentElement;
  3062. // load session
  3063. this.session = this.getItem(this.options.appID);
  3064. this.session = this.session ? JSON.parse(this.session) : undefined;
  3065. // user most likely came from a direct link containing our token, we don't need it and we remove it
  3066. if (ath.hasToken && ( !ath.isCompatible || !this.session )) {
  3067. ath.hasToken = false;
  3068. _removeToken();
  3069. }
  3070. // the device is not supported
  3071. if (!ath.isCompatible) {
  3072. this.doLog("Add to homescreen: not displaying callout because device not supported");
  3073. return;
  3074. }
  3075. this.session = this.session || _defaultSession;
  3076. // check if we can use the local storage
  3077. try {
  3078. if (!localStorage) {
  3079. throw new Error('localStorage is not defined');
  3080. }
  3081. localStorage.setItem(this.options.appID, JSON.stringify(this.session));
  3082. ath.hasLocalStorage = true;
  3083. } catch (e) {
  3084. // we are most likely in private mode
  3085. ath.hasLocalStorage = false;
  3086. if (this.options.onPrivate) {
  3087. this.options.onPrivate.call(this);
  3088. }
  3089. }
  3090. // check if this is a valid location
  3091. var isValidLocation = !this.options.validLocation.length;
  3092. for (var i = this.options.validLocation.length; i--;) {
  3093. if (this.options.validLocation[i].test(document.location.href)) {
  3094. isValidLocation = true;
  3095. break;
  3096. }
  3097. }
  3098. // check compatibility with old versions of add to homescreen. Opt-out if an old session is found
  3099. if (this.getItem('addToHome')) {
  3100. this.optOut();
  3101. }
  3102. // critical errors:
  3103. if (this.session.optedout) {
  3104. this.doLog("Add to homescreen: not displaying callout because user opted out");
  3105. return;
  3106. }
  3107. if (this.session.added) {
  3108. this.doLog("Add to homescreen: not displaying callout because already added to the homescreen");
  3109. return;
  3110. }
  3111. if (!isValidLocation) {
  3112. this.doLog("Add to homescreen: not displaying callout because not a valid location");
  3113. return;
  3114. }
  3115. // check if the app is in stand alone mode
  3116. if (ath.isStandalone) {
  3117. // execute the onAdd event if we haven't already
  3118. if (!this.session.added) {
  3119. this.session.added = true;
  3120. this.updateSession();
  3121. if (this.options.onAdd && ath.hasLocalStorage) { // double check on localstorage to avoid multiple calls to the custom event
  3122. this.options.onAdd.call(this);
  3123. }
  3124. }
  3125. this.doLog("Add to homescreen: not displaying callout because in standalone mode");
  3126. return;
  3127. }
  3128. // (try to) check if the page has been added to the homescreen
  3129. if (this.options.detectHomescreen) {
  3130. // the URL has the token, we are likely coming from the homescreen
  3131. if (ath.hasToken) {
  3132. _removeToken(); // we don't actually need the token anymore, we remove it to prevent redistribution
  3133. // this is called the first time the user opens the app from the homescreen
  3134. if (!this.session.added) {
  3135. this.session.added = true;
  3136. this.updateSession();
  3137. if (this.options.onAdd && ath.hasLocalStorage) { // double check on localstorage to avoid multiple calls to the custom event
  3138. this.options.onAdd.call(this);
  3139. }
  3140. }
  3141. this.doLog("Add to homescreen: not displaying callout because URL has token, so we are likely coming from homescreen");
  3142. return;
  3143. }
  3144. // URL doesn't have the token, so add it
  3145. if (this.options.detectHomescreen == 'hash') {
  3146. history.replaceState('', window.document.title, document.location.href + '#ath');
  3147. } else if (this.options.detectHomescreen == 'smartURL') {
  3148. history.replaceState('', window.document.title, document.location.href.replace(/(\/)?$/, '/ath$1'));
  3149. } else {
  3150. history.replaceState('', window.document.title, document.location.href + (document.location.search ? '&' : '?' ) + 'ath=');
  3151. }
  3152. }
  3153. // check if this is a returning visitor
  3154. if (!this.session.returningVisitor) {
  3155. this.session.returningVisitor = true;
  3156. this.updateSession();
  3157. // we do not show the message if this is your first visit
  3158. if (this.options.skipFirstVisit) {
  3159. this.doLog("Add to homescreen: not displaying callout because skipping first visit");
  3160. return;
  3161. }
  3162. }
  3163. // we do no show the message in private mode
  3164. if (!this.options.privateModeOverride && !ath.hasLocalStorage) {
  3165. this.doLog("Add to homescreen: not displaying callout because browser is in private mode");
  3166. return;
  3167. }
  3168. // all checks passed, ready to display
  3169. this.ready = true;
  3170. if (this.options.onInit) {
  3171. this.options.onInit.call(this);
  3172. }
  3173. if (this.options.autostart) {
  3174. this.doLog("Add to homescreen: autostart displaying callout");
  3175. this.show();
  3176. }
  3177. };
  3178. ath.Class.prototype = {
  3179. // event type to method conversion
  3180. events: {
  3181. load: '_delayedShow',
  3182. error: '_delayedShow',
  3183. orientationchange: 'resize',
  3184. resize: 'resize',
  3185. scroll: 'resize',
  3186. click: 'remove',
  3187. touchmove: '_preventDefault',
  3188. transitionend: '_removeElements',
  3189. webkitTransitionEnd: '_removeElements',
  3190. MSTransitionEnd: '_removeElements'
  3191. },
  3192. handleEvent: function(e) {
  3193. var type = this.events[e.type];
  3194. if (type) {
  3195. this[type](e);
  3196. }
  3197. },
  3198. show: function(force) {
  3199. // in autostart mode wait for the document to be ready
  3200. if (this.options.autostart && !_DOMReady) {
  3201. setTimeout(this.show.bind(this), 50);
  3202. // we are not displaying callout because DOM not ready, but don't log that because
  3203. // it would log too frequently
  3204. return;
  3205. }
  3206. // message already on screen
  3207. if (this.shown) {
  3208. this.doLog("Add to homescreen: not displaying callout because already shown on screen");
  3209. return;
  3210. }
  3211. var now = Date.now();
  3212. var lastDisplayTime = this.session.lastDisplayTime;
  3213. if (force !== true) {
  3214. // this is needed if autostart is disabled and you programmatically call the show() method
  3215. if (!this.ready) {
  3216. this.doLog("Add to homescreen: not displaying callout because not ready");
  3217. return;
  3218. }
  3219. // we obey the display pace (prevent the message to popup too often)
  3220. if (now - lastDisplayTime < this.options.displayPace * 60000) {
  3221. this.doLog("Add to homescreen: not displaying callout because displayed recently");
  3222. return;
  3223. }
  3224. // obey the maximum number of display count
  3225. if (this.options.maxDisplayCount && this.session.displayCount >= this.options.maxDisplayCount) {
  3226. this.doLog("Add to homescreen: not displaying callout because displayed too many times already");
  3227. return;
  3228. }
  3229. }
  3230. this.shown = true;
  3231. // increment the display count
  3232. this.session.lastDisplayTime = now;
  3233. this.session.displayCount++;
  3234. this.updateSession();
  3235. // try to get the highest resolution application icon
  3236. if (!this.applicationIcon) {
  3237. if (ath.OS == 'ios') {
  3238. this.applicationIcon = document.querySelector('head link[rel^=apple-touch-icon][sizes="152x152"],head link[rel^=apple-touch-icon][sizes="144x144"],head link[rel^=apple-touch-icon][sizes="120x120"],head link[rel^=apple-touch-icon][sizes="114x114"],head link[rel^=apple-touch-icon]');
  3239. } else {
  3240. this.applicationIcon = document.querySelector('head link[rel^="shortcut icon"][sizes="196x196"],head link[rel^=apple-touch-icon]');
  3241. }
  3242. }
  3243. var message = '';
  3244. if (typeof this.options.message == 'object' && ath.language in this.options.message) { // use custom language message
  3245. message = this.options.message[ath.language][ath.OS];
  3246. } else if (typeof this.options.message == 'object' && ath.OS in this.options.message) { // use custom os message
  3247. message = this.options.message[ath.OS];
  3248. } else if (this.options.message in ath.intl) { // you can force the locale
  3249. message = ath.intl[this.options.message][ath.OS];
  3250. } else if (this.options.message !== '') { // use a custom message
  3251. message = this.options.message;
  3252. } else if (ath.OS in ath.intl[ath.language]) { // otherwise we use our message
  3253. message = ath.intl[ath.language][ath.OS];
  3254. }
  3255. // add the action icon
  3256. message = '<p>' + message.replace('%icon', '<span class="ath-action-icon">icon</span>') + '</p>';
  3257. // create the message container
  3258. this.viewport = document.createElement('div');
  3259. this.viewport.className = 'ath-viewport';
  3260. if (this.options.modal) {
  3261. this.viewport.className += ' ath-modal';
  3262. }
  3263. if (this.options.mandatory) {
  3264. this.viewport.className += ' ath-mandatory';
  3265. }
  3266. this.viewport.style.position = 'absolute';
  3267. // create the actual message element
  3268. this.element = document.createElement('div');
  3269. this.element.className = 'ath-container ath-' + ath.OS + ' ath-' + ath.OS + (ath.OSVersion + '').substr(0, 1) + ' ath-' + (ath.isTablet ? 'tablet' : 'phone');
  3270. this.element.style.cssText = '-webkit-transition-property:-webkit-transform,opacity;-webkit-transition-duration:0s;-webkit-transition-timing-function:ease-out;transition-property:transform,opacity;transition-duration:0s;transition-timing-function:ease-out;';
  3271. this.element.style.webkitTransform = 'translate3d(0,-' + window.innerHeight + 'px,0)';
  3272. this.element.style.transform = 'translate3d(0,-' + window.innerHeight + 'px,0)';
  3273. // add the application icon
  3274. if (this.options.icon && this.applicationIcon) {
  3275. this.element.className += ' ath-icon';
  3276. this.img = document.createElement('img');
  3277. this.img.className = 'ath-application-icon';
  3278. this.img.addEventListener('load', this, false);
  3279. this.img.addEventListener('error', this, false);
  3280. this.img.src = this.applicationIcon.href;
  3281. this.element.appendChild(this.img);
  3282. }
  3283. this.element.innerHTML += message;
  3284. // we are not ready to show, place the message out of sight
  3285. this.viewport.style.left = '-99999em';
  3286. // attach all elements to the DOM
  3287. this.viewport.appendChild(this.element);
  3288. this.container.appendChild(this.viewport);
  3289. // if we don't have to wait for an image to load, show the message right away
  3290. if (this.img) {
  3291. this.doLog("Add to homescreen: not displaying callout because waiting for img to load");
  3292. } else {
  3293. this._delayedShow();
  3294. }
  3295. },
  3296. _delayedShow: function(e) {
  3297. setTimeout(this._show.bind(this), this.options.startDelay * 1000 + 500);
  3298. },
  3299. _show: function() {
  3300. var that = this;
  3301. // update the viewport size and orientation
  3302. this.updateViewport();
  3303. // reposition/resize the message on orientation change
  3304. window.addEventListener('resize', this, false);
  3305. window.addEventListener('scroll', this, false);
  3306. window.addEventListener('orientationchange', this, false);
  3307. if (this.options.modal) {
  3308. // lock any other interaction
  3309. document.addEventListener('touchmove', this, true);
  3310. }
  3311. // Enable closing after 1 second
  3312. if (!this.options.mandatory) {
  3313. setTimeout(function() {
  3314. that.element.addEventListener('click', that, true);
  3315. }, 1000);
  3316. }
  3317. // kick the animation
  3318. setTimeout(function() {
  3319. that.element.style.webkitTransitionDuration = '1.2s';
  3320. that.element.style.transitionDuration = '1.2s';
  3321. that.element.style.webkitTransform = 'translate3d(0,0,0)';
  3322. that.element.style.transform = 'translate3d(0,0,0)';
  3323. }, 0);
  3324. // set the destroy timer
  3325. if (this.options.lifespan) {
  3326. this.removeTimer = setTimeout(this.remove.bind(this), this.options.lifespan * 1000);
  3327. }
  3328. // fire the custom onShow event
  3329. if (this.options.onShow) {
  3330. this.options.onShow.call(this);
  3331. }
  3332. },
  3333. remove: function() {
  3334. clearTimeout(this.removeTimer);
  3335. // clear up the event listeners
  3336. if (this.img) {
  3337. this.img.removeEventListener('load', this, false);
  3338. this.img.removeEventListener('error', this, false);
  3339. }
  3340. window.removeEventListener('resize', this, false);
  3341. window.removeEventListener('scroll', this, false);
  3342. window.removeEventListener('orientationchange', this, false);
  3343. document.removeEventListener('touchmove', this, true);
  3344. this.element.removeEventListener('click', this, true);
  3345. // remove the message element on transition end
  3346. this.element.addEventListener('transitionend', this, false);
  3347. this.element.addEventListener('webkitTransitionEnd', this, false);
  3348. this.element.addEventListener('MSTransitionEnd', this, false);
  3349. // start the fade out animation
  3350. this.element.style.webkitTransitionDuration = '0.3s';
  3351. this.element.style.opacity = '0';
  3352. },
  3353. _removeElements: function() {
  3354. this.element.removeEventListener('transitionend', this, false);
  3355. this.element.removeEventListener('webkitTransitionEnd', this, false);
  3356. this.element.removeEventListener('MSTransitionEnd', this, false);
  3357. // remove the message from the DOM
  3358. this.container.removeChild(this.viewport);
  3359. this.shown = false;
  3360. // fire the custom onRemove event
  3361. if (this.options.onRemove) {
  3362. this.options.onRemove.call(this);
  3363. }
  3364. },
  3365. updateViewport: function() {
  3366. if (!this.shown) {
  3367. return;
  3368. }
  3369. this.viewport.style.width = window.innerWidth + 'px';
  3370. this.viewport.style.height = window.innerHeight + 'px';
  3371. this.viewport.style.left = window.scrollX + 'px';
  3372. this.viewport.style.top = window.scrollY + 'px';
  3373. var clientWidth = document.documentElement.clientWidth;
  3374. this.orientation = clientWidth > document.documentElement.clientHeight ? 'landscape' : 'portrait';
  3375. var screenWidth = ath.OS == 'ios' ? this.orientation == 'portrait' ? screen.width : screen.height : screen.width;
  3376. this.scale = screen.width > clientWidth ? 1 : screenWidth / window.innerWidth;
  3377. this.element.style.fontSize = this.options.fontSize / this.scale + 'px';
  3378. },
  3379. resize: function() {
  3380. clearTimeout(this.resizeTimer);
  3381. this.resizeTimer = setTimeout(this.updateViewport.bind(this), 100);
  3382. },
  3383. updateSession: function() {
  3384. if (ath.hasLocalStorage === false) {
  3385. return;
  3386. }
  3387. if (localStorage) {
  3388. localStorage.setItem(this.options.appID, JSON.stringify(this.session));
  3389. }
  3390. },
  3391. clearSession: function() {
  3392. this.session = _defaultSession;
  3393. this.updateSession();
  3394. },
  3395. getItem: function(item) {
  3396. try {
  3397. if (!localStorage) {
  3398. throw new Error('localStorage is not defined');
  3399. }
  3400. return localStorage.getItem(item);
  3401. } catch (e) {
  3402. // Preventing exception for some browsers when fetching localStorage key
  3403. ath.hasLocalStorage = false;
  3404. }
  3405. },
  3406. optOut: function() {
  3407. this.session.optedout = true;
  3408. this.updateSession();
  3409. },
  3410. optIn: function() {
  3411. this.session.optedout = false;
  3412. this.updateSession();
  3413. },
  3414. clearDisplayCount: function() {
  3415. this.session.displayCount = 0;
  3416. this.updateSession();
  3417. },
  3418. _preventDefault: function(e) {
  3419. e.preventDefault();
  3420. e.stopPropagation();
  3421. }
  3422. };
  3423. // utility
  3424. function _extend(target, obj) {
  3425. for (var i in obj) {
  3426. target[i] = obj[i];
  3427. }
  3428. return target;
  3429. }
  3430. function _removeToken() {
  3431. if (document.location.hash == '#ath') {
  3432. history.replaceState('', window.document.title, document.location.href.split('#')[0]);
  3433. }
  3434. if (_reSmartURL.test(document.location.href)) {
  3435. history.replaceState('', window.document.title, document.location.href.replace(_reSmartURL, '$1'));
  3436. }
  3437. if (_reQueryString.test(document.location.search)) {
  3438. history.replaceState('', window.document.title, document.location.href.replace(_reQueryString, '$2'));
  3439. }
  3440. }
  3441. /* jshint +W101, +W106 */
  3442. ath.VERSION = '3.2.2';
  3443. module.exports = UI.addToHomescreen = ath;
  3444. /***/ },
  3445. /* 5 */
  3446. /***/ function(module, exports, __webpack_require__) {
  3447. 'use strict';
  3448. var $ = __webpack_require__(1);
  3449. var UI = __webpack_require__(2);
  3450. /**
  3451. * @via https://github.com/Minwe/bootstrap/blob/master/js/alert.js
  3452. * @copyright Copyright 2013 Twitter, Inc.
  3453. * @license Apache 2.0
  3454. */
  3455. // Alert Class
  3456. // NOTE: removeElement option is unavailable now
  3457. var Alert = function(element, options) {
  3458. var _this = this;
  3459. this.options = $.extend({}, Alert.DEFAULTS, options);
  3460. this.$element = $(element);
  3461. this.$element
  3462. .addClass('am-fade am-in')
  3463. .on('click.alert.amui', '.am-close', function() {
  3464. _this.close();
  3465. });
  3466. };
  3467. Alert.DEFAULTS = {
  3468. removeElement: true
  3469. };
  3470. Alert.prototype.close = function() {
  3471. var $element = this.$element;
  3472. $element.trigger('close.alert.amui').removeClass('am-in');
  3473. function processAlert() {
  3474. $element.trigger('closed.alert.amui').remove();
  3475. }
  3476. UI.support.transition && $element.hasClass('am-fade') ?
  3477. $element
  3478. .one(UI.support.transition.end, processAlert)
  3479. .emulateTransitionEnd(200) :
  3480. processAlert();
  3481. };
  3482. // plugin
  3483. UI.plugin('alert', Alert);
  3484. // Init code
  3485. $(document).on('click.alert.amui.data-api', '[data-am-alert]', function(e) {
  3486. var $target = $(e.target);
  3487. $target.is('.am-close') && $(this).alert('close');
  3488. });
  3489. module.exports = Alert;
  3490. /***/ },
  3491. /* 6 */
  3492. /***/ function(module, exports, __webpack_require__) {
  3493. 'use strict';
  3494. var $ = __webpack_require__(1);
  3495. var UI = __webpack_require__(2);
  3496. /**
  3497. * @via https://github.com/twbs/bootstrap/blob/master/js/button.js
  3498. * @copyright (c) 2011-2014 Twitter, Inc
  3499. * @license The MIT License
  3500. */
  3501. var Button = function(element, options) {
  3502. this.$element = $(element);
  3503. this.options = $.extend({}, Button.DEFAULTS, options);
  3504. this.isLoading = false;
  3505. this.hasSpinner = false;
  3506. };
  3507. Button.DEFAULTS = {
  3508. loadingText: 'loading...',
  3509. disabledClassName: 'am-disabled',
  3510. activeClassName: 'am-active',
  3511. spinner: undefined
  3512. };
  3513. Button.prototype.setState = function(state, stateText) {
  3514. var $element = this.$element;
  3515. var disabled = 'disabled';
  3516. var data = $element.data();
  3517. var options = this.options;
  3518. var val = $element.is('input') ? 'val' : 'html';
  3519. var stateClassName = 'am-btn-' + state + ' ' + options.disabledClassName;
  3520. state += 'Text';
  3521. if (!options.resetText) {
  3522. options.resetText = $element[val]();
  3523. }
  3524. // add spinner for element with html()
  3525. if (UI.support.animation && options.spinner &&
  3526. val === 'html' && !this.hasSpinner) {
  3527. options.loadingText = '<span class="am-icon-' + options.spinner +
  3528. ' am-icon-spin"></span>' + options.loadingText;
  3529. this.hasSpinner = true;
  3530. }
  3531. stateText = stateText ||
  3532. (data[state] === undefined ? options[state] : data[state]);
  3533. $element[val](stateText);
  3534. // push to event loop to allow forms to submit
  3535. setTimeout($.proxy(function() {
  3536. // TODO: add stateClass for other states
  3537. if (state === 'loadingText') {
  3538. $element.addClass(stateClassName).attr(disabled, disabled);
  3539. this.isLoading = true;
  3540. } else if (this.isLoading) {
  3541. $element.removeClass(stateClassName).removeAttr(disabled);
  3542. this.isLoading = false;
  3543. }
  3544. }, this), 0);
  3545. };
  3546. Button.prototype.toggle = function() {
  3547. var changed = true;
  3548. var $element = this.$element;
  3549. var $parent = this.$element.parent('[class*="am-btn-group"]');
  3550. var activeClassName = Button.DEFAULTS.activeClassName;
  3551. if ($parent.length) {
  3552. var $input = this.$element.find('input');
  3553. if ($input.prop('type') == 'radio') {
  3554. if ($input.prop('checked') && $element.hasClass(activeClassName)) {
  3555. changed = false;
  3556. } else {
  3557. $parent.find('.' + activeClassName).removeClass(activeClassName);
  3558. }
  3559. }
  3560. if (changed) {
  3561. $input.prop('checked',
  3562. !$element.hasClass(activeClassName)).trigger('change');
  3563. }
  3564. }
  3565. if (changed) {
  3566. $element.toggleClass(activeClassName);
  3567. if (!$element.hasClass(activeClassName)) {
  3568. $element.blur();
  3569. }
  3570. }
  3571. };
  3572. UI.plugin('button', Button, {
  3573. dataOptions: 'data-am-loading',
  3574. methodCall: function(args, instance) {
  3575. if (args[0] === 'toggle') {
  3576. instance.toggle();
  3577. } else if (typeof args[0] === 'string') {
  3578. instance.setState.apply(instance, args);
  3579. }
  3580. }
  3581. });
  3582. // Init code
  3583. $(document).on('click.button.amui.data-api', '[data-am-button]', function(e) {
  3584. e.preventDefault();
  3585. var $btn = $(e.target);
  3586. if (!$btn.hasClass('am-btn')) {
  3587. $btn = $btn.closest('.am-btn');
  3588. }
  3589. $btn.button('toggle');
  3590. });
  3591. UI.ready(function(context) {
  3592. $('[data-am-loading]', context).button();
  3593. // resolves #866
  3594. $('[data-am-button]', context).find('input:checked').each(function() {
  3595. $(this).parent('label').addClass(Button.DEFAULTS.activeClassName);
  3596. });
  3597. });
  3598. module.exports = UI.button = Button;
  3599. /***/ },
  3600. /* 7 */
  3601. /***/ function(module, exports, __webpack_require__) {
  3602. 'use strict';
  3603. var $ = __webpack_require__(1);
  3604. var UI = __webpack_require__(2);
  3605. /**
  3606. * @via https://github.com/twbs/bootstrap/blob/master/js/collapse.js
  3607. * @copyright (c) 2011-2014 Twitter, Inc
  3608. * @license The MIT License
  3609. */
  3610. var Collapse = function(element, options) {
  3611. this.$element = $(element);
  3612. this.options = $.extend({}, Collapse.DEFAULTS, options);
  3613. this.transitioning = null;
  3614. if (this.options.parent) {
  3615. this.$parent = $(this.options.parent);
  3616. }
  3617. if (this.options.toggle) {
  3618. this.toggle();
  3619. }
  3620. };
  3621. Collapse.DEFAULTS = {
  3622. toggle: true
  3623. };
  3624. Collapse.prototype.open = function() {
  3625. if (this.transitioning || this.$element.hasClass('am-in')) {
  3626. return;
  3627. }
  3628. var startEvent = $.Event('open.collapse.amui');
  3629. this.$element.trigger(startEvent);
  3630. if (startEvent.isDefaultPrevented()) {
  3631. return;
  3632. }
  3633. var actives = this.$parent && this.$parent.find('> .am-panel > .am-in');
  3634. if (actives && actives.length) {
  3635. var hasData = actives.data('amui.collapse');
  3636. if (hasData && hasData.transitioning) {
  3637. return;
  3638. }
  3639. Plugin.call(actives, 'close');
  3640. hasData || actives.data('amui.collapse', null);
  3641. }
  3642. this.$element
  3643. .removeClass('am-collapse')
  3644. .addClass('am-collapsing').height(0);
  3645. this.transitioning = 1;
  3646. var complete = function() {
  3647. this.$element
  3648. .removeClass('am-collapsing')
  3649. .addClass('am-collapse am-in')
  3650. .height('')
  3651. .trigger('opened.collapse.amui');
  3652. this.transitioning = 0;
  3653. };
  3654. if (!UI.support.transition) {
  3655. return complete.call(this);
  3656. }
  3657. var scrollHeight = this.$element[0].scrollHeight;
  3658. this.$element
  3659. .one(UI.support.transition.end, $.proxy(complete, this))
  3660. .emulateTransitionEnd(300)
  3661. .css({height: scrollHeight}); // 当折叠的容器有 padding 时,如果用 height() 只能设置内容的宽度
  3662. };
  3663. Collapse.prototype.close = function() {
  3664. if (this.transitioning || !this.$element.hasClass('am-in')) {
  3665. return;
  3666. }
  3667. var startEvent = $.Event('close.collapse.amui');
  3668. this.$element.trigger(startEvent);
  3669. if (startEvent.isDefaultPrevented()) {
  3670. return;
  3671. }
  3672. this.$element.height(this.$element.height()).redraw();
  3673. this.$element.addClass('am-collapsing').
  3674. removeClass('am-collapse am-in');
  3675. this.transitioning = 1;
  3676. var complete = function() {
  3677. this.transitioning = 0;
  3678. this.$element
  3679. .trigger('closed.collapse.amui')
  3680. .removeClass('am-collapsing')
  3681. .addClass('am-collapse');
  3682. // css({height: '0'});
  3683. };
  3684. if (!UI.support.transition) {
  3685. return complete.call(this);
  3686. }
  3687. this.$element.height(0)
  3688. .one(UI.support.transition.end, $.proxy(complete, this))
  3689. .emulateTransitionEnd(300);
  3690. };
  3691. Collapse.prototype.toggle = function() {
  3692. this[this.$element.hasClass('am-in') ? 'close' : 'open']();
  3693. };
  3694. // Collapse Plugin
  3695. function Plugin(option) {
  3696. return this.each(function() {
  3697. var $this = $(this);
  3698. var data = $this.data('amui.collapse');
  3699. var options = $.extend({}, Collapse.DEFAULTS,
  3700. UI.utils.options($this.attr('data-am-collapse')),
  3701. typeof option == 'object' && option);
  3702. if (!data && options.toggle && option === 'open') {
  3703. option = !option;
  3704. }
  3705. if (!data) {
  3706. $this.data('amui.collapse', (data = new Collapse(this, options)));
  3707. }
  3708. if (typeof option == 'string') {
  3709. data[option]();
  3710. }
  3711. });
  3712. }
  3713. $.fn.collapse = Plugin;
  3714. // Init code
  3715. $(document).on('click.collapse.amui.data-api', '[data-am-collapse]',
  3716. function(e) {
  3717. var href;
  3718. var $this = $(this);
  3719. var options = UI.utils.options($this.attr('data-am-collapse'));
  3720. var target = options.target ||
  3721. e.preventDefault() ||
  3722. (href = $this.attr('href')) &&
  3723. href.replace(/.*(?=#[^\s]+$)/, '');
  3724. var $target = $(target);
  3725. var data = $target.data('amui.collapse');
  3726. var option = data ? 'toggle' : options;
  3727. var parent = options.parent;
  3728. var $parent = parent && $(parent);
  3729. if (!data || !data.transitioning) {
  3730. if ($parent) {
  3731. // '[data-am-collapse*="{parent: \'' + parent + '"]
  3732. $parent.find('[data-am-collapse]').not($this).addClass('am-collapsed');
  3733. }
  3734. $this[$target.hasClass('am-in') ?
  3735. 'addClass' : 'removeClass']('am-collapsed');
  3736. }
  3737. Plugin.call($target, option);
  3738. });
  3739. module.exports = UI.collapse = Collapse;
  3740. // TODO: 更好的 target 选择方式
  3741. // 折叠的容器必须没有 border/padding 才能正常处理,否则动画会有一些小问题
  3742. // 寻找更好的未知高度 transition 动画解决方案,max-height 之类的就算了
  3743. /***/ },
  3744. /* 8 */
  3745. /***/ function(module, exports, __webpack_require__) {
  3746. 'use strict';
  3747. var $ = __webpack_require__(1);
  3748. var UI = __webpack_require__(2);
  3749. var $doc = $(document);
  3750. /**
  3751. * bootstrap-datepicker.js
  3752. * @via http://www.eyecon.ro/bootstrap-datepicker
  3753. * @license http://www.apache.org/licenses/LICENSE-2.0
  3754. */
  3755. var Datepicker = function(element, options) {
  3756. this.$element = $(element);
  3757. this.options = $.extend({}, Datepicker.DEFAULTS, options);
  3758. this.format = DPGlobal.parseFormat(this.options.format);
  3759. this.$element.data('date', this.options.date);
  3760. this.language = this.getLocale(this.options.locale);
  3761. this.theme = this.options.theme;
  3762. this.$picker = $(DPGlobal.template).appendTo('body').on({
  3763. click: $.proxy(this.click, this)
  3764. // mousedown: $.proxy(this.mousedown, this)
  3765. });
  3766. this.isInput = this.$element.is('input');
  3767. this.component = this.$element.is('.am-datepicker-date') ?
  3768. this.$element.find('.am-datepicker-add-on') : false;
  3769. if (this.isInput) {
  3770. this.$element.on({
  3771. 'click.datepicker.amui': $.proxy(this.open, this),
  3772. // blur: $.proxy(this.close, this),
  3773. 'keyup.datepicker.amui': $.proxy(this.update, this)
  3774. });
  3775. } else {
  3776. if (this.component) {
  3777. this.component.on('click.datepicker.amui', $.proxy(this.open, this));
  3778. } else {
  3779. this.$element.on('click.datepicker.amui', $.proxy(this.open, this));
  3780. }
  3781. }
  3782. this.minViewMode = this.options.minViewMode;
  3783. if (typeof this.minViewMode === 'string') {
  3784. switch (this.minViewMode) {
  3785. case 'months':
  3786. this.minViewMode = 1;
  3787. break;
  3788. case 'years':
  3789. this.minViewMode = 2;
  3790. break;
  3791. default:
  3792. this.minViewMode = 0;
  3793. break;
  3794. }
  3795. }
  3796. this.viewMode = this.options.viewMode;
  3797. if (typeof this.viewMode === 'string') {
  3798. switch (this.viewMode) {
  3799. case 'months':
  3800. this.viewMode = 1;
  3801. break;
  3802. case 'years':
  3803. this.viewMode = 2;
  3804. break;
  3805. default:
  3806. this.viewMode = 0;
  3807. break;
  3808. }
  3809. }
  3810. this.startViewMode = this.viewMode;
  3811. this.weekStart = ((this.options.weekStart ||
  3812. Datepicker.locales[this.language].weekStart || 0) % 7);
  3813. this.weekEnd = ((this.weekStart + 6) % 7);
  3814. this.onRender = this.options.onRender;
  3815. this.setTheme();
  3816. this.fillDow();
  3817. this.fillMonths();
  3818. this.update();
  3819. this.showMode();
  3820. };
  3821. Datepicker.DEFAULTS = {
  3822. locale: 'zh_CN',
  3823. format: 'yyyy-mm-dd',
  3824. weekStart: undefined,
  3825. viewMode: 0,
  3826. minViewMode: 0,
  3827. date: '',
  3828. theme: '',
  3829. autoClose: 1,
  3830. onRender: function(date) {
  3831. return '';
  3832. }
  3833. };
  3834. Datepicker.prototype.open = function(e) {
  3835. this.$picker.show();
  3836. this.height = this.component ?
  3837. this.component.outerHeight() : this.$element.outerHeight();
  3838. this.place();
  3839. $(window).on('resize.datepicker.amui', $.proxy(this.place, this));
  3840. if (e) {
  3841. e.stopPropagation();
  3842. e.preventDefault();
  3843. }
  3844. var that = this;
  3845. $doc.on('mousedown.datapicker.amui touchstart.datepicker.amui', function(ev) {
  3846. if ($(ev.target).closest('.am-datepicker').length === 0) {
  3847. that.close();
  3848. }
  3849. });
  3850. this.$element.trigger({
  3851. type: 'open.datepicker.amui',
  3852. date: this.date
  3853. });
  3854. };
  3855. Datepicker.prototype.close = function() {
  3856. this.$picker.hide();
  3857. $(window).off('resize.datepicker.amui', this.place);
  3858. this.viewMode = this.startViewMode;
  3859. this.showMode();
  3860. if (!this.isInput) {
  3861. $(document).off('mousedown.datapicker.amui touchstart.datepicker.amui',
  3862. this.close);
  3863. }
  3864. // this.set();
  3865. this.$element.trigger({
  3866. type: 'close.datepicker.amui',
  3867. date: this.date
  3868. });
  3869. };
  3870. Datepicker.prototype.set = function() {
  3871. var formatted = DPGlobal.formatDate(this.date, this.format);
  3872. var $input;
  3873. if (!this.isInput) {
  3874. if (this.component) {
  3875. $input = this.$element.find('input').attr('value', formatted);
  3876. }
  3877. this.$element.data('date', formatted);
  3878. } else {
  3879. $input = this.$element.attr('value', formatted);
  3880. }
  3881. // fixes https://github.com/amazeui/amazeui/issues/711
  3882. $input && $input.trigger('change');
  3883. };
  3884. Datepicker.prototype.setValue = function(newDate) {
  3885. if (typeof newDate === 'string') {
  3886. this.date = DPGlobal.parseDate(newDate, this.format);
  3887. } else {
  3888. this.date = new Date(newDate);
  3889. }
  3890. this.set();
  3891. this.viewDate = new Date(this.date.getFullYear(),
  3892. this.date.getMonth(), 1, 0, 0, 0, 0);
  3893. this.fill();
  3894. };
  3895. Datepicker.prototype.place = function() {
  3896. var offset = this.component ?
  3897. this.component.offset() : this.$element.offset();
  3898. var $width = this.component ?
  3899. this.component.width() : this.$element.width();
  3900. var top = offset.top + this.height;
  3901. var left = offset.left;
  3902. var right = $doc.width() - offset.left - $width;
  3903. var isOutView = this.isOutView();
  3904. this.$picker.removeClass('am-datepicker-right');
  3905. this.$picker.removeClass('am-datepicker-up');
  3906. if ($doc.width() > 640) {
  3907. if (isOutView.outRight) {
  3908. this.$picker.addClass('am-datepicker-right');
  3909. this.$picker.css({
  3910. top: top,
  3911. left: 'auto',
  3912. right: right
  3913. });
  3914. return;
  3915. }
  3916. if (isOutView.outBottom) {
  3917. this.$picker.addClass('am-datepicker-up');
  3918. top = offset.top - this.$picker.outerHeight(true);
  3919. }
  3920. } else {
  3921. left = 0;
  3922. }
  3923. this.$picker.css({
  3924. top: top,
  3925. left: left
  3926. });
  3927. };
  3928. Datepicker.prototype.update = function(newDate) {
  3929. this.date = DPGlobal.parseDate(
  3930. typeof newDate === 'string' ? newDate : (this.isInput ?
  3931. this.$element.prop('value') : this.$element.data('date')),
  3932. this.format
  3933. );
  3934. this.viewDate = new Date(this.date.getFullYear(),
  3935. this.date.getMonth(), 1, 0, 0, 0, 0);
  3936. this.fill();
  3937. };
  3938. // Days of week
  3939. Datepicker.prototype.fillDow = function() {
  3940. var dowCount = this.weekStart;
  3941. var html = '<tr>';
  3942. while (dowCount < this.weekStart + 7) {
  3943. // NOTE: do % then add 1
  3944. html += '<th class="am-datepicker-dow">' +
  3945. Datepicker.locales[this.language].daysMin[(dowCount++) % 7] +
  3946. '</th>';
  3947. }
  3948. html += '</tr>';
  3949. this.$picker.find('.am-datepicker-days thead').append(html);
  3950. };
  3951. Datepicker.prototype.fillMonths = function() {
  3952. var html = '';
  3953. var i = 0;
  3954. while (i < 12) {
  3955. html += '<span class="am-datepicker-month">' +
  3956. Datepicker.locales[this.language].monthsShort[i++] + '</span>';
  3957. }
  3958. this.$picker.find('.am-datepicker-months td').append(html);
  3959. };
  3960. Datepicker.prototype.fill = function() {
  3961. var d = new Date(this.viewDate);
  3962. var year = d.getFullYear();
  3963. var month = d.getMonth();
  3964. var currentDate = this.date.valueOf();
  3965. var prevMonth = new Date(year, month - 1, 28, 0, 0, 0, 0);
  3966. var day = DPGlobal
  3967. .getDaysInMonth(prevMonth.getFullYear(), prevMonth.getMonth());
  3968. var daysSelect = this.$picker
  3969. .find('.am-datepicker-days .am-datepicker-select');
  3970. if (this.language === 'zh_CN') {
  3971. daysSelect.text(year + Datepicker.locales[this.language].year[0] +
  3972. ' ' + Datepicker.locales[this.language].months[month]);
  3973. } else {
  3974. daysSelect.text(Datepicker.locales[this.language].months[month] +
  3975. ' ' + year);
  3976. }
  3977. prevMonth.setDate(day);
  3978. prevMonth.setDate(day - (prevMonth.getDay() - this.weekStart + 7) % 7);
  3979. var nextMonth = new Date(prevMonth);
  3980. nextMonth.setDate(nextMonth.getDate() + 42);
  3981. nextMonth = nextMonth.valueOf();
  3982. var html = [];
  3983. var className;
  3984. var prevY;
  3985. var prevM;
  3986. while (prevMonth.valueOf() < nextMonth) {
  3987. if (prevMonth.getDay() === this.weekStart) {
  3988. html.push('<tr>');
  3989. }
  3990. className = this.onRender(prevMonth, 0);
  3991. prevY = prevMonth.getFullYear();
  3992. prevM = prevMonth.getMonth();
  3993. if ((prevM < month && prevY === year) || prevY < year) {
  3994. className += ' am-datepicker-old';
  3995. } else if ((prevM > month && prevY === year) || prevY > year) {
  3996. className += ' am-datepicker-new';
  3997. }
  3998. if (prevMonth.valueOf() === currentDate) {
  3999. className += ' am-active';
  4000. }
  4001. html.push('<td class="am-datepicker-day ' +
  4002. className + '">' + prevMonth.getDate() + '</td>');
  4003. if (prevMonth.getDay() === this.weekEnd) {
  4004. html.push('</tr>');
  4005. }
  4006. prevMonth.setDate(prevMonth.getDate() + 1);
  4007. }
  4008. this.$picker.find('.am-datepicker-days tbody')
  4009. .empty().append(html.join(''));
  4010. var currentYear = this.date.getFullYear();
  4011. var months = this.$picker.find('.am-datepicker-months')
  4012. .find('.am-datepicker-select')
  4013. .text(year);
  4014. months = months.end()
  4015. .find('span').removeClass('am-active').removeClass('am-disabled');
  4016. var monthLen = 0;
  4017. while (monthLen < 12) {
  4018. if (this.onRender(d.setFullYear(year, monthLen), 1)) {
  4019. months.eq(monthLen).addClass('am-disabled');
  4020. }
  4021. monthLen++;
  4022. }
  4023. if (currentYear === year) {
  4024. months.eq(this.date.getMonth())
  4025. .removeClass('am-disabled')
  4026. .addClass('am-active');
  4027. }
  4028. html = '';
  4029. year = parseInt(year / 10, 10) * 10;
  4030. var yearCont = this.$picker
  4031. .find('.am-datepicker-years')
  4032. .find('.am-datepicker-select')
  4033. .text(year + '-' + (year + 9))
  4034. .end()
  4035. .find('td');
  4036. var yearClassName;
  4037. // fixes https://github.com/amazeui/amazeui/issues/770
  4038. // maybe not need now
  4039. var viewDate = new Date(this.viewDate);
  4040. year -= 1;
  4041. for (var i = -1; i < 11; i++) {
  4042. yearClassName = this.onRender(viewDate.setFullYear(year), 2);
  4043. html += '<span class="' + yearClassName + '' +
  4044. (i === -1 || i === 10 ? ' am-datepicker-old' : '') +
  4045. (currentYear === year ? ' am-active' : '') + '">' + year + '</span>';
  4046. year += 1;
  4047. }
  4048. yearCont.html(html);
  4049. };
  4050. Datepicker.prototype.click = function(event) {
  4051. event.stopPropagation();
  4052. event.preventDefault();
  4053. var month;
  4054. var year;
  4055. var $dayActive = this.$picker.find('.am-datepicker-days').find('.am-active');
  4056. var $months = this.$picker.find('.am-datepicker-months');
  4057. var $monthIndex = $months.find('.am-active').index();
  4058. var $target = $(event.target).closest('span, td, th');
  4059. if ($target.length === 1) {
  4060. switch ($target[0].nodeName.toLowerCase()) {
  4061. case 'th':
  4062. switch ($target[0].className) {
  4063. case 'am-datepicker-switch':
  4064. this.showMode(1);
  4065. break;
  4066. case 'am-datepicker-prev':
  4067. case 'am-datepicker-next':
  4068. this.viewDate['set' + DPGlobal.modes[this.viewMode].navFnc].call(
  4069. this.viewDate,
  4070. this.viewDate
  4071. ['get' + DPGlobal.modes[this.viewMode].navFnc]
  4072. .call(this.viewDate) +
  4073. DPGlobal.modes[this.viewMode].navStep *
  4074. ($target[0].className === 'am-datepicker-prev' ? -1 : 1)
  4075. );
  4076. this.fill();
  4077. this.set();
  4078. break;
  4079. }
  4080. break;
  4081. case 'span':
  4082. if ($target.is('.am-disabled')) {
  4083. return;
  4084. }
  4085. if ($target.is('.am-datepicker-month')) {
  4086. month = $target.parent().find('span').index($target);
  4087. if ($target.is('.am-active')) {
  4088. this.viewDate.setMonth(month, $dayActive.text());
  4089. } else {
  4090. this.viewDate.setMonth(month);
  4091. }
  4092. } else {
  4093. year = parseInt($target.text(), 10) || 0;
  4094. if ($target.is('.am-active')) {
  4095. this.viewDate.setFullYear(year, $monthIndex, $dayActive.text());
  4096. } else {
  4097. this.viewDate.setFullYear(year);
  4098. }
  4099. }
  4100. if (this.viewMode !== 0) {
  4101. this.date = new Date(this.viewDate);
  4102. this.$element.trigger({
  4103. type: 'changeDate.datepicker.amui',
  4104. date: this.date,
  4105. viewMode: DPGlobal.modes[this.viewMode].clsName
  4106. });
  4107. }
  4108. this.showMode(-1);
  4109. this.fill();
  4110. this.set();
  4111. break;
  4112. case 'td':
  4113. if ($target.is('.am-datepicker-day') && !$target.is('.am-disabled')) {
  4114. var day = parseInt($target.text(), 10) || 1;
  4115. month = this.viewDate.getMonth();
  4116. if ($target.is('.am-datepicker-old')) {
  4117. month -= 1;
  4118. } else if ($target.is('.am-datepicker-new')) {
  4119. month += 1;
  4120. }
  4121. year = this.viewDate.getFullYear();
  4122. this.date = new Date(year, month, day, 0, 0, 0, 0);
  4123. this.viewDate = new Date(year, month, Math.min(28, day), 0, 0, 0, 0);
  4124. this.fill();
  4125. this.set();
  4126. this.$element.trigger({
  4127. type: 'changeDate.datepicker.amui',
  4128. date: this.date,
  4129. viewMode: DPGlobal.modes[this.viewMode].clsName
  4130. });
  4131. this.options.autoClose && this.close();
  4132. }
  4133. break;
  4134. }
  4135. }
  4136. };
  4137. Datepicker.prototype.mousedown = function(event) {
  4138. event.stopPropagation();
  4139. event.preventDefault();
  4140. };
  4141. Datepicker.prototype.showMode = function(dir) {
  4142. if (dir) {
  4143. this.viewMode = Math.max(this.minViewMode,
  4144. Math.min(2, this.viewMode + dir));
  4145. }
  4146. this.$picker.find('>div').hide().
  4147. filter('.am-datepicker-' + DPGlobal.modes[this.viewMode].clsName).show();
  4148. };
  4149. Datepicker.prototype.isOutView = function() {
  4150. var offset = this.component ?
  4151. this.component.offset() : this.$element.offset();
  4152. var isOutView = {
  4153. outRight: false,
  4154. outBottom: false
  4155. };
  4156. var $picker = this.$picker;
  4157. var width = offset.left + $picker.outerWidth(true);
  4158. var height = offset.top + $picker.outerHeight(true) +
  4159. this.$element.innerHeight();
  4160. if (width > $doc.width()) {
  4161. isOutView.outRight = true;
  4162. }
  4163. if (height > $doc.height()) {
  4164. isOutView.outBottom = true;
  4165. }
  4166. return isOutView;
  4167. };
  4168. Datepicker.prototype.getLocale = function(locale) {
  4169. if (!locale) {
  4170. locale = navigator.language && navigator.language.split('-');
  4171. locale[1] = locale[1].toUpperCase();
  4172. locale = locale.join('_');
  4173. }
  4174. if (!Datepicker.locales[locale]) {
  4175. locale = 'en_US';
  4176. }
  4177. return locale;
  4178. };
  4179. Datepicker.prototype.setTheme = function() {
  4180. if (this.theme) {
  4181. this.$picker.addClass('am-datepicker-' + this.theme);
  4182. }
  4183. };
  4184. // Datepicker locales
  4185. Datepicker.locales = {
  4186. en_US: {
  4187. days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
  4188. 'Friday', 'Saturday'],
  4189. daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
  4190. daysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
  4191. months: ['January', 'February', 'March', 'April', 'May', 'June',
  4192. 'July', 'August', 'September', 'October', 'November', 'December'],
  4193. monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
  4194. 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
  4195. weekStart: 0
  4196. },
  4197. zh_CN: {
  4198. days: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
  4199. daysShort: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
  4200. daysMin: ['日', '一', '二', '三', '四', '五', '六'],
  4201. months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月',
  4202. '八月', '九月', '十月', '十一月', '十二月'],
  4203. monthsShort: ['一月', '二月', '三月', '四月', '五月', '六月',
  4204. '七月', '八月', '九月', '十月', '十一月', '十二月'],
  4205. weekStart: 1,
  4206. year: ['年']
  4207. }
  4208. };
  4209. var DPGlobal = {
  4210. modes: [
  4211. {
  4212. clsName: 'days',
  4213. navFnc: 'Month',
  4214. navStep: 1
  4215. },
  4216. {
  4217. clsName: 'months',
  4218. navFnc: 'FullYear',
  4219. navStep: 1
  4220. },
  4221. {
  4222. clsName: 'years',
  4223. navFnc: 'FullYear',
  4224. navStep: 10
  4225. }
  4226. ],
  4227. isLeapYear: function(year) {
  4228. return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
  4229. },
  4230. getDaysInMonth: function(year, month) {
  4231. return [31, (DPGlobal.isLeapYear(year) ? 29 : 28),
  4232. 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
  4233. },
  4234. parseFormat: function(format) {
  4235. var separator = format.match(/[.\/\-\s].*?/);
  4236. var parts = format.split(/\W+/);
  4237. if (!separator || !parts || parts.length === 0) {
  4238. throw new Error('Invalid date format.');
  4239. }
  4240. return {
  4241. separator: separator,
  4242. parts: parts
  4243. };
  4244. },
  4245. parseDate: function(date, format) {
  4246. var parts = date.split(format.separator);
  4247. var val;
  4248. date = new Date();
  4249. date.setHours(0);
  4250. date.setMinutes(0);
  4251. date.setSeconds(0);
  4252. date.setMilliseconds(0);
  4253. if (parts.length === format.parts.length) {
  4254. var year = date.getFullYear();
  4255. var day = date.getDate();
  4256. var month = date.getMonth();
  4257. for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
  4258. val = parseInt(parts[i], 10) || 1;
  4259. switch (format.parts[i]) {
  4260. case 'dd':
  4261. case 'd':
  4262. day = val;
  4263. date.setDate(val);
  4264. break;
  4265. case 'mm':
  4266. case 'm':
  4267. month = val - 1;
  4268. date.setMonth(val - 1);
  4269. break;
  4270. case 'yy':
  4271. year = 2000 + val;
  4272. date.setFullYear(2000 + val);
  4273. break;
  4274. case 'yyyy':
  4275. year = val;
  4276. date.setFullYear(val);
  4277. break;
  4278. }
  4279. }
  4280. date = new Date(year, month, day, 0, 0, 0);
  4281. }
  4282. return date;
  4283. },
  4284. formatDate: function(date, format) {
  4285. var val = {
  4286. d: date.getDate(),
  4287. m: date.getMonth() + 1,
  4288. yy: date.getFullYear().toString().substring(2),
  4289. yyyy: date.getFullYear()
  4290. };
  4291. var dateArray = [];
  4292. val.dd = (val.d < 10 ? '0' : '') + val.d;
  4293. val.mm = (val.m < 10 ? '0' : '') + val.m;
  4294. for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
  4295. dateArray.push(val[format.parts[i]]);
  4296. }
  4297. return dateArray.join(format.separator);
  4298. },
  4299. headTemplate: '<thead>' +
  4300. '<tr class="am-datepicker-header">' +
  4301. '<th class="am-datepicker-prev">' +
  4302. '<i class="am-datepicker-prev-icon"></i></th>' +
  4303. '<th colspan="5" class="am-datepicker-switch">' +
  4304. '<div class="am-datepicker-select"></div></th>' +
  4305. '<th class="am-datepicker-next"><i class="am-datepicker-next-icon"></i>' +
  4306. '</th></tr></thead>',
  4307. contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
  4308. };
  4309. DPGlobal.template = '<div class="am-datepicker am-datepicker-dropdown">' +
  4310. '<div class="am-datepicker-caret"></div>' +
  4311. '<div class="am-datepicker-days">' +
  4312. '<table class="am-datepicker-table">' +
  4313. DPGlobal.headTemplate +
  4314. '<tbody></tbody>' +
  4315. '</table>' +
  4316. '</div>' +
  4317. '<div class="am-datepicker-months">' +
  4318. '<table class="am-datepicker-table">' +
  4319. DPGlobal.headTemplate +
  4320. DPGlobal.contTemplate +
  4321. '</table>' +
  4322. '</div>' +
  4323. '<div class="am-datepicker-years">' +
  4324. '<table class="am-datepicker-table">' +
  4325. DPGlobal.headTemplate +
  4326. DPGlobal.contTemplate +
  4327. '</table>' +
  4328. '</div>' +
  4329. '</div>';
  4330. // jQuery plugin
  4331. UI.plugin('datepicker', Datepicker);
  4332. // Init code
  4333. UI.ready(function(context) {
  4334. $('[data-am-datepicker]').datepicker();
  4335. });
  4336. module.exports = UI.datepicker = Datepicker;
  4337. // TODO: 1. 载入动画
  4338. // 2. less 优化
  4339. /***/ },
  4340. /* 9 */
  4341. /***/ function(module, exports, __webpack_require__) {
  4342. 'use strict';
  4343. var $ = __webpack_require__(1);
  4344. var UI = __webpack_require__(2);
  4345. var $doc = $(document);
  4346. var transition = UI.support.transition;
  4347. var Dimmer = function() {
  4348. this.id = UI.utils.generateGUID('am-dimmer');
  4349. this.$element = $(Dimmer.DEFAULTS.tpl, {
  4350. id: this.id
  4351. });
  4352. this.inited = false;
  4353. this.scrollbarWidth = 0;
  4354. this.$used = $([]);
  4355. };
  4356. Dimmer.DEFAULTS = {
  4357. tpl: '<div class="am-dimmer" data-am-dimmer></div>'
  4358. };
  4359. Dimmer.prototype.init = function() {
  4360. if (!this.inited) {
  4361. $(document.body).append(this.$element);
  4362. this.inited = true;
  4363. $doc.trigger('init.dimmer.amui');
  4364. this.$element.on('touchmove.dimmer.amui', function(e) {
  4365. e.preventDefault();
  4366. });
  4367. }
  4368. return this;
  4369. };
  4370. Dimmer.prototype.open = function(relatedElement) {
  4371. if (!this.inited) {
  4372. this.init();
  4373. }
  4374. var $element = this.$element;
  4375. // 用于多重调用
  4376. if (relatedElement) {
  4377. this.$used = this.$used.add($(relatedElement));
  4378. }
  4379. this.checkScrollbar().setScrollbar();
  4380. $element.show().trigger('open.dimmer.amui');
  4381. transition && $element.off(transition.end);
  4382. setTimeout(function() {
  4383. $element.addClass('am-active');
  4384. }, 0);
  4385. return this;
  4386. };
  4387. Dimmer.prototype.close = function(relatedElement, force) {
  4388. this.$used = this.$used.not($(relatedElement));
  4389. if (!force && this.$used.length) {
  4390. return this;
  4391. }
  4392. var $element = this.$element;
  4393. $element.removeClass('am-active').trigger('close.dimmer.amui');
  4394. function complete() {
  4395. $element.hide();
  4396. this.resetScrollbar();
  4397. }
  4398. // transition ? $element.one(transition.end, $.proxy(complete, this)) :
  4399. complete.call(this);
  4400. return this;
  4401. };
  4402. Dimmer.prototype.checkScrollbar = function() {
  4403. this.scrollbarWidth = UI.utils.measureScrollbar();
  4404. return this;
  4405. };
  4406. Dimmer.prototype.setScrollbar = function() {
  4407. var $body = $(document.body);
  4408. var bodyPaddingRight = parseInt(($body.css('padding-right') || 0), 10);
  4409. if (this.scrollbarWidth) {
  4410. $body.css('padding-right', bodyPaddingRight + this.scrollbarWidth);
  4411. }
  4412. $body.addClass('am-dimmer-active');
  4413. return this;
  4414. };
  4415. Dimmer.prototype.resetScrollbar = function() {
  4416. $(document.body).css('padding-right', '').removeClass('am-dimmer-active');
  4417. return this;
  4418. };
  4419. module.exports = UI.dimmer = new Dimmer();
  4420. /***/ },
  4421. /* 10 */
  4422. /***/ function(module, exports, __webpack_require__) {
  4423. 'use strict';
  4424. var $ = __webpack_require__(1);
  4425. var UI = __webpack_require__(2);
  4426. var animation = UI.support.animation;
  4427. /**
  4428. * @via https://github.com/Minwe/bootstrap/blob/master/js/dropdown.js
  4429. * @copyright (c) 2011-2014 Twitter, Inc
  4430. * @license The MIT License
  4431. */
  4432. // var toggle = '[data-am-dropdown] > .am-dropdown-toggle';
  4433. var Dropdown = function(element, options) {
  4434. this.options = $.extend({}, Dropdown.DEFAULTS, options);
  4435. options = this.options;
  4436. this.$element = $(element);
  4437. this.$toggle = this.$element.find(options.selector.toggle);
  4438. this.$dropdown = this.$element.find(options.selector.dropdown);
  4439. this.$boundary = (options.boundary === window) ? $(window) :
  4440. this.$element.closest(options.boundary);
  4441. this.$justify = (options.justify && $(options.justify).length &&
  4442. $(options.justify)) || undefined;
  4443. !this.$boundary.length && (this.$boundary = $(window));
  4444. this.active = this.$element.hasClass('am-active') ? true : false;
  4445. this.animating = null;
  4446. this.events();
  4447. };
  4448. Dropdown.DEFAULTS = {
  4449. animation: 'am-animation-slide-top-fixed',
  4450. boundary: window,
  4451. justify: undefined,
  4452. selector: {
  4453. dropdown: '.am-dropdown-content',
  4454. toggle: '.am-dropdown-toggle'
  4455. },
  4456. trigger: 'click'
  4457. };
  4458. Dropdown.prototype.toggle = function() {
  4459. this.clear();
  4460. if (this.animating) {
  4461. return;
  4462. }
  4463. this[this.active ? 'close' : 'open']();
  4464. };
  4465. Dropdown.prototype.open = function(e) {
  4466. var $toggle = this.$toggle;
  4467. var $element = this.$element;
  4468. var $dropdown = this.$dropdown;
  4469. if ($toggle.is('.am-disabled, :disabled')) {
  4470. return;
  4471. }
  4472. if (this.active) {
  4473. return;
  4474. }
  4475. $element.trigger('open.dropdown.amui').addClass('am-active');
  4476. $toggle.trigger('focus');
  4477. this.checkDimensions(e);
  4478. var complete = $.proxy(function() {
  4479. $element.trigger('opened.dropdown.amui');
  4480. this.active = true;
  4481. this.animating = 0;
  4482. }, this);
  4483. if (animation) {
  4484. this.animating = 1;
  4485. $dropdown.addClass(this.options.animation).
  4486. on(animation.end + '.open.dropdown.amui', $.proxy(function() {
  4487. complete();
  4488. $dropdown.removeClass(this.options.animation);
  4489. }, this));
  4490. } else {
  4491. complete();
  4492. }
  4493. };
  4494. Dropdown.prototype.close = function() {
  4495. if (!this.active) {
  4496. return;
  4497. }
  4498. // fix #165
  4499. // var animationName = this.options.animation + ' am-animation-reverse';
  4500. var animationName = 'am-dropdown-animation';
  4501. var $element = this.$element;
  4502. var $dropdown = this.$dropdown;
  4503. $element.trigger('close.dropdown.amui');
  4504. var complete = $.proxy(function complete() {
  4505. $element.
  4506. removeClass('am-active').
  4507. trigger('closed.dropdown.amui');
  4508. this.active = false;
  4509. this.animating = 0;
  4510. this.$toggle.blur();
  4511. }, this);
  4512. if (animation) {
  4513. $dropdown.removeClass(this.options.animation);
  4514. $dropdown.addClass(animationName);
  4515. this.animating = 1;
  4516. // animation
  4517. $dropdown.one(animation.end + '.close.dropdown.amui', function() {
  4518. $dropdown.removeClass(animationName);
  4519. complete();
  4520. });
  4521. } else {
  4522. complete();
  4523. }
  4524. };
  4525. Dropdown.prototype.enable = function() {
  4526. this.$toggle.prop('disabled', false);
  4527. },
  4528. Dropdown.prototype.disable = function() {
  4529. this.$toggle.prop('disabled', true);
  4530. },
  4531. Dropdown.prototype.checkDimensions = function(e) {
  4532. if (!this.$dropdown.length) {
  4533. return;
  4534. }
  4535. var $dropdown = this.$dropdown;
  4536. // @see #873
  4537. if (e && e.offset) {
  4538. $dropdown.offset(e.offset);
  4539. }
  4540. var offset = $dropdown.offset();
  4541. var width = $dropdown.outerWidth();
  4542. var boundaryWidth = this.$boundary.width();
  4543. var boundaryOffset = $.isWindow(this.boundary) && this.$boundary.offset() ?
  4544. this.$boundary.offset().left : 0;
  4545. if (this.$justify) {
  4546. // jQuery.fn.width() is really...
  4547. $dropdown.css({'min-width': this.$justify.css('width')});
  4548. }
  4549. if ((width + (offset.left - boundaryOffset)) > boundaryWidth) {
  4550. this.$element.addClass('am-dropdown-flip');
  4551. }
  4552. };
  4553. Dropdown.prototype.clear = function() {
  4554. $('[data-am-dropdown]').not(this.$element).each(function() {
  4555. var data = $(this).data('amui.dropdown');
  4556. data && data.close();
  4557. });
  4558. };
  4559. Dropdown.prototype.events = function() {
  4560. var eventNS = 'dropdown.amui';
  4561. // triggers = this.options.trigger.split(' '),
  4562. var $toggle = this.$toggle;
  4563. $toggle.on('click.' + eventNS, $.proxy(function(e) {
  4564. e.preventDefault();
  4565. this.toggle();
  4566. }, this));
  4567. /*for (var i = triggers.length; i--;) {
  4568. var trigger = triggers[i];
  4569. if (trigger === 'click') {
  4570. $toggle.on('click.' + eventNS, $.proxy(this.toggle, this))
  4571. }
  4572. if (trigger === 'focus' || trigger === 'hover') {
  4573. var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin';
  4574. var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout';
  4575. this.$element.on(eventIn + '.' + eventNS, $.proxy(this.open, this))
  4576. .on(eventOut + '.' + eventNS, $.proxy(this.close, this));
  4577. }
  4578. }*/
  4579. $(document).on('keydown.dropdown.amui', $.proxy(function(e) {
  4580. e.keyCode === 27 && this.active && this.close();
  4581. }, this)).on('click.outer.dropdown.amui', $.proxy(function(e) {
  4582. // var $target = $(e.target);
  4583. if (this.active &&
  4584. (this.$element[0] === e.target || !this.$element.find(e.target).length)) {
  4585. this.close();
  4586. }
  4587. }, this));
  4588. };
  4589. // Dropdown Plugin
  4590. UI.plugin('dropdown', Dropdown);
  4591. // Init code
  4592. UI.ready(function(context) {
  4593. $('[data-am-dropdown]', context).dropdown();
  4594. });
  4595. $(document).on('click.dropdown.amui.data-api', '.am-dropdown form',
  4596. function(e) {
  4597. e.stopPropagation();
  4598. });
  4599. module.exports = UI.dropdown = Dropdown;
  4600. // TODO: 1. 处理链接 focus
  4601. // 2. 增加 mouseenter / mouseleave 选项
  4602. // 3. 宽度适应
  4603. /***/ },
  4604. /* 11 */
  4605. /***/ function(module, exports, __webpack_require__) {
  4606. /* WEBPACK VAR INJECTION */(function(setImmediate) {var $ = __webpack_require__(1);
  4607. var UI = __webpack_require__(2);
  4608. // MODIFIED:
  4609. // - LINE 252: add `<i></i>`
  4610. // - namespace
  4611. // - Init code
  4612. // TODO: start after x ms when pause on actions
  4613. /*
  4614. * jQuery FlexSlider v2.6.1
  4615. * Copyright 2012 WooThemes
  4616. * Contributing Author: Tyler Smith
  4617. */
  4618. var focused = true;
  4619. // FlexSlider: Object Instance
  4620. $.flexslider = function(el, options) {
  4621. var slider = $(el);
  4622. // making variables public
  4623. slider.vars = $.extend({}, $.flexslider.defaults, options);
  4624. var namespace = slider.vars.namespace,
  4625. msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture,
  4626. touch = (( "ontouchstart" in window ) || msGesture || window.DocumentTouch && document instanceof DocumentTouch) && slider.vars.touch,
  4627. // depricating this idea, as devices are being released with both of these events
  4628. eventType = "click touchend MSPointerUp keyup",
  4629. watchedEvent = "",
  4630. watchedEventClearTimer,
  4631. vertical = slider.vars.direction === "vertical",
  4632. reverse = slider.vars.reverse,
  4633. carousel = (slider.vars.itemWidth > 0),
  4634. fade = slider.vars.animation === "fade",
  4635. asNav = slider.vars.asNavFor !== "",
  4636. methods = {};
  4637. // Store a reference to the slider object
  4638. $.data(el, 'flexslider', slider);
  4639. // Private slider methods
  4640. methods = {
  4641. init: function() {
  4642. slider.animating = false;
  4643. // Get current slide and make sure it is a number
  4644. slider.currentSlide = parseInt((slider.vars.startAt ? slider.vars.startAt : 0), 10);
  4645. if (isNaN(slider.currentSlide)) {
  4646. slider.currentSlide = 0;
  4647. }
  4648. slider.animatingTo = slider.currentSlide;
  4649. slider.atEnd = (slider.currentSlide === 0 || slider.currentSlide === slider.last);
  4650. slider.containerSelector = slider.vars.selector.substr(0, slider.vars.selector.search(' '));
  4651. slider.slides = $(slider.vars.selector, slider);
  4652. slider.container = $(slider.containerSelector, slider);
  4653. slider.count = slider.slides.length;
  4654. // SYNC:
  4655. slider.syncExists = $(slider.vars.sync).length > 0;
  4656. // SLIDE:
  4657. if (slider.vars.animation === "slide") {
  4658. slider.vars.animation = "swing";
  4659. }
  4660. slider.prop = (vertical) ? "top" : "marginLeft";
  4661. slider.args = {};
  4662. // SLIDESHOW:
  4663. slider.manualPause = false;
  4664. slider.stopped = false;
  4665. //PAUSE WHEN INVISIBLE
  4666. slider.started = false;
  4667. slider.startTimeout = null;
  4668. // TOUCH/USECSS:
  4669. slider.transitions = !slider.vars.video && !fade && slider.vars.useCSS && (function() {
  4670. var obj = document.createElement('div'),
  4671. props = ['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];
  4672. for (var i in props) {
  4673. if (obj.style[props[i]] !== undefined) {
  4674. slider.pfx = props[i].replace('Perspective', '').toLowerCase();
  4675. slider.prop = "-" + slider.pfx + "-transform";
  4676. return true;
  4677. }
  4678. }
  4679. return false;
  4680. }());
  4681. slider.ensureAnimationEnd = '';
  4682. // CONTROLSCONTAINER:
  4683. if (slider.vars.controlsContainer !== "") slider.controlsContainer = $(slider.vars.controlsContainer).length > 0 && $(slider.vars.controlsContainer);
  4684. // MANUAL:
  4685. if (slider.vars.manualControls !== "") slider.manualControls = $(slider.vars.manualControls).length > 0 && $(slider.vars.manualControls);
  4686. // CUSTOM DIRECTION NAV:
  4687. if (slider.vars.customDirectionNav !== "") slider.customDirectionNav = $(slider.vars.customDirectionNav).length === 2 && $(slider.vars.customDirectionNav);
  4688. // RANDOMIZE:
  4689. if (slider.vars.randomize) {
  4690. slider.slides.sort(function() {
  4691. return (Math.round(Math.random()) - 0.5);
  4692. });
  4693. slider.container.empty().append(slider.slides);
  4694. }
  4695. slider.doMath();
  4696. // INIT
  4697. slider.setup("init");
  4698. // CONTROLNAV:
  4699. if (slider.vars.controlNav) {
  4700. methods.controlNav.setup();
  4701. }
  4702. // DIRECTIONNAV:
  4703. if (slider.vars.directionNav) {
  4704. methods.directionNav.setup();
  4705. }
  4706. // KEYBOARD:
  4707. if (slider.vars.keyboard && ($(slider.containerSelector).length === 1 || slider.vars.multipleKeyboard)) {
  4708. $(document).bind('keyup', function(event) {
  4709. var keycode = event.keyCode;
  4710. if (!slider.animating && (keycode === 39 || keycode === 37)) {
  4711. var target = (keycode === 39) ? slider.getTarget('next') :
  4712. (keycode === 37) ? slider.getTarget('prev') : false;
  4713. slider.flexAnimate(target, slider.vars.pauseOnAction);
  4714. }
  4715. });
  4716. }
  4717. // MOUSEWHEEL:
  4718. if (slider.vars.mousewheel) {
  4719. slider.bind('mousewheel', function(event, delta, deltaX, deltaY) {
  4720. event.preventDefault();
  4721. var target = (delta < 0) ? slider.getTarget('next') : slider.getTarget('prev');
  4722. slider.flexAnimate(target, slider.vars.pauseOnAction);
  4723. });
  4724. }
  4725. // PAUSEPLAY
  4726. if (slider.vars.pausePlay) {
  4727. methods.pausePlay.setup();
  4728. }
  4729. //PAUSE WHEN INVISIBLE
  4730. if (slider.vars.slideshow && slider.vars.pauseInvisible) {
  4731. methods.pauseInvisible.init();
  4732. }
  4733. // SLIDSESHOW
  4734. if (slider.vars.slideshow) {
  4735. if (slider.vars.pauseOnHover) {
  4736. slider.hover(function() {
  4737. if (!slider.manualPlay && !slider.manualPause) {slider.pause();}
  4738. }, function() {
  4739. if (!slider.manualPause && !slider.manualPlay && !slider.stopped) {slider.play();}
  4740. });
  4741. }
  4742. // initialize animation
  4743. // If we're visible, or we don't use PageVisibility API
  4744. if (!slider.vars.pauseInvisible || !methods.pauseInvisible.isHidden()) {
  4745. (slider.vars.initDelay > 0) ? slider.startTimeout = setTimeout(slider.play, slider.vars.initDelay) : slider.play();
  4746. }
  4747. }
  4748. // ASNAV:
  4749. if (asNav) {methods.asNav.setup();}
  4750. // TOUCH
  4751. if (touch && slider.vars.touch) {methods.touch();}
  4752. // FADE&&SMOOTHHEIGHT || SLIDE:
  4753. if (!fade || (fade && slider.vars.smoothHeight)) {$(window).bind("resize orientationchange focus", methods.resize);}
  4754. slider.find("img").attr("draggable", "false");
  4755. // API: start() Callback
  4756. setTimeout(function() {
  4757. slider.vars.start(slider);
  4758. }, 200);
  4759. },
  4760. asNav: {
  4761. setup: function() {
  4762. slider.asNav = true;
  4763. slider.animatingTo = Math.floor(slider.currentSlide / slider.move);
  4764. slider.currentItem = slider.currentSlide;
  4765. slider.slides.removeClass(namespace + "active-slide").eq(slider.currentItem).addClass(namespace + "active-slide");
  4766. if (!msGesture) {
  4767. slider.slides.on(eventType, function(e) {
  4768. e.preventDefault();
  4769. var $slide = $(this),
  4770. target = $slide.index();
  4771. var posFromLeft = $slide.offset().left - $(slider).scrollLeft(); // Find position of slide relative to left of slider container
  4772. if (posFromLeft <= 0 && $slide.hasClass(namespace + 'active-slide')) {
  4773. slider.flexAnimate(slider.getTarget("prev"), true);
  4774. } else if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass(namespace + "active-slide")) {
  4775. slider.direction = (slider.currentItem < target) ? "next" : "prev";
  4776. slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);
  4777. }
  4778. });
  4779. } else {
  4780. el._slider = slider;
  4781. slider.slides.each(function() {
  4782. var that = this;
  4783. that._gesture = new MSGesture();
  4784. that._gesture.target = that;
  4785. that.addEventListener("MSPointerDown", function(e) {
  4786. e.preventDefault();
  4787. if (e.currentTarget._gesture) {
  4788. e.currentTarget._gesture.addPointer(e.pointerId);
  4789. }
  4790. }, false);
  4791. that.addEventListener("MSGestureTap", function(e) {
  4792. e.preventDefault();
  4793. var $slide = $(this),
  4794. target = $slide.index();
  4795. if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass('active')) {
  4796. slider.direction = (slider.currentItem < target) ? "next" : "prev";
  4797. slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);
  4798. }
  4799. });
  4800. });
  4801. }
  4802. }
  4803. },
  4804. controlNav: {
  4805. setup: function() {
  4806. if (!slider.manualControls) {
  4807. methods.controlNav.setupPaging();
  4808. } else { // MANUALCONTROLS:
  4809. methods.controlNav.setupManual();
  4810. }
  4811. },
  4812. setupPaging: function() {
  4813. var type = (slider.vars.controlNav === "thumbnails") ? 'control-thumbs' : 'control-paging',
  4814. j = 1,
  4815. item,
  4816. slide;
  4817. slider.controlNavScaffold = $('<ol class="' + namespace + 'control-nav ' + namespace + type + '"></ol>');
  4818. if (slider.pagingCount > 1) {
  4819. for (var i = 0; i < slider.pagingCount; i++) {
  4820. slide = slider.slides.eq(i);
  4821. if (undefined === slide.attr('data-thumb-alt')) {
  4822. slide.attr('data-thumb-alt', '');
  4823. }
  4824. var altText = ('' !== slide.attr('data-thumb-alt')) ? altText = ' alt="' + slide.attr('data-thumb-alt') + '"' : '';
  4825. item = (slider.vars.controlNav === "thumbnails") ? '<img src="' + slide.attr( 'data-thumb' ) + '"' + altText + '/>' : '<a href="#">' + j + '</a>';
  4826. if ('thumbnails' === slider.vars.controlNav && true === slider.vars.thumbCaptions) {
  4827. var captn = slide.attr('data-thumbcaption');
  4828. if ('' !== captn && undefined !== captn) {item += '<span class="' + namespace + 'caption">' + captn + '</span>';}
  4829. }
  4830. // slider.controlNavScaffold.append('<li>' + item + '</li>');
  4831. slider.controlNavScaffold.append('<li>' + item + '<i></i></li>');
  4832. j++;
  4833. }
  4834. }
  4835. // CONTROLSCONTAINER:
  4836. (slider.controlsContainer) ? $(slider.controlsContainer).append(slider.controlNavScaffold) : slider.append(slider.controlNavScaffold);
  4837. methods.controlNav.set();
  4838. methods.controlNav.active();
  4839. slider.controlNavScaffold.delegate('a, img', eventType, function(event) {
  4840. event.preventDefault();
  4841. if (watchedEvent === "" || watchedEvent === event.type) {
  4842. var $this = $(this),
  4843. target = slider.controlNav.index($this);
  4844. if (!$this.hasClass(namespace + 'active')) {
  4845. slider.direction = (target > slider.currentSlide) ? "next" : "prev";
  4846. slider.flexAnimate(target, slider.vars.pauseOnAction);
  4847. }
  4848. }
  4849. // setup flags to prevent event duplication
  4850. if (watchedEvent === "") {
  4851. watchedEvent = event.type;
  4852. }
  4853. methods.setToClearWatchedEvent();
  4854. });
  4855. },
  4856. setupManual: function() {
  4857. slider.controlNav = slider.manualControls;
  4858. methods.controlNav.active();
  4859. slider.controlNav.bind(eventType, function(event) {
  4860. event.preventDefault();
  4861. if (watchedEvent === "" || watchedEvent === event.type) {
  4862. var $this = $(this),
  4863. target = slider.controlNav.index($this);
  4864. if (!$this.hasClass(namespace + 'active')) {
  4865. (target > slider.currentSlide) ? slider.direction = "next" : slider.direction = "prev";
  4866. slider.flexAnimate(target, slider.vars.pauseOnAction);
  4867. }
  4868. }
  4869. // setup flags to prevent event duplication
  4870. if (watchedEvent === "") {
  4871. watchedEvent = event.type;
  4872. }
  4873. methods.setToClearWatchedEvent();
  4874. });
  4875. },
  4876. set: function() {
  4877. var selector = (slider.vars.controlNav === "thumbnails") ? 'img' : 'a';
  4878. slider.controlNav = $('.' + namespace + 'control-nav li ' + selector, (slider.controlsContainer) ? slider.controlsContainer : slider);
  4879. },
  4880. active: function() {
  4881. slider.controlNav.removeClass(namespace + "active").eq(slider.animatingTo).addClass(namespace + "active");
  4882. },
  4883. update: function(action, pos) {
  4884. if (slider.pagingCount > 1 && action === "add") {
  4885. slider.controlNavScaffold.append($('<li><a href="#">' + slider.count + '</a></li>'));
  4886. } else if (slider.pagingCount === 1) {
  4887. slider.controlNavScaffold.find('li').remove();
  4888. } else {
  4889. slider.controlNav.eq(pos).closest('li').remove();
  4890. }
  4891. methods.controlNav.set();
  4892. (slider.pagingCount > 1 && slider.pagingCount !== slider.controlNav.length) ? slider.update(pos, action) : methods.controlNav.active();
  4893. }
  4894. },
  4895. directionNav: {
  4896. setup: function() {
  4897. var directionNavScaffold = $('<ul class="' + namespace + 'direction-nav"><li class="' + namespace + 'nav-prev"><a class="' + namespace + 'prev" href="#">' + slider.vars.prevText + '</a></li><li class="' + namespace + 'nav-next"><a class="' + namespace + 'next" href="#">' + slider.vars.nextText + '</a></li></ul>');
  4898. // CUSTOM DIRECTION NAV:
  4899. if (slider.customDirectionNav) {
  4900. slider.directionNav = slider.customDirectionNav;
  4901. } else if (slider.controlsContainer) { // CONTROLSCONTAINER:
  4902. $(slider.controlsContainer).append(directionNavScaffold);
  4903. slider.directionNav = $('.' + namespace + 'direction-nav li a', slider.controlsContainer);
  4904. } else {
  4905. slider.append(directionNavScaffold);
  4906. slider.directionNav = $('.' + namespace + 'direction-nav li a', slider);
  4907. }
  4908. methods.directionNav.update();
  4909. slider.directionNav.bind(eventType, function(event) {
  4910. event.preventDefault();
  4911. var target;
  4912. if (watchedEvent === "" || watchedEvent === event.type) {
  4913. target = ($(this).hasClass(namespace + 'next')) ? slider.getTarget('next') : slider.getTarget('prev');
  4914. slider.flexAnimate(target, slider.vars.pauseOnAction);
  4915. }
  4916. // setup flags to prevent event duplication
  4917. if (watchedEvent === "") {
  4918. watchedEvent = event.type;
  4919. }
  4920. methods.setToClearWatchedEvent();
  4921. });
  4922. },
  4923. update: function() {
  4924. var disabledClass = namespace + 'disabled';
  4925. if (slider.pagingCount === 1) {
  4926. slider.directionNav.addClass(disabledClass).attr('tabindex', '-1');
  4927. } else if (!slider.vars.animationLoop) {
  4928. if (slider.animatingTo === 0) {
  4929. slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "prev").addClass(disabledClass).attr('tabindex', '-1');
  4930. } else if (slider.animatingTo === slider.last) {
  4931. slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "next").addClass(disabledClass).attr('tabindex', '-1');
  4932. } else {
  4933. slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');
  4934. }
  4935. } else {
  4936. slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');
  4937. }
  4938. }
  4939. },
  4940. pausePlay: {
  4941. setup: function() {
  4942. var pausePlayScaffold = $('<div class="' + namespace + 'pauseplay"><a href="#"></a></div>');
  4943. // CONTROLSCONTAINER:
  4944. if (slider.controlsContainer) {
  4945. slider.controlsContainer.append(pausePlayScaffold);
  4946. slider.pausePlay = $('.' + namespace + 'pauseplay a', slider.controlsContainer);
  4947. } else {
  4948. slider.append(pausePlayScaffold);
  4949. slider.pausePlay = $('.' + namespace + 'pauseplay a', slider);
  4950. }
  4951. methods.pausePlay.update((slider.vars.slideshow) ? namespace + 'pause' : namespace + 'play');
  4952. slider.pausePlay.bind(eventType, function(event) {
  4953. event.preventDefault();
  4954. if (watchedEvent === "" || watchedEvent === event.type) {
  4955. if ($(this).hasClass(namespace + 'pause')) {
  4956. slider.manualPause = true;
  4957. slider.manualPlay = false;
  4958. slider.pause();
  4959. } else {
  4960. slider.manualPause = false;
  4961. slider.manualPlay = true;
  4962. slider.play();
  4963. }
  4964. }
  4965. // setup flags to prevent event duplication
  4966. if (watchedEvent === "") {
  4967. watchedEvent = event.type;
  4968. }
  4969. methods.setToClearWatchedEvent();
  4970. });
  4971. },
  4972. update: function(state) {
  4973. (state === "play") ? slider.pausePlay.removeClass(namespace + 'pause').addClass(namespace + 'play').html(slider.vars.playText) : slider.pausePlay.removeClass(namespace + 'play').addClass(namespace + 'pause').html(slider.vars.pauseText);
  4974. }
  4975. },
  4976. touch: function() {
  4977. var startX,
  4978. startY,
  4979. offset,
  4980. cwidth,
  4981. dx,
  4982. startT,
  4983. onTouchStart,
  4984. onTouchMove,
  4985. onTouchEnd,
  4986. scrolling = false,
  4987. localX = 0,
  4988. localY = 0,
  4989. accDx = 0;
  4990. if (!msGesture) {
  4991. onTouchStart = function(e) {
  4992. if (slider.animating) {
  4993. e.preventDefault();
  4994. } else if (( window.navigator.msPointerEnabled ) || e.touches.length === 1) {
  4995. slider.pause();
  4996. // CAROUSEL:
  4997. cwidth = (vertical) ? slider.h : slider.w;
  4998. startT = Number(new Date());
  4999. // CAROUSEL:
  5000. // Local vars for X and Y points.
  5001. localX = e.touches[0].pageX;
  5002. localY = e.touches[0].pageY;
  5003. offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :
  5004. (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
  5005. (carousel && slider.currentSlide === slider.last) ? slider.limit :
  5006. (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :
  5007. (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;
  5008. startX = (vertical) ? localY : localX;
  5009. startY = (vertical) ? localX : localY;
  5010. el.addEventListener('touchmove', onTouchMove, false);
  5011. el.addEventListener('touchend', onTouchEnd, false);
  5012. }
  5013. };
  5014. onTouchMove = function(e) {
  5015. // Local vars for X and Y points.
  5016. localX = e.touches[0].pageX;
  5017. localY = e.touches[0].pageY;
  5018. dx = (vertical) ? startX - localY : startX - localX;
  5019. scrolling = (vertical) ? (Math.abs(dx) < Math.abs(localX - startY)) : (Math.abs(dx) < Math.abs(localY - startY));
  5020. var fxms = 500;
  5021. if (!scrolling || Number(new Date()) - startT > fxms) {
  5022. e.preventDefault();
  5023. if (!fade && slider.transitions) {
  5024. if (!slider.vars.animationLoop) {
  5025. dx = dx / ((slider.currentSlide === 0 && dx < 0 || slider.currentSlide === slider.last && dx > 0) ? (Math.abs(dx) / cwidth + 2) : 1);
  5026. }
  5027. slider.setProps(offset + dx, "setTouch");
  5028. }
  5029. }
  5030. };
  5031. onTouchEnd = function(e) {
  5032. // finish the touch by undoing the touch session
  5033. el.removeEventListener('touchmove', onTouchMove, false);
  5034. if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {
  5035. var updateDx = (reverse) ? -dx : dx,
  5036. target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');
  5037. if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth / 2)) {
  5038. slider.flexAnimate(target, slider.vars.pauseOnAction);
  5039. } else {
  5040. if (!fade) {slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true);}
  5041. }
  5042. }
  5043. el.removeEventListener('touchend', onTouchEnd, false);
  5044. startX = null;
  5045. startY = null;
  5046. dx = null;
  5047. offset = null;
  5048. };
  5049. el.addEventListener('touchstart', onTouchStart, false);
  5050. } else {
  5051. el.style.msTouchAction = "none";
  5052. el._gesture = new MSGesture();
  5053. el._gesture.target = el;
  5054. el.addEventListener("MSPointerDown", onMSPointerDown, false);
  5055. el._slider = slider;
  5056. el.addEventListener("MSGestureChange", onMSGestureChange, false);
  5057. el.addEventListener("MSGestureEnd", onMSGestureEnd, false);
  5058. function onMSPointerDown(e) {
  5059. e.stopPropagation();
  5060. if (slider.animating) {
  5061. e.preventDefault();
  5062. } else {
  5063. slider.pause();
  5064. el._gesture.addPointer(e.pointerId);
  5065. accDx = 0;
  5066. cwidth = (vertical) ? slider.h : slider.w;
  5067. startT = Number(new Date());
  5068. // CAROUSEL:
  5069. offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :
  5070. (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
  5071. (carousel && slider.currentSlide === slider.last) ? slider.limit :
  5072. (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :
  5073. (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;
  5074. }
  5075. }
  5076. function onMSGestureChange(e) {
  5077. e.stopPropagation();
  5078. var slider = e.target._slider;
  5079. if (!slider) {
  5080. return;
  5081. }
  5082. var transX = -e.translationX,
  5083. transY = -e.translationY;
  5084. //Accumulate translations.
  5085. accDx = accDx + ((vertical) ? transY : transX);
  5086. dx = accDx;
  5087. scrolling = (vertical) ? (Math.abs(accDx) < Math.abs(-transX)) : (Math.abs(accDx) < Math.abs(-transY));
  5088. if (e.detail === e.MSGESTURE_FLAG_INERTIA) {
  5089. setImmediate(function() {
  5090. el._gesture.stop();
  5091. });
  5092. return;
  5093. }
  5094. if (!scrolling || Number(new Date()) - startT > 500) {
  5095. e.preventDefault();
  5096. if (!fade && slider.transitions) {
  5097. if (!slider.vars.animationLoop) {
  5098. dx = accDx / ((slider.currentSlide === 0 && accDx < 0 || slider.currentSlide === slider.last && accDx > 0) ? (Math.abs(accDx) / cwidth + 2) : 1);
  5099. }
  5100. slider.setProps(offset + dx, "setTouch");
  5101. }
  5102. }
  5103. }
  5104. function onMSGestureEnd(e) {
  5105. e.stopPropagation();
  5106. var slider = e.target._slider;
  5107. if (!slider) {
  5108. return;
  5109. }
  5110. if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {
  5111. var updateDx = (reverse) ? -dx : dx,
  5112. target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');
  5113. if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth / 2)) {
  5114. slider.flexAnimate(target, slider.vars.pauseOnAction);
  5115. } else {
  5116. if (!fade) {slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true);}
  5117. }
  5118. }
  5119. startX = null;
  5120. startY = null;
  5121. dx = null;
  5122. offset = null;
  5123. accDx = 0;
  5124. }
  5125. }
  5126. },
  5127. resize: function() {
  5128. if (!slider.animating && slider.is(':visible')) {
  5129. if (!carousel) {slider.doMath()};
  5130. if (fade) {
  5131. // SMOOTH HEIGHT:
  5132. methods.smoothHeight();
  5133. } else if (carousel) { //CAROUSEL:
  5134. slider.slides.width(slider.computedW);
  5135. slider.update(slider.pagingCount);
  5136. slider.setProps();
  5137. }
  5138. else if (vertical) { //VERTICAL:
  5139. slider.viewport.height(slider.h);
  5140. slider.setProps(slider.h, "setTotal");
  5141. } else {
  5142. // SMOOTH HEIGHT:
  5143. if (slider.vars.smoothHeight) {methods.smoothHeight();}
  5144. slider.newSlides.width(slider.computedW);
  5145. slider.setProps(slider.computedW, "setTotal");
  5146. }
  5147. }
  5148. },
  5149. smoothHeight: function(dur) {
  5150. if (!vertical || fade) {
  5151. var $obj = (fade) ? slider : slider.viewport;
  5152. (dur) ? $obj.animate({"height": slider.slides.eq(slider.animatingTo).innerHeight()}, dur) : $obj.innerHeight(slider.slides.eq(slider.animatingTo).innerHeight());
  5153. }
  5154. },
  5155. sync: function(action) {
  5156. var $obj = $(slider.vars.sync).data("flexslider"),
  5157. target = slider.animatingTo;
  5158. switch (action) {
  5159. case "animate":
  5160. $obj.flexAnimate(target, slider.vars.pauseOnAction, false, true);
  5161. break;
  5162. case "play":
  5163. if (!$obj.playing && !$obj.asNav) {
  5164. $obj.play();
  5165. }
  5166. break;
  5167. case "pause":
  5168. $obj.pause();
  5169. break;
  5170. }
  5171. },
  5172. uniqueID: function($clone) {
  5173. // Append _clone to current level and children elements with id attributes
  5174. $clone.filter('[id]').add($clone.find('[id]')).each(function() {
  5175. var $this = $(this);
  5176. $this.attr('id', $this.attr('id') + '_clone');
  5177. });
  5178. return $clone;
  5179. },
  5180. pauseInvisible: {
  5181. visProp: null,
  5182. init: function() {
  5183. var visProp = methods.pauseInvisible.getHiddenProp();
  5184. if (visProp) {
  5185. var evtname = visProp.replace(/[H|h]idden/,'') + 'visibilitychange';
  5186. document.addEventListener(evtname, function() {
  5187. if (methods.pauseInvisible.isHidden()) {
  5188. if(slider.startTimeout) {
  5189. clearTimeout(slider.startTimeout); //If clock is ticking, stop timer and prevent from starting while invisible
  5190. } else {
  5191. slider.pause(); //Or just pause
  5192. }
  5193. }
  5194. else {
  5195. if(slider.started) {
  5196. slider.play(); //Initiated before, just play
  5197. } else {
  5198. if (slider.vars.initDelay > 0) {
  5199. setTimeout(slider.play, slider.vars.initDelay);
  5200. } else {
  5201. slider.play(); //Didn't init before: simply init or wait for it
  5202. }
  5203. }
  5204. }
  5205. });
  5206. }
  5207. },
  5208. isHidden: function() {
  5209. var prop = methods.pauseInvisible.getHiddenProp();
  5210. if (!prop) {
  5211. return false;
  5212. }
  5213. return document[prop];
  5214. },
  5215. getHiddenProp: function() {
  5216. var prefixes = ['webkit','moz','ms','o'];
  5217. // if 'hidden' is natively supported just return it
  5218. if ('hidden' in document) {
  5219. return 'hidden';
  5220. }
  5221. // otherwise loop over all the known prefixes until we find one
  5222. for (var i = 0; i < prefixes.length; i++ ) {
  5223. if ((prefixes[i] + 'Hidden') in document) {
  5224. return prefixes[i] + 'Hidden';
  5225. }
  5226. }
  5227. // otherwise it's not supported
  5228. return null;
  5229. }
  5230. },
  5231. setToClearWatchedEvent: function() {
  5232. clearTimeout(watchedEventClearTimer);
  5233. watchedEventClearTimer = setTimeout(function() {
  5234. watchedEvent = "";
  5235. }, 3000);
  5236. }
  5237. };
  5238. // public methods
  5239. slider.flexAnimate = function(target, pause, override, withSync, fromNav) {
  5240. if (!slider.vars.animationLoop && target !== slider.currentSlide) {
  5241. slider.direction = (target > slider.currentSlide) ? "next" : "prev";
  5242. }
  5243. if (asNav && slider.pagingCount === 1) slider.direction = (slider.currentItem < target) ? "next" : "prev";
  5244. if (!slider.animating && (slider.canAdvance(target, fromNav) || override) && slider.is(":visible")) {
  5245. if (asNav && withSync) {
  5246. var master = $(slider.vars.asNavFor).data('flexslider');
  5247. slider.atEnd = target === 0 || target === slider.count - 1;
  5248. master.flexAnimate(target, true, false, true, fromNav);
  5249. slider.direction = (slider.currentItem < target) ? "next" : "prev";
  5250. master.direction = slider.direction;
  5251. if (Math.ceil((target + 1) / slider.visible) - 1 !== slider.currentSlide && target !== 0) {
  5252. slider.currentItem = target;
  5253. slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide");
  5254. target = Math.floor(target / slider.visible);
  5255. } else {
  5256. slider.currentItem = target;
  5257. slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide");
  5258. return false;
  5259. }
  5260. }
  5261. slider.animating = true;
  5262. slider.animatingTo = target;
  5263. // SLIDESHOW:
  5264. if (pause) {slider.pause();}
  5265. // API: before() animation Callback
  5266. slider.vars.before(slider);
  5267. // SYNC:
  5268. if (slider.syncExists && !fromNav) {methods.sync("animate");}
  5269. // CONTROLNAV
  5270. if (slider.vars.controlNav) {methods.controlNav.active();}
  5271. // !CAROUSEL:
  5272. // CANDIDATE: slide active class (for add/remove slide)
  5273. if (!carousel) {slider.slides.removeClass(namespace + 'active-slide').eq(target).addClass(namespace + 'active-slide');}
  5274. // INFINITE LOOP:
  5275. // CANDIDATE: atEnd
  5276. slider.atEnd = target === 0 || target === slider.last;
  5277. // DIRECTIONNAV:
  5278. if (slider.vars.directionNav) {methods.directionNav.update();}
  5279. if (target === slider.last) {
  5280. // API: end() of cycle Callback
  5281. slider.vars.end(slider);
  5282. // SLIDESHOW && !INFINITE LOOP:
  5283. if (!slider.vars.animationLoop) {slider.pause();}
  5284. }
  5285. // SLIDE:
  5286. if (!fade) {
  5287. var dimension = (vertical) ? slider.slides.filter(':first').height() : slider.computedW,
  5288. margin, slideString, calcNext;
  5289. // INFINITE LOOP / REVERSE:
  5290. if (carousel) {
  5291. //margin = (slider.vars.itemWidth > slider.w) ? slider.vars.itemMargin * 2 : slider.vars.itemMargin;
  5292. margin = slider.vars.itemMargin;
  5293. calcNext = ((slider.itemW + margin) * slider.move) * slider.animatingTo;
  5294. slideString = (calcNext > slider.limit && slider.visible !== 1) ? slider.limit : calcNext;
  5295. } else if (slider.currentSlide === 0 && target === slider.count - 1 && slider.vars.animationLoop && slider.direction !== "next") {
  5296. slideString = (reverse) ? (slider.count + slider.cloneOffset) * dimension : 0;
  5297. } else if (slider.currentSlide === slider.last && target === 0 && slider.vars.animationLoop && slider.direction !== "prev") {
  5298. slideString = (reverse) ? 0 : (slider.count + 1) * dimension;
  5299. } else {
  5300. slideString = (reverse) ? ((slider.count - 1) - target + slider.cloneOffset) * dimension : (target + slider.cloneOffset) * dimension;
  5301. }
  5302. slider.setProps(slideString, "", slider.vars.animationSpeed);
  5303. if (slider.transitions) {
  5304. if (!slider.vars.animationLoop || !slider.atEnd) {
  5305. slider.animating = false;
  5306. slider.currentSlide = slider.animatingTo;
  5307. }
  5308. // Unbind previous transitionEnd events and re-bind new transitionEnd event
  5309. slider.container.unbind("webkitTransitionEnd transitionend");
  5310. slider.container.bind("webkitTransitionEnd transitionend", function() {
  5311. clearTimeout(slider.ensureAnimationEnd);
  5312. slider.wrapup(dimension);
  5313. });
  5314. // Insurance for the ever-so-fickle transitionEnd event
  5315. clearTimeout(slider.ensureAnimationEnd);
  5316. slider.ensureAnimationEnd = setTimeout(function() {
  5317. slider.wrapup(dimension);
  5318. }, slider.vars.animationSpeed + 100);
  5319. } else {
  5320. slider.container.animate(slider.args, slider.vars.animationSpeed, slider.vars.easing, function(){
  5321. slider.wrapup(dimension);
  5322. });
  5323. }
  5324. } else { // FADE:
  5325. if (!touch) {
  5326. //slider.slides.eq(slider.currentSlide).fadeOut(slider.vars.animationSpeed, slider.vars.easing);
  5327. //slider.slides.eq(target).fadeIn(slider.vars.animationSpeed, slider.vars.easing, slider.wrapup);
  5328. slider.slides.eq(slider.currentSlide).css({"zIndex": 1}).animate({"opacity": 0}, slider.vars.animationSpeed, slider.vars.easing);
  5329. slider.slides.eq(target).css({"zIndex": 2}).animate({"opacity": 1}, slider.vars.animationSpeed, slider.vars.easing, slider.wrapup);
  5330. } else {
  5331. slider.slides.eq(slider.currentSlide).css({
  5332. "opacity": 0,
  5333. "zIndex": 1
  5334. });
  5335. slider.slides.eq(target).css({"opacity": 1, "zIndex": 2});
  5336. slider.wrapup(dimension);
  5337. }
  5338. }
  5339. // SMOOTH HEIGHT:
  5340. if (slider.vars.smoothHeight) {methods.smoothHeight(slider.vars.animationSpeed)};
  5341. }
  5342. };
  5343. slider.wrapup = function(dimension) {
  5344. // SLIDE:
  5345. if (!fade && !carousel) {
  5346. if (slider.currentSlide === 0 && slider.animatingTo === slider.last && slider.vars.animationLoop) {
  5347. slider.setProps(dimension, "jumpEnd");
  5348. } else if (slider.currentSlide === slider.last && slider.animatingTo === 0 && slider.vars.animationLoop) {
  5349. slider.setProps(dimension, "jumpStart");
  5350. }
  5351. }
  5352. slider.animating = false;
  5353. slider.currentSlide = slider.animatingTo;
  5354. // API: after() animation Callback
  5355. slider.vars.after(slider);
  5356. };
  5357. // SLIDESHOW:
  5358. slider.animateSlides = function() {
  5359. if (!slider.animating && focused) {slider.flexAnimate(slider.getTarget("next"));}
  5360. };
  5361. // SLIDESHOW:
  5362. slider.pause = function() {
  5363. clearInterval(slider.animatedSlides);
  5364. slider.animatedSlides = null;
  5365. slider.playing = false;
  5366. // PAUSEPLAY:
  5367. if (slider.vars.pausePlay) {methods.pausePlay.update("play");}
  5368. // SYNC:
  5369. if (slider.syncExists) {methods.sync("pause");}
  5370. };
  5371. // SLIDESHOW:
  5372. slider.play = function() {
  5373. if (slider.playing) {clearInterval(slider.animatedSlides);}
  5374. slider.animatedSlides = slider.animatedSlides || setInterval(slider.animateSlides, slider.vars.slideshowSpeed);
  5375. slider.started = slider.playing = true;
  5376. // PAUSEPLAY:
  5377. if (slider.vars.pausePlay) {methods.pausePlay.update("pause");}
  5378. // SYNC:
  5379. if (slider.syncExists) {methods.sync("play");}
  5380. };
  5381. // STOP:
  5382. slider.stop = function() {
  5383. slider.pause();
  5384. slider.stopped = true;
  5385. };
  5386. slider.canAdvance = function(target, fromNav) {
  5387. // ASNAV:
  5388. var last = (asNav) ? slider.pagingCount - 1 : slider.last;
  5389. return (fromNav) ? true :
  5390. (asNav && slider.currentItem === slider.count - 1 && target === 0 && slider.direction === "prev") ? true :
  5391. (asNav && slider.currentItem === 0 && target === slider.pagingCount - 1 && slider.direction !== "next") ? false :
  5392. (target === slider.currentSlide && !asNav) ? false :
  5393. (slider.vars.animationLoop) ? true :
  5394. (slider.atEnd && slider.currentSlide === 0 && target === last && slider.direction !== "next") ? false :
  5395. (slider.atEnd && slider.currentSlide === last && target === 0 && slider.direction === "next") ? false :
  5396. true;
  5397. };
  5398. slider.getTarget = function(dir) {
  5399. slider.direction = dir;
  5400. if (dir === "next") {
  5401. return (slider.currentSlide === slider.last) ? 0 : slider.currentSlide + 1;
  5402. } else {
  5403. return (slider.currentSlide === 0) ? slider.last : slider.currentSlide - 1;
  5404. }
  5405. };
  5406. // SLIDE:
  5407. slider.setProps = function(pos, special, dur) {
  5408. var target = (function() {
  5409. var posCheck = (pos) ? pos : ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo,
  5410. posCalc = (function() {
  5411. if (carousel) {
  5412. return (special === "setTouch") ? pos :
  5413. (reverse && slider.animatingTo === slider.last) ? 0 :
  5414. (reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
  5415. (slider.animatingTo === slider.last) ? slider.limit : posCheck;
  5416. } else {
  5417. switch (special) {
  5418. case "setTotal":
  5419. return (reverse) ? ((slider.count - 1) - slider.currentSlide + slider.cloneOffset) * pos : (slider.currentSlide + slider.cloneOffset) * pos;
  5420. case "setTouch":
  5421. return (reverse) ? pos : pos;
  5422. case "jumpEnd":
  5423. return (reverse) ? pos : slider.count * pos;
  5424. case "jumpStart":
  5425. return (reverse) ? slider.count * pos : pos;
  5426. default:
  5427. return pos;
  5428. }
  5429. }
  5430. }());
  5431. return (posCalc * -1) + "px";
  5432. }());
  5433. if (slider.transitions) {
  5434. target = (vertical) ? "translate3d(0," + target + ",0)" : "translate3d(" + target + ",0,0)";
  5435. dur = (dur !== undefined) ? (dur / 1000) + "s" : "0s";
  5436. slider.container.css("-" + slider.pfx + "-transition-duration", dur);
  5437. slider.container.css("transition-duration", dur);
  5438. }
  5439. slider.args[slider.prop] = target;
  5440. if (slider.transitions || dur === undefined) {slider.container.css(slider.args);}
  5441. slider.container.css('transform', target);
  5442. };
  5443. slider.setup = function(type) {
  5444. // SLIDE:
  5445. if (!fade) {
  5446. var sliderOffset, arr;
  5447. if (type === "init") {
  5448. slider.viewport = $('<div class="' + namespace + 'viewport"></div>').css({
  5449. "overflow": "hidden",
  5450. "position": "relative"
  5451. }).appendTo(slider).append(slider.container);
  5452. // INFINITE LOOP:
  5453. slider.cloneCount = 0;
  5454. slider.cloneOffset = 0;
  5455. // REVERSE:
  5456. if (reverse) {
  5457. arr = $.makeArray(slider.slides).reverse();
  5458. slider.slides = $(arr);
  5459. slider.container.empty().append(slider.slides);
  5460. }
  5461. }
  5462. // INFINITE LOOP && !CAROUSEL:
  5463. if (slider.vars.animationLoop && !carousel) {
  5464. slider.cloneCount = 2;
  5465. slider.cloneOffset = 1;
  5466. // clear out old clones
  5467. if (type !== "init") { slider.container.find('.clone').remove(); }
  5468. slider.container.append(methods.uniqueID(slider.slides.first().clone().addClass('clone')).attr('aria-hidden', 'true'))
  5469. .prepend(methods.uniqueID(slider.slides.last().clone().addClass('clone')).attr('aria-hidden', 'true'));
  5470. }
  5471. slider.newSlides = $(slider.vars.selector, slider);
  5472. sliderOffset = (reverse) ? slider.count - 1 - slider.currentSlide + slider.cloneOffset : slider.currentSlide + slider.cloneOffset;
  5473. // VERTICAL:
  5474. if (vertical && !carousel) {
  5475. slider.container.height((slider.count + slider.cloneCount) * 200 + "%").css("position", "absolute").width("100%");
  5476. setTimeout(function() {
  5477. slider.newSlides.css({"display": "block"});
  5478. slider.doMath();
  5479. slider.viewport.height(slider.h);
  5480. slider.setProps(sliderOffset * slider.h, "init");
  5481. }, (type === "init") ? 100 : 0);
  5482. } else {
  5483. slider.container.width((slider.count + slider.cloneCount) * 200 + "%");
  5484. slider.setProps(sliderOffset * slider.computedW, "init");
  5485. setTimeout(function() {
  5486. slider.doMath();
  5487. slider.newSlides.css({"width": slider.computedW, "marginRight" : slider.computedM, "float": "left", "display": "block"});
  5488. // SMOOTH HEIGHT:
  5489. if (slider.vars.smoothHeight) {methods.smoothHeight();}
  5490. }, (type === "init") ? 100 : 0);
  5491. }
  5492. } else { // FADE:
  5493. slider.slides.css({
  5494. "width": "100%",
  5495. "float": "left",
  5496. "marginRight": "-100%",
  5497. "position": "relative"
  5498. });
  5499. if (type === "init") {
  5500. if (!touch) {
  5501. //slider.slides.eq(slider.currentSlide).fadeIn(slider.vars.animationSpeed, slider.vars.easing);
  5502. if (slider.vars.fadeFirstSlide == false) {
  5503. slider.slides.css({ "opacity": 0, "display": "block", "zIndex": 1 }).eq(slider.currentSlide).css({"zIndex": 2}).css({"opacity": 1});
  5504. } else {
  5505. slider.slides.css({ "opacity": 0, "display": "block", "zIndex": 1 }).eq(slider.currentSlide).css({"zIndex": 2}).animate({"opacity": 1},slider.vars.animationSpeed,slider.vars.easing);
  5506. }
  5507. } else {
  5508. slider.slides.css({ "opacity": 0, "display": "block", "webkitTransition": "opacity " + slider.vars.animationSpeed / 1000 + "s ease", "zIndex": 1 }).eq(slider.currentSlide).css({ "opacity": 1, "zIndex": 2});
  5509. }
  5510. }
  5511. // SMOOTH HEIGHT:
  5512. if (slider.vars.smoothHeight) {methods.smoothHeight();}
  5513. }
  5514. // !CAROUSEL:
  5515. // CANDIDATE: active slide
  5516. if (!carousel) {slider.slides.removeClass(namespace + "active-slide").eq(slider.currentSlide).addClass(namespace + "active-slide");}
  5517. //FlexSlider: init() Callback
  5518. slider.vars.init(slider);
  5519. };
  5520. slider.doMath = function() {
  5521. var slide = slider.slides.first(),
  5522. slideMargin = slider.vars.itemMargin,
  5523. minItems = slider.vars.minItems,
  5524. maxItems = slider.vars.maxItems;
  5525. slider.w = (slider.viewport === undefined) ? slider.width() : slider.viewport.width();
  5526. slider.h = slide.height();
  5527. slider.boxPadding = slide.outerWidth() - slide.width();
  5528. // CAROUSEL:
  5529. if (carousel) {
  5530. slider.itemT = slider.vars.itemWidth + slideMargin;
  5531. slider.itemM = slideMargin;
  5532. slider.minW = (minItems) ? minItems * slider.itemT : slider.w;
  5533. slider.maxW = (maxItems) ? (maxItems * slider.itemT) - slideMargin : slider.w;
  5534. slider.itemW = (slider.minW > slider.w) ? (slider.w - (slideMargin * (minItems - 1))) / minItems :
  5535. (slider.maxW < slider.w) ? (slider.w - (slideMargin * (maxItems - 1))) / maxItems :
  5536. (slider.vars.itemWidth > slider.w) ? slider.w : slider.vars.itemWidth;
  5537. slider.visible = Math.floor(slider.w / (slider.itemW));
  5538. slider.move = (slider.vars.move > 0 && slider.vars.move < slider.visible ) ? slider.vars.move : slider.visible;
  5539. slider.pagingCount = Math.ceil(((slider.count - slider.visible) / slider.move) + 1);
  5540. slider.last = slider.pagingCount - 1;
  5541. slider.limit = (slider.pagingCount === 1) ? 0 :
  5542. (slider.vars.itemWidth > slider.w) ? (slider.itemW * (slider.count - 1)) + (slideMargin * (slider.count - 1)) : ((slider.itemW + slideMargin) * slider.count) - slider.w - slideMargin;
  5543. } else {
  5544. slider.itemW = slider.w;
  5545. slider.itemM = slideMargin;
  5546. slider.pagingCount = slider.count;
  5547. slider.last = slider.count - 1;
  5548. }
  5549. slider.computedW = slider.itemW - slider.boxPadding;
  5550. slider.computedM = slider.itemM;
  5551. };
  5552. slider.update = function(pos, action) {
  5553. slider.doMath();
  5554. // update currentSlide and slider.animatingTo if necessary
  5555. if (!carousel) {
  5556. if (pos < slider.currentSlide) {
  5557. slider.currentSlide += 1;
  5558. } else if (pos <= slider.currentSlide && pos !== 0) {
  5559. slider.currentSlide -= 1;
  5560. }
  5561. slider.animatingTo = slider.currentSlide;
  5562. }
  5563. // update controlNav
  5564. if (slider.vars.controlNav && !slider.manualControls) {
  5565. if ((action === "add" && !carousel) || slider.pagingCount > slider.controlNav.length) {
  5566. methods.controlNav.update("add");
  5567. } else if ((action === "remove" && !carousel) || slider.pagingCount < slider.controlNav.length) {
  5568. if (carousel && slider.currentSlide > slider.last) {
  5569. slider.currentSlide -= 1;
  5570. slider.animatingTo -= 1;
  5571. }
  5572. methods.controlNav.update("remove", slider.last);
  5573. }
  5574. }
  5575. // update directionNav
  5576. if (slider.vars.directionNav) {methods.directionNav.update();}
  5577. };
  5578. slider.addSlide = function(obj, pos) {
  5579. var $obj = $(obj);
  5580. slider.count += 1;
  5581. slider.last = slider.count - 1;
  5582. // append new slide
  5583. if (vertical && reverse) {
  5584. (pos !== undefined) ? slider.slides.eq(slider.count - pos).after($obj) : slider.container.prepend($obj);
  5585. } else {
  5586. (pos !== undefined) ? slider.slides.eq(pos).before($obj) : slider.container.append($obj);
  5587. }
  5588. // update currentSlide, animatingTo, controlNav, and directionNav
  5589. slider.update(pos, "add");
  5590. // update slider.slides
  5591. slider.slides = $(slider.vars.selector + ':not(.clone)', slider);
  5592. // re-setup the slider to accomdate new slide
  5593. slider.setup();
  5594. //FlexSlider: added() Callback
  5595. slider.vars.added(slider);
  5596. };
  5597. slider.removeSlide = function(obj) {
  5598. var pos = (isNaN(obj)) ? slider.slides.index($(obj)) : obj;
  5599. // update count
  5600. slider.count -= 1;
  5601. slider.last = slider.count - 1;
  5602. // remove slide
  5603. if (isNaN(obj)) {
  5604. $(obj, slider.slides).remove();
  5605. } else {
  5606. (vertical && reverse) ? slider.slides.eq(slider.last).remove() : slider.slides.eq(obj).remove();
  5607. }
  5608. // update currentSlide, animatingTo, controlNav, and directionNav
  5609. slider.doMath();
  5610. slider.update(pos, "remove");
  5611. // update slider.slides
  5612. slider.slides = $(slider.vars.selector + ':not(.clone)', slider);
  5613. // re-setup the slider to accomdate new slide
  5614. slider.setup();
  5615. // FlexSlider: removed() Callback
  5616. slider.vars.removed(slider);
  5617. };
  5618. //FlexSlider: Initialize
  5619. methods.init();
  5620. };
  5621. // Ensure the slider isn't focussed if the window loses focus.
  5622. $(window).blur(function(e) {
  5623. focused = false;
  5624. }).focus(function(e) {
  5625. focused = true;
  5626. });
  5627. // FlexSlider: Default Settings
  5628. $.flexslider.defaults = {
  5629. namespace: 'am-', // {NEW} String: Prefix string attached to the class of every element generated by the plugin
  5630. selector: '.am-slides > li', // {NEW} Selector: Must match a simple pattern. '{container} > {slide}' -- Ignore pattern at your own peril
  5631. animation: 'slide', // String: Select your animation type, 'fade' or 'slide'
  5632. easing: 'swing', // {NEW} String: Determines the easing method used in jQuery transitions. jQuery easing plugin is supported!
  5633. direction: 'horizontal', // String: Select the sliding direction, "horizontal" or "vertical"
  5634. reverse: false, // {NEW} Boolean: Reverse the animation direction
  5635. animationLoop: true, // Boolean: Should the animation loop? If false, directionNav will received "disable" classes at either end
  5636. smoothHeight: false, // {NEW} Boolean: Allow height of the slider to animate smoothly in horizontal mode
  5637. startAt: 0, // Integer: The slide that the slider should start on. Array notation (0 = first slide)
  5638. slideshow: true, // Boolean: Animate slider automatically
  5639. slideshowSpeed: 5000, // Integer: Set the speed of the slideshow cycling, in milliseconds
  5640. animationSpeed: 600, // Integer: Set the speed of animations, in milliseconds
  5641. initDelay: 0, // {NEW} Integer: Set an initialization delay, in milliseconds
  5642. randomize: false, // Boolean: Randomize slide order
  5643. fadeFirstSlide: true, // Boolean: Fade in the first slide when animation type is "fade"
  5644. thumbCaptions: false, // Boolean: Whether or not to put captions on thumbnails when using the "thumbnails" controlNav.
  5645. // Usability features
  5646. pauseOnAction: true, // Boolean: Pause the slideshow when interacting with control elements, highly recommended.
  5647. pauseOnHover: false, // Boolean: Pause the slideshow when hovering over slider, then resume when no longer hovering
  5648. pauseInvisible: true, // {NEW} Boolean: Pause the slideshow when tab is invisible, resume when visible. Provides better UX, lower CPU usage.
  5649. useCSS: true, // {NEW} Boolean: Slider will use CSS3 transitions if available
  5650. touch: true, // {NEW} Boolean: Allow touch swipe navigation of the slider on touch-enabled devices
  5651. video: false, // {NEW} Boolean: If using video in the slider, will prevent CSS3 3D Transforms to avoid graphical glitches
  5652. // Primary Controls
  5653. controlNav: true, // Boolean: Create navigation for paging control of each slide? Note: Leave true for manualControls usage
  5654. directionNav: true, // Boolean: Create navigation for previous/next navigation? (true/false)
  5655. prevText: ' ', // String: Set the text for the "previous" directionNav item
  5656. nextText: ' ', // String: Set the text for the "next" directionNav item
  5657. // Secondary Navigation
  5658. keyboard: true, // Boolean: Allow slider navigating via keyboard left/right keys
  5659. multipleKeyboard: false, // {NEW} Boolean: Allow keyboard navigation to affect multiple sliders. Default behavior cuts out keyboard navigation with more than one slider present.
  5660. mousewheel: false, // {UPDATED} Boolean: Requires jquery.mousewheel.js (https://github.com/brandonaaron/jquery-mousewheel) - Allows slider navigating via mousewheel
  5661. pausePlay: false, // Boolean: Create pause/play dynamic element
  5662. pauseText: 'Pause', // String: Set the text for the 'pause' pausePlay item
  5663. playText: 'Play', // String: Set the text for the 'play' pausePlay item
  5664. // Special properties
  5665. controlsContainer: '', // {UPDATED} jQuery Object/Selector: Declare which container the navigation elements should be appended too. Default container is the FlexSlider element. Example use would be $('.flexslider-container'). Property is ignored if given element is not found.
  5666. manualControls: '', // {UPDATED} jQuery Object/Selector: Declare custom control navigation. Examples would be $(".flex-control-nav li") or "#tabs-nav li img", etc. The number of elements in your controlNav should match the number of slides/tabs.
  5667. customDirectionNav: '', // {NEW} jQuery Object/Selector: Custom prev / next button. Must be two jQuery elements. In order to make the events work they have to have the classes "prev" and "next" (plus namespace)
  5668. sync: '', // {NEW} Selector: Mirror the actions performed on this slider with another slider. Use with care.
  5669. asNavFor: '', // {NEW} Selector: Internal property exposed for turning the slider into a thumbnail navigation for another slider
  5670. // Carousel Options
  5671. itemWidth: 0, // {NEW} Integer: Box-model width of individual carousel items, including horizontal borders and padding.
  5672. itemMargin: 0, // {NEW} Integer: Margin between carousel items.
  5673. minItems: 1, // {NEW} Integer: Minimum number of carousel items that should be visible. Items will resize fluidly when below this.
  5674. maxItems: 0, // {NEW} Integer: Maxmimum number of carousel items that should be visible. Items will resize fluidly when above this limit.
  5675. move: 0, // {NEW} Integer: Number of carousel items that should move on animation. If 0, slider will move all visible items.
  5676. allowOneSlide: true, // {NEW} Boolean: Whether or not to allow a slider comprised of a single slide
  5677. // Callback API
  5678. start: function() {
  5679. }, // Callback: function(slider) - Fires when the slider loads the first slide
  5680. before: function() {
  5681. }, // Callback: function(slider) - Fires asynchronously with each slider animation
  5682. after: function() {
  5683. }, // Callback: function(slider) - Fires after each slider animation completes
  5684. end: function() {
  5685. }, // Callback: function(slider) - Fires when the slider reaches the last slide (asynchronous)
  5686. added: function() {
  5687. }, // {NEW} Callback: function(slider) - Fires after a slide is added
  5688. removed: function() {
  5689. }, // {NEW} Callback: function(slider) - Fires after a slide is removed
  5690. init: function() {
  5691. } // {NEW} Callback: function(slider) - Fires after the slider is initially setup
  5692. };
  5693. // FlexSlider: Plugin Function
  5694. $.fn.flexslider = function(options) {
  5695. var args = Array.prototype.slice.call(arguments, 1);
  5696. if (options === undefined) {options = {};}
  5697. if (typeof options === 'object') {
  5698. return this.each(function() {
  5699. var $this = $(this);
  5700. var selector = (options.selector) ? options.selector : '.am-slides > li';
  5701. var $slides = $this.find(selector);
  5702. if (( $slides.length === 1 && options.allowOneSlide === false) || $slides.length === 0) {
  5703. $slides.fadeIn(400);
  5704. if (options.start) {options.start($this);}
  5705. } else if ($this.data('flexslider') === undefined) {
  5706. new $.flexslider(this, options);
  5707. }
  5708. });
  5709. } else {
  5710. // Helper strings to quickly pecdrform functions on the slider
  5711. var $slider = $(this).data('flexslider');
  5712. var methodReturn;
  5713. switch (options) {
  5714. case 'next':
  5715. $slider.flexAnimate($slider.getTarget('next'), true);
  5716. break;
  5717. case 'prev':
  5718. case 'previous':
  5719. $slider.flexAnimate($slider.getTarget('prev'), true);
  5720. break;
  5721. default:
  5722. if (typeof options === 'number') {
  5723. $slider.flexAnimate(options, true);
  5724. } else if (typeof options === 'string') {
  5725. methodReturn = (typeof $slider[options] === 'function') ?
  5726. $slider[options].apply($slider, args) : $slider[options];
  5727. }
  5728. }
  5729. return methodReturn === undefined ? this : methodReturn;
  5730. }
  5731. };
  5732. // Init code
  5733. UI.ready(function(context) {
  5734. $('[data-am-flexslider]', context).each(function(i, item) {
  5735. var $slider = $(item);
  5736. var options = UI.utils.parseOptions($slider.data('amFlexslider'));
  5737. options.before = function(slider) {
  5738. if (slider._pausedTimer) {
  5739. window.clearTimeout(slider._pausedTimer);
  5740. slider._pausedTimer = null;
  5741. }
  5742. };
  5743. options.after = function(slider) {
  5744. var pauseTime = slider.vars.playAfterPaused;
  5745. if (pauseTime && !isNaN(pauseTime) && !slider.playing) {
  5746. if (!slider.manualPause && !slider.manualPlay && !slider.stopped) {
  5747. slider._pausedTimer = window.setTimeout(function() {
  5748. slider.play();
  5749. }, pauseTime);
  5750. }
  5751. }
  5752. };
  5753. $slider.flexslider(options);
  5754. });
  5755. });
  5756. module.exports = $.flexslider;
  5757. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12).setImmediate))
  5758. /***/ },
  5759. /* 12 */
  5760. /***/ function(module, exports, __webpack_require__) {
  5761. /* WEBPACK VAR INJECTION */(function(setImmediate, clearImmediate) {var nextTick = __webpack_require__(13).nextTick;
  5762. var apply = Function.prototype.apply;
  5763. var slice = Array.prototype.slice;
  5764. var immediateIds = {};
  5765. var nextImmediateId = 0;
  5766. // DOM APIs, for completeness
  5767. exports.setTimeout = function() {
  5768. return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);
  5769. };
  5770. exports.setInterval = function() {
  5771. return new Timeout(apply.call(setInterval, window, arguments), clearInterval);
  5772. };
  5773. exports.clearTimeout =
  5774. exports.clearInterval = function(timeout) { timeout.close(); };
  5775. function Timeout(id, clearFn) {
  5776. this._id = id;
  5777. this._clearFn = clearFn;
  5778. }
  5779. Timeout.prototype.unref = Timeout.prototype.ref = function() {};
  5780. Timeout.prototype.close = function() {
  5781. this._clearFn.call(window, this._id);
  5782. };
  5783. // Does not start the time, just sets up the members needed.
  5784. exports.enroll = function(item, msecs) {
  5785. clearTimeout(item._idleTimeoutId);
  5786. item._idleTimeout = msecs;
  5787. };
  5788. exports.unenroll = function(item) {
  5789. clearTimeout(item._idleTimeoutId);
  5790. item._idleTimeout = -1;
  5791. };
  5792. exports._unrefActive = exports.active = function(item) {
  5793. clearTimeout(item._idleTimeoutId);
  5794. var msecs = item._idleTimeout;
  5795. if (msecs >= 0) {
  5796. item._idleTimeoutId = setTimeout(function onTimeout() {
  5797. if (item._onTimeout)
  5798. item._onTimeout();
  5799. }, msecs);
  5800. }
  5801. };
  5802. // That's not how node.js implements it but the exposed api is the same.
  5803. exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) {
  5804. var id = nextImmediateId++;
  5805. var args = arguments.length < 2 ? false : slice.call(arguments, 1);
  5806. immediateIds[id] = true;
  5807. nextTick(function onNextTick() {
  5808. if (immediateIds[id]) {
  5809. // fn.call() is faster so we optimize for the common use-case
  5810. // @see http://jsperf.com/call-apply-segu
  5811. if (args) {
  5812. fn.apply(null, args);
  5813. } else {
  5814. fn.call(null);
  5815. }
  5816. // Prevent ids from leaking
  5817. exports.clearImmediate(id);
  5818. }
  5819. });
  5820. return id;
  5821. };
  5822. exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) {
  5823. delete immediateIds[id];
  5824. };
  5825. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12).setImmediate, __webpack_require__(12).clearImmediate))
  5826. /***/ },
  5827. /* 13 */
  5828. /***/ function(module, exports) {
  5829. // shim for using process in browser
  5830. var process = module.exports = {};
  5831. // cached from whatever global is present so that test runners that stub it
  5832. // don't break things. But we need to wrap it in a try catch in case it is
  5833. // wrapped in strict mode code which doesn't define any globals. It's inside a
  5834. // function because try/catches deoptimize in certain engines.
  5835. var cachedSetTimeout;
  5836. var cachedClearTimeout;
  5837. function defaultSetTimout() {
  5838. throw new Error('setTimeout has not been defined');
  5839. }
  5840. function defaultClearTimeout () {
  5841. throw new Error('clearTimeout has not been defined');
  5842. }
  5843. (function () {
  5844. try {
  5845. if (typeof setTimeout === 'function') {
  5846. cachedSetTimeout = setTimeout;
  5847. } else {
  5848. cachedSetTimeout = defaultSetTimout;
  5849. }
  5850. } catch (e) {
  5851. cachedSetTimeout = defaultSetTimout;
  5852. }
  5853. try {
  5854. if (typeof clearTimeout === 'function') {
  5855. cachedClearTimeout = clearTimeout;
  5856. } else {
  5857. cachedClearTimeout = defaultClearTimeout;
  5858. }
  5859. } catch (e) {
  5860. cachedClearTimeout = defaultClearTimeout;
  5861. }
  5862. } ())
  5863. function runTimeout(fun) {
  5864. if (cachedSetTimeout === setTimeout) {
  5865. //normal enviroments in sane situations
  5866. return setTimeout(fun, 0);
  5867. }
  5868. // if setTimeout wasn't available but was latter defined
  5869. if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
  5870. cachedSetTimeout = setTimeout;
  5871. return setTimeout(fun, 0);
  5872. }
  5873. try {
  5874. // when when somebody has screwed with setTimeout but no I.E. maddness
  5875. return cachedSetTimeout(fun, 0);
  5876. } catch(e){
  5877. try {
  5878. // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
  5879. return cachedSetTimeout.call(null, fun, 0);
  5880. } catch(e){
  5881. // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
  5882. return cachedSetTimeout.call(this, fun, 0);
  5883. }
  5884. }
  5885. }
  5886. function runClearTimeout(marker) {
  5887. if (cachedClearTimeout === clearTimeout) {
  5888. //normal enviroments in sane situations
  5889. return clearTimeout(marker);
  5890. }
  5891. // if clearTimeout wasn't available but was latter defined
  5892. if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
  5893. cachedClearTimeout = clearTimeout;
  5894. return clearTimeout(marker);
  5895. }
  5896. try {
  5897. // when when somebody has screwed with setTimeout but no I.E. maddness
  5898. return cachedClearTimeout(marker);
  5899. } catch (e){
  5900. try {
  5901. // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
  5902. return cachedClearTimeout.call(null, marker);
  5903. } catch (e){
  5904. // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
  5905. // Some versions of I.E. have different rules for clearTimeout vs setTimeout
  5906. return cachedClearTimeout.call(this, marker);
  5907. }
  5908. }
  5909. }
  5910. var queue = [];
  5911. var draining = false;
  5912. var currentQueue;
  5913. var queueIndex = -1;
  5914. function cleanUpNextTick() {
  5915. if (!draining || !currentQueue) {
  5916. return;
  5917. }
  5918. draining = false;
  5919. if (currentQueue.length) {
  5920. queue = currentQueue.concat(queue);
  5921. } else {
  5922. queueIndex = -1;
  5923. }
  5924. if (queue.length) {
  5925. drainQueue();
  5926. }
  5927. }
  5928. function drainQueue() {
  5929. if (draining) {
  5930. return;
  5931. }
  5932. var timeout = runTimeout(cleanUpNextTick);
  5933. draining = true;
  5934. var len = queue.length;
  5935. while(len) {
  5936. currentQueue = queue;
  5937. queue = [];
  5938. while (++queueIndex < len) {
  5939. if (currentQueue) {
  5940. currentQueue[queueIndex].run();
  5941. }
  5942. }
  5943. queueIndex = -1;
  5944. len = queue.length;
  5945. }
  5946. currentQueue = null;
  5947. draining = false;
  5948. runClearTimeout(timeout);
  5949. }
  5950. process.nextTick = function (fun) {
  5951. var args = new Array(arguments.length - 1);
  5952. if (arguments.length > 1) {
  5953. for (var i = 1; i < arguments.length; i++) {
  5954. args[i - 1] = arguments[i];
  5955. }
  5956. }
  5957. queue.push(new Item(fun, args));
  5958. if (queue.length === 1 && !draining) {
  5959. runTimeout(drainQueue);
  5960. }
  5961. };
  5962. // v8 likes predictible objects
  5963. function Item(fun, array) {
  5964. this.fun = fun;
  5965. this.array = array;
  5966. }
  5967. Item.prototype.run = function () {
  5968. this.fun.apply(null, this.array);
  5969. };
  5970. process.title = 'browser';
  5971. process.browser = true;
  5972. process.env = {};
  5973. process.argv = [];
  5974. process.version = ''; // empty string to avoid regexp issues
  5975. process.versions = {};
  5976. function noop() {}
  5977. process.on = noop;
  5978. process.addListener = noop;
  5979. process.once = noop;
  5980. process.off = noop;
  5981. process.removeListener = noop;
  5982. process.removeAllListeners = noop;
  5983. process.emit = noop;
  5984. process.binding = function (name) {
  5985. throw new Error('process.binding is not supported');
  5986. };
  5987. process.cwd = function () { return '/' };
  5988. process.chdir = function (dir) {
  5989. throw new Error('process.chdir is not supported');
  5990. };
  5991. process.umask = function() { return 0; };
  5992. /***/ },
  5993. /* 14 */
  5994. /***/ function(module, exports, __webpack_require__) {
  5995. 'use strict';
  5996. var UI = __webpack_require__(2);
  5997. /*! iScroll v5.2.0
  5998. * (c) 2008-2016 Matteo Spinelli
  5999. * http://cubiq.org/license
  6000. */
  6001. var rAF = UI.utils.rAF;
  6002. var utils = (function() {
  6003. var me = {};
  6004. var _elementStyle = document.createElement('div').style;
  6005. var _vendor = (function() {
  6006. var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
  6007. transform,
  6008. i = 0,
  6009. l = vendors.length;
  6010. for (; i < l; i++) {
  6011. transform = vendors[i] + 'ransform';
  6012. if (transform in _elementStyle) return vendors[i].substr(0, vendors[i].length - 1);
  6013. }
  6014. return false;
  6015. })();
  6016. function _prefixStyle(style) {
  6017. if (_vendor === false) return false;
  6018. if (_vendor === '') return style;
  6019. return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
  6020. }
  6021. me.getTime = Date.now || function getTime() {
  6022. return new Date().getTime();
  6023. };
  6024. me.extend = function(target, obj) {
  6025. for (var i in obj) {
  6026. target[i] = obj[i];
  6027. }
  6028. };
  6029. me.addEvent = function(el, type, fn, capture) {
  6030. el.addEventListener(type, fn, !!capture);
  6031. };
  6032. me.removeEvent = function(el, type, fn, capture) {
  6033. el.removeEventListener(type, fn, !!capture);
  6034. };
  6035. me.prefixPointerEvent = function(pointerEvent) {
  6036. return window.MSPointerEvent ?
  6037. 'MSPointer' + pointerEvent.charAt(7)
  6038. .toUpperCase() + pointerEvent.substr(8) :
  6039. pointerEvent;
  6040. };
  6041. me.momentum = function(current, start, time, lowerMargin, wrapperSize, deceleration) {
  6042. var distance = current - start,
  6043. speed = Math.abs(distance) / time,
  6044. destination,
  6045. duration;
  6046. deceleration = deceleration === undefined ? 0.0006 : deceleration;
  6047. destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
  6048. duration = speed / deceleration;
  6049. if (destination < lowerMargin) {
  6050. destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
  6051. distance = Math.abs(destination - current);
  6052. duration = distance / speed;
  6053. } else if (destination > 0) {
  6054. destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
  6055. distance = Math.abs(current) + destination;
  6056. duration = distance / speed;
  6057. }
  6058. return {
  6059. destination: Math.round(destination),
  6060. duration: duration
  6061. };
  6062. };
  6063. var _transform = _prefixStyle('transform');
  6064. me.extend(me, {
  6065. hasTransform: _transform !== false,
  6066. hasPerspective: _prefixStyle('perspective') in _elementStyle,
  6067. hasTouch: 'ontouchstart' in window,
  6068. hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed
  6069. hasTransition: _prefixStyle('transition') in _elementStyle
  6070. });
  6071. /*
  6072. This should find all Android browsers lower than build 535.19 (both stock browser and webview)
  6073. - galaxy S2 is ok
  6074. - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`
  6075. - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
  6076. - galaxy S3 is badAndroid (stock brower, webview)
  6077. `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
  6078. - galaxy S4 is badAndroid (stock brower, webview)
  6079. `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
  6080. - galaxy S5 is OK
  6081. `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
  6082. - galaxy S6 is OK
  6083. `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
  6084. */
  6085. me.isBadAndroid = (function() {
  6086. var appVersion = window.navigator.appVersion;
  6087. // Android browser is not a chrome browser.
  6088. if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) {
  6089. var safariVersion = appVersion.match(/Safari\/(\d+.\d)/);
  6090. if (safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) {
  6091. return parseFloat(safariVersion[1]) < 535.19;
  6092. } else {
  6093. return true;
  6094. }
  6095. } else {
  6096. return false;
  6097. }
  6098. })();
  6099. me.extend(me.style = {}, {
  6100. transform: _transform,
  6101. transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
  6102. transitionDuration: _prefixStyle('transitionDuration'),
  6103. transitionDelay: _prefixStyle('transitionDelay'),
  6104. transformOrigin: _prefixStyle('transformOrigin')
  6105. });
  6106. me.hasClass = function(e, c) {
  6107. var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
  6108. return re.test(e.className);
  6109. };
  6110. me.addClass = function(e, c) {
  6111. if (me.hasClass(e, c)) {
  6112. return;
  6113. }
  6114. var newclass = e.className.split(' ');
  6115. newclass.push(c);
  6116. e.className = newclass.join(' ');
  6117. };
  6118. me.removeClass = function(e, c) {
  6119. if (!me.hasClass(e, c)) {
  6120. return;
  6121. }
  6122. var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
  6123. e.className = e.className.replace(re, ' ');
  6124. };
  6125. me.offset = function(el) {
  6126. var left = -el.offsetLeft,
  6127. top = -el.offsetTop;
  6128. // jshint -W084
  6129. while (el = el.offsetParent) {
  6130. left -= el.offsetLeft;
  6131. top -= el.offsetTop;
  6132. }
  6133. // jshint +W084
  6134. return {
  6135. left: left,
  6136. top: top
  6137. };
  6138. };
  6139. me.preventDefaultException = function(el, exceptions) {
  6140. for (var i in exceptions) {
  6141. if (exceptions[i].test(el[i])) {
  6142. return true;
  6143. }
  6144. }
  6145. return false;
  6146. };
  6147. me.extend(me.eventType = {}, {
  6148. touchstart: 1,
  6149. touchmove: 1,
  6150. touchend: 1,
  6151. mousedown: 2,
  6152. mousemove: 2,
  6153. mouseup: 2,
  6154. pointerdown: 3,
  6155. pointermove: 3,
  6156. pointerup: 3,
  6157. MSPointerDown: 3,
  6158. MSPointerMove: 3,
  6159. MSPointerUp: 3
  6160. });
  6161. me.extend(me.ease = {}, {
  6162. quadratic: {
  6163. style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
  6164. fn: function(k) {
  6165. return k * ( 2 - k );
  6166. }
  6167. },
  6168. circular: {
  6169. style: 'cubic-bezier(0.1, 0.57, 0.1, 1)', // Not properly "circular" but this looks better, it should be (0.075, 0.82, 0.165, 1)
  6170. fn: function(k) {
  6171. return Math.sqrt(1 - ( --k * k ));
  6172. }
  6173. },
  6174. back: {
  6175. style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
  6176. fn: function(k) {
  6177. var b = 4;
  6178. return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
  6179. }
  6180. },
  6181. bounce: {
  6182. style: '',
  6183. fn: function(k) {
  6184. if (( k /= 1 ) < ( 1 / 2.75 )) {
  6185. return 7.5625 * k * k;
  6186. } else if (k < ( 2 / 2.75 )) {
  6187. return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
  6188. } else if (k < ( 2.5 / 2.75 )) {
  6189. return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
  6190. } else {
  6191. return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
  6192. }
  6193. }
  6194. },
  6195. elastic: {
  6196. style: '',
  6197. fn: function(k) {
  6198. var f = 0.22,
  6199. e = 0.4;
  6200. if (k === 0) {
  6201. return 0;
  6202. }
  6203. if (k == 1) {
  6204. return 1;
  6205. }
  6206. return ( e * Math.pow(2, -10 * k) * Math.sin(( k - f / 4 ) * ( 2 * Math.PI ) / f) + 1 );
  6207. }
  6208. }
  6209. });
  6210. me.tap = function(e, eventName) {
  6211. var ev = document.createEvent('Event');
  6212. ev.initEvent(eventName, true, true);
  6213. ev.pageX = e.pageX;
  6214. ev.pageY = e.pageY;
  6215. e.target.dispatchEvent(ev);
  6216. };
  6217. me.click = function(e) {
  6218. var target = e.target,
  6219. ev;
  6220. if (!(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName)) {
  6221. // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
  6222. // initMouseEvent is deprecated.
  6223. ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');
  6224. ev.initEvent('click', true, true);
  6225. ev.view = e.view || window;
  6226. ev.detail = 1;
  6227. ev.screenX = target.screenX || 0;
  6228. ev.screenY = target.screenY || 0;
  6229. ev.clientX = target.clientX || 0;
  6230. ev.clientY = target.clientY || 0;
  6231. ev.ctrlKey = !!e.ctrlKey;
  6232. ev.altKey = !!e.altKey;
  6233. ev.shiftKey = !!e.shiftKey;
  6234. ev.metaKey = !!e.metaKey;
  6235. ev.button = 0;
  6236. ev.relatedTarget = null;
  6237. ev._constructed = true;
  6238. target.dispatchEvent(ev);
  6239. }
  6240. };
  6241. return me;
  6242. })();
  6243. function IScroll(el, options) {
  6244. this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
  6245. this.scroller = this.wrapper.children[0];
  6246. this.scrollerStyle = this.scroller.style; // cache style for better performance
  6247. this.options = {
  6248. // INSERT POINT: OPTIONS
  6249. disablePointer: !utils.hasPointer,
  6250. disableTouch: utils.hasPointer || !utils.hasTouch,
  6251. disableMouse: utils.hasPointer || utils.hasTouch,
  6252. startX: 0,
  6253. startY: 0,
  6254. scrollY: true,
  6255. directionLockThreshold: 5,
  6256. momentum: true,
  6257. bounce: true,
  6258. bounceTime: 600,
  6259. bounceEasing: '',
  6260. preventDefault: true,
  6261. preventDefaultException: {tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/},
  6262. HWCompositing: true,
  6263. useTransition: true,
  6264. useTransform: true,
  6265. bindToWrapper: typeof window.onmousedown === "undefined"
  6266. };
  6267. for (var i in options) {
  6268. this.options[i] = options[i];
  6269. }
  6270. // Normalize options
  6271. this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
  6272. this.options.useTransition = utils.hasTransition && this.options.useTransition;
  6273. this.options.useTransform = utils.hasTransform && this.options.useTransform;
  6274. this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
  6275. this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
  6276. // If you want eventPassthrough I have to lock one of the axes
  6277. this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
  6278. this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
  6279. // With eventPassthrough we also need lockDirection mechanism
  6280. this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
  6281. this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
  6282. this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
  6283. this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
  6284. if (this.options.tap === true) {
  6285. this.options.tap = 'tap';
  6286. }
  6287. // https://github.com/cubiq/iscroll/issues/1029
  6288. if (!this.options.useTransition && !this.options.useTransform) {
  6289. if (!(/relative|absolute/i).test(this.scrollerStyle.position)) {
  6290. this.scrollerStyle.position = "relative";
  6291. }
  6292. }
  6293. // INSERT POINT: NORMALIZATION
  6294. // Some defaults
  6295. this.x = 0;
  6296. this.y = 0;
  6297. this.directionX = 0;
  6298. this.directionY = 0;
  6299. this._events = {};
  6300. // INSERT POINT: DEFAULTS
  6301. this._init();
  6302. this.refresh();
  6303. this.scrollTo(this.options.startX, this.options.startY);
  6304. this.enable();
  6305. }
  6306. IScroll.prototype = {
  6307. version: '5.2.0',
  6308. _init: function() {
  6309. this._initEvents();
  6310. // INSERT POINT: _init
  6311. },
  6312. destroy: function() {
  6313. this._initEvents(true);
  6314. clearTimeout(this.resizeTimeout);
  6315. this.resizeTimeout = null;
  6316. this._execEvent('destroy');
  6317. },
  6318. _transitionEnd: function(e) {
  6319. if (e.target != this.scroller || !this.isInTransition) {
  6320. return;
  6321. }
  6322. this._transitionTime();
  6323. if (!this.resetPosition(this.options.bounceTime)) {
  6324. this.isInTransition = false;
  6325. this._execEvent('scrollEnd');
  6326. }
  6327. },
  6328. _start: function(e) {
  6329. // React to left mouse button only
  6330. if (utils.eventType[e.type] != 1) {
  6331. // for button property
  6332. // http://unixpapa.com/js/mouse.html
  6333. var button;
  6334. if (!e.which) {
  6335. /* IE case */
  6336. button = (e.button < 2) ? 0 :
  6337. ((e.button == 4) ? 1 : 2);
  6338. } else {
  6339. /* All others */
  6340. button = e.button;
  6341. }
  6342. if (button !== 0) {
  6343. return;
  6344. }
  6345. }
  6346. if (!this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated)) {
  6347. return;
  6348. }
  6349. if (this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException)) {
  6350. e.preventDefault();
  6351. }
  6352. var point = e.touches ? e.touches[0] : e,
  6353. pos;
  6354. this.initiated = utils.eventType[e.type];
  6355. this.moved = false;
  6356. this.distX = 0;
  6357. this.distY = 0;
  6358. this.directionX = 0;
  6359. this.directionY = 0;
  6360. this.directionLocked = 0;
  6361. this.startTime = utils.getTime();
  6362. if (this.options.useTransition && this.isInTransition) {
  6363. this._transitionTime();
  6364. this.isInTransition = false;
  6365. pos = this.getComputedPosition();
  6366. this._translate(Math.round(pos.x), Math.round(pos.y));
  6367. this._execEvent('scrollEnd');
  6368. } else if (!this.options.useTransition && this.isAnimating) {
  6369. this.isAnimating = false;
  6370. this._execEvent('scrollEnd');
  6371. }
  6372. this.startX = this.x;
  6373. this.startY = this.y;
  6374. this.absStartX = this.x;
  6375. this.absStartY = this.y;
  6376. this.pointX = point.pageX;
  6377. this.pointY = point.pageY;
  6378. this._execEvent('beforeScrollStart');
  6379. },
  6380. _move: function(e) {
  6381. if (!this.enabled || utils.eventType[e.type] !== this.initiated) {
  6382. return;
  6383. }
  6384. if (this.options.preventDefault) { // increases performance on Android? TODO: check!
  6385. e.preventDefault();
  6386. }
  6387. var point = e.touches ? e.touches[0] : e,
  6388. deltaX = point.pageX - this.pointX,
  6389. deltaY = point.pageY - this.pointY,
  6390. timestamp = utils.getTime(),
  6391. newX, newY,
  6392. absDistX, absDistY;
  6393. this.pointX = point.pageX;
  6394. this.pointY = point.pageY;
  6395. this.distX += deltaX;
  6396. this.distY += deltaY;
  6397. absDistX = Math.abs(this.distX);
  6398. absDistY = Math.abs(this.distY);
  6399. // We need to move at least 10 pixels for the scrolling to initiate
  6400. if (timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10)) {
  6401. return;
  6402. }
  6403. // If you are scrolling in one direction lock the other
  6404. if (!this.directionLocked && !this.options.freeScroll) {
  6405. if (absDistX > absDistY + this.options.directionLockThreshold) {
  6406. this.directionLocked = 'h'; // lock horizontally
  6407. } else if (absDistY >= absDistX + this.options.directionLockThreshold) {
  6408. this.directionLocked = 'v'; // lock vertically
  6409. } else {
  6410. this.directionLocked = 'n'; // no lock
  6411. }
  6412. }
  6413. if (this.directionLocked == 'h') {
  6414. if (this.options.eventPassthrough == 'vertical') {
  6415. e.preventDefault();
  6416. } else if (this.options.eventPassthrough == 'horizontal') {
  6417. this.initiated = false;
  6418. return;
  6419. }
  6420. deltaY = 0;
  6421. } else if (this.directionLocked == 'v') {
  6422. if (this.options.eventPassthrough == 'horizontal') {
  6423. e.preventDefault();
  6424. } else if (this.options.eventPassthrough == 'vertical') {
  6425. this.initiated = false;
  6426. return;
  6427. }
  6428. deltaX = 0;
  6429. }
  6430. deltaX = this.hasHorizontalScroll ? deltaX : 0;
  6431. deltaY = this.hasVerticalScroll ? deltaY : 0;
  6432. newX = this.x + deltaX;
  6433. newY = this.y + deltaY;
  6434. // Slow down if outside of the boundaries
  6435. if (newX > 0 || newX < this.maxScrollX) {
  6436. newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
  6437. }
  6438. if (newY > 0 || newY < this.maxScrollY) {
  6439. newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
  6440. }
  6441. this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
  6442. this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
  6443. if (!this.moved) {
  6444. this._execEvent('scrollStart');
  6445. }
  6446. this.moved = true;
  6447. this._translate(newX, newY);
  6448. /* REPLACE START: _move */
  6449. if (timestamp - this.startTime > 300) {
  6450. this.startTime = timestamp;
  6451. this.startX = this.x;
  6452. this.startY = this.y;
  6453. }
  6454. /* REPLACE END: _move */
  6455. },
  6456. _end: function(e) {
  6457. if (!this.enabled || utils.eventType[e.type] !== this.initiated) {
  6458. return;
  6459. }
  6460. if (this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException)) {
  6461. e.preventDefault();
  6462. }
  6463. var point = e.changedTouches ? e.changedTouches[0] : e,
  6464. momentumX,
  6465. momentumY,
  6466. duration = utils.getTime() - this.startTime,
  6467. newX = Math.round(this.x),
  6468. newY = Math.round(this.y),
  6469. distanceX = Math.abs(newX - this.startX),
  6470. distanceY = Math.abs(newY - this.startY),
  6471. time = 0,
  6472. easing = '';
  6473. this.isInTransition = 0;
  6474. this.initiated = 0;
  6475. this.endTime = utils.getTime();
  6476. // reset if we are outside of the boundaries
  6477. if (this.resetPosition(this.options.bounceTime)) {
  6478. return;
  6479. }
  6480. this.scrollTo(newX, newY); // ensures that the last position is rounded
  6481. // we scrolled less than 10 pixels
  6482. if (!this.moved) {
  6483. if (this.options.tap) {
  6484. utils.tap(e, this.options.tap);
  6485. }
  6486. if (this.options.click) {
  6487. utils.click(e);
  6488. }
  6489. this._execEvent('scrollCancel');
  6490. return;
  6491. }
  6492. if (this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100) {
  6493. this._execEvent('flick');
  6494. return;
  6495. }
  6496. // start momentum animation if needed
  6497. if (this.options.momentum && duration < 300) {
  6498. momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : {
  6499. destination: newX,
  6500. duration: 0
  6501. };
  6502. momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : {
  6503. destination: newY,
  6504. duration: 0
  6505. };
  6506. newX = momentumX.destination;
  6507. newY = momentumY.destination;
  6508. time = Math.max(momentumX.duration, momentumY.duration);
  6509. this.isInTransition = 1;
  6510. }
  6511. // INSERT POINT: _end
  6512. if (newX != this.x || newY != this.y) {
  6513. // change easing function when scroller goes out of the boundaries
  6514. if (newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY) {
  6515. easing = utils.ease.quadratic;
  6516. }
  6517. this.scrollTo(newX, newY, time, easing);
  6518. return;
  6519. }
  6520. this._execEvent('scrollEnd');
  6521. },
  6522. _resize: function() {
  6523. var that = this;
  6524. clearTimeout(this.resizeTimeout);
  6525. this.resizeTimeout = setTimeout(function() {
  6526. that.refresh();
  6527. }, this.options.resizePolling);
  6528. },
  6529. resetPosition: function(time) {
  6530. var x = this.x,
  6531. y = this.y;
  6532. time = time || 0;
  6533. if (!this.hasHorizontalScroll || this.x > 0) {
  6534. x = 0;
  6535. } else if (this.x < this.maxScrollX) {
  6536. x = this.maxScrollX;
  6537. }
  6538. if (!this.hasVerticalScroll || this.y > 0) {
  6539. y = 0;
  6540. } else if (this.y < this.maxScrollY) {
  6541. y = this.maxScrollY;
  6542. }
  6543. if (x == this.x && y == this.y) {
  6544. return false;
  6545. }
  6546. this.scrollTo(x, y, time, this.options.bounceEasing);
  6547. return true;
  6548. },
  6549. disable: function() {
  6550. this.enabled = false;
  6551. },
  6552. enable: function() {
  6553. this.enabled = true;
  6554. },
  6555. refresh: function() {
  6556. var rf = this.wrapper.offsetHeight; // Force reflow
  6557. this.wrapperWidth = this.wrapper.clientWidth;
  6558. this.wrapperHeight = this.wrapper.clientHeight;
  6559. /* REPLACE START: refresh */
  6560. this.scrollerWidth = this.scroller.offsetWidth;
  6561. this.scrollerHeight = this.scroller.offsetHeight;
  6562. this.maxScrollX = this.wrapperWidth - this.scrollerWidth;
  6563. this.maxScrollY = this.wrapperHeight - this.scrollerHeight;
  6564. /* REPLACE END: refresh */
  6565. this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0;
  6566. this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0;
  6567. if (!this.hasHorizontalScroll) {
  6568. this.maxScrollX = 0;
  6569. this.scrollerWidth = this.wrapperWidth;
  6570. }
  6571. if (!this.hasVerticalScroll) {
  6572. this.maxScrollY = 0;
  6573. this.scrollerHeight = this.wrapperHeight;
  6574. }
  6575. this.endTime = 0;
  6576. this.directionX = 0;
  6577. this.directionY = 0;
  6578. this.wrapperOffset = utils.offset(this.wrapper);
  6579. this._execEvent('refresh');
  6580. this.resetPosition();
  6581. // INSERT POINT: _refresh
  6582. },
  6583. on: function(type, fn) {
  6584. if (!this._events[type]) {
  6585. this._events[type] = [];
  6586. }
  6587. this._events[type].push(fn);
  6588. },
  6589. off: function(type, fn) {
  6590. if (!this._events[type]) {
  6591. return;
  6592. }
  6593. var index = this._events[type].indexOf(fn);
  6594. if (index > -1) {
  6595. this._events[type].splice(index, 1);
  6596. }
  6597. },
  6598. _execEvent: function(type) {
  6599. if (!this._events[type]) {
  6600. return;
  6601. }
  6602. var i = 0,
  6603. l = this._events[type].length;
  6604. if (!l) {
  6605. return;
  6606. }
  6607. for (; i < l; i++) {
  6608. this._events[type][i].apply(this, [].slice.call(arguments, 1));
  6609. }
  6610. },
  6611. scrollBy: function(x, y, time, easing) {
  6612. x = this.x + x;
  6613. y = this.y + y;
  6614. time = time || 0;
  6615. this.scrollTo(x, y, time, easing);
  6616. },
  6617. scrollTo: function(x, y, time, easing) {
  6618. easing = easing || utils.ease.circular;
  6619. this.isInTransition = this.options.useTransition && time > 0;
  6620. var transitionType = this.options.useTransition && easing.style;
  6621. if (!time || transitionType) {
  6622. if (transitionType) {
  6623. this._transitionTimingFunction(easing.style);
  6624. this._transitionTime(time);
  6625. }
  6626. this._translate(x, y);
  6627. } else {
  6628. this._animate(x, y, time, easing.fn);
  6629. }
  6630. },
  6631. scrollToElement: function(el, time, offsetX, offsetY, easing) {
  6632. el = el.nodeType ? el : this.scroller.querySelector(el);
  6633. if (!el) {
  6634. return;
  6635. }
  6636. var pos = utils.offset(el);
  6637. pos.left -= this.wrapperOffset.left;
  6638. pos.top -= this.wrapperOffset.top;
  6639. // if offsetX/Y are true we center the element to the screen
  6640. if (offsetX === true) {
  6641. offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
  6642. }
  6643. if (offsetY === true) {
  6644. offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
  6645. }
  6646. pos.left -= offsetX || 0;
  6647. pos.top -= offsetY || 0;
  6648. pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
  6649. pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top;
  6650. time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x - pos.left), Math.abs(this.y - pos.top)) : time;
  6651. this.scrollTo(pos.left, pos.top, time, easing);
  6652. },
  6653. _transitionTime: function(time) {
  6654. if (!this.options.useTransition) {
  6655. return;
  6656. }
  6657. time = time || 0;
  6658. var durationProp = utils.style.transitionDuration;
  6659. if (!durationProp) {
  6660. return;
  6661. }
  6662. this.scrollerStyle[durationProp] = time + 'ms';
  6663. if (!time && utils.isBadAndroid) {
  6664. this.scrollerStyle[durationProp] = '0.0001ms';
  6665. // remove 0.0001ms
  6666. var self = this;
  6667. rAF(function() {
  6668. if (self.scrollerStyle[durationProp] === '0.0001ms') {
  6669. self.scrollerStyle[durationProp] = '0s';
  6670. }
  6671. });
  6672. }
  6673. // INSERT POINT: _transitionTime
  6674. },
  6675. _transitionTimingFunction: function(easing) {
  6676. this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
  6677. // INSERT POINT: _transitionTimingFunction
  6678. },
  6679. _translate: function(x, y) {
  6680. if (this.options.useTransform) {
  6681. /* REPLACE START: _translate */
  6682. this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
  6683. /* REPLACE END: _translate */
  6684. } else {
  6685. x = Math.round(x);
  6686. y = Math.round(y);
  6687. this.scrollerStyle.left = x + 'px';
  6688. this.scrollerStyle.top = y + 'px';
  6689. }
  6690. this.x = x;
  6691. this.y = y;
  6692. // INSERT POINT: _translate
  6693. },
  6694. _initEvents: function(remove) {
  6695. var eventType = remove ? utils.removeEvent : utils.addEvent,
  6696. target = this.options.bindToWrapper ? this.wrapper : window;
  6697. eventType(window, 'orientationchange', this);
  6698. eventType(window, 'resize', this);
  6699. if (this.options.click) {
  6700. eventType(this.wrapper, 'click', this, true);
  6701. }
  6702. if (!this.options.disableMouse) {
  6703. eventType(this.wrapper, 'mousedown', this);
  6704. eventType(target, 'mousemove', this);
  6705. eventType(target, 'mousecancel', this);
  6706. eventType(target, 'mouseup', this);
  6707. }
  6708. if (utils.hasPointer && !this.options.disablePointer) {
  6709. eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
  6710. eventType(target, utils.prefixPointerEvent('pointermove'), this);
  6711. eventType(target, utils.prefixPointerEvent('pointercancel'), this);
  6712. eventType(target, utils.prefixPointerEvent('pointerup'), this);
  6713. }
  6714. if (utils.hasTouch && !this.options.disableTouch) {
  6715. eventType(this.wrapper, 'touchstart', this);
  6716. eventType(target, 'touchmove', this);
  6717. eventType(target, 'touchcancel', this);
  6718. eventType(target, 'touchend', this);
  6719. }
  6720. eventType(this.scroller, 'transitionend', this);
  6721. eventType(this.scroller, 'webkitTransitionEnd', this);
  6722. eventType(this.scroller, 'oTransitionEnd', this);
  6723. eventType(this.scroller, 'MSTransitionEnd', this);
  6724. },
  6725. getComputedPosition: function() {
  6726. var matrix = window.getComputedStyle(this.scroller, null),
  6727. x, y;
  6728. if (this.options.useTransform) {
  6729. matrix = matrix[utils.style.transform].split(')')[0].split(', ');
  6730. x = +(matrix[12] || matrix[4]);
  6731. y = +(matrix[13] || matrix[5]);
  6732. } else {
  6733. x = +matrix.left.replace(/[^-\d.]/g, '');
  6734. y = +matrix.top.replace(/[^-\d.]/g, '');
  6735. }
  6736. return {x: x, y: y};
  6737. },
  6738. _animate: function(destX, destY, duration, easingFn) {
  6739. var that = this,
  6740. startX = this.x,
  6741. startY = this.y,
  6742. startTime = utils.getTime(),
  6743. destTime = startTime + duration;
  6744. function step() {
  6745. var now = utils.getTime(),
  6746. newX, newY,
  6747. easing;
  6748. if (now >= destTime) {
  6749. that.isAnimating = false;
  6750. that._translate(destX, destY);
  6751. if (!that.resetPosition(that.options.bounceTime)) {
  6752. that._execEvent('scrollEnd');
  6753. }
  6754. return;
  6755. }
  6756. now = ( now - startTime ) / duration;
  6757. easing = easingFn(now);
  6758. newX = ( destX - startX ) * easing + startX;
  6759. newY = ( destY - startY ) * easing + startY;
  6760. that._translate(newX, newY);
  6761. if (that.isAnimating) {
  6762. rAF(step);
  6763. }
  6764. }
  6765. this.isAnimating = true;
  6766. step();
  6767. },
  6768. handleEvent: function(e) {
  6769. switch (e.type) {
  6770. case 'touchstart':
  6771. case 'pointerdown':
  6772. case 'MSPointerDown':
  6773. case 'mousedown':
  6774. this._start(e);
  6775. break;
  6776. case 'touchmove':
  6777. case 'pointermove':
  6778. case 'MSPointerMove':
  6779. case 'mousemove':
  6780. this._move(e);
  6781. break;
  6782. case 'touchend':
  6783. case 'pointerup':
  6784. case 'MSPointerUp':
  6785. case 'mouseup':
  6786. case 'touchcancel':
  6787. case 'pointercancel':
  6788. case 'MSPointerCancel':
  6789. case 'mousecancel':
  6790. this._end(e);
  6791. break;
  6792. case 'orientationchange':
  6793. case 'resize':
  6794. this._resize();
  6795. break;
  6796. case 'transitionend':
  6797. case 'webkitTransitionEnd':
  6798. case 'oTransitionEnd':
  6799. case 'MSTransitionEnd':
  6800. this._transitionEnd(e);
  6801. break;
  6802. case 'wheel':
  6803. case 'DOMMouseScroll':
  6804. case 'mousewheel':
  6805. this._wheel(e);
  6806. break;
  6807. case 'keydown':
  6808. this._key(e);
  6809. break;
  6810. case 'click':
  6811. if (this.enabled && !e._constructed) {
  6812. e.preventDefault();
  6813. e.stopPropagation();
  6814. }
  6815. break;
  6816. }
  6817. }
  6818. };
  6819. IScroll.utils = utils;
  6820. module.exports = UI.iScroll = IScroll;
  6821. /* jshint unused: true */
  6822. /* jshint +W101, +W116, +W109 */
  6823. /***/ },
  6824. /* 15 */
  6825. /***/ function(module, exports, __webpack_require__) {
  6826. 'use strict';
  6827. var $ = __webpack_require__(1);
  6828. var UI = __webpack_require__(2);
  6829. var dimmer = __webpack_require__(9);
  6830. var $doc = $(document);
  6831. var supportTransition = UI.support.transition;
  6832. /**
  6833. * @reference https://github.com/nolimits4web/Framework7/blob/master/src/js/modals.js
  6834. * @license https://github.com/nolimits4web/Framework7/blob/master/LICENSE
  6835. */
  6836. var Modal = function(element, options) {
  6837. this.options = $.extend({}, Modal.DEFAULTS, options || {});
  6838. this.$element = $(element);
  6839. this.$dialog = this.$element.find('.am-modal-dialog');
  6840. if (!this.$element.attr('id')) {
  6841. this.$element.attr('id', UI.utils.generateGUID('am-modal'));
  6842. }
  6843. this.isPopup = this.$element.hasClass('am-popup');
  6844. this.isActions = this.$element.hasClass('am-modal-actions');
  6845. this.isPrompt = this.$element.hasClass('am-modal-prompt');
  6846. this.isLoading = this.$element.hasClass('am-modal-loading');
  6847. this.active = this.transitioning = this.relatedTarget = null;
  6848. this.dimmer = this.options.dimmer ? dimmer : {
  6849. open: function() {
  6850. },
  6851. close: function() {
  6852. }
  6853. };
  6854. this.events();
  6855. };
  6856. Modal.DEFAULTS = {
  6857. className: {
  6858. active: 'am-modal-active',
  6859. out: 'am-modal-out'
  6860. },
  6861. selector: {
  6862. modal: '.am-modal',
  6863. active: '.am-modal-active'
  6864. },
  6865. closeViaDimmer: true,
  6866. cancelable: true,
  6867. onConfirm: function() {
  6868. },
  6869. onCancel: function() {
  6870. },
  6871. closeOnCancel: true,
  6872. closeOnConfirm: true,
  6873. dimmer: true,
  6874. height: undefined,
  6875. width: undefined,
  6876. duration: 300, // must equal the CSS transition duration
  6877. transitionEnd: supportTransition && supportTransition.end + '.modal.amui'
  6878. };
  6879. Modal.prototype.toggle = function(relatedTarget) {
  6880. return this.active ? this.close() : this.open(relatedTarget);
  6881. };
  6882. Modal.prototype.open = function(relatedTarget) {
  6883. var $element = this.$element;
  6884. var options = this.options;
  6885. var isPopup = this.isPopup;
  6886. var width = options.width;
  6887. var height = options.height;
  6888. var style = {};
  6889. if (this.active) {
  6890. return;
  6891. }
  6892. if (!this.$element.length) {
  6893. return;
  6894. }
  6895. // callback hook
  6896. relatedTarget && (this.relatedTarget = relatedTarget);
  6897. // 判断如果还在动画,就先触发之前的closed事件
  6898. if (this.transitioning) {
  6899. clearTimeout($element.transitionEndTimmer);
  6900. $element.transitionEndTimmer = null;
  6901. $element.trigger(options.transitionEnd)
  6902. .off(options.transitionEnd);
  6903. }
  6904. isPopup && this.$element.show();
  6905. this.active = true;
  6906. $element.trigger($.Event('open.modal.amui', {relatedTarget: relatedTarget}));
  6907. this.dimmer.open($element);
  6908. $element.show().redraw();
  6909. // apply Modal width/height if set
  6910. if (!isPopup && !this.isActions) {
  6911. if (width) {
  6912. style.width = parseInt(width, 10) + 'px';
  6913. }
  6914. if (height) {
  6915. style.height = parseInt(height, 10) + 'px';
  6916. }
  6917. this.$dialog.css(style);
  6918. }
  6919. $element
  6920. .removeClass(options.className.out)
  6921. .addClass(options.className.active);
  6922. this.transitioning = 1;
  6923. var complete = function() {
  6924. $element.trigger($.Event('opened.modal.amui', {
  6925. relatedTarget: relatedTarget
  6926. }));
  6927. this.transitioning = 0;
  6928. // Prompt auto focus
  6929. if (this.isPrompt) {
  6930. this.$dialog.find('input').eq(0).focus();
  6931. }
  6932. };
  6933. if (!supportTransition) {
  6934. return complete.call(this);
  6935. }
  6936. $element
  6937. .one(options.transitionEnd, $.proxy(complete, this))
  6938. .emulateTransitionEnd(options.duration);
  6939. };
  6940. Modal.prototype.close = function(relatedTarget) {
  6941. if (!this.active) {
  6942. return;
  6943. }
  6944. var $element = this.$element;
  6945. var options = this.options;
  6946. var isPopup = this.isPopup;
  6947. // 判断如果还在动画,就先触发之前的opened事件
  6948. if (this.transitioning) {
  6949. clearTimeout($element.transitionEndTimmer);
  6950. $element.transitionEndTimmer = null;
  6951. $element.trigger(options.transitionEnd).off(options.transitionEnd);
  6952. this.dimmer.close($element, true);
  6953. }
  6954. this.$element.trigger($.Event('close.modal.amui', {
  6955. relatedTarget: relatedTarget
  6956. }));
  6957. this.transitioning = 1;
  6958. var complete = function() {
  6959. $element.trigger('closed.modal.amui');
  6960. isPopup && $element.removeClass(options.className.out);
  6961. $element.hide();
  6962. this.transitioning = 0;
  6963. // 不强制关闭 Dimmer,以便多个 Modal 可以共享 Dimmer
  6964. this.dimmer.close($element, false);
  6965. this.active = false;
  6966. };
  6967. $element.removeClass(options.className.active)
  6968. .addClass(options.className.out);
  6969. if (!supportTransition) {
  6970. return complete.call(this);
  6971. }
  6972. $element.one(options.transitionEnd, $.proxy(complete, this))
  6973. .emulateTransitionEnd(options.duration);
  6974. };
  6975. Modal.prototype.events = function() {
  6976. var _this = this;
  6977. var options = this.options;
  6978. var $element = this.$element;
  6979. var $dimmer = this.dimmer.$element;
  6980. var $ipt = $element.find('.am-modal-prompt-input');
  6981. var $confirm = $element.find('[data-am-modal-confirm]');
  6982. var $cancel = $element.find('[data-am-modal-cancel]');
  6983. var getData = function() {
  6984. var data = [];
  6985. $ipt.each(function() {
  6986. data.push($(this).val());
  6987. });
  6988. return (data.length === 0) ? undefined :
  6989. ((data.length === 1) ? data[0] : data);
  6990. };
  6991. // close via Esc key
  6992. if (this.options.cancelable) {
  6993. $element.on('keyup.modal.amui', function(e) {
  6994. if (_this.active && e.which === 27) {
  6995. $element.trigger('cancel.modal.amui');
  6996. _this.close();
  6997. }
  6998. });
  6999. }
  7000. // Close Modal when dimmer clicked
  7001. if (this.options.dimmer && this.options.closeViaDimmer && !this.isLoading) {
  7002. $dimmer.on('click.dimmer.modal.amui', function() {
  7003. _this.close();
  7004. });
  7005. }
  7006. // Close Modal when button clicked
  7007. $element.on(
  7008. 'click.close.modal.amui',
  7009. '[data-am-modal-close], .am-modal-btn',
  7010. function(e) {
  7011. e.preventDefault();
  7012. var $this = $(this);
  7013. if ($this.is($confirm)) {
  7014. options.closeOnConfirm && _this.close();
  7015. } else if ($this.is($cancel)) {
  7016. options.closeOnCancel && _this.close();
  7017. } else {
  7018. _this.close();
  7019. }
  7020. }
  7021. )
  7022. // trigger dimmer click event if non-dialog area clicked
  7023. // fixes #882 caused by https://github.com/amazeui/amazeui/commit/b6be7719681193f1c4cb04af89cb9fd9f4422163
  7024. .on('click', function(e) {
  7025. // fixes #900
  7026. // e.stopPropagation();
  7027. $(e.target).is($element) && $dimmer.trigger('click.dimmer.modal.amui');
  7028. });
  7029. $confirm.on('click.confirm.modal.amui',
  7030. function() {
  7031. $element.trigger($.Event('confirm.modal.amui', {
  7032. trigger: this
  7033. }));
  7034. });
  7035. $cancel.on('click.cancel.modal.amui', function() {
  7036. $element.trigger($.Event('cancel.modal.amui', {
  7037. trigger: this
  7038. }));
  7039. });
  7040. $element.on('confirm.modal.amui', function(e) {
  7041. e.data = getData();
  7042. _this.options.onConfirm.call(_this, e);
  7043. }).on('cancel.modal.amui', function(e) {
  7044. e.data = getData();
  7045. _this.options.onCancel.call(_this, e);
  7046. });
  7047. };
  7048. function Plugin(option, relatedTarget) {
  7049. return this.each(function() {
  7050. var $this = $(this);
  7051. var data = $this.data('amui.modal');
  7052. var options = typeof option == 'object' && option;
  7053. if (!data) {
  7054. $this.data('amui.modal', (data = new Modal(this, options)));
  7055. }
  7056. if (typeof option == 'string') {
  7057. data[option] && data[option](relatedTarget);
  7058. } else {
  7059. data.toggle(option && option.relatedTarget || undefined);
  7060. }
  7061. });
  7062. }
  7063. $.fn.modal = Plugin;
  7064. // Init
  7065. $doc.on('click.modal.amui.data-api', '[data-am-modal]', function() {
  7066. var $this = $(this);
  7067. var options = UI.utils.parseOptions($this.attr('data-am-modal'));
  7068. var $target = $(options.target ||
  7069. (this.href && this.href.replace(/.*(?=#[^\s]+$)/, '')));
  7070. var option = $target.data('amui.modal') ? 'toggle' : options;
  7071. Plugin.call($target, option, this);
  7072. });
  7073. module.exports = UI.modal = Modal;
  7074. /***/ },
  7075. /* 16 */
  7076. /***/ function(module, exports, __webpack_require__) {
  7077. 'use strict';
  7078. var $ = __webpack_require__(1);
  7079. var UI = __webpack_require__(2);
  7080. __webpack_require__(3);
  7081. var $win = $(window);
  7082. var $doc = $(document);
  7083. var scrollPos;
  7084. /**
  7085. * @via https://github.com/uikit/uikit/blob/master/src/js/offcanvas.js
  7086. * @license https://github.com/uikit/uikit/blob/master/LICENSE.md
  7087. */
  7088. var OffCanvas = function(element, options) {
  7089. this.$element = $(element);
  7090. this.options = $.extend({}, OffCanvas.DEFAULTS, options);
  7091. this.active = null;
  7092. this.bindEvents();
  7093. };
  7094. OffCanvas.DEFAULTS = {
  7095. duration: 300,
  7096. effect: 'overlay' // {push|overlay}, push is too expensive
  7097. };
  7098. OffCanvas.prototype.open = function(relatedElement) {
  7099. var _this = this;
  7100. var $element = this.$element;
  7101. if (!$element.length || $element.hasClass('am-active')) {
  7102. return;
  7103. }
  7104. var effect = this.options.effect;
  7105. var $html = $('html');
  7106. var $body = $('body');
  7107. var $bar = $element.find('.am-offcanvas-bar').first();
  7108. var dir = $bar.hasClass('am-offcanvas-bar-flip') ? -1 : 1;
  7109. $bar.addClass('am-offcanvas-bar-' + effect);
  7110. scrollPos = {x: window.scrollX, y: window.scrollY};
  7111. $element.addClass('am-active');
  7112. $body.css({
  7113. width: window.innerWidth,
  7114. height: $win.height()
  7115. }).addClass('am-offcanvas-page');
  7116. if (effect !== 'overlay') {
  7117. $body.css({
  7118. 'margin-left': $bar.outerWidth() * dir
  7119. }).width(); // force redraw
  7120. }
  7121. $html.css('margin-top', scrollPos.y * -1);
  7122. setTimeout(function() {
  7123. $bar.addClass('am-offcanvas-bar-active').width();
  7124. }, 0);
  7125. $element.trigger('open.offcanvas.amui');
  7126. this.active = 1;
  7127. // Close OffCanvas when none content area clicked
  7128. $element.on('click.offcanvas.amui', function(e) {
  7129. var $target = $(e.target);
  7130. if ($target.hasClass('am-offcanvas-bar')) {
  7131. return;
  7132. }
  7133. if ($target.parents('.am-offcanvas-bar').first().length) {
  7134. return;
  7135. }
  7136. // https://developer.mozilla.org/zh-CN/docs/DOM/event.stopImmediatePropagation
  7137. e.stopImmediatePropagation();
  7138. _this.close();
  7139. });
  7140. $html.on('keydown.offcanvas.amui', function(e) {
  7141. (e.keyCode === 27) && _this.close();
  7142. });
  7143. };
  7144. OffCanvas.prototype.close = function(relatedElement) {
  7145. var _this = this;
  7146. var $html = $('html');
  7147. var $body = $('body');
  7148. var $element = this.$element;
  7149. var $bar = $element.find('.am-offcanvas-bar').first();
  7150. if (!$element.length || !this.active || !$element.hasClass('am-active')) {
  7151. return;
  7152. }
  7153. $element.trigger('close.offcanvas.amui');
  7154. function complete() {
  7155. $body
  7156. .removeClass('am-offcanvas-page')
  7157. .css({
  7158. width: '',
  7159. height: '',
  7160. 'margin-left': '',
  7161. 'margin-right': ''
  7162. });
  7163. $element.removeClass('am-active');
  7164. $bar.removeClass('am-offcanvas-bar-active');
  7165. $html.css('margin-top', '');
  7166. window.scrollTo(scrollPos.x, scrollPos.y);
  7167. $element.trigger('closed.offcanvas.amui');
  7168. _this.active = 0;
  7169. }
  7170. if (UI.support.transition) {
  7171. setTimeout(function() {
  7172. $bar.removeClass('am-offcanvas-bar-active');
  7173. }, 0);
  7174. $body.css('margin-left', '').one(UI.support.transition.end, function() {
  7175. complete();
  7176. }).emulateTransitionEnd(this.options.duration);
  7177. } else {
  7178. complete();
  7179. }
  7180. $element.off('click.offcanvas.amui');
  7181. $html.off('.offcanvas.amui');
  7182. };
  7183. OffCanvas.prototype.bindEvents = function() {
  7184. var _this = this;
  7185. $doc.on('click.offcanvas.amui', '[data-am-dismiss="offcanvas"]', function(e) {
  7186. e.preventDefault();
  7187. _this.close();
  7188. });
  7189. $win.on('resize.offcanvas.amui orientationchange.offcanvas.amui',
  7190. function() {
  7191. _this.active && _this.close();
  7192. });
  7193. this.$element.hammer().on('swipeleft swipeleft', function(e) {
  7194. e.preventDefault();
  7195. _this.close();
  7196. });
  7197. return this;
  7198. };
  7199. function Plugin(option, relatedElement) {
  7200. var args = Array.prototype.slice.call(arguments, 1);
  7201. return this.each(function() {
  7202. var $this = $(this);
  7203. var data = $this.data('amui.offcanvas');
  7204. var options = $.extend({}, typeof option == 'object' && option);
  7205. if (!data) {
  7206. $this.data('amui.offcanvas', (data = new OffCanvas(this, options)));
  7207. (!option || typeof option == 'object') && data.open(relatedElement);
  7208. }
  7209. if (typeof option == 'string') {
  7210. data[option] && data[option].apply(data, args);
  7211. }
  7212. });
  7213. }
  7214. $.fn.offCanvas = Plugin;
  7215. // Init code
  7216. $doc.on('click.offcanvas.amui', '[data-am-offcanvas]', function(e) {
  7217. e.preventDefault();
  7218. var $this = $(this);
  7219. var options = UI.utils.parseOptions($this.data('amOffcanvas'));
  7220. var $target = $(options.target ||
  7221. (this.href && this.href.replace(/.*(?=#[^\s]+$)/, '')));
  7222. var option = $target.data('amui.offcanvas') ? 'open' : options;
  7223. Plugin.call($target, option, this);
  7224. });
  7225. module.exports = UI.offcanvas = OffCanvas;
  7226. // TODO: 优化动画效果
  7227. // http://dbushell.github.io/Responsive-Off-Canvas-Menu/step4.html
  7228. /***/ },
  7229. /* 17 */
  7230. /***/ function(module, exports, __webpack_require__) {
  7231. 'use strict';
  7232. var $ = __webpack_require__(1);
  7233. var UI = __webpack_require__(2);
  7234. var requestAnimationFrame = UI.utils.rAF;
  7235. /**
  7236. * @via https://github.com/manuelstofer/pinchzoom/blob/master/src/pinchzoom.js
  7237. * @license the MIT License.
  7238. */
  7239. var definePinchZoom = function($) {
  7240. /**
  7241. * Pinch zoom using jQuery
  7242. * @version 0.0.2
  7243. * @author Manuel Stofer <mst@rtp.ch>
  7244. * @param el
  7245. * @param options
  7246. * @constructor
  7247. */
  7248. var PinchZoom = function(el, options) {
  7249. this.el = $(el);
  7250. this.zoomFactor = 1;
  7251. this.lastScale = 1;
  7252. this.offset = {
  7253. x: 0,
  7254. y: 0
  7255. };
  7256. this.options = $.extend({}, this.defaults, options);
  7257. this.setupMarkup();
  7258. this.bindEvents();
  7259. this.update();
  7260. // default enable.
  7261. this.enable();
  7262. },
  7263. sum = function(a, b) {
  7264. return a + b;
  7265. },
  7266. isCloseTo = function(value, expected) {
  7267. return value > expected - 0.01 && value < expected + 0.01;
  7268. };
  7269. PinchZoom.prototype = {
  7270. defaults: {
  7271. tapZoomFactor: 2,
  7272. zoomOutFactor: 1.3,
  7273. animationDuration: 300,
  7274. maxZoom: 4,
  7275. minZoom: 0.5,
  7276. lockDragAxis: false,
  7277. use2d: true,
  7278. zoomStartEventName: 'pz_zoomstart',
  7279. zoomEndEventName: 'pz_zoomend',
  7280. dragStartEventName: 'pz_dragstart',
  7281. dragEndEventName: 'pz_dragend',
  7282. doubleTapEventName: 'pz_doubletap'
  7283. },
  7284. /**
  7285. * Event handler for 'dragstart'
  7286. * @param event
  7287. */
  7288. handleDragStart: function(event) {
  7289. this.el.trigger(this.options.dragStartEventName);
  7290. this.stopAnimation();
  7291. this.lastDragPosition = false;
  7292. this.hasInteraction = true;
  7293. this.handleDrag(event);
  7294. },
  7295. /**
  7296. * Event handler for 'drag'
  7297. * @param event
  7298. */
  7299. handleDrag: function(event) {
  7300. if (this.zoomFactor > 1.0) {
  7301. var touch = this.getTouches(event)[0];
  7302. this.drag(touch, this.lastDragPosition);
  7303. this.offset = this.sanitizeOffset(this.offset);
  7304. this.lastDragPosition = touch;
  7305. }
  7306. },
  7307. handleDragEnd: function() {
  7308. this.el.trigger(this.options.dragEndEventName);
  7309. this.end();
  7310. },
  7311. /**
  7312. * Event handler for 'zoomstart'
  7313. * @param event
  7314. */
  7315. handleZoomStart: function(event) {
  7316. this.el.trigger(this.options.zoomStartEventName);
  7317. this.stopAnimation();
  7318. this.lastScale = 1;
  7319. this.nthZoom = 0;
  7320. this.lastZoomCenter = false;
  7321. this.hasInteraction = true;
  7322. },
  7323. /**
  7324. * Event handler for 'zoom'
  7325. * @param event
  7326. */
  7327. handleZoom: function(event, newScale) {
  7328. // a relative scale factor is used
  7329. var touchCenter = this.getTouchCenter(this.getTouches(event)),
  7330. scale = newScale / this.lastScale;
  7331. this.lastScale = newScale;
  7332. // the first touch events are thrown away since they are not precise
  7333. this.nthZoom += 1;
  7334. if (this.nthZoom > 3) {
  7335. this.scale(scale, touchCenter);
  7336. this.drag(touchCenter, this.lastZoomCenter);
  7337. }
  7338. this.lastZoomCenter = touchCenter;
  7339. },
  7340. handleZoomEnd: function() {
  7341. this.el.trigger(this.options.zoomEndEventName);
  7342. this.end();
  7343. },
  7344. /**
  7345. * Event handler for 'doubletap'
  7346. * @param event
  7347. */
  7348. handleDoubleTap: function(event) {
  7349. var center = this.getTouches(event)[0],
  7350. zoomFactor = this.zoomFactor > 1 ? 1 : this.options.tapZoomFactor,
  7351. startZoomFactor = this.zoomFactor,
  7352. updateProgress = (function(progress) {
  7353. this.scaleTo(startZoomFactor + progress * (zoomFactor - startZoomFactor), center);
  7354. }).bind(this);
  7355. if (this.hasInteraction) {
  7356. return;
  7357. }
  7358. if (startZoomFactor > zoomFactor) {
  7359. center = this.getCurrentZoomCenter();
  7360. }
  7361. this.animate(this.options.animationDuration, updateProgress, this.swing);
  7362. this.el.trigger(this.options.doubleTapEventName);
  7363. },
  7364. /**
  7365. * Max / min values for the offset
  7366. * @param offset
  7367. * @return {Object} the sanitized offset
  7368. */
  7369. sanitizeOffset: function(offset) {
  7370. var maxX = (this.zoomFactor - 1) * this.getContainerX(),
  7371. maxY = (this.zoomFactor - 1) * this.getContainerY(),
  7372. maxOffsetX = Math.max(maxX, 0),
  7373. maxOffsetY = Math.max(maxY, 0),
  7374. minOffsetX = Math.min(maxX, 0),
  7375. minOffsetY = Math.min(maxY, 0);
  7376. return {
  7377. x: Math.min(Math.max(offset.x, minOffsetX), maxOffsetX),
  7378. y: Math.min(Math.max(offset.y, minOffsetY), maxOffsetY)
  7379. };
  7380. },
  7381. /**
  7382. * Scale to a specific zoom factor (not relative)
  7383. * @param zoomFactor
  7384. * @param center
  7385. */
  7386. scaleTo: function(zoomFactor, center) {
  7387. this.scale(zoomFactor / this.zoomFactor, center);
  7388. },
  7389. /**
  7390. * Scales the element from specified center
  7391. * @param scale
  7392. * @param center
  7393. */
  7394. scale: function(scale, center) {
  7395. scale = this.scaleZoomFactor(scale);
  7396. this.addOffset({
  7397. x: (scale - 1) * (center.x + this.offset.x),
  7398. y: (scale - 1) * (center.y + this.offset.y)
  7399. });
  7400. },
  7401. /**
  7402. * Scales the zoom factor relative to current state
  7403. * @param scale
  7404. * @return the actual scale (can differ because of max min zoom factor)
  7405. */
  7406. scaleZoomFactor: function(scale) {
  7407. var originalZoomFactor = this.zoomFactor;
  7408. this.zoomFactor *= scale;
  7409. this.zoomFactor = Math.min(this.options.maxZoom, Math.max(this.zoomFactor, this.options.minZoom));
  7410. return this.zoomFactor / originalZoomFactor;
  7411. },
  7412. /**
  7413. * Drags the element
  7414. * @param center
  7415. * @param lastCenter
  7416. */
  7417. drag: function(center, lastCenter) {
  7418. if (lastCenter) {
  7419. if (this.options.lockDragAxis) {
  7420. // lock scroll to position that was changed the most
  7421. if (Math.abs(center.x - lastCenter.x) > Math.abs(center.y - lastCenter.y)) {
  7422. this.addOffset({
  7423. x: -(center.x - lastCenter.x),
  7424. y: 0
  7425. });
  7426. }
  7427. else {
  7428. this.addOffset({
  7429. y: -(center.y - lastCenter.y),
  7430. x: 0
  7431. });
  7432. }
  7433. }
  7434. else {
  7435. this.addOffset({
  7436. y: -(center.y - lastCenter.y),
  7437. x: -(center.x - lastCenter.x)
  7438. });
  7439. }
  7440. }
  7441. },
  7442. /**
  7443. * Calculates the touch center of multiple touches
  7444. * @param touches
  7445. * @return {Object}
  7446. */
  7447. getTouchCenter: function(touches) {
  7448. return this.getVectorAvg(touches);
  7449. },
  7450. /**
  7451. * Calculates the average of multiple vectors (x, y values)
  7452. */
  7453. getVectorAvg: function(vectors) {
  7454. return {
  7455. x: vectors.map(function(v) {
  7456. return v.x;
  7457. }).reduce(sum) / vectors.length,
  7458. y: vectors.map(function(v) {
  7459. return v.y;
  7460. }).reduce(sum) / vectors.length
  7461. };
  7462. },
  7463. /**
  7464. * Adds an offset
  7465. * @param offset the offset to add
  7466. * @return return true when the offset change was accepted
  7467. */
  7468. addOffset: function(offset) {
  7469. this.offset = {
  7470. x: this.offset.x + offset.x,
  7471. y: this.offset.y + offset.y
  7472. };
  7473. },
  7474. sanitize: function() {
  7475. if (this.zoomFactor < this.options.zoomOutFactor) {
  7476. this.zoomOutAnimation();
  7477. } else if (this.isInsaneOffset(this.offset)) {
  7478. this.sanitizeOffsetAnimation();
  7479. }
  7480. },
  7481. /**
  7482. * Checks if the offset is ok with the current zoom factor
  7483. * @param offset
  7484. * @return {Boolean}
  7485. */
  7486. isInsaneOffset: function(offset) {
  7487. var sanitizedOffset = this.sanitizeOffset(offset);
  7488. return sanitizedOffset.x !== offset.x ||
  7489. sanitizedOffset.y !== offset.y;
  7490. },
  7491. /**
  7492. * Creates an animation moving to a sane offset
  7493. */
  7494. sanitizeOffsetAnimation: function() {
  7495. var targetOffset = this.sanitizeOffset(this.offset),
  7496. startOffset = {
  7497. x: this.offset.x,
  7498. y: this.offset.y
  7499. },
  7500. updateProgress = (function(progress) {
  7501. this.offset.x = startOffset.x + progress * (targetOffset.x - startOffset.x);
  7502. this.offset.y = startOffset.y + progress * (targetOffset.y - startOffset.y);
  7503. this.update();
  7504. }).bind(this);
  7505. this.animate(
  7506. this.options.animationDuration,
  7507. updateProgress,
  7508. this.swing
  7509. );
  7510. },
  7511. /**
  7512. * Zooms back to the original position,
  7513. * (no offset and zoom factor 1)
  7514. */
  7515. zoomOutAnimation: function() {
  7516. var startZoomFactor = this.zoomFactor,
  7517. zoomFactor = 1,
  7518. center = this.getCurrentZoomCenter(),
  7519. updateProgress = (function(progress) {
  7520. this.scaleTo(startZoomFactor + progress * (zoomFactor - startZoomFactor), center);
  7521. }).bind(this);
  7522. this.animate(
  7523. this.options.animationDuration,
  7524. updateProgress,
  7525. this.swing
  7526. );
  7527. },
  7528. /**
  7529. * Updates the aspect ratio
  7530. */
  7531. updateAspectRatio: function() {
  7532. this.setContainerY(this.getContainerX() / this.getAspectRatio());
  7533. },
  7534. /**
  7535. * Calculates the initial zoom factor (for the element to fit into the container)
  7536. * @return the initial zoom factor
  7537. */
  7538. getInitialZoomFactor: function() {
  7539. // use .offsetWidth instead of width()
  7540. // because jQuery-width() return the original width but Zepto-width() will calculate width with transform.
  7541. // the same as .height()
  7542. return this.container[0].offsetWidth / this.el[0].offsetWidth;
  7543. },
  7544. /**
  7545. * Calculates the aspect ratio of the element
  7546. * @return the aspect ratio
  7547. */
  7548. getAspectRatio: function() {
  7549. return this.el[0].offsetWidth / this.el[0].offsetHeight;
  7550. },
  7551. /**
  7552. * Calculates the virtual zoom center for the current offset and zoom factor
  7553. * (used for reverse zoom)
  7554. * @return {Object} the current zoom center
  7555. */
  7556. getCurrentZoomCenter: function() {
  7557. // uses following formula to calculate the zoom center x value
  7558. // offset_left / offset_right = zoomcenter_x / (container_x - zoomcenter_x)
  7559. var length = this.container[0].offsetWidth * this.zoomFactor,
  7560. offsetLeft = this.offset.x,
  7561. offsetRight = length - offsetLeft - this.container[0].offsetWidth,
  7562. widthOffsetRatio = offsetLeft / offsetRight,
  7563. centerX = widthOffsetRatio * this.container[0].offsetWidth / (widthOffsetRatio + 1),
  7564. // the same for the zoomcenter y
  7565. height = this.container[0].offsetHeight * this.zoomFactor,
  7566. offsetTop = this.offset.y,
  7567. offsetBottom = height - offsetTop - this.container[0].offsetHeight,
  7568. heightOffsetRatio = offsetTop / offsetBottom,
  7569. centerY = heightOffsetRatio * this.container[0].offsetHeight / (heightOffsetRatio + 1);
  7570. // prevents division by zero
  7571. if (offsetRight === 0) {
  7572. centerX = this.container[0].offsetWidth;
  7573. }
  7574. if (offsetBottom === 0) {
  7575. centerY = this.container[0].offsetHeight;
  7576. }
  7577. return {
  7578. x: centerX,
  7579. y: centerY
  7580. };
  7581. },
  7582. canDrag: function() {
  7583. return !isCloseTo(this.zoomFactor, 1);
  7584. },
  7585. /**
  7586. * Returns the touches of an event relative to the container offset
  7587. * @param event
  7588. * @return array touches
  7589. */
  7590. getTouches: function(event) {
  7591. var position = this.container.offset();
  7592. return Array.prototype.slice.call(event.touches).map(function(touch) {
  7593. return {
  7594. x: touch.pageX - position.left,
  7595. y: touch.pageY - position.top
  7596. };
  7597. });
  7598. },
  7599. /**
  7600. * Animation loop
  7601. * does not support simultaneous animations
  7602. * @param duration
  7603. * @param framefn
  7604. * @param timefn
  7605. * @param callback
  7606. */
  7607. animate: function(duration, framefn, timefn, callback) {
  7608. var startTime = new Date().getTime(),
  7609. renderFrame = (function() {
  7610. if (!this.inAnimation) {
  7611. return;
  7612. }
  7613. var frameTime = new Date().getTime() - startTime,
  7614. progress = frameTime / duration;
  7615. if (frameTime >= duration) {
  7616. framefn(1);
  7617. if (callback) {
  7618. callback();
  7619. }
  7620. this.update();
  7621. this.stopAnimation();
  7622. this.update();
  7623. } else {
  7624. if (timefn) {
  7625. progress = timefn(progress);
  7626. }
  7627. framefn(progress);
  7628. this.update();
  7629. requestAnimationFrame(renderFrame);
  7630. }
  7631. }).bind(this);
  7632. this.inAnimation = true;
  7633. requestAnimationFrame(renderFrame);
  7634. },
  7635. /**
  7636. * Stops the animation
  7637. */
  7638. stopAnimation: function() {
  7639. this.inAnimation = false;
  7640. },
  7641. /**
  7642. * Swing timing function for animations
  7643. * @param p
  7644. * @return {Number}
  7645. */
  7646. swing: function(p) {
  7647. return -Math.cos(p * Math.PI) / 2 + 0.5;
  7648. },
  7649. getContainerX: function() {
  7650. return this.container[0].offsetWidth;
  7651. },
  7652. getContainerY: function() {
  7653. return this.container[0].offsetHeight;
  7654. },
  7655. setContainerY: function(y) {
  7656. return this.container.height(y);
  7657. },
  7658. /**
  7659. * Creates the expected html structure
  7660. */
  7661. setupMarkup: function() {
  7662. this.container = $('<div class="pinch-zoom-container"></div>');
  7663. this.el.before(this.container);
  7664. this.container.append(this.el);
  7665. this.container.css({
  7666. 'overflow': 'hidden',
  7667. 'position': 'relative'
  7668. });
  7669. // Zepto doesn't recognize `webkitTransform..` style
  7670. this.el.css({
  7671. '-webkit-transform-origin': '0% 0%',
  7672. '-moz-transform-origin': '0% 0%',
  7673. '-ms-transform-origin': '0% 0%',
  7674. '-o-transform-origin': '0% 0%',
  7675. 'transform-origin': '0% 0%',
  7676. 'position': 'absolute'
  7677. });
  7678. },
  7679. end: function() {
  7680. this.hasInteraction = false;
  7681. this.sanitize();
  7682. this.update();
  7683. },
  7684. /**
  7685. * Binds all required event listeners
  7686. */
  7687. bindEvents: function() {
  7688. detectGestures(this.container.get(0), this);
  7689. // Zepto and jQuery both know about `on`
  7690. $(window).on('resize', this.update.bind(this));
  7691. $(this.el).find('img').on('load', this.update.bind(this));
  7692. },
  7693. /**
  7694. * Updates the css values according to the current zoom factor and offset
  7695. */
  7696. update: function() {
  7697. if (this.updatePlaned) {
  7698. return;
  7699. }
  7700. this.updatePlaned = true;
  7701. setTimeout((function() {
  7702. this.updatePlaned = false;
  7703. this.updateAspectRatio();
  7704. var zoomFactor = this.getInitialZoomFactor() * this.zoomFactor,
  7705. offsetX = -this.offset.x / zoomFactor,
  7706. offsetY = -this.offset.y / zoomFactor,
  7707. transform3d = 'scale3d(' + zoomFactor + ', ' + zoomFactor + ',1) ' +
  7708. 'translate3d(' + offsetX + 'px,' + offsetY + 'px,0px)',
  7709. transform2d = 'scale(' + zoomFactor + ', ' + zoomFactor + ') ' +
  7710. 'translate(' + offsetX + 'px,' + offsetY + 'px)',
  7711. removeClone = (function() {
  7712. if (this.clone) {
  7713. this.clone.remove();
  7714. delete this.clone;
  7715. }
  7716. }).bind(this);
  7717. // Scale 3d and translate3d are faster (at least on ios)
  7718. // but they also reduce the quality.
  7719. // PinchZoom uses the 3d transformations during interactions
  7720. // after interactions it falls back to 2d transformations
  7721. if (!this.options.use2d || this.hasInteraction || this.inAnimation) {
  7722. this.is3d = true;
  7723. removeClone();
  7724. this.el.css({
  7725. '-webkit-transform': transform3d,
  7726. '-o-transform': transform2d,
  7727. '-ms-transform': transform2d,
  7728. '-moz-transform': transform2d,
  7729. 'transform': transform3d
  7730. });
  7731. } else {
  7732. // When changing from 3d to 2d transform webkit has some glitches.
  7733. // To avoid this, a copy of the 3d transformed element is displayed in the
  7734. // foreground while the element is converted from 3d to 2d transform
  7735. if (this.is3d) {
  7736. this.clone = this.el.clone();
  7737. this.clone.css('pointer-events', 'none');
  7738. this.clone.appendTo(this.container);
  7739. setTimeout(removeClone, 200);
  7740. }
  7741. this.el.css({
  7742. '-webkit-transform': transform2d,
  7743. '-o-transform': transform2d,
  7744. '-ms-transform': transform2d,
  7745. '-moz-transform': transform2d,
  7746. 'transform': transform2d
  7747. });
  7748. this.is3d = false;
  7749. }
  7750. }).bind(this), 0);
  7751. },
  7752. /**
  7753. * Enables event handling for gestures
  7754. */
  7755. enable: function() {
  7756. this.enabled = true;
  7757. },
  7758. /**
  7759. * Disables event handling for gestures
  7760. */
  7761. disable: function() {
  7762. this.enabled = false;
  7763. }
  7764. };
  7765. var detectGestures = function(el, target) {
  7766. var interaction = null,
  7767. fingers = 0,
  7768. lastTouchStart = null,
  7769. startTouches = null,
  7770. setInteraction = function(newInteraction, event) {
  7771. if (interaction !== newInteraction) {
  7772. if (interaction && !newInteraction) {
  7773. switch (interaction) {
  7774. case "zoom":
  7775. target.handleZoomEnd(event);
  7776. break;
  7777. case 'drag':
  7778. target.handleDragEnd(event);
  7779. break;
  7780. }
  7781. }
  7782. switch (newInteraction) {
  7783. case 'zoom':
  7784. target.handleZoomStart(event);
  7785. break;
  7786. case 'drag':
  7787. target.handleDragStart(event);
  7788. break;
  7789. }
  7790. }
  7791. interaction = newInteraction;
  7792. },
  7793. updateInteraction = function(event) {
  7794. if (fingers === 2) {
  7795. setInteraction('zoom');
  7796. } else if (fingers === 1 && target.canDrag()) {
  7797. setInteraction('drag', event);
  7798. } else {
  7799. setInteraction(null, event);
  7800. }
  7801. },
  7802. targetTouches = function(touches) {
  7803. return Array.prototype.slice.call(touches).map(function(touch) {
  7804. return {
  7805. x: touch.pageX,
  7806. y: touch.pageY
  7807. };
  7808. });
  7809. },
  7810. getDistance = function(a, b) {
  7811. var x, y;
  7812. x = a.x - b.x;
  7813. y = a.y - b.y;
  7814. return Math.sqrt(x * x + y * y);
  7815. },
  7816. calculateScale = function(startTouches, endTouches) {
  7817. var startDistance = getDistance(startTouches[0], startTouches[1]),
  7818. endDistance = getDistance(endTouches[0], endTouches[1]);
  7819. return endDistance / startDistance;
  7820. },
  7821. cancelEvent = function(event) {
  7822. event.stopPropagation();
  7823. event.preventDefault();
  7824. },
  7825. detectDoubleTap = function(event) {
  7826. var time = (new Date()).getTime();
  7827. if (fingers > 1) {
  7828. lastTouchStart = null;
  7829. }
  7830. if (time - lastTouchStart < 300) {
  7831. cancelEvent(event);
  7832. target.handleDoubleTap(event);
  7833. switch (interaction) {
  7834. case 'zoom':
  7835. target.handleZoomEnd(event);
  7836. break;
  7837. case 'drag':
  7838. target.handleDragEnd(event);
  7839. break;
  7840. }
  7841. }
  7842. if (fingers === 1) {
  7843. lastTouchStart = time;
  7844. }
  7845. },
  7846. firstMove = true;
  7847. el.addEventListener('touchstart', function(event) {
  7848. if (target.enabled) {
  7849. firstMove = true;
  7850. fingers = event.touches.length;
  7851. detectDoubleTap(event);
  7852. }
  7853. });
  7854. el.addEventListener('touchmove', function(event) {
  7855. if (target.enabled) {
  7856. if (firstMove) {
  7857. updateInteraction(event);
  7858. if (interaction) {
  7859. cancelEvent(event);
  7860. }
  7861. startTouches = targetTouches(event.touches);
  7862. } else {
  7863. switch (interaction) {
  7864. case 'zoom':
  7865. target.handleZoom(event, calculateScale(startTouches, targetTouches(event.touches)));
  7866. break;
  7867. case 'drag':
  7868. target.handleDrag(event);
  7869. break;
  7870. }
  7871. if (interaction) {
  7872. cancelEvent(event);
  7873. target.update();
  7874. }
  7875. }
  7876. firstMove = false;
  7877. }
  7878. });
  7879. el.addEventListener('touchend', function(event) {
  7880. if (target.enabled) {
  7881. fingers = event.touches.length;
  7882. updateInteraction(event);
  7883. }
  7884. });
  7885. };
  7886. return PinchZoom;
  7887. };
  7888. module.exports = UI.pichzoom = definePinchZoom($);
  7889. /***/ },
  7890. /* 18 */
  7891. /***/ function(module, exports, __webpack_require__) {
  7892. 'use strict';
  7893. var $ = __webpack_require__(1);
  7894. var UI = __webpack_require__(2);
  7895. var $w = $(window);
  7896. /**
  7897. * @reference https://github.com/nolimits4web/Framework7/blob/master/src/js/modals.js
  7898. * @license https://github.com/nolimits4web/Framework7/blob/master/LICENSE
  7899. */
  7900. var Popover = function(element, options) {
  7901. this.options = $.extend({}, Popover.DEFAULTS, options);
  7902. this.$element = $(element);
  7903. this.active = null;
  7904. this.$popover = (this.options.target && $(this.options.target)) || null;
  7905. this.init();
  7906. this._bindEvents();
  7907. };
  7908. Popover.DEFAULTS = {
  7909. theme: null,
  7910. trigger: 'click',
  7911. content: '',
  7912. open: false,
  7913. target: null,
  7914. tpl: '<div class="am-popover">' +
  7915. '<div class="am-popover-inner"></div>' +
  7916. '<div class="am-popover-caret"></div></div>'
  7917. };
  7918. Popover.prototype.init = function() {
  7919. var _this = this;
  7920. var $element = this.$element;
  7921. var $popover;
  7922. if (!this.options.target) {
  7923. this.$popover = this.getPopover();
  7924. this.setContent();
  7925. }
  7926. $popover = this.$popover;
  7927. $popover.appendTo($('body'));
  7928. this.sizePopover();
  7929. function sizePopover() {
  7930. _this.sizePopover();
  7931. }
  7932. // TODO: 监听页面内容变化,重新调整位置
  7933. $element.on('open.popover.amui', function() {
  7934. $(window).on('resize.popover.amui', UI.utils.debounce(sizePopover, 50));
  7935. });
  7936. $element.on('close.popover.amui', function() {
  7937. $(window).off('resize.popover.amui', sizePopover);
  7938. });
  7939. this.options.open && this.open();
  7940. };
  7941. Popover.prototype.sizePopover = function sizePopover() {
  7942. var $element = this.$element;
  7943. var $popover = this.$popover;
  7944. if (!$popover || !$popover.length) {
  7945. return;
  7946. }
  7947. var popWidth = $popover.outerWidth();
  7948. var popHeight = $popover.outerHeight();
  7949. var $popCaret = $popover.find('.am-popover-caret');
  7950. var popCaretSize = ($popCaret.outerWidth() / 2) || 8;
  7951. // 取不到 $popCaret.outerHeight() 的值,所以直接加 8
  7952. var popTotalHeight = popHeight + 8; // $popCaret.outerHeight();
  7953. var triggerWidth = $element.outerWidth();
  7954. var triggerHeight = $element.outerHeight();
  7955. var triggerOffset = $element.offset();
  7956. var triggerRect = $element[0].getBoundingClientRect();
  7957. var winHeight = $w.height();
  7958. var winWidth = $w.width();
  7959. var popTop = 0;
  7960. var popLeft = 0;
  7961. var diff = 0;
  7962. var spacing = 2;
  7963. var popPosition = 'top';
  7964. $popover.css({left: '', top: ''}).removeClass('am-popover-left ' +
  7965. 'am-popover-right am-popover-top am-popover-bottom');
  7966. // $popCaret.css({left: '', top: ''});
  7967. if (popTotalHeight - spacing < triggerRect.top + spacing) {
  7968. // Popover on the top of trigger
  7969. popTop = triggerOffset.top - popTotalHeight - spacing;
  7970. } else if (popTotalHeight <
  7971. winHeight - triggerRect.top - triggerRect.height) {
  7972. // On bottom
  7973. popPosition = 'bottom';
  7974. popTop = triggerOffset.top + triggerHeight + popCaretSize + spacing;
  7975. } else { // On middle
  7976. popPosition = 'middle';
  7977. popTop = triggerHeight / 2 + triggerOffset.top - popHeight / 2;
  7978. }
  7979. // Horizontal Position
  7980. if (popPosition === 'top' || popPosition === 'bottom') {
  7981. popLeft = triggerWidth / 2 + triggerOffset.left - popWidth / 2;
  7982. diff = popLeft;
  7983. if (popLeft < 5) {
  7984. popLeft = 5;
  7985. }
  7986. if (popLeft + popWidth > winWidth) {
  7987. popLeft = (winWidth - popWidth - 20);
  7988. // console.log('left %d, win %d, popw %d', popLeft, winWidth, popWidth);
  7989. }
  7990. if (popPosition === 'top') {
  7991. // This is the Popover position, NOT caret position
  7992. // Popover on the Top of trigger, caret on the bottom of Popover
  7993. $popover.addClass('am-popover-top');
  7994. }
  7995. if (popPosition === 'bottom') {
  7996. $popover.addClass('am-popover-bottom');
  7997. }
  7998. diff = diff - popLeft;
  7999. // $popCaret.css({left: (popWidth / 2 - popCaretSize + diff) + 'px'});
  8000. } else if (popPosition === 'middle') {
  8001. popLeft = triggerOffset.left - popWidth - popCaretSize;
  8002. $popover.addClass('am-popover-left');
  8003. if (popLeft < 5) {
  8004. popLeft = triggerOffset.left + triggerWidth + popCaretSize;
  8005. $popover.removeClass('am-popover-left').addClass('am-popover-right');
  8006. }
  8007. if (popLeft + popWidth > winWidth) {
  8008. popLeft = winWidth - popWidth - 5;
  8009. $popover.removeClass('am-popover-left').addClass('am-popover-right');
  8010. }
  8011. // $popCaret.css({top: (popHeight / 2 - popCaretSize / 2) + 'px'});
  8012. }
  8013. // Apply position style
  8014. $popover.css({top: popTop + 'px', left: popLeft + 'px'});
  8015. };
  8016. Popover.prototype.toggle = function() {
  8017. return this[this.active ? 'close' : 'open']();
  8018. };
  8019. Popover.prototype.open = function() {
  8020. var $popover = this.$popover;
  8021. this.$element.trigger('open.popover.amui');
  8022. this.sizePopover();
  8023. $popover.show().addClass('am-active');
  8024. this.active = true;
  8025. };
  8026. Popover.prototype.close = function() {
  8027. var $popover = this.$popover;
  8028. this.$element.trigger('close.popover.amui');
  8029. $popover
  8030. .removeClass('am-active')
  8031. .trigger('closed.popover.amui')
  8032. .hide();
  8033. this.active = false;
  8034. };
  8035. Popover.prototype.getPopover = function() {
  8036. var uid = UI.utils.generateGUID('am-popover');
  8037. var theme = [];
  8038. if (this.options.theme) {
  8039. $.each(this.options.theme.split(' '), function(i, item) {
  8040. theme.push('am-popover-' + $.trim(item));
  8041. });
  8042. }
  8043. return $(this.options.tpl).attr('id', uid).addClass(theme.join(' '));
  8044. };
  8045. Popover.prototype.setContent = function(content) {
  8046. content = content || this.options.content;
  8047. this.$popover && this.$popover.find('.am-popover-inner')
  8048. .empty().html(content);
  8049. };
  8050. Popover.prototype._bindEvents = function() {
  8051. var eventNS = 'popover.amui';
  8052. var triggers = this.options.trigger.split(' ');
  8053. for (var i = triggers.length; i--;) {
  8054. var trigger = triggers[i];
  8055. if (trigger === 'click') {
  8056. this.$element.on('click.' + eventNS, $.proxy(this.toggle, this));
  8057. } else { // hover or focus
  8058. var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin';
  8059. var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout';
  8060. this.$element.on(eventIn + '.' + eventNS, $.proxy(this.open, this));
  8061. this.$element.on(eventOut + '.' + eventNS, $.proxy(this.close, this));
  8062. }
  8063. }
  8064. };
  8065. Popover.prototype.destroy = function() {
  8066. this.$element.off('.popover.amui').removeData('amui.popover');
  8067. this.$popover.remove();
  8068. };
  8069. UI.plugin('popover', Popover);
  8070. // Init code
  8071. UI.ready(function(context) {
  8072. $('[data-am-popover]', context).popover();
  8073. });
  8074. module.exports = Popover;
  8075. // TODO: 允许用户定义位置
  8076. /***/ },
  8077. /* 19 */
  8078. /***/ function(module, exports, __webpack_require__) {
  8079. 'use strict';
  8080. var UI = __webpack_require__(2);
  8081. var Progress = (function() {
  8082. /**
  8083. * NProgress (c) 2013, Rico Sta. Cruz
  8084. * @via http://ricostacruz.com/nprogress
  8085. */
  8086. var NProgress = {};
  8087. NProgress.version = '0.2.0';
  8088. var Settings = NProgress.settings = {
  8089. minimum: 0.08,
  8090. easing: 'ease',
  8091. positionUsing: '',
  8092. speed: 200,
  8093. trickle: true,
  8094. trickleRate: 0.02,
  8095. trickleSpeed: 800,
  8096. showSpinner: true,
  8097. parent: 'body',
  8098. barSelector: '[role="nprogress-bar"]',
  8099. spinnerSelector: '[role="nprogress-spinner"]',
  8100. template: '<div class="nprogress-bar" role="nprogress-bar">' +
  8101. '<div class="nprogress-peg"></div></div>' +
  8102. '<div class="nprogress-spinner" role="nprogress-spinner">' +
  8103. '<div class="nprogress-spinner-icon"></div></div>'
  8104. };
  8105. /**
  8106. * Updates configuration.
  8107. *
  8108. * NProgress.configure({
  8109. * minimum: 0.1
  8110. * });
  8111. */
  8112. NProgress.configure = function(options) {
  8113. var key, value;
  8114. for (key in options) {
  8115. value = options[key];
  8116. if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value;
  8117. }
  8118. return this;
  8119. };
  8120. /**
  8121. * Last number.
  8122. */
  8123. NProgress.status = null;
  8124. /**
  8125. * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.
  8126. *
  8127. * NProgress.set(0.4);
  8128. * NProgress.set(1.0);
  8129. */
  8130. NProgress.set = function(n) {
  8131. var started = NProgress.isStarted();
  8132. n = clamp(n, Settings.minimum, 1);
  8133. NProgress.status = (n === 1 ? null : n);
  8134. var progress = NProgress.render(!started),
  8135. bar = progress.querySelector(Settings.barSelector),
  8136. speed = Settings.speed,
  8137. ease = Settings.easing;
  8138. progress.offsetWidth; /* Repaint */
  8139. queue(function(next) {
  8140. // Set positionUsing if it hasn't already been set
  8141. if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS();
  8142. // Add transition
  8143. css(bar, barPositionCSS(n, speed, ease));
  8144. if (n === 1) {
  8145. // Fade out
  8146. css(progress, {
  8147. transition: 'none',
  8148. opacity: 1
  8149. });
  8150. progress.offsetWidth; /* Repaint */
  8151. setTimeout(function() {
  8152. css(progress, {
  8153. transition: 'all ' + speed + 'ms linear',
  8154. opacity: 0
  8155. });
  8156. setTimeout(function() {
  8157. NProgress.remove();
  8158. next();
  8159. }, speed);
  8160. }, speed);
  8161. } else {
  8162. setTimeout(next, speed);
  8163. }
  8164. });
  8165. return this;
  8166. };
  8167. NProgress.isStarted = function() {
  8168. return typeof NProgress.status === 'number';
  8169. };
  8170. /**
  8171. * Shows the progress bar.
  8172. * This is the same as setting the status to 0%, except that it doesn't go backwards.
  8173. *
  8174. * NProgress.start();
  8175. *
  8176. */
  8177. NProgress.start = function() {
  8178. if (!NProgress.status) NProgress.set(0);
  8179. var work = function() {
  8180. setTimeout(function() {
  8181. if (!NProgress.status) return;
  8182. NProgress.trickle();
  8183. work();
  8184. }, Settings.trickleSpeed);
  8185. };
  8186. if (Settings.trickle) work();
  8187. return this;
  8188. };
  8189. /**
  8190. * Hides the progress bar.
  8191. * This is the *sort of* the same as setting the status to 100%, with the
  8192. * difference being `done()` makes some placebo effect of some realistic motion.
  8193. *
  8194. * NProgress.done();
  8195. *
  8196. * If `true` is passed, it will show the progress bar even if its hidden.
  8197. *
  8198. * NProgress.done(true);
  8199. */
  8200. NProgress.done = function(force) {
  8201. if (!force && !NProgress.status) return this;
  8202. return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);
  8203. };
  8204. /**
  8205. * Increments by a random amount.
  8206. */
  8207. NProgress.inc = function(amount) {
  8208. var n = NProgress.status;
  8209. if (!n) {
  8210. return NProgress.start();
  8211. } else {
  8212. if (typeof amount !== 'number') {
  8213. amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);
  8214. }
  8215. n = clamp(n + amount, 0, 0.994);
  8216. return NProgress.set(n);
  8217. }
  8218. };
  8219. NProgress.trickle = function() {
  8220. return NProgress.inc(Math.random() * Settings.trickleRate);
  8221. };
  8222. /**
  8223. * Waits for all supplied jQuery promises and
  8224. * increases the progress as the promises resolve.
  8225. *
  8226. * @param $promise jQUery Promise
  8227. */
  8228. (function() {
  8229. var initial = 0, current = 0;
  8230. NProgress.promise = function($promise) {
  8231. if (!$promise || $promise.state() === "resolved") {
  8232. return this;
  8233. }
  8234. if (current === 0) {
  8235. NProgress.start();
  8236. }
  8237. initial++;
  8238. current++;
  8239. $promise.always(function() {
  8240. current--;
  8241. if (current === 0) {
  8242. initial = 0;
  8243. NProgress.done();
  8244. } else {
  8245. NProgress.set((initial - current) / initial);
  8246. }
  8247. });
  8248. return this;
  8249. };
  8250. })();
  8251. /**
  8252. * (Internal) renders the progress bar markup based on the `template`
  8253. * setting.
  8254. */
  8255. NProgress.render = function(fromStart) {
  8256. if (NProgress.isRendered()) return document.getElementById('nprogress');
  8257. addClass(document.documentElement, 'nprogress-busy');
  8258. var progress = document.createElement('div');
  8259. progress.id = 'nprogress';
  8260. progress.innerHTML = Settings.template;
  8261. var bar = progress.querySelector(Settings.barSelector),
  8262. perc = fromStart ? '-100' : toBarPerc(NProgress.status || 0),
  8263. parent = document.querySelector(Settings.parent),
  8264. spinner;
  8265. css(bar, {
  8266. transition: 'all 0 linear',
  8267. transform: 'translate3d(' + perc + '%,0,0)'
  8268. });
  8269. if (!Settings.showSpinner) {
  8270. spinner = progress.querySelector(Settings.spinnerSelector);
  8271. spinner && removeElement(spinner);
  8272. }
  8273. if (parent != document.body) {
  8274. addClass(parent, 'nprogress-custom-parent');
  8275. }
  8276. parent.appendChild(progress);
  8277. return progress;
  8278. };
  8279. /**
  8280. * Removes the element. Opposite of render().
  8281. */
  8282. NProgress.remove = function() {
  8283. removeClass(document.documentElement, 'nprogress-busy');
  8284. removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent');
  8285. var progress = document.getElementById('nprogress');
  8286. progress && removeElement(progress);
  8287. };
  8288. /**
  8289. * Checks if the progress bar is rendered.
  8290. */
  8291. NProgress.isRendered = function() {
  8292. return !!document.getElementById('nprogress');
  8293. };
  8294. /**
  8295. * Determine which positioning CSS rule to use.
  8296. */
  8297. NProgress.getPositioningCSS = function() {
  8298. // Sniff on document.body.style
  8299. var bodyStyle = document.body.style;
  8300. // Sniff prefixes
  8301. var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :
  8302. ('MozTransform' in bodyStyle) ? 'Moz' :
  8303. ('msTransform' in bodyStyle) ? 'ms' :
  8304. ('OTransform' in bodyStyle) ? 'O' : '';
  8305. if (vendorPrefix + 'Perspective' in bodyStyle) {
  8306. // Modern browsers with 3D support, e.g. Webkit, IE10
  8307. return 'translate3d';
  8308. } else if (vendorPrefix + 'Transform' in bodyStyle) {
  8309. // Browsers without 3D support, e.g. IE9
  8310. return 'translate';
  8311. } else {
  8312. // Browsers without translate() support, e.g. IE7-8
  8313. return 'margin';
  8314. }
  8315. };
  8316. /**
  8317. * Helpers
  8318. */
  8319. function clamp(n, min, max) {
  8320. if (n < min) return min;
  8321. if (n > max) return max;
  8322. return n;
  8323. }
  8324. /**
  8325. * (Internal) converts a percentage (`0..1`) to a bar translateX
  8326. * percentage (`-100%..0%`).
  8327. */
  8328. function toBarPerc(n) {
  8329. return (-1 + n) * 100;
  8330. }
  8331. /**
  8332. * (Internal) returns the correct CSS for changing the bar's
  8333. * position given an n percentage, and speed and ease from Settings
  8334. */
  8335. function barPositionCSS(n, speed, ease) {
  8336. var barCSS;
  8337. if (Settings.positionUsing === 'translate3d') {
  8338. barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };
  8339. } else if (Settings.positionUsing === 'translate') {
  8340. barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };
  8341. } else {
  8342. barCSS = { 'margin-left': toBarPerc(n)+'%' };
  8343. }
  8344. barCSS.transition = 'all '+speed+'ms '+ease;
  8345. return barCSS;
  8346. }
  8347. /**
  8348. * (Internal) Queues a function to be executed.
  8349. */
  8350. var queue = (function() {
  8351. var pending = [];
  8352. function next() {
  8353. var fn = pending.shift();
  8354. if (fn) {
  8355. fn(next);
  8356. }
  8357. }
  8358. return function(fn) {
  8359. pending.push(fn);
  8360. if (pending.length == 1) next();
  8361. };
  8362. })();
  8363. /**
  8364. * (Internal) Applies css properties to an element, similar to the jQuery
  8365. * css method.
  8366. *
  8367. * While this helper does assist with vendor prefixed property names, it
  8368. * does not perform any manipulation of values prior to setting styles.
  8369. */
  8370. var css = (function() {
  8371. var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ],
  8372. cssProps = {};
  8373. function camelCase(string) {
  8374. return string.replace(/^-ms-/, 'ms-').replace(/-([\da-z])/gi, function(match, letter) {
  8375. return letter.toUpperCase();
  8376. });
  8377. }
  8378. function getVendorProp(name) {
  8379. var style = document.body.style;
  8380. if (name in style) return name;
  8381. var i = cssPrefixes.length,
  8382. capName = name.charAt(0).toUpperCase() + name.slice(1),
  8383. vendorName;
  8384. while (i--) {
  8385. vendorName = cssPrefixes[i] + capName;
  8386. if (vendorName in style) return vendorName;
  8387. }
  8388. return name;
  8389. }
  8390. function getStyleProp(name) {
  8391. name = camelCase(name);
  8392. return cssProps[name] || (cssProps[name] = getVendorProp(name));
  8393. }
  8394. function applyCss(element, prop, value) {
  8395. prop = getStyleProp(prop);
  8396. element.style[prop] = value;
  8397. }
  8398. return function(element, properties) {
  8399. var args = arguments,
  8400. prop,
  8401. value;
  8402. if (args.length == 2) {
  8403. for (prop in properties) {
  8404. value = properties[prop];
  8405. if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value);
  8406. }
  8407. } else {
  8408. applyCss(element, args[1], args[2]);
  8409. }
  8410. }
  8411. })();
  8412. /**
  8413. * (Internal) Determines if an element or space separated list of class names contains a class name.
  8414. */
  8415. function hasClass(element, name) {
  8416. var list = typeof element == 'string' ? element : classList(element);
  8417. return list.indexOf(' ' + name + ' ') >= 0;
  8418. }
  8419. /**
  8420. * (Internal) Adds a class to an element.
  8421. */
  8422. function addClass(element, name) {
  8423. var oldList = classList(element),
  8424. newList = oldList + name;
  8425. if (hasClass(oldList, name)) return;
  8426. // Trim the opening space.
  8427. element.className = newList.substring(1);
  8428. }
  8429. /**
  8430. * (Internal) Removes a class from an element.
  8431. */
  8432. function removeClass(element, name) {
  8433. var oldList = classList(element),
  8434. newList;
  8435. if (!hasClass(element, name)) return;
  8436. // Replace the class name.
  8437. newList = oldList.replace(' ' + name + ' ', ' ');
  8438. // Trim the opening and closing spaces.
  8439. element.className = newList.substring(1, newList.length - 1);
  8440. }
  8441. /**
  8442. * (Internal) Gets a space separated list of the class names on the element.
  8443. * The list is wrapped with a single space on each end to facilitate finding
  8444. * matches within the list.
  8445. */
  8446. function classList(element) {
  8447. return (' ' + (element.className || '') + ' ').replace(/\s+/gi, ' ');
  8448. }
  8449. /**
  8450. * (Internal) Removes an element from the DOM.
  8451. */
  8452. function removeElement(element) {
  8453. element && element.parentNode && element.parentNode.removeChild(element);
  8454. }
  8455. return NProgress;
  8456. })();
  8457. module.exports = UI.progress = Progress;
  8458. /***/ },
  8459. /* 20 */
  8460. /***/ function(module, exports, __webpack_require__) {
  8461. 'use strict';
  8462. var $ = __webpack_require__(1);
  8463. var UI = __webpack_require__(2);
  8464. var PinchZoom = __webpack_require__(17);
  8465. var Hammer = __webpack_require__(3);
  8466. var animation = UI.support.animation;
  8467. var transition = UI.support.transition;
  8468. /**
  8469. * PureView
  8470. * @desc Image browser for Mobile
  8471. * @param element
  8472. * @param options
  8473. * @constructor
  8474. */
  8475. var PureView = function(element, options) {
  8476. this.$element = $(element);
  8477. this.$body = $(document.body);
  8478. this.options = $.extend({}, PureView.DEFAULTS, options);
  8479. this.$pureview = $(this.options.tpl).attr('id',
  8480. UI.utils.generateGUID('am-pureview'));
  8481. this.$slides = null;
  8482. this.transitioning = null;
  8483. this.scrollbarWidth = 0;
  8484. this.init();
  8485. };
  8486. PureView.DEFAULTS = {
  8487. tpl: '<div class="am-pureview am-pureview-bar-active">' +
  8488. '<ul class="am-pureview-slider"></ul>' +
  8489. '<ul class="am-pureview-direction">' +
  8490. '<li class="am-pureview-prev"><a href=""></a></li>' +
  8491. '<li class="am-pureview-next"><a href=""></a></li></ul>' +
  8492. '<ol class="am-pureview-nav"></ol>' +
  8493. '<div class="am-pureview-bar am-active">' +
  8494. '<span class="am-pureview-title"></span>' +
  8495. '<div class="am-pureview-counter"><span class="am-pureview-current"></span> / ' +
  8496. '<span class="am-pureview-total"></span></div></div>' +
  8497. '<div class="am-pureview-actions am-active">' +
  8498. '<a href="javascript: void(0)" class="am-icon-chevron-left" ' +
  8499. 'data-am-close="pureview"></a></div>' +
  8500. '</div>',
  8501. className: {
  8502. prevSlide: 'am-pureview-slide-prev',
  8503. nextSlide: 'am-pureview-slide-next',
  8504. onlyOne: 'am-pureview-only',
  8505. active: 'am-active',
  8506. barActive: 'am-pureview-bar-active',
  8507. activeBody: 'am-pureview-active'
  8508. },
  8509. selector: {
  8510. slider: '.am-pureview-slider',
  8511. close: '[data-am-close="pureview"]',
  8512. total: '.am-pureview-total',
  8513. current: '.am-pureview-current',
  8514. title: '.am-pureview-title',
  8515. actions: '.am-pureview-actions',
  8516. bar: '.am-pureview-bar',
  8517. pinchZoom: '.am-pinch-zoom',
  8518. nav: '.am-pureview-nav'
  8519. },
  8520. shareBtn: false,
  8521. // press to toggle Toolbar
  8522. toggleToolbar: true,
  8523. // 从何处获取图片,img 可以使用 data-rel 指定大图
  8524. target: 'img',
  8525. // 微信 Webview 中调用微信的图片浏览器
  8526. // 实现图片保存、分享好友、收藏图片等功能
  8527. weChatImagePreview: true
  8528. };
  8529. PureView.prototype.init = function() {
  8530. var _this = this;
  8531. var options = this.options;
  8532. var $element = this.$element;
  8533. var $pureview = this.$pureview;
  8534. this.refreshSlides();
  8535. $('body').append($pureview);
  8536. this.$title = $pureview.find(options.selector.title);
  8537. this.$current = $pureview.find(options.selector.current);
  8538. this.$bar = $pureview.find(options.selector.bar);
  8539. this.$actions = $pureview.find(options.selector.actions);
  8540. if (options.shareBtn) {
  8541. this.$actions.append('<a href="javascript: void(0)" ' +
  8542. 'class="am-icon-share-square-o" data-am-toggle="share"></a>');
  8543. }
  8544. this.$element.on('click.pureview.amui', options.target, function(e) {
  8545. e.preventDefault();
  8546. var clicked = _this.$images.index(this);
  8547. // Invoke WeChat ImagePreview in WeChat
  8548. // TODO: detect WeChat before init
  8549. if (options.weChatImagePreview && window.WeixinJSBridge) {
  8550. window.WeixinJSBridge.invoke('imagePreview', {
  8551. current: _this.imgUrls[clicked],
  8552. urls: _this.imgUrls
  8553. });
  8554. } else {
  8555. _this.open(clicked);
  8556. }
  8557. });
  8558. $pureview.find('.am-pureview-direction').
  8559. on('click.direction.pureview.amui', 'li', function(e) {
  8560. e.preventDefault();
  8561. if ($(this).is('.am-pureview-prev')) {
  8562. _this.prevSlide();
  8563. } else {
  8564. _this.nextSlide();
  8565. }
  8566. });
  8567. // Nav Contorl
  8568. $pureview.find(options.selector.nav).on('click.nav.pureview.amui', 'li',
  8569. function() {
  8570. var index = _this.$navItems.index($(this));
  8571. _this.activate(_this.$slides.eq(index));
  8572. });
  8573. // Close Icon
  8574. $pureview.find(options.selector.close).
  8575. on('click.close.pureview.amui', function(e) {
  8576. e.preventDefault();
  8577. _this.close();
  8578. });
  8579. this.$slider.hammer().on('swipeleft.pureview.amui', function(e) {
  8580. e.preventDefault();
  8581. _this.nextSlide();
  8582. }).on('swiperight.pureview.amui', function(e) {
  8583. e.preventDefault();
  8584. _this.prevSlide();
  8585. }).on('press.pureview.amui', function(e) {
  8586. e.preventDefault();
  8587. options.toggleToolbar && _this.toggleToolBar();
  8588. });
  8589. this.$slider.data('hammer').get('swipe').set({
  8590. direction: Hammer.DIRECTION_HORIZONTAL,
  8591. velocity: 0.35
  8592. });
  8593. // Observe DOM
  8594. $element.DOMObserve({
  8595. childList: true,
  8596. subtree: true
  8597. }, function(mutations, observer) {
  8598. // _this.refreshSlides();
  8599. // console.log('mutations[0].type);
  8600. });
  8601. // NOTE:
  8602. // trigger this event manually if MutationObserver not supported
  8603. // when new images appended, or call refreshSlides()
  8604. // if (!UI.support.mutationobserver) $element.trigger('changed.dom.amui')
  8605. $element.on('changed.dom.amui', function(e) {
  8606. e.stopPropagation();
  8607. _this.refreshSlides();
  8608. });
  8609. $(document).on('keydown.pureview.amui', $.proxy(function(e) {
  8610. var keyCode = e.keyCode;
  8611. if (keyCode == 37) {
  8612. this.prevSlide();
  8613. } else if (keyCode == 39) {
  8614. this.nextSlide();
  8615. } else if (keyCode == 27) {
  8616. this.close();
  8617. }
  8618. }, this));
  8619. };
  8620. PureView.prototype.refreshSlides = function() {
  8621. // update images collections
  8622. this.$images = this.$element.find(this.options.target);
  8623. var _this = this;
  8624. var options = this.options;
  8625. var $pureview = this.$pureview;
  8626. var $slides = $([]);
  8627. var $navItems = $([]);
  8628. var $images = this.$images;
  8629. var total = $images.length;
  8630. this.$slider = $pureview.find(options.selector.slider);
  8631. this.$nav = $pureview.find(options.selector.nav);
  8632. var viewedFlag = 'data-am-pureviewed';
  8633. // for WeChat Image Preview
  8634. this.imgUrls = this.imgUrls || [];
  8635. if (!total) {
  8636. return;
  8637. }
  8638. if (total === 1) {
  8639. $pureview.addClass(options.className.onlyOne);
  8640. }
  8641. $images.not('[' + viewedFlag + ']').each(function(i, item) {
  8642. var src;
  8643. var title;
  8644. // get image URI from link's href attribute
  8645. if (item.nodeName === 'A') {
  8646. src = item.href; // to absolute path
  8647. title = item.title || '';
  8648. } else {
  8649. // NOTE: `data-rel` should be a full URL, otherwise,
  8650. // WeChat images preview will not work
  8651. src = $(item).data('rel') || item.src; // <img src='' data-rel='' />
  8652. src = UI.utils.getAbsoluteUrl(src);
  8653. title = $(item).attr('alt') || '';
  8654. }
  8655. // add pureviewed flag
  8656. item.setAttribute(viewedFlag, '1');
  8657. // hide bar: wechat_webview_type=1
  8658. // http://tmt.io/wechat/ not working?
  8659. _this.imgUrls.push(src);
  8660. $slides = $slides.add($('<li data-src="' + src + '" data-title="' + title +
  8661. '"></li>'));
  8662. $navItems = $navItems.add($('<li>' + (i + 1) + '</li>'));
  8663. });
  8664. $pureview.find(options.selector.total).text(total);
  8665. this.$slider.append($slides);
  8666. this.$nav.append($navItems);
  8667. this.$navItems = this.$nav.find('li');
  8668. this.$slides = this.$slider.find('li');
  8669. };
  8670. PureView.prototype.loadImage = function($slide, callback) {
  8671. var appendedFlag = 'image-appended';
  8672. if (!$slide.data(appendedFlag)) {
  8673. var $img = $('<img>', {
  8674. src: $slide.data('src'),
  8675. alt: $slide.data('title')
  8676. });
  8677. $slide.html($img).wrapInner('<div class="am-pinch-zoom"></div>').redraw();
  8678. var $pinchWrapper = $slide.find(this.options.selector.pinchZoom);
  8679. $pinchWrapper.data('amui.pinchzoom', new PinchZoom($pinchWrapper[0], {}));
  8680. $slide.data('image-appended', true);
  8681. }
  8682. callback && callback.call(this);
  8683. };
  8684. PureView.prototype.activate = function($slide) {
  8685. var options = this.options;
  8686. var $slides = this.$slides;
  8687. var activeIndex = $slides.index($slide);
  8688. var title = $slide.data('title') || '';
  8689. var active = options.className.active;
  8690. if ($slides.find('.' + active).is($slide)) {
  8691. return;
  8692. }
  8693. if (this.transitioning) {
  8694. return;
  8695. }
  8696. this.loadImage($slide, function() {
  8697. UI.utils.imageLoader($slide.find('img'), function(image) {
  8698. $slide.find('.am-pinch-zoom').addClass('am-pureview-loaded');
  8699. $(image).addClass('am-img-loaded');
  8700. });
  8701. });
  8702. this.transitioning = 1;
  8703. this.$title.text(title);
  8704. this.$current.text(activeIndex + 1);
  8705. $slides.removeClass();
  8706. $slide.addClass(active);
  8707. $slides.eq(activeIndex - 1).addClass(options.className.prevSlide);
  8708. $slides.eq(activeIndex + 1).addClass(options.className.nextSlide);
  8709. this.$navItems.removeClass().
  8710. eq(activeIndex).addClass(options.className.active);
  8711. if (transition) {
  8712. $slide.one(transition.end, $.proxy(function() {
  8713. this.transitioning = 0;
  8714. }, this)).emulateTransitionEnd(300);
  8715. } else {
  8716. this.transitioning = 0;
  8717. }
  8718. // TODO: pre-load next image
  8719. };
  8720. PureView.prototype.nextSlide = function() {
  8721. if (this.$slides.length === 1) {
  8722. return;
  8723. }
  8724. var $slides = this.$slides;
  8725. var $active = $slides.filter('.am-active');
  8726. var activeIndex = $slides.index($active);
  8727. var rightSpring = 'am-animation-right-spring';
  8728. if (activeIndex + 1 >= $slides.length) { // last one
  8729. animation && $active.addClass(rightSpring).on(animation.end, function() {
  8730. $active.removeClass(rightSpring);
  8731. });
  8732. } else {
  8733. this.activate($slides.eq(activeIndex + 1));
  8734. }
  8735. };
  8736. PureView.prototype.prevSlide = function() {
  8737. if (this.$slides.length === 1) {
  8738. return;
  8739. }
  8740. var $slides = this.$slides;
  8741. var $active = $slides.filter('.am-active');
  8742. var activeIndex = this.$slides.index(($active));
  8743. var leftSpring = 'am-animation-left-spring';
  8744. if (activeIndex === 0) { // first one
  8745. animation && $active.addClass(leftSpring).on(animation.end, function() {
  8746. $active.removeClass(leftSpring);
  8747. });
  8748. } else {
  8749. this.activate($slides.eq(activeIndex - 1));
  8750. }
  8751. };
  8752. PureView.prototype.toggleToolBar = function() {
  8753. this.$pureview.toggleClass(this.options.className.barActive);
  8754. };
  8755. PureView.prototype.open = function(index) {
  8756. var active = index || 0;
  8757. this.checkScrollbar();
  8758. this.setScrollbar();
  8759. this.activate(this.$slides.eq(active));
  8760. this.$pureview.show().redraw().addClass(this.options.className.active);
  8761. this.$body.addClass(this.options.className.activeBody);
  8762. };
  8763. PureView.prototype.close = function() {
  8764. var options = this.options;
  8765. this.$pureview.removeClass(options.className.active);
  8766. this.$slides.removeClass();
  8767. function resetBody() {
  8768. this.$pureview.hide();
  8769. this.$body.removeClass(options.className.activeBody);
  8770. this.resetScrollbar();
  8771. }
  8772. if (transition) {
  8773. this.$pureview.one(transition.end, $.proxy(resetBody, this)).
  8774. emulateTransitionEnd(300);
  8775. } else {
  8776. resetBody.call(this);
  8777. }
  8778. };
  8779. PureView.prototype.checkScrollbar = function() {
  8780. this.scrollbarWidth = UI.utils.measureScrollbar();
  8781. };
  8782. PureView.prototype.setScrollbar = function() {
  8783. var bodyPaddingRight = parseInt((this.$body.css('padding-right') || 0), 10);
  8784. if (this.scrollbarWidth) {
  8785. this.$body.css('padding-right', bodyPaddingRight + this.scrollbarWidth);
  8786. }
  8787. };
  8788. PureView.prototype.resetScrollbar = function() {
  8789. this.$body.css('padding-right', '');
  8790. };
  8791. UI.plugin('pureview', PureView);
  8792. // Init code
  8793. UI.ready(function(context) {
  8794. $('[data-am-pureview]', context).pureview();
  8795. });
  8796. module.exports = PureView;
  8797. // TODO: 1. 动画改进
  8798. // 2. 改变图片的时候恢复 Zoom
  8799. // 3. 选项
  8800. // 4. 图片高度问题:由于 PinchZoom 的原因,过高的图片如果设置看了滚动,则放大以后显示不全
  8801. /***/ },
  8802. /* 21 */
  8803. /***/ function(module, exports, __webpack_require__) {
  8804. 'use strict';
  8805. var $ = __webpack_require__(1);
  8806. var UI = __webpack_require__(2);
  8807. /**
  8808. * @via https://github.com/uikit/uikit/blob/master/src/js/scrollspy.js
  8809. * @license https://github.com/uikit/uikit/blob/master/LICENSE.md
  8810. */
  8811. var ScrollSpy = function(element, options) {
  8812. if (!UI.support.animation) {
  8813. return;
  8814. }
  8815. this.options = $.extend({}, ScrollSpy.DEFAULTS, options);
  8816. this.$element = $(element);
  8817. var checkViewRAF = function() {
  8818. UI.utils.rAF.call(window, $.proxy(this.checkView, this));
  8819. }.bind(this);
  8820. this.$window = $(window).on('scroll.scrollspy.amui', checkViewRAF)
  8821. .on('resize.scrollspy.amui orientationchange.scrollspy.amui',
  8822. UI.utils.debounce(checkViewRAF, 50));
  8823. this.timer = this.inViewState = this.initInView = null;
  8824. checkViewRAF();
  8825. };
  8826. ScrollSpy.DEFAULTS = {
  8827. animation: 'fade',
  8828. className: {
  8829. inView: 'am-scrollspy-inview',
  8830. init: 'am-scrollspy-init'
  8831. },
  8832. repeat: true,
  8833. delay: 0,
  8834. topOffset: 0,
  8835. leftOffset: 0
  8836. };
  8837. ScrollSpy.prototype.checkView = function() {
  8838. var $element = this.$element;
  8839. var options = this.options;
  8840. var inView = UI.utils.isInView($element, options);
  8841. var animation = options.animation ?
  8842. ' am-animation-' + options.animation : '';
  8843. if (inView && !this.inViewState) {
  8844. if (this.timer) {
  8845. clearTimeout(this.timer);
  8846. }
  8847. if (!this.initInView) {
  8848. $element.addClass(options.className.init);
  8849. this.offset = $element.offset();
  8850. this.initInView = true;
  8851. $element.trigger('init.scrollspy.amui');
  8852. }
  8853. this.timer = setTimeout(function() {
  8854. if (inView) {
  8855. $element.addClass(options.className.inView + animation).width();
  8856. }
  8857. }, options.delay);
  8858. this.inViewState = true;
  8859. $element.trigger('inview.scrollspy.amui');
  8860. }
  8861. if (!inView && this.inViewState && options.repeat) {
  8862. $element.removeClass(options.className.inView + animation);
  8863. this.inViewState = false;
  8864. $element.trigger('outview.scrollspy.amui');
  8865. }
  8866. };
  8867. ScrollSpy.prototype.check = function() {
  8868. UI.utils.rAF.call(window, $.proxy(this.checkView, this));
  8869. };
  8870. // Sticky Plugin
  8871. UI.plugin('scrollspy', ScrollSpy);
  8872. // Init code
  8873. UI.ready(function(context) {
  8874. $('[data-am-scrollspy]', context).scrollspy();
  8875. });
  8876. module.exports = ScrollSpy;
  8877. /***/ },
  8878. /* 22 */
  8879. /***/ function(module, exports, __webpack_require__) {
  8880. 'use strict';
  8881. var $ = __webpack_require__(1);
  8882. var UI = __webpack_require__(2);
  8883. __webpack_require__(23);
  8884. /**
  8885. * @via https://github.com/uikit/uikit/
  8886. * @license https://github.com/uikit/uikit/blob/master/LICENSE.md
  8887. */
  8888. // ScrollSpyNav Class
  8889. var ScrollSpyNav = function(element, options) {
  8890. this.options = $.extend({}, ScrollSpyNav.DEFAULTS, options);
  8891. this.$element = $(element);
  8892. this.anchors = [];
  8893. this.$links = this.$element.find('a[href^="#"]').each(function(i, link) {
  8894. this.anchors.push($(link).attr('href'));
  8895. }.bind(this));
  8896. this.$targets = $(this.anchors.join(', '));
  8897. var processRAF = function() {
  8898. UI.utils.rAF.call(window, $.proxy(this.process, this));
  8899. }.bind(this);
  8900. this.$window = $(window).on('scroll.scrollspynav.amui', processRAF)
  8901. .on('resize.scrollspynav.amui orientationchange.scrollspynav.amui',
  8902. UI.utils.debounce(processRAF, 50));
  8903. processRAF();
  8904. this.scrollProcess();
  8905. };
  8906. ScrollSpyNav.DEFAULTS = {
  8907. className: {
  8908. active: 'am-active'
  8909. },
  8910. closest: false,
  8911. smooth: true,
  8912. offsetTop: 0
  8913. };
  8914. ScrollSpyNav.prototype.process = function() {
  8915. var scrollTop = this.$window.scrollTop();
  8916. var options = this.options;
  8917. var inViews = [];
  8918. var $links = this.$links;
  8919. var $targets = this.$targets;
  8920. $targets.each(function(i, target) {
  8921. if (UI.utils.isInView(target, options)) {
  8922. inViews.push(target);
  8923. }
  8924. });
  8925. // console.log(inViews.length);
  8926. if (inViews.length) {
  8927. var $target;
  8928. $.each(inViews, function(i, item) {
  8929. if ($(item).offset().top >= scrollTop) {
  8930. $target = $(item);
  8931. return false; // break
  8932. }
  8933. });
  8934. if (!$target) {
  8935. return;
  8936. }
  8937. if (options.closest) {
  8938. $links.closest(options.closest).removeClass(options.className.active);
  8939. $links.filter('a[href="#' + $target.attr('id') + '"]').
  8940. closest(options.closest).addClass(options.className.active);
  8941. } else {
  8942. $links.removeClass(options.className.active).
  8943. filter('a[href="#' + $target.attr('id') + '"]').
  8944. addClass(options.className.active);
  8945. }
  8946. }
  8947. };
  8948. ScrollSpyNav.prototype.scrollProcess = function() {
  8949. var $links = this.$links;
  8950. var options = this.options;
  8951. // smoothScroll
  8952. if (options.smooth && $.fn.smoothScroll) {
  8953. $links.on('click', function(e) {
  8954. e.preventDefault();
  8955. var $this = $(this);
  8956. var $target = $($this.attr('href'));
  8957. if (!$target) {
  8958. return;
  8959. }
  8960. var offsetTop = options.offsetTop &&
  8961. !isNaN(parseInt(options.offsetTop)) && parseInt(options.offsetTop) || 0;
  8962. $(window).smoothScroll({position: $target.offset().top - offsetTop});
  8963. });
  8964. }
  8965. };
  8966. // ScrollSpyNav Plugin
  8967. UI.plugin('scrollspynav', ScrollSpyNav);
  8968. // Init code
  8969. UI.ready(function(context) {
  8970. $('[data-am-scrollspynav]', context).scrollspynav();
  8971. });
  8972. module.exports = ScrollSpyNav;
  8973. // TODO: 1. 算法改进
  8974. // 2. 多级菜单支持
  8975. // 3. smooth scroll pushState
  8976. /***/ },
  8977. /* 23 */
  8978. /***/ function(module, exports, __webpack_require__) {
  8979. 'use strict';
  8980. var $ = __webpack_require__(1);
  8981. var UI = __webpack_require__(2);
  8982. var rAF = UI.utils.rAF;
  8983. var cAF = UI.utils.cancelAF;
  8984. /**
  8985. * Smooth Scroll
  8986. * @param position
  8987. * @via http://mir.aculo.us/2014/01/19/scrolling-dom-elements-to-the-top-a-zepto-plugin/
  8988. */
  8989. // Usage: $(window).smoothScroll([options])
  8990. // only allow one scroll to top operation to be in progress at a time,
  8991. // which is probably what you want
  8992. var smoothScrollInProgress = false;
  8993. var SmoothScroll = function(element, options) {
  8994. options = options || {};
  8995. var $this = $(element);
  8996. var targetY = parseInt(options.position) || SmoothScroll.DEFAULTS.position;
  8997. var initialY = $this.scrollTop();
  8998. var lastY = initialY;
  8999. var delta = targetY - initialY;
  9000. // duration in ms, make it a bit shorter for short distances
  9001. // this is not scientific and you might want to adjust this for
  9002. // your preferences
  9003. var speed = options.speed ||
  9004. Math.min(750, Math.min(1500, Math.abs(initialY - targetY)));
  9005. // temp variables (t will be a position between 0 and 1, y is the calculated scrollTop)
  9006. var start;
  9007. var t;
  9008. var y;
  9009. var cancelScroll = function() {
  9010. abort();
  9011. };
  9012. // abort if already in progress or nothing to scroll
  9013. if (smoothScrollInProgress) {
  9014. return;
  9015. }
  9016. if (delta === 0) {
  9017. return;
  9018. }
  9019. // quint ease-in-out smoothing, from
  9020. // https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js#L127-L136
  9021. function smooth(pos) {
  9022. if ((pos /= 0.5) < 1) {
  9023. return 0.5 * Math.pow(pos, 5);
  9024. }
  9025. return 0.5 * (Math.pow((pos - 2), 5) + 2);
  9026. }
  9027. function abort() {
  9028. $this.off('touchstart.smoothscroll.amui', cancelScroll);
  9029. smoothScrollInProgress = false;
  9030. }
  9031. // when there's a touch detected while scrolling is in progress, abort
  9032. // the scrolling (emulates native scrolling behavior)
  9033. $this.on('touchstart.smoothscroll.amui', cancelScroll);
  9034. smoothScrollInProgress = true;
  9035. // start rendering away! note the function given to frame
  9036. // is named "render" so we can reference it again further down
  9037. function render(now) {
  9038. if (!smoothScrollInProgress) {
  9039. return;
  9040. }
  9041. if (!start) {
  9042. start = now;
  9043. }
  9044. // calculate t, position of animation in [0..1]
  9045. t = Math.min(1, Math.max((now - start) / speed, 0));
  9046. // calculate the new scrollTop position (don't forget to smooth)
  9047. y = Math.round(initialY + delta * smooth(t));
  9048. // bracket scrollTop so we're never over-scrolling
  9049. if (delta > 0 && y > targetY) {
  9050. y = targetY;
  9051. }
  9052. if (delta < 0 && y < targetY) {
  9053. y = targetY;
  9054. }
  9055. // only actually set scrollTop if there was a change fromt he last frame
  9056. if (lastY != y) {
  9057. $this.scrollTop(y);
  9058. }
  9059. lastY = y;
  9060. // if we're not done yet, queue up an other frame to render,
  9061. // or clean up
  9062. if (y !== targetY) {
  9063. cAF(scrollRAF);
  9064. scrollRAF = rAF(render);
  9065. } else {
  9066. cAF(scrollRAF);
  9067. abort();
  9068. }
  9069. }
  9070. var scrollRAF = rAF(render);
  9071. };
  9072. SmoothScroll.DEFAULTS = {
  9073. position: 0
  9074. };
  9075. $.fn.smoothScroll = function(option) {
  9076. return this.each(function() {
  9077. new SmoothScroll(this, option);
  9078. });
  9079. };
  9080. // Init code
  9081. $(document).on('click.smoothScroll.amui.data-api', '[data-am-smooth-scroll]',
  9082. function(e) {
  9083. e.preventDefault();
  9084. var options = UI.utils.parseOptions($(this).data('amSmoothScroll'));
  9085. $(window).smoothScroll(options);
  9086. });
  9087. module.exports = SmoothScroll;
  9088. /***/ },
  9089. /* 24 */
  9090. /***/ function(module, exports, __webpack_require__) {
  9091. 'use strict';
  9092. var $ = __webpack_require__(1);
  9093. var UI = __webpack_require__(2);
  9094. // require('./ui.dropdown');
  9095. // Make jQuery :contains Case-Insensitive
  9096. $.expr[':'].containsNC = function(elem, i, match, array) {
  9097. return (elem.textContent || elem.innerText || '').toLowerCase().
  9098. indexOf((match[3] || '').toLowerCase()) >= 0;
  9099. };
  9100. /**
  9101. * Selected
  9102. * @desc HTML select replacer
  9103. * @via https://github.com/silviomoreto/bootstrap-select
  9104. * @license https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE
  9105. * @param element
  9106. * @param options
  9107. * @constructor
  9108. */
  9109. var Selected = function(element, options) {
  9110. this.$element = $(element);
  9111. this.options = $.extend({}, Selected.DEFAULTS, {
  9112. placeholder: element.getAttribute('placeholder') ||
  9113. Selected.DEFAULTS.placeholder
  9114. }, options);
  9115. this.$originalOptions = this.$element.find('option');
  9116. this.multiple = element.multiple;
  9117. this.$selector = null;
  9118. this.initialized = false;
  9119. this.init();
  9120. };
  9121. Selected.DEFAULTS = {
  9122. btnWidth: null,
  9123. btnSize: null,
  9124. btnStyle: 'default',
  9125. dropUp: 0,
  9126. maxHeight: null,
  9127. maxChecked: null,
  9128. placeholder: '点击选择...',
  9129. selectedClass: 'am-checked',
  9130. disabledClass: 'am-disabled',
  9131. searchBox: false,
  9132. tpl: '<div class="am-selected am-dropdown ' +
  9133. '<%= dropUp ? \'am-dropdown-up\': \'\' %>" id="<%= id %>" data-am-dropdown>' +
  9134. ' <button type="button" class="am-selected-btn am-btn am-dropdown-toggle">' +
  9135. ' <span class="am-selected-status am-fl"></span>' +
  9136. ' <i class="am-selected-icon am-icon-caret-' +
  9137. '<%= dropUp ? \'up\' : \'down\' %>"></i>' +
  9138. ' </button>' +
  9139. ' <div class="am-selected-content am-dropdown-content">' +
  9140. ' <h2 class="am-selected-header">' +
  9141. '<span class="am-icon-chevron-left">返回</span></h2>' +
  9142. ' <% if (searchBox) { %>' +
  9143. ' <div class="am-selected-search">' +
  9144. ' <input autocomplete="off" class="am-form-field am-input-sm" />' +
  9145. ' </div>' +
  9146. ' <% } %>' +
  9147. ' <ul class="am-selected-list">' +
  9148. ' <% for (var i = 0; i < options.length; i++) { %>' +
  9149. ' <% var option = options[i] %>' +
  9150. ' <% if (option.header) { %>' +
  9151. ' <li data-group="<%= option.group %>" class="am-selected-list-header">' +
  9152. ' <%= option.text %></li>' +
  9153. ' <% } else { %>' +
  9154. ' <li class="<%= option.classNames%>" ' +
  9155. ' data-index="<%= option.index %>" ' +
  9156. ' data-group="<%= option.group || 0 %>" ' +
  9157. ' data-value="<%= option.value %>" >' +
  9158. ' <span class="am-selected-text"><%= option.text %></span>' +
  9159. ' <i class="am-icon-check"></i></li>' +
  9160. ' <% } %>' +
  9161. ' <% } %>' +
  9162. ' </ul>' +
  9163. ' <div class="am-selected-hint"></div>' +
  9164. ' </div>' +
  9165. '</div>',
  9166. listTpl: '<% for (var i = 0; i < options.length; i++) { %>' +
  9167. ' <% var option = options[i] %>' +
  9168. ' <% if (option.header) { %>' +
  9169. ' <li data-group="<%= option.group %>" class="am-selected-list-header">' +
  9170. ' <%= option.text %></li>' +
  9171. ' <% } else { %>' +
  9172. ' <li class="<%= option.classNames %>" ' +
  9173. ' data-index="<%= option.index %>" ' +
  9174. ' data-group="<%= option.group || 0 %>" ' +
  9175. ' data-value="<%= option.value %>" >' +
  9176. ' <span class="am-selected-text"><%= option.text %></span>' +
  9177. ' <i class="am-icon-check"></i></li>' +
  9178. ' <% } %>' +
  9179. ' <% } %>'
  9180. };
  9181. Selected.prototype.init = function() {
  9182. var _this = this;
  9183. var $element = this.$element;
  9184. var options = this.options;
  9185. $element.hide();
  9186. var data = {
  9187. id: UI.utils.generateGUID('am-selected'),
  9188. multiple: this.multiple,
  9189. options: [],
  9190. searchBox: options.searchBox,
  9191. dropUp: options.dropUp,
  9192. placeholder: options.placeholder
  9193. };
  9194. this.$selector = $(UI.template(this.options.tpl, data));
  9195. // set select button styles
  9196. this.$selector.css({width: this.options.btnWidth});
  9197. this.$list = this.$selector.find('.am-selected-list');
  9198. this.$searchField = this.$selector.find('.am-selected-search input');
  9199. this.$hint = this.$selector.find('.am-selected-hint');
  9200. var $selectorBtn = this.$selector.find('.am-selected-btn');
  9201. var btnClassNames = [];
  9202. options.btnSize && btnClassNames.push('am-btn-' + options.btnSize);
  9203. options.btnStyle && btnClassNames.push('am-btn-' + options.btnStyle);
  9204. $selectorBtn.addClass(btnClassNames.join(' '));
  9205. this.$selector.dropdown({
  9206. justify: $selectorBtn
  9207. });
  9208. // disable Selected instance if <selected> is disabled
  9209. // should call .disable() after Dropdown initialed
  9210. if ($element[0].disabled) {
  9211. this.disable();
  9212. }
  9213. // set list height
  9214. if (options.maxHeight) {
  9215. this.$selector.find('.am-selected-list').css({
  9216. 'max-height': options.maxHeight,
  9217. 'overflow-y': 'scroll'
  9218. });
  9219. }
  9220. // set hint text
  9221. var hint = [];
  9222. var min = $element.attr('minchecked');
  9223. var max = $element.attr('maxchecked') || options.maxChecked;
  9224. this.maxChecked = max || Infinity;
  9225. if ($element[0].required) {
  9226. hint.push('必选');
  9227. }
  9228. if (min || max) {
  9229. min && hint.push('至少选择 ' + min + ' 项');
  9230. max && hint.push('至多选择 ' + max + ' 项');
  9231. }
  9232. this.$hint.text(hint.join(','));
  9233. // render dropdown list
  9234. this.renderOptions();
  9235. // append $selector after <select>
  9236. this.$element.after(this.$selector);
  9237. this.dropdown = this.$selector.data('amui.dropdown');
  9238. this.$status = this.$selector.find('.am-selected-status');
  9239. // #try to fixes #476
  9240. setTimeout(function() {
  9241. _this.syncData();
  9242. _this.initialized = true;
  9243. }, 0);
  9244. this.bindEvents();
  9245. };
  9246. Selected.prototype.renderOptions = function() {
  9247. var $element = this.$element;
  9248. var options = this.options;
  9249. var optionItems = [];
  9250. var $optgroup = $element.find('optgroup');
  9251. this.$originalOptions = this.$element.find('option');
  9252. // 单选框使用 JS 禁用已经选择的 option 以后,
  9253. // 浏览器会重新选定第一个 option,但有一定延迟,致使 JS 获取 value 时返回 null
  9254. if (!this.multiple && ($element.val() === null)) {
  9255. this.$originalOptions.length &&
  9256. (this.$originalOptions.get(0).selected = true);
  9257. }
  9258. function pushOption(index, item, group) {
  9259. if (item.value === '') {
  9260. // skip to next iteration
  9261. // @see http://stackoverflow.com/questions/481601/how-to-skip-to-next-iteration-in-jquery-each-util
  9262. return true;
  9263. }
  9264. var classNames = '';
  9265. item.disabled && (classNames += options.disabledClass);
  9266. !item.disabled && item.selected && (classNames += options.selectedClass);
  9267. optionItems.push({
  9268. group: group,
  9269. index: index,
  9270. classNames: classNames,
  9271. text: item.text,
  9272. value: item.value
  9273. });
  9274. }
  9275. // select with option groups
  9276. if ($optgroup.length) {
  9277. $optgroup.each(function(i) {
  9278. // push group name
  9279. optionItems.push({
  9280. header: true,
  9281. group: i + 1,
  9282. text: this.label
  9283. });
  9284. $optgroup.eq(i).find('option').each(function(index, item) {
  9285. pushOption(index, item, i);
  9286. });
  9287. });
  9288. } else {
  9289. // without option groups
  9290. this.$originalOptions.each(function(index, item) {
  9291. pushOption(index, item, null);
  9292. });
  9293. }
  9294. this.$list.html(UI.template(options.listTpl, {options: optionItems}));
  9295. this.$shadowOptions = this.$list.find('> li').
  9296. not('.am-selected-list-header');
  9297. };
  9298. Selected.prototype.setChecked = function(item) {
  9299. var options = this.options;
  9300. var $item = $(item);
  9301. var isChecked = $item.hasClass(options.selectedClass);
  9302. if (this.multiple) {
  9303. // multiple
  9304. var checkedLength = this.$list.find('.' + options.selectedClass).length;
  9305. if (!isChecked && this.maxChecked <= checkedLength) {
  9306. this.$element.trigger('checkedOverflow.selected.amui', {
  9307. selected: this
  9308. });
  9309. return false;
  9310. }
  9311. } else {
  9312. // close dropdown whether item is checked or not
  9313. // @see #860
  9314. this.dropdown.close();
  9315. if (isChecked) {
  9316. return false;
  9317. }
  9318. this.$shadowOptions.not($item).removeClass(options.selectedClass);
  9319. }
  9320. $item.toggleClass(options.selectedClass);
  9321. this.syncData(item);
  9322. };
  9323. /**
  9324. * syncData
  9325. *
  9326. * @description if `item` set, only sync `item` related option
  9327. * @param {Object} [item]
  9328. */
  9329. Selected.prototype.syncData = function(item) {
  9330. var _this = this;
  9331. var options = this.options;
  9332. var status = [];
  9333. var $checked = $([]);
  9334. this.$shadowOptions.filter('.' + options.selectedClass).each(function() {
  9335. var $this = $(this);
  9336. status.push($this.find('.am-selected-text').text());
  9337. if (!item) {
  9338. $checked = $checked.add(_this.$originalOptions
  9339. .filter('[value="' + $this.data('value') + '"]')
  9340. .prop('selected', true));
  9341. }
  9342. });
  9343. if (item) {
  9344. var $item = $(item);
  9345. this.$originalOptions
  9346. .filter('[value="' + $item.data('value') + '"]')
  9347. .prop('selected', $item.hasClass(options.selectedClass));
  9348. } else {
  9349. this.$originalOptions.not($checked).prop('selected', false);
  9350. }
  9351. // nothing selected
  9352. if (!this.$element.val()) {
  9353. status = [options.placeholder];
  9354. }
  9355. this.$status.text(status.join(', '));
  9356. // Do not trigger change event on initializing
  9357. this.initialized && this.$element.trigger('change');
  9358. };
  9359. Selected.prototype.bindEvents = function() {
  9360. var _this = this;
  9361. var header = 'am-selected-list-header';
  9362. var handleKeyup = UI.utils.debounce(function(e) {
  9363. _this.$shadowOptions.not('.' + header).hide().
  9364. filter(':containsNC("' + e.target.value + '")').show();
  9365. }, 100);
  9366. this.$list.on('click', '> li', function(e) {
  9367. var $this = $(this);
  9368. !$this.hasClass(_this.options.disabledClass) &&
  9369. !$this.hasClass(header) && _this.setChecked(this);
  9370. });
  9371. // simple search with jQuery :contains
  9372. this.$searchField.on('keyup.selected.amui', handleKeyup);
  9373. // empty search keywords
  9374. this.$selector.on('closed.dropdown.amui', function() {
  9375. _this.$searchField.val('');
  9376. _this.$shadowOptions.css({display: ''});
  9377. });
  9378. // work with Validator
  9379. // @since 2.5
  9380. this.$element.on('validated.field.validator.amui', function(e) {
  9381. if (e.validity) {
  9382. var valid = e.validity.valid;
  9383. var errorClassName = 'am-invalid';
  9384. _this.$selector[(!valid ? 'add' : 'remove') + 'Class'](errorClassName);
  9385. }
  9386. });
  9387. // observe DOM
  9388. if (UI.support.mutationobserver) {
  9389. this.observer = new UI.support.mutationobserver(function() {
  9390. _this.$element.trigger('changed.selected.amui');
  9391. });
  9392. this.observer.observe(this.$element[0], {
  9393. childList: true,
  9394. subtree: true,
  9395. characterData: true
  9396. });
  9397. }
  9398. // custom event
  9399. this.$element.on('changed.selected.amui', function() {
  9400. _this.renderOptions();
  9401. _this.syncData();
  9402. });
  9403. };
  9404. // @since: 2.5
  9405. Selected.prototype.select = function(item) {
  9406. var $item;
  9407. if (typeof item === 'number') {
  9408. $item = this.$list.find('> li').not('.am-selected-list-header').eq(item);
  9409. } else if (typeof item === 'string') {
  9410. $item = this.$list.find(item);
  9411. } else {
  9412. $item = $(item);
  9413. }
  9414. $item.trigger('click');
  9415. };
  9416. // @since: 2.5
  9417. Selected.prototype.enable = function() {
  9418. this.$element.prop('disable', false);
  9419. this.$selector.dropdown('enable');
  9420. };
  9421. // @since: 2.5
  9422. Selected.prototype.disable = function() {
  9423. this.$element.prop('disable', true);
  9424. this.$selector.dropdown('disable');
  9425. };
  9426. Selected.prototype.destroy = function() {
  9427. this.$element.removeData('amui.selected').show();
  9428. this.$selector.remove();
  9429. };
  9430. UI.plugin('selected', Selected);
  9431. // Conflict with jQuery form
  9432. // https://github.com/malsup/form/blob/6bf24a5f6d8be65f4e5491863180c09356d9dadd/jquery.form.js#L1240-L1258
  9433. // https://github.com/allmobilize/amazeui/issues/379
  9434. // @deprecated: $.fn.selected = $.fn.selectIt = Plugin;
  9435. // New way to resolve conflict:
  9436. // @see https://github.com/amazeui/amazeui/issues/781#issuecomment-158873541
  9437. UI.ready(function(context) {
  9438. $('[data-am-selected]', context).selected();
  9439. });
  9440. module.exports = Selected;
  9441. /***/ },
  9442. /* 25 */
  9443. /***/ function(module, exports, __webpack_require__) {
  9444. 'use strict';
  9445. __webpack_require__(15);
  9446. var $ = __webpack_require__(1);
  9447. var UI = __webpack_require__(2);
  9448. var QRCode = __webpack_require__(26);
  9449. var doc = document;
  9450. var $doc = $(doc);
  9451. var Share = function(options) {
  9452. this.options = $.extend({}, Share.DEFAULTS, options || {});
  9453. this.$element = null;
  9454. this.$wechatQr = null;
  9455. this.pics = null;
  9456. this.inited = false;
  9457. this.active = false;
  9458. // this.init();
  9459. };
  9460. Share.DEFAULTS = {
  9461. sns: ['weibo', 'qq', 'qzone', 'tqq', 'wechat', 'renren'],
  9462. title: '分享到',
  9463. cancel: '取消',
  9464. closeOnShare: true,
  9465. id: UI.utils.generateGUID('am-share'),
  9466. desc: 'Hi,孤夜观天象,发现一个不错的西西,分享一下下 ;-)',
  9467. via: 'Amaze UI',
  9468. tpl: '<div class="am-share am-modal-actions" id="<%= id %>">' +
  9469. '<h3 class="am-share-title"><%= title %></h3>' +
  9470. '<ul class="am-share-sns am-avg-sm-3">' +
  9471. '<% for(var i = 0; i < sns.length; i++) {%>' +
  9472. '<li>' +
  9473. '<a href="<%= sns[i].shareUrl %>" ' +
  9474. 'data-am-share-to="<%= sns[i].id %>" >' +
  9475. '<i class="am-icon-<%= sns[i].icon %>"></i>' +
  9476. '<span><%= sns[i].title %></span>' +
  9477. '</a></li>' +
  9478. '<% } %></ul>' +
  9479. '<div class="am-share-footer">' +
  9480. '<button class="am-btn am-btn-default am-btn-block" ' +
  9481. 'data-am-share-close><%= cancel %></button></div>' +
  9482. '</div>'
  9483. };
  9484. Share.SNS = {
  9485. weibo: {
  9486. title: '新浪微博',
  9487. url: 'http://service.weibo.com/share/share.php',
  9488. width: 620,
  9489. height: 450,
  9490. icon: 'weibo'
  9491. },
  9492. // url 链接地址
  9493. // title:”, 分享的文字内容(可选,默认为所在页面的title)
  9494. // appkey:”, 您申请的应用appkey,显示分享来源(可选)
  9495. // pic:”, 分享图片的路径(可选)
  9496. // ralateUid:”, 关联用户的UID,分享微博会@该用户(可选)
  9497. // NOTE: 会自动抓取图片,不用指定 pic
  9498. qq: {
  9499. title: 'QQ 好友',
  9500. url: 'http://connect.qq.com/widget/shareqq/index.html',
  9501. icon: 'qq'
  9502. },
  9503. // url:,
  9504. // title:'', 分享标题(可选)
  9505. // pics:'', 分享图片的路径(可选)
  9506. // summary:'', 分享摘要(可选)
  9507. // site:'', 分享来源 如:腾讯网(可选)
  9508. // desc: '' 发送给用户的消息
  9509. // NOTE: 经过测试,最终发给用户的只有 url 和 desc
  9510. qzone: {
  9511. title: 'QQ 空间',
  9512. url: 'http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey',
  9513. icon: 'star'
  9514. },
  9515. // http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=xxx&title=xxx&desc=&summary=&site=
  9516. // url:,
  9517. // title:'', 分享标题(可选)
  9518. // desc:'', 默认分享理由(可选)
  9519. // summary:'', 分享摘要(可选)
  9520. // site:'', 分享来源 如:腾讯网(可选)
  9521. // pics:'', 分享图片的路径(可选),不会自动抓取,多个图片用|分隔
  9522. tqq: {
  9523. title: '腾讯微博',
  9524. url: 'http://v.t.qq.com/share/share.php',
  9525. icon: 'tencent-weibo'
  9526. },
  9527. // url=xx&title=&appkey=801cf76d3cfc44ada52ec13114e84a96
  9528. // url
  9529. // title
  9530. // pic 多个图片用 | 分隔
  9531. // appkey
  9532. // NOTE: 不会自动抓取图片
  9533. wechat: {
  9534. title: '微信',
  9535. url: '[qrcode]',
  9536. icon: 'wechat'
  9537. },
  9538. // 生成一个二维码 供用户扫描
  9539. // 相关接口 https://github.com/zxlie/WeixinApi
  9540. renren: {
  9541. title: '人人网',
  9542. url: 'http://widget.renren.com/dialog/share',
  9543. icon: 'renren'
  9544. },
  9545. // http://widget.renren.com/dialog/share?resourceUrl=www&srcUrl=www&title=ww&description=xxx
  9546. // 550 * 400
  9547. // resourceUrl : '', // 分享的资源Url
  9548. // srcUrl : '', // 分享的资源来源Url,
  9549. // // 默认为header中的Referer,如果分享失败可以调整此值为resourceUrl试试
  9550. // pic : '', // 分享的主题图片,会自动抓取
  9551. // title : '', // 分享的标题
  9552. // description : '' // 分享的详细描述
  9553. // NOTE: 经过测试,直接使用 url 参数即可
  9554. douban: {
  9555. title: '豆瓣',
  9556. url: 'http://www.douban.com/recommend/',
  9557. icon: 'share-alt'
  9558. },
  9559. // http://www.douban.com/service/sharebutton
  9560. // 450 * 330
  9561. // http://www.douban.com/share/service?bm=1&image=&href=xxx&updated=&name=
  9562. // href 链接
  9563. // name 标题
  9564. /* void (function() {
  9565. var d = document, e = encodeURIComponent,
  9566. s1 = window.getSelection, s2 = d.getSelection,
  9567. s3 = d.selection, s = s1 ? s1()
  9568. : s2 ? s2() : s3 ? s3.createRange().text : '',
  9569. r = 'http://www.douban.com/recommend/?url=&title=&sel=&v=1&r=1'
  9570. })();
  9571. */
  9572. // tsohu: '',
  9573. // http://t.sohu.com/third/post.jsp?url=&title=&content=utf-8&pic=
  9574. // print: '',
  9575. mail: {
  9576. title: '邮件分享',
  9577. url: 'mailto:',
  9578. icon: 'envelope-o'
  9579. },
  9580. sms: {
  9581. title: '短信分享',
  9582. url: 'sms:',
  9583. icon: 'comment'
  9584. }
  9585. };
  9586. Share.prototype.render = function() {
  9587. var options = this.options;
  9588. var snsData = [];
  9589. var title = encodeURIComponent(doc.title);
  9590. var link = encodeURIComponent(doc.location);
  9591. var msgBody = '?body=' + title + link;
  9592. options.sns.forEach(function(item, i) {
  9593. if (Share.SNS[item]) {
  9594. var tmp = Share.SNS[item];
  9595. var shareUrl;
  9596. tmp.id = item;
  9597. if (item === 'mail') {
  9598. shareUrl = msgBody + '&subject=' + options.desc;
  9599. } else if (item === 'sms') {
  9600. shareUrl = msgBody;
  9601. } else {
  9602. shareUrl = '?url=' + link + '&title=' + title;
  9603. }
  9604. tmp.shareUrl = tmp.url + shareUrl;
  9605. snsData.push(tmp);
  9606. }
  9607. });
  9608. return UI.template(options.tpl, $.extend({}, options, {sns: snsData}));
  9609. };
  9610. Share.prototype.init = function() {
  9611. if (this.inited) {
  9612. return;
  9613. }
  9614. var me = this;
  9615. var shareItem = '[data-am-share-to]';
  9616. $doc.ready($.proxy(function() {
  9617. $('body').append(this.render()); // append share DOM to body
  9618. this.$element = $('#' + this.options.id);
  9619. this.$element.find('[data-am-share-close]').
  9620. on('click.share.amui', function() {
  9621. me.close();
  9622. });
  9623. }, this));
  9624. $doc.on('click.share.amui', shareItem, $.proxy(function(e) {
  9625. var $clicked = $(e.target);
  9626. var $target = $clicked.is(shareItem) && $clicked ||
  9627. $clicked.parent(shareItem);
  9628. var sns = $target.attr('data-am-share-to');
  9629. if (!(sns === 'mail' || sns === 'sms')) {
  9630. e.preventDefault();
  9631. this.shareTo(sns, this.setData(sns));
  9632. }
  9633. this.close();
  9634. }, this));
  9635. this.inited = true;
  9636. };
  9637. Share.prototype.open = function() {
  9638. !this.inited && this.init();
  9639. this.$element && this.$element.modal('open');
  9640. this.$element.trigger('open.share.amui');
  9641. this.active = true;
  9642. };
  9643. Share.prototype.close = function() {
  9644. this.$element && this.$element.modal('close');
  9645. this.$element.trigger('close.share.amui');
  9646. this.active = false;
  9647. };
  9648. Share.prototype.toggle = function() {
  9649. this.active ? this.close() : this.open();
  9650. };
  9651. Share.prototype.setData = function(sns) {
  9652. if (!sns) {
  9653. return;
  9654. }
  9655. var shareData = {
  9656. url: doc.location,
  9657. title: doc.title
  9658. };
  9659. var desc = this.options.desc;
  9660. var imgSrc = this.pics || [];
  9661. var qqReg = /^(qzone|qq|tqq)$/;
  9662. if (qqReg.test(sns) && !imgSrc.length) {
  9663. var allImages = doc.images;
  9664. for (var i = 0; i < allImages.length && i < 10; i++) {
  9665. !!allImages[i].src && imgSrc.push(encodeURIComponent(allImages[i].src));
  9666. }
  9667. this.pics = imgSrc; // 缓存图片
  9668. }
  9669. switch (sns) {
  9670. case 'qzone':
  9671. shareData.desc = desc;
  9672. shareData.site = this.options.via;
  9673. shareData.pics = imgSrc.join('|');
  9674. // TODO: 抓取图片多张
  9675. break;
  9676. case 'qq':
  9677. shareData.desc = desc;
  9678. shareData.site = this.options.via;
  9679. shareData.pics = imgSrc[0];
  9680. // 抓取一张图片
  9681. break;
  9682. case 'tqq':
  9683. // 抓取图片多张
  9684. shareData.pic = imgSrc.join('|');
  9685. break;
  9686. }
  9687. return shareData;
  9688. };
  9689. Share.prototype.shareTo = function(sns, data) {
  9690. var snsInfo = Share.SNS[sns];
  9691. if (!snsInfo) {
  9692. return;
  9693. }
  9694. if (sns === 'wechat' || sns === 'weixin') {
  9695. return this.wechatQr();
  9696. }
  9697. var query = [];
  9698. for (var key in data) {
  9699. if (data[key]) {
  9700. // 避免 encode 图片分隔符 |
  9701. query.push(key.toString() + '=' + ((key === 'pic' || key === 'pics') ?
  9702. data[key] : encodeURIComponent(data[key])));
  9703. }
  9704. }
  9705. window.open(snsInfo.url + '?' + query.join('&'));
  9706. };
  9707. Share.prototype.wechatQr = function() {
  9708. if (!this.$wechatQr) {
  9709. var qrId = UI.utils.generateGUID('am-share-wechat');
  9710. var $qr = $('<div class="am-modal am-modal-no-btn am-share-wechat-qr">' +
  9711. '<div class="am-modal-dialog"><div class="am-modal-hd">分享到微信 ' +
  9712. '<a href="" class="am-close am-close-spin" ' +
  9713. 'data-am-modal-close>&times;</a> </div>' +
  9714. '<div class="am-modal-bd">' +
  9715. '<div class="am-share-wx-qr"></div>' +
  9716. '<div class="am-share-wechat-tip">' +
  9717. '打开微信,点击底部的<em>发现</em>,<br/> ' +
  9718. '使用<em>扫一扫</em>将网页分享至朋友圈</div></div></div></div>');
  9719. $qr.attr('id', qrId);
  9720. var qrNode = new QRCode({
  9721. render: 'canvas',
  9722. correctLevel: 0,
  9723. text: doc.location.href,
  9724. width: 180,
  9725. height: 180,
  9726. background: '#fff',
  9727. foreground: '#000'
  9728. });
  9729. $qr.find('.am-share-wx-qr').html(qrNode);
  9730. $qr.appendTo($('body'));
  9731. this.$wechatQr = $('#' + qrId);
  9732. }
  9733. this.$wechatQr.modal('open');
  9734. };
  9735. var share = new Share();
  9736. $doc.on('click.share.amui.data-api', '[data-am-toggle="share"]', function(e) {
  9737. e.preventDefault();
  9738. share.toggle();
  9739. });
  9740. module.exports = UI.share = share;
  9741. /***/ },
  9742. /* 26 */
  9743. /***/ function(module, exports, __webpack_require__) {
  9744. var $ = __webpack_require__(1);
  9745. var UI = __webpack_require__(2);
  9746. /**
  9747. * @ver 1.1.0
  9748. * @via https://github.com/aralejs/qrcode/blob/master/src/qrcode.js
  9749. * @license http://aralejs.org/
  9750. */
  9751. var qrcodeAlgObjCache = [];
  9752. /**
  9753. * 二维码构造函数,主要用于绘制
  9754. * @param {Object} opt 传递参数
  9755. * @return {String} qrcode
  9756. * @constructor
  9757. */
  9758. var QRCode = function(opt) {
  9759. if (typeof opt === 'string') { // 只编码ASCII字符串
  9760. opt = {
  9761. text: opt
  9762. };
  9763. }
  9764. // 设置默认参数
  9765. this.options = $.extend({}, {
  9766. text: "",
  9767. render: "",
  9768. width: 256,
  9769. height: 256,
  9770. correctLevel: 3,
  9771. background: "#ffffff",
  9772. foreground: "#000000"
  9773. }, opt);
  9774. // 使用QRCodeAlg创建二维码结构
  9775. var qrCodeAlg = null;
  9776. for (var i = 0, l = qrcodeAlgObjCache.length; i < l; i++) {
  9777. if (qrcodeAlgObjCache[i].text == this.options.text && qrcodeAlgObjCache[i].text.correctLevel == this.options.correctLevel) {
  9778. qrCodeAlg = qrcodeAlgObjCache[i].obj;
  9779. break;
  9780. }
  9781. }
  9782. if (i == l) {
  9783. qrCodeAlg = new QRCodeAlg(this.options.text, this.options.correctLevel);
  9784. qrcodeAlgObjCache.push({
  9785. text: this.options.text,
  9786. correctLevel: this.options.correctLevel,
  9787. obj: qrCodeAlg
  9788. });
  9789. }
  9790. if (this.options.render) {
  9791. switch (this.options.render) {
  9792. case "canvas":
  9793. return this.createCanvas(qrCodeAlg);
  9794. case "table":
  9795. return this.createTable(qrCodeAlg);
  9796. case "svg":
  9797. return this.createSVG(qrCodeAlg);
  9798. default:
  9799. return this.createDefault(qrCodeAlg);
  9800. }
  9801. }
  9802. return this.createDefault(qrCodeAlg);
  9803. };
  9804. /**
  9805. * 使用Canvas来画二维码
  9806. * @return {}
  9807. */
  9808. QRCode.prototype.createDefault = function(qrCodeAlg) {
  9809. var canvas = document.createElement('canvas');
  9810. if (canvas.getContext)
  9811. return this.createCanvas(qrCodeAlg);
  9812. if (!!document.createElementNS && !!document.createElementNS(SVG_NS, 'svg').createSVGRect)
  9813. return this.createSVG(qrCodeAlg);
  9814. return this.createTable(qrCodeAlg);
  9815. };
  9816. QRCode.prototype.createCanvas = function(qrCodeAlg) {
  9817. //创建canvas节点
  9818. var canvas = document.createElement('canvas');
  9819. canvas.width = this.options.width;
  9820. canvas.height = this.options.height;
  9821. var ctx = canvas.getContext('2d');
  9822. //计算每个点的长宽
  9823. var tileW = (this.options.width / qrCodeAlg.getModuleCount()).toPrecision(4);
  9824. var tileH = this.options.height / qrCodeAlg.getModuleCount().toPrecision(4);
  9825. //绘制
  9826. for (var row = 0; row < qrCodeAlg.getModuleCount(); row++) {
  9827. for (var col = 0; col < qrCodeAlg.getModuleCount(); col++) {
  9828. ctx.fillStyle = qrCodeAlg.modules[row][col] ? this.options.foreground : this.options.background;
  9829. var w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW));
  9830. var h = (Math.ceil((row + 1) * tileW) - Math.floor(row * tileW));
  9831. ctx.fillRect(Math.round(col * tileW), Math.round(row * tileH), w, h);
  9832. }
  9833. }
  9834. //返回绘制的节点
  9835. return canvas;
  9836. };
  9837. /**
  9838. * 使用table来绘制二维码
  9839. * @return {}
  9840. */
  9841. QRCode.prototype.createTable = function(qrCodeAlg) {
  9842. //创建table节点
  9843. var s = [];
  9844. s.push('<table style="border:0px; margin:0px; padding:0px; border-collapse:collapse; background-color: ' +
  9845. this.options.background +
  9846. ';">');
  9847. // 计算每个节点的长宽;取整,防止点之间出现分离
  9848. var tileW = -1, tileH = -1, caculateW = -1, caculateH = -1;
  9849. tileW = caculateW = Math.floor(this.options.width / qrCodeAlg.getModuleCount());
  9850. tileH = caculateH = Math.floor(this.options.height / qrCodeAlg.getModuleCount());
  9851. if (caculateW <= 0) {
  9852. if (qrCodeAlg.getModuleCount() < 80) {
  9853. tileW = 2;
  9854. } else {
  9855. tileW = 1;
  9856. }
  9857. }
  9858. if (caculateH <= 0) {
  9859. if (qrCodeAlg.getModuleCount() < 80) {
  9860. tileH = 2;
  9861. } else {
  9862. tileH = 1;
  9863. }
  9864. }
  9865. // 绘制二维码
  9866. foreTd = '<td style="border:0px; margin:0px; padding:0px; width:' + tileW + 'px; background-color: ' + this.options.foreground + '"></td>',
  9867. backTd = '<td style="border:0px; margin:0px; padding:0px; width:' + tileW + 'px; background-color: ' + this.options.background + '"></td>',
  9868. l = qrCodeAlg.getModuleCount();
  9869. for (var row = 0; row < l; row++) {
  9870. s.push('<tr style="border:0px; margin:0px; padding:0px; height: ' + tileH + 'px">');
  9871. for (var col = 0; col < l; col++) {
  9872. s.push(qrCodeAlg.modules[row][col] ? foreTd : backTd);
  9873. }
  9874. s.push('</tr>');
  9875. }
  9876. s.push('</table>');
  9877. var span = document.createElement("span");
  9878. span.innerHTML = s.join('');
  9879. return span.firstChild;
  9880. };
  9881. /**
  9882. * 使用SVG开绘制二维码
  9883. * @return {}
  9884. */
  9885. QRCode.prototype.createSVG = function(qrCodeAlg) {
  9886. var x, dx, y, dy,
  9887. moduleCount = qrCodeAlg.getModuleCount(),
  9888. scale = this.options.height / this.options.width,
  9889. svg = '<svg xmlns="http://www.w3.org/2000/svg" '
  9890. + 'width="' + this.options.width + 'px" height="' + this.options.height + 'px" '
  9891. + 'viewbox="0 0 ' + moduleCount * 10 + ' ' + moduleCount * 10 * scale + '">',
  9892. rectHead = '<path ',
  9893. foreRect = ' style="stroke-width:0.5;stroke:' + this.options.foreground
  9894. + ';fill:' + this.options.foreground + ';"></path>',
  9895. backRect = ' style="stroke-width:0.5;stroke:' + this.options.background
  9896. + ';fill:' + this.options.background + ';"></path>';
  9897. // draw in the svg
  9898. for (var row = 0; row < moduleCount; row++) {
  9899. for (var col = 0; col < moduleCount; col++) {
  9900. x = col * 10;
  9901. y = row * 10 * scale;
  9902. dx = (col + 1) * 10;
  9903. dy = (row + 1) * 10 * scale;
  9904. svg += rectHead + 'd="M ' + x + ',' + y
  9905. + ' L ' + dx + ',' + y
  9906. + ' L ' + dx + ',' + dy
  9907. + ' L ' + x + ',' + dy
  9908. + ' Z"';
  9909. svg += qrCodeAlg.modules[row][col] ? foreRect : backRect;
  9910. }
  9911. }
  9912. svg += '</svg>';
  9913. // return just built svg
  9914. return $(svg)[0];
  9915. };
  9916. /**
  9917. * 获取单个字符的utf8编码
  9918. * unicode BMP平面约65535个字符
  9919. * @param {num} code
  9920. * return {array}
  9921. */
  9922. function unicodeFormat8(code) {
  9923. // 1 byte
  9924. if (code < 128) {
  9925. return [code];
  9926. // 2 bytes
  9927. } else if (code < 2048) {
  9928. c0 = 192 + (code >> 6);
  9929. c1 = 128 + (code & 63);
  9930. return [c0, c1];
  9931. // 3 bytes
  9932. } else {
  9933. c0 = 224 + (code >> 12);
  9934. c1 = 128 + (code >> 6 & 63);
  9935. c2 = 128 + (code & 63);
  9936. return [c0, c1, c2];
  9937. }
  9938. }
  9939. /**
  9940. * 获取字符串的utf8编码字节串
  9941. * @param {string} string
  9942. * @return {array}
  9943. */
  9944. function getUTF8Bytes(string) {
  9945. var utf8codes = [];
  9946. for (var i = 0; i < string.length; i++) {
  9947. var code = string.charCodeAt(i);
  9948. var utf8 = unicodeFormat8(code);
  9949. for (var j = 0; j < utf8.length; j++) {
  9950. utf8codes.push(utf8[j]);
  9951. }
  9952. }
  9953. return utf8codes;
  9954. }
  9955. /**
  9956. * 二维码算法实现
  9957. * @param {string} data 要编码的信息字符串
  9958. * @param {num} errorCorrectLevel 纠错等级
  9959. */
  9960. function QRCodeAlg(data, errorCorrectLevel) {
  9961. this.typeNumber = -1; // 版本
  9962. this.errorCorrectLevel = errorCorrectLevel;
  9963. this.modules = null; // 二维矩阵,存放最终结果
  9964. this.moduleCount = 0; // 矩阵大小
  9965. this.dataCache = null; // 数据缓存
  9966. this.rsBlocks = null; // 版本数据信息
  9967. this.totalDataCount = -1; // 可使用的数据量
  9968. this.data = data;
  9969. this.utf8bytes = getUTF8Bytes(data);
  9970. this.make();
  9971. }
  9972. QRCodeAlg.prototype = {
  9973. constructor: QRCodeAlg,
  9974. /**
  9975. * 获取二维码矩阵大小
  9976. * @return {num} 矩阵大小
  9977. */
  9978. getModuleCount: function() {
  9979. return this.moduleCount;
  9980. },
  9981. /**
  9982. * 编码
  9983. */
  9984. make: function() {
  9985. this.getRightType();
  9986. this.dataCache = this.createData();
  9987. this.createQrcode();
  9988. },
  9989. /**
  9990. * 设置二位矩阵功能图形
  9991. * @param {bool} test 表示是否在寻找最好掩膜阶段
  9992. * @param {num} maskPattern 掩膜的版本
  9993. */
  9994. makeImpl: function(maskPattern) {
  9995. this.moduleCount = this.typeNumber * 4 + 17;
  9996. this.modules = new Array(this.moduleCount);
  9997. for (var row = 0; row < this.moduleCount; row++) {
  9998. this.modules[row] = new Array(this.moduleCount);
  9999. }
  10000. this.setupPositionProbePattern(0, 0);
  10001. this.setupPositionProbePattern(this.moduleCount - 7, 0);
  10002. this.setupPositionProbePattern(0, this.moduleCount - 7);
  10003. this.setupPositionAdjustPattern();
  10004. this.setupTimingPattern();
  10005. this.setupTypeInfo(true, maskPattern);
  10006. if (this.typeNumber >= 7) {
  10007. this.setupTypeNumber(true);
  10008. }
  10009. this.mapData(this.dataCache, maskPattern);
  10010. },
  10011. /**
  10012. * 设置二维码的位置探测图形
  10013. * @param {num} row 探测图形的中心横坐标
  10014. * @param {num} col 探测图形的中心纵坐标
  10015. */
  10016. setupPositionProbePattern: function(row, col) {
  10017. for (var r = -1; r <= 7; r++) {
  10018. if (row + r <= -1 || this.moduleCount <= row + r) continue;
  10019. for (var c = -1; c <= 7; c++) {
  10020. if (col + c <= -1 || this.moduleCount <= col + c) continue;
  10021. if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || (0 <= c && c <= 6 && (r == 0 || r == 6)) || (2 <= r && r <= 4 && 2 <= c && c <= 4)) {
  10022. this.modules[row + r][col + c] = true;
  10023. } else {
  10024. this.modules[row + r][col + c] = false;
  10025. }
  10026. }
  10027. }
  10028. },
  10029. /**
  10030. * 创建二维码
  10031. * @return {[type]} [description]
  10032. */
  10033. createQrcode: function() {
  10034. var minLostPoint = 0;
  10035. var pattern = 0;
  10036. var bestModules = null;
  10037. for (var i = 0; i < 8; i++) {
  10038. this.makeImpl(i);
  10039. var lostPoint = QRUtil.getLostPoint(this);
  10040. if (i == 0 || minLostPoint > lostPoint) {
  10041. minLostPoint = lostPoint;
  10042. pattern = i;
  10043. bestModules = this.modules;
  10044. }
  10045. }
  10046. this.modules = bestModules;
  10047. this.setupTypeInfo(false, pattern);
  10048. if (this.typeNumber >= 7) {
  10049. this.setupTypeNumber(false);
  10050. }
  10051. },
  10052. /**
  10053. * 设置定位图形
  10054. * @return {[type]} [description]
  10055. */
  10056. setupTimingPattern: function() {
  10057. for (var r = 8; r < this.moduleCount - 8; r++) {
  10058. if (this.modules[r][6] != null) {
  10059. continue;
  10060. }
  10061. this.modules[r][6] = (r % 2 == 0);
  10062. if (this.modules[6][r] != null) {
  10063. continue;
  10064. }
  10065. this.modules[6][r] = (r % 2 == 0);
  10066. }
  10067. },
  10068. /**
  10069. * 设置矫正图形
  10070. * @return {[type]} [description]
  10071. */
  10072. setupPositionAdjustPattern: function() {
  10073. var pos = QRUtil.getPatternPosition(this.typeNumber);
  10074. for (var i = 0; i < pos.length; i++) {
  10075. for (var j = 0; j < pos.length; j++) {
  10076. var row = pos[i];
  10077. var col = pos[j];
  10078. if (this.modules[row][col] != null) {
  10079. continue;
  10080. }
  10081. for (var r = -2; r <= 2; r++) {
  10082. for (var c = -2; c <= 2; c++) {
  10083. if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) {
  10084. this.modules[row + r][col + c] = true;
  10085. } else {
  10086. this.modules[row + r][col + c] = false;
  10087. }
  10088. }
  10089. }
  10090. }
  10091. }
  10092. },
  10093. /**
  10094. * 设置版本信息(7以上版本才有)
  10095. * @param {bool} test 是否处于判断最佳掩膜阶段
  10096. * @return {[type]} [description]
  10097. */
  10098. setupTypeNumber: function(test) {
  10099. var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
  10100. for (var i = 0; i < 18; i++) {
  10101. var mod = (!test && ((bits >> i) & 1) == 1);
  10102. this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
  10103. this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
  10104. }
  10105. },
  10106. /**
  10107. * 设置格式信息(纠错等级和掩膜版本)
  10108. * @param {bool} test
  10109. * @param {num} maskPattern 掩膜版本
  10110. * @return {}
  10111. */
  10112. setupTypeInfo: function(test, maskPattern) {
  10113. var data = (QRErrorCorrectLevel[this.errorCorrectLevel] << 3) | maskPattern;
  10114. var bits = QRUtil.getBCHTypeInfo(data);
  10115. // vertical
  10116. for (var i = 0; i < 15; i++) {
  10117. var mod = (!test && ((bits >> i) & 1) == 1);
  10118. if (i < 6) {
  10119. this.modules[i][8] = mod;
  10120. } else if (i < 8) {
  10121. this.modules[i + 1][8] = mod;
  10122. } else {
  10123. this.modules[this.moduleCount - 15 + i][8] = mod;
  10124. }
  10125. // horizontal
  10126. var mod = (!test && ((bits >> i) & 1) == 1);
  10127. if (i < 8) {
  10128. this.modules[8][this.moduleCount - i - 1] = mod;
  10129. } else if (i < 9) {
  10130. this.modules[8][15 - i - 1 + 1] = mod;
  10131. } else {
  10132. this.modules[8][15 - i - 1] = mod;
  10133. }
  10134. }
  10135. // fixed module
  10136. this.modules[this.moduleCount - 8][8] = (!test);
  10137. },
  10138. /**
  10139. * 数据编码
  10140. * @return {[type]} [description]
  10141. */
  10142. createData: function() {
  10143. var buffer = new QRBitBuffer();
  10144. var lengthBits = this.typeNumber > 9 ? 16 : 8;
  10145. buffer.put(4, 4); //添加模式
  10146. buffer.put(this.utf8bytes.length, lengthBits);
  10147. for (var i = 0, l = this.utf8bytes.length; i < l; i++) {
  10148. buffer.put(this.utf8bytes[i], 8);
  10149. }
  10150. if (buffer.length + 4 <= this.totalDataCount * 8) {
  10151. buffer.put(0, 4);
  10152. }
  10153. // padding
  10154. while (buffer.length % 8 != 0) {
  10155. buffer.putBit(false);
  10156. }
  10157. // padding
  10158. while (true) {
  10159. if (buffer.length >= this.totalDataCount * 8) {
  10160. break;
  10161. }
  10162. buffer.put(QRCodeAlg.PAD0, 8);
  10163. if (buffer.length >= this.totalDataCount * 8) {
  10164. break;
  10165. }
  10166. buffer.put(QRCodeAlg.PAD1, 8);
  10167. }
  10168. return this.createBytes(buffer);
  10169. },
  10170. /**
  10171. * 纠错码编码
  10172. * @param {buffer} buffer 数据编码
  10173. * @return {[type]}
  10174. */
  10175. createBytes: function(buffer) {
  10176. var offset = 0;
  10177. var maxDcCount = 0;
  10178. var maxEcCount = 0;
  10179. var length = this.rsBlock.length / 3;
  10180. var rsBlocks = new Array();
  10181. for (var i = 0; i < length; i++) {
  10182. var count = this.rsBlock[i * 3 + 0];
  10183. var totalCount = this.rsBlock[i * 3 + 1];
  10184. var dataCount = this.rsBlock[i * 3 + 2];
  10185. for (var j = 0; j < count; j++) {
  10186. rsBlocks.push([dataCount, totalCount]);
  10187. }
  10188. }
  10189. var dcdata = new Array(rsBlocks.length);
  10190. var ecdata = new Array(rsBlocks.length);
  10191. for (var r = 0; r < rsBlocks.length; r++) {
  10192. var dcCount = rsBlocks[r][0];
  10193. var ecCount = rsBlocks[r][1] - dcCount;
  10194. maxDcCount = Math.max(maxDcCount, dcCount);
  10195. maxEcCount = Math.max(maxEcCount, ecCount);
  10196. dcdata[r] = new Array(dcCount);
  10197. for (var i = 0; i < dcdata[r].length; i++) {
  10198. dcdata[r][i] = 0xff & buffer.buffer[i + offset];
  10199. }
  10200. offset += dcCount;
  10201. var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
  10202. var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
  10203. var modPoly = rawPoly.mod(rsPoly);
  10204. ecdata[r] = new Array(rsPoly.getLength() - 1);
  10205. for (var i = 0; i < ecdata[r].length; i++) {
  10206. var modIndex = i + modPoly.getLength() - ecdata[r].length;
  10207. ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;
  10208. }
  10209. }
  10210. var data = new Array(this.totalDataCount);
  10211. var index = 0;
  10212. for (var i = 0; i < maxDcCount; i++) {
  10213. for (var r = 0; r < rsBlocks.length; r++) {
  10214. if (i < dcdata[r].length) {
  10215. data[index++] = dcdata[r][i];
  10216. }
  10217. }
  10218. }
  10219. for (var i = 0; i < maxEcCount; i++) {
  10220. for (var r = 0; r < rsBlocks.length; r++) {
  10221. if (i < ecdata[r].length) {
  10222. data[index++] = ecdata[r][i];
  10223. }
  10224. }
  10225. }
  10226. return data;
  10227. },
  10228. /**
  10229. * 布置模块,构建最终信息
  10230. * @param {} data
  10231. * @param {} maskPattern
  10232. * @return {}
  10233. */
  10234. mapData: function(data, maskPattern) {
  10235. var inc = -1;
  10236. var row = this.moduleCount - 1;
  10237. var bitIndex = 7;
  10238. var byteIndex = 0;
  10239. for (var col = this.moduleCount - 1; col > 0; col -= 2) {
  10240. if (col == 6) col--;
  10241. while (true) {
  10242. for (var c = 0; c < 2; c++) {
  10243. if (this.modules[row][col - c] == null) {
  10244. var dark = false;
  10245. if (byteIndex < data.length) {
  10246. dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);
  10247. }
  10248. var mask = QRUtil.getMask(maskPattern, row, col - c);
  10249. if (mask) {
  10250. dark = !dark;
  10251. }
  10252. this.modules[row][col - c] = dark;
  10253. bitIndex--;
  10254. if (bitIndex == -1) {
  10255. byteIndex++;
  10256. bitIndex = 7;
  10257. }
  10258. }
  10259. }
  10260. row += inc;
  10261. if (row < 0 || this.moduleCount <= row) {
  10262. row -= inc;
  10263. inc = -inc;
  10264. break;
  10265. }
  10266. }
  10267. }
  10268. }
  10269. };
  10270. /**
  10271. * 填充字段
  10272. */
  10273. QRCodeAlg.PAD0 = 0xEC;
  10274. QRCodeAlg.PAD1 = 0x11;
  10275. //---------------------------------------------------------------------
  10276. // 纠错等级对应的编码
  10277. //---------------------------------------------------------------------
  10278. var QRErrorCorrectLevel = [1, 0, 3, 2];
  10279. //---------------------------------------------------------------------
  10280. // 掩膜版本
  10281. //---------------------------------------------------------------------
  10282. var QRMaskPattern = {
  10283. PATTERN000: 0,
  10284. PATTERN001: 1,
  10285. PATTERN010: 2,
  10286. PATTERN011: 3,
  10287. PATTERN100: 4,
  10288. PATTERN101: 5,
  10289. PATTERN110: 6,
  10290. PATTERN111: 7
  10291. };
  10292. //---------------------------------------------------------------------
  10293. // 工具类
  10294. //---------------------------------------------------------------------
  10295. var QRUtil = {
  10296. /*
  10297. 每个版本矫正图形的位置
  10298. */
  10299. PATTERN_POSITION_TABLE: [
  10300. [],
  10301. [6, 18],
  10302. [6, 22],
  10303. [6, 26],
  10304. [6, 30],
  10305. [6, 34],
  10306. [6, 22, 38],
  10307. [6, 24, 42],
  10308. [6, 26, 46],
  10309. [6, 28, 50],
  10310. [6, 30, 54],
  10311. [6, 32, 58],
  10312. [6, 34, 62],
  10313. [6, 26, 46, 66],
  10314. [6, 26, 48, 70],
  10315. [6, 26, 50, 74],
  10316. [6, 30, 54, 78],
  10317. [6, 30, 56, 82],
  10318. [6, 30, 58, 86],
  10319. [6, 34, 62, 90],
  10320. [6, 28, 50, 72, 94],
  10321. [6, 26, 50, 74, 98],
  10322. [6, 30, 54, 78, 102],
  10323. [6, 28, 54, 80, 106],
  10324. [6, 32, 58, 84, 110],
  10325. [6, 30, 58, 86, 114],
  10326. [6, 34, 62, 90, 118],
  10327. [6, 26, 50, 74, 98, 122],
  10328. [6, 30, 54, 78, 102, 126],
  10329. [6, 26, 52, 78, 104, 130],
  10330. [6, 30, 56, 82, 108, 134],
  10331. [6, 34, 60, 86, 112, 138],
  10332. [6, 30, 58, 86, 114, 142],
  10333. [6, 34, 62, 90, 118, 146],
  10334. [6, 30, 54, 78, 102, 126, 150],
  10335. [6, 24, 50, 76, 102, 128, 154],
  10336. [6, 28, 54, 80, 106, 132, 158],
  10337. [6, 32, 58, 84, 110, 136, 162],
  10338. [6, 26, 54, 82, 110, 138, 166],
  10339. [6, 30, 58, 86, 114, 142, 170]
  10340. ],
  10341. G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
  10342. G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
  10343. G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
  10344. /*
  10345. BCH编码格式信息
  10346. */
  10347. getBCHTypeInfo: function(data) {
  10348. var d = data << 10;
  10349. while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
  10350. d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)));
  10351. }
  10352. return ((data << 10) | d) ^ QRUtil.G15_MASK;
  10353. },
  10354. /*
  10355. BCH编码版本信息
  10356. */
  10357. getBCHTypeNumber: function(data) {
  10358. var d = data << 12;
  10359. while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
  10360. d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)));
  10361. }
  10362. return (data << 12) | d;
  10363. },
  10364. /*
  10365. 获取BCH位信息
  10366. */
  10367. getBCHDigit: function(data) {
  10368. var digit = 0;
  10369. while (data != 0) {
  10370. digit++;
  10371. data >>>= 1;
  10372. }
  10373. return digit;
  10374. },
  10375. /*
  10376. 获取版本对应的矫正图形位置
  10377. */
  10378. getPatternPosition: function(typeNumber) {
  10379. return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
  10380. },
  10381. /*
  10382. 掩膜算法
  10383. */
  10384. getMask: function(maskPattern, i, j) {
  10385. switch (maskPattern) {
  10386. case QRMaskPattern.PATTERN000:
  10387. return (i + j) % 2 == 0;
  10388. case QRMaskPattern.PATTERN001:
  10389. return i % 2 == 0;
  10390. case QRMaskPattern.PATTERN010:
  10391. return j % 3 == 0;
  10392. case QRMaskPattern.PATTERN011:
  10393. return (i + j) % 3 == 0;
  10394. case QRMaskPattern.PATTERN100:
  10395. return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
  10396. case QRMaskPattern.PATTERN101:
  10397. return (i * j) % 2 + (i * j) % 3 == 0;
  10398. case QRMaskPattern.PATTERN110:
  10399. return ((i * j) % 2 + (i * j) % 3) % 2 == 0;
  10400. case QRMaskPattern.PATTERN111:
  10401. return ((i * j) % 3 + (i + j) % 2) % 2 == 0;
  10402. default:
  10403. throw new Error("bad maskPattern:" + maskPattern);
  10404. }
  10405. },
  10406. /*
  10407. 获取RS的纠错多项式
  10408. */
  10409. getErrorCorrectPolynomial: function(errorCorrectLength) {
  10410. var a = new QRPolynomial([1], 0);
  10411. for (var i = 0; i < errorCorrectLength; i++) {
  10412. a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));
  10413. }
  10414. return a;
  10415. },
  10416. /*
  10417. 获取评价
  10418. */
  10419. getLostPoint: function(qrCode) {
  10420. var moduleCount = qrCode.getModuleCount(),
  10421. lostPoint = 0,
  10422. darkCount = 0;
  10423. for (var row = 0; row < moduleCount; row++) {
  10424. var sameCount = 0;
  10425. var head = qrCode.modules[row][0];
  10426. for (var col = 0; col < moduleCount; col++) {
  10427. var current = qrCode.modules[row][col];
  10428. //level 3 评价
  10429. if (col < moduleCount - 6) {
  10430. if (current && !qrCode.modules[row][col + 1] && qrCode.modules[row][col + 2] && qrCode.modules[row][col + 3] && qrCode.modules[row][col + 4] && !qrCode.modules[row][col + 5] && qrCode.modules[row][col + 6]) {
  10431. if (col < moduleCount - 10) {
  10432. if (qrCode.modules[row][col + 7] && qrCode.modules[row][col + 8] && qrCode.modules[row][col + 9] && qrCode.modules[row][col + 10]) {
  10433. lostPoint += 40;
  10434. }
  10435. } else if (col > 3) {
  10436. if (qrCode.modules[row][col - 1] && qrCode.modules[row][col - 2] && qrCode.modules[row][col - 3] && qrCode.modules[row][col - 4]) {
  10437. lostPoint += 40;
  10438. }
  10439. }
  10440. }
  10441. }
  10442. //level 2 评价
  10443. if ((row < moduleCount - 1) && (col < moduleCount - 1)) {
  10444. var count = 0;
  10445. if (current) count++;
  10446. if (qrCode.modules[row + 1][col]) count++;
  10447. if (qrCode.modules[row][col + 1]) count++;
  10448. if (qrCode.modules[row + 1][col + 1]) count++;
  10449. if (count == 0 || count == 4) {
  10450. lostPoint += 3;
  10451. }
  10452. }
  10453. //level 1 评价
  10454. if (head ^ current) {
  10455. sameCount++;
  10456. } else {
  10457. head = current;
  10458. if (sameCount >= 5) {
  10459. lostPoint += (3 + sameCount - 5);
  10460. }
  10461. sameCount = 1;
  10462. }
  10463. //level 4 评价
  10464. if (current) {
  10465. darkCount++;
  10466. }
  10467. }
  10468. }
  10469. for (var col = 0; col < moduleCount; col++) {
  10470. var sameCount = 0;
  10471. var head = qrCode.modules[0][col];
  10472. for (var row = 0; row < moduleCount; row++) {
  10473. var current = qrCode.modules[row][col];
  10474. //level 3 评价
  10475. if (row < moduleCount - 6) {
  10476. if (current && !qrCode.modules[row + 1][col] && qrCode.modules[row + 2][col] && qrCode.modules[row + 3][col] && qrCode.modules[row + 4][col] && !qrCode.modules[row + 5][col] && qrCode.modules[row + 6][col]) {
  10477. if (row < moduleCount - 10) {
  10478. if (qrCode.modules[row + 7][col] && qrCode.modules[row + 8][col] && qrCode.modules[row + 9][col] && qrCode.modules[row + 10][col]) {
  10479. lostPoint += 40;
  10480. }
  10481. } else if (row > 3) {
  10482. if (qrCode.modules[row - 1][col] && qrCode.modules[row - 2][col] && qrCode.modules[row - 3][col] && qrCode.modules[row - 4][col]) {
  10483. lostPoint += 40;
  10484. }
  10485. }
  10486. }
  10487. }
  10488. //level 1 评价
  10489. if (head ^ current) {
  10490. sameCount++;
  10491. } else {
  10492. head = current;
  10493. if (sameCount >= 5) {
  10494. lostPoint += (3 + sameCount - 5);
  10495. }
  10496. sameCount = 1;
  10497. }
  10498. }
  10499. }
  10500. // LEVEL4
  10501. var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
  10502. lostPoint += ratio * 10;
  10503. return lostPoint;
  10504. }
  10505. };
  10506. //---------------------------------------------------------------------
  10507. // QRMath使用的数学工具
  10508. //---------------------------------------------------------------------
  10509. var QRMath = {
  10510. /*
  10511. 将n转化为a^m
  10512. */
  10513. glog: function(n) {
  10514. if (n < 1) {
  10515. throw new Error("glog(" + n + ")");
  10516. }
  10517. return QRMath.LOG_TABLE[n];
  10518. },
  10519. /*
  10520. 将a^m转化为n
  10521. */
  10522. gexp: function(n) {
  10523. while (n < 0) {
  10524. n += 255;
  10525. }
  10526. while (n >= 256) {
  10527. n -= 255;
  10528. }
  10529. return QRMath.EXP_TABLE[n];
  10530. },
  10531. EXP_TABLE: new Array(256),
  10532. LOG_TABLE: new Array(256)
  10533. };
  10534. for (var i = 0; i < 8; i++) {
  10535. QRMath.EXP_TABLE[i] = 1 << i;
  10536. }
  10537. for (var i = 8; i < 256; i++) {
  10538. QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8];
  10539. }
  10540. for (var i = 0; i < 255; i++) {
  10541. QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;
  10542. }
  10543. //---------------------------------------------------------------------
  10544. // QRPolynomial 多项式
  10545. //---------------------------------------------------------------------
  10546. /**
  10547. * 多项式类
  10548. * @param {Array} num 系数
  10549. * @param {num} shift a^shift
  10550. */
  10551. function QRPolynomial(num, shift) {
  10552. if (num.length == undefined) {
  10553. throw new Error(num.length + "/" + shift);
  10554. }
  10555. var offset = 0;
  10556. while (offset < num.length && num[offset] == 0) {
  10557. offset++;
  10558. }
  10559. this.num = new Array(num.length - offset + shift);
  10560. for (var i = 0; i < num.length - offset; i++) {
  10561. this.num[i] = num[i + offset];
  10562. }
  10563. }
  10564. QRPolynomial.prototype = {
  10565. get: function(index) {
  10566. return this.num[index];
  10567. },
  10568. getLength: function() {
  10569. return this.num.length;
  10570. },
  10571. /**
  10572. * 多项式乘法
  10573. * @param {QRPolynomial} e 被乘多项式
  10574. * @return {[type]} [description]
  10575. */
  10576. multiply: function(e) {
  10577. var num = new Array(this.getLength() + e.getLength() - 1);
  10578. for (var i = 0; i < this.getLength(); i++) {
  10579. for (var j = 0; j < e.getLength(); j++) {
  10580. num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
  10581. }
  10582. }
  10583. return new QRPolynomial(num, 0);
  10584. },
  10585. /**
  10586. * 多项式模运算
  10587. * @param {QRPolynomial} e 模多项式
  10588. * @return {}
  10589. */
  10590. mod: function(e) {
  10591. var tl = this.getLength(),
  10592. el = e.getLength();
  10593. if (tl - el < 0) {
  10594. return this;
  10595. }
  10596. var num = new Array(tl);
  10597. for (var i = 0; i < tl; i++) {
  10598. num[i] = this.get(i);
  10599. }
  10600. while (num.length >= el) {
  10601. var ratio = QRMath.glog(num[0]) - QRMath.glog(e.get(0));
  10602. for (var i = 0; i < e.getLength(); i++) {
  10603. num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
  10604. }
  10605. while (num[0] == 0) {
  10606. num.shift();
  10607. }
  10608. }
  10609. return new QRPolynomial(num, 0);
  10610. }
  10611. };
  10612. //---------------------------------------------------------------------
  10613. // RS_BLOCK_TABLE
  10614. //---------------------------------------------------------------------
  10615. /*
  10616. 二维码各个版本信息[块数, 每块中的数据块数, 每块中的信息块数]
  10617. */
  10618. var RS_BLOCK_TABLE = [
  10619. // L
  10620. // M
  10621. // Q
  10622. // H
  10623. // 1
  10624. [1, 26, 19],
  10625. [1, 26, 16],
  10626. [1, 26, 13],
  10627. [1, 26, 9],
  10628. // 2
  10629. [1, 44, 34],
  10630. [1, 44, 28],
  10631. [1, 44, 22],
  10632. [1, 44, 16],
  10633. // 3
  10634. [1, 70, 55],
  10635. [1, 70, 44],
  10636. [2, 35, 17],
  10637. [2, 35, 13],
  10638. // 4
  10639. [1, 100, 80],
  10640. [2, 50, 32],
  10641. [2, 50, 24],
  10642. [4, 25, 9],
  10643. // 5
  10644. [1, 134, 108],
  10645. [2, 67, 43],
  10646. [2, 33, 15, 2, 34, 16],
  10647. [2, 33, 11, 2, 34, 12],
  10648. // 6
  10649. [2, 86, 68],
  10650. [4, 43, 27],
  10651. [4, 43, 19],
  10652. [4, 43, 15],
  10653. // 7
  10654. [2, 98, 78],
  10655. [4, 49, 31],
  10656. [2, 32, 14, 4, 33, 15],
  10657. [4, 39, 13, 1, 40, 14],
  10658. // 8
  10659. [2, 121, 97],
  10660. [2, 60, 38, 2, 61, 39],
  10661. [4, 40, 18, 2, 41, 19],
  10662. [4, 40, 14, 2, 41, 15],
  10663. // 9
  10664. [2, 146, 116],
  10665. [3, 58, 36, 2, 59, 37],
  10666. [4, 36, 16, 4, 37, 17],
  10667. [4, 36, 12, 4, 37, 13],
  10668. // 10
  10669. [2, 86, 68, 2, 87, 69],
  10670. [4, 69, 43, 1, 70, 44],
  10671. [6, 43, 19, 2, 44, 20],
  10672. [6, 43, 15, 2, 44, 16],
  10673. // 11
  10674. [4, 101, 81],
  10675. [1, 80, 50, 4, 81, 51],
  10676. [4, 50, 22, 4, 51, 23],
  10677. [3, 36, 12, 8, 37, 13],
  10678. // 12
  10679. [2, 116, 92, 2, 117, 93],
  10680. [6, 58, 36, 2, 59, 37],
  10681. [4, 46, 20, 6, 47, 21],
  10682. [7, 42, 14, 4, 43, 15],
  10683. // 13
  10684. [4, 133, 107],
  10685. [8, 59, 37, 1, 60, 38],
  10686. [8, 44, 20, 4, 45, 21],
  10687. [12, 33, 11, 4, 34, 12],
  10688. // 14
  10689. [3, 145, 115, 1, 146, 116],
  10690. [4, 64, 40, 5, 65, 41],
  10691. [11, 36, 16, 5, 37, 17],
  10692. [11, 36, 12, 5, 37, 13],
  10693. // 15
  10694. [5, 109, 87, 1, 110, 88],
  10695. [5, 65, 41, 5, 66, 42],
  10696. [5, 54, 24, 7, 55, 25],
  10697. [11, 36, 12],
  10698. // 16
  10699. [5, 122, 98, 1, 123, 99],
  10700. [7, 73, 45, 3, 74, 46],
  10701. [15, 43, 19, 2, 44, 20],
  10702. [3, 45, 15, 13, 46, 16],
  10703. // 17
  10704. [1, 135, 107, 5, 136, 108],
  10705. [10, 74, 46, 1, 75, 47],
  10706. [1, 50, 22, 15, 51, 23],
  10707. [2, 42, 14, 17, 43, 15],
  10708. // 18
  10709. [5, 150, 120, 1, 151, 121],
  10710. [9, 69, 43, 4, 70, 44],
  10711. [17, 50, 22, 1, 51, 23],
  10712. [2, 42, 14, 19, 43, 15],
  10713. // 19
  10714. [3, 141, 113, 4, 142, 114],
  10715. [3, 70, 44, 11, 71, 45],
  10716. [17, 47, 21, 4, 48, 22],
  10717. [9, 39, 13, 16, 40, 14],
  10718. // 20
  10719. [3, 135, 107, 5, 136, 108],
  10720. [3, 67, 41, 13, 68, 42],
  10721. [15, 54, 24, 5, 55, 25],
  10722. [15, 43, 15, 10, 44, 16],
  10723. // 21
  10724. [4, 144, 116, 4, 145, 117],
  10725. [17, 68, 42],
  10726. [17, 50, 22, 6, 51, 23],
  10727. [19, 46, 16, 6, 47, 17],
  10728. // 22
  10729. [2, 139, 111, 7, 140, 112],
  10730. [17, 74, 46],
  10731. [7, 54, 24, 16, 55, 25],
  10732. [34, 37, 13],
  10733. // 23
  10734. [4, 151, 121, 5, 152, 122],
  10735. [4, 75, 47, 14, 76, 48],
  10736. [11, 54, 24, 14, 55, 25],
  10737. [16, 45, 15, 14, 46, 16],
  10738. // 24
  10739. [6, 147, 117, 4, 148, 118],
  10740. [6, 73, 45, 14, 74, 46],
  10741. [11, 54, 24, 16, 55, 25],
  10742. [30, 46, 16, 2, 47, 17],
  10743. // 25
  10744. [8, 132, 106, 4, 133, 107],
  10745. [8, 75, 47, 13, 76, 48],
  10746. [7, 54, 24, 22, 55, 25],
  10747. [22, 45, 15, 13, 46, 16],
  10748. // 26
  10749. [10, 142, 114, 2, 143, 115],
  10750. [19, 74, 46, 4, 75, 47],
  10751. [28, 50, 22, 6, 51, 23],
  10752. [33, 46, 16, 4, 47, 17],
  10753. // 27
  10754. [8, 152, 122, 4, 153, 123],
  10755. [22, 73, 45, 3, 74, 46],
  10756. [8, 53, 23, 26, 54, 24],
  10757. [12, 45, 15, 28, 46, 16],
  10758. // 28
  10759. [3, 147, 117, 10, 148, 118],
  10760. [3, 73, 45, 23, 74, 46],
  10761. [4, 54, 24, 31, 55, 25],
  10762. [11, 45, 15, 31, 46, 16],
  10763. // 29
  10764. [7, 146, 116, 7, 147, 117],
  10765. [21, 73, 45, 7, 74, 46],
  10766. [1, 53, 23, 37, 54, 24],
  10767. [19, 45, 15, 26, 46, 16],
  10768. // 30
  10769. [5, 145, 115, 10, 146, 116],
  10770. [19, 75, 47, 10, 76, 48],
  10771. [15, 54, 24, 25, 55, 25],
  10772. [23, 45, 15, 25, 46, 16],
  10773. // 31
  10774. [13, 145, 115, 3, 146, 116],
  10775. [2, 74, 46, 29, 75, 47],
  10776. [42, 54, 24, 1, 55, 25],
  10777. [23, 45, 15, 28, 46, 16],
  10778. // 32
  10779. [17, 145, 115],
  10780. [10, 74, 46, 23, 75, 47],
  10781. [10, 54, 24, 35, 55, 25],
  10782. [19, 45, 15, 35, 46, 16],
  10783. // 33
  10784. [17, 145, 115, 1, 146, 116],
  10785. [14, 74, 46, 21, 75, 47],
  10786. [29, 54, 24, 19, 55, 25],
  10787. [11, 45, 15, 46, 46, 16],
  10788. // 34
  10789. [13, 145, 115, 6, 146, 116],
  10790. [14, 74, 46, 23, 75, 47],
  10791. [44, 54, 24, 7, 55, 25],
  10792. [59, 46, 16, 1, 47, 17],
  10793. // 35
  10794. [12, 151, 121, 7, 152, 122],
  10795. [12, 75, 47, 26, 76, 48],
  10796. [39, 54, 24, 14, 55, 25],
  10797. [22, 45, 15, 41, 46, 16],
  10798. // 36
  10799. [6, 151, 121, 14, 152, 122],
  10800. [6, 75, 47, 34, 76, 48],
  10801. [46, 54, 24, 10, 55, 25],
  10802. [2, 45, 15, 64, 46, 16],
  10803. // 37
  10804. [17, 152, 122, 4, 153, 123],
  10805. [29, 74, 46, 14, 75, 47],
  10806. [49, 54, 24, 10, 55, 25],
  10807. [24, 45, 15, 46, 46, 16],
  10808. // 38
  10809. [4, 152, 122, 18, 153, 123],
  10810. [13, 74, 46, 32, 75, 47],
  10811. [48, 54, 24, 14, 55, 25],
  10812. [42, 45, 15, 32, 46, 16],
  10813. // 39
  10814. [20, 147, 117, 4, 148, 118],
  10815. [40, 75, 47, 7, 76, 48],
  10816. [43, 54, 24, 22, 55, 25],
  10817. [10, 45, 15, 67, 46, 16],
  10818. // 40
  10819. [19, 148, 118, 6, 149, 119],
  10820. [18, 75, 47, 31, 76, 48],
  10821. [34, 54, 24, 34, 55, 25],
  10822. [20, 45, 15, 61, 46, 16]
  10823. ];
  10824. /**
  10825. * 根据数据获取对应版本
  10826. * @return {[type]} [description]
  10827. */
  10828. QRCodeAlg.prototype.getRightType = function() {
  10829. for (var typeNumber = 1; typeNumber < 41; typeNumber++) {
  10830. var rsBlock = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + this.errorCorrectLevel];
  10831. if (rsBlock == undefined) {
  10832. throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + this.errorCorrectLevel);
  10833. }
  10834. var length = rsBlock.length / 3;
  10835. var totalDataCount = 0;
  10836. for (var i = 0; i < length; i++) {
  10837. var count = rsBlock[i * 3 + 0];
  10838. var dataCount = rsBlock[i * 3 + 2];
  10839. totalDataCount += dataCount * count;
  10840. }
  10841. var lengthBytes = typeNumber > 9 ? 2 : 1;
  10842. if (this.utf8bytes.length + lengthBytes < totalDataCount || typeNumber == 40) {
  10843. this.typeNumber = typeNumber;
  10844. this.rsBlock = rsBlock;
  10845. this.totalDataCount = totalDataCount;
  10846. break;
  10847. }
  10848. }
  10849. };
  10850. //---------------------------------------------------------------------
  10851. // QRBitBuffer
  10852. //---------------------------------------------------------------------
  10853. function QRBitBuffer() {
  10854. this.buffer = new Array();
  10855. this.length = 0;
  10856. }
  10857. QRBitBuffer.prototype = {
  10858. get: function(index) {
  10859. var bufIndex = Math.floor(index / 8);
  10860. return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1);
  10861. },
  10862. put: function(num, length) {
  10863. for (var i = 0; i < length; i++) {
  10864. this.putBit(((num >>> (length - i - 1)) & 1));
  10865. }
  10866. },
  10867. putBit: function(bit) {
  10868. var bufIndex = Math.floor(this.length / 8);
  10869. if (this.buffer.length <= bufIndex) {
  10870. this.buffer.push(0);
  10871. }
  10872. if (bit) {
  10873. this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));
  10874. }
  10875. this.length++;
  10876. }
  10877. };
  10878. /**
  10879. * 获取单个字符的utf8编码
  10880. * unicode BMP平面约65535个字符
  10881. * @param {num} code
  10882. * return {array}
  10883. */
  10884. function unicodeFormat8(code) {
  10885. // 1 byte
  10886. if (code < 128) {
  10887. return [code];
  10888. // 2 bytes
  10889. } else if (code < 2048) {
  10890. c0 = 192 + (code >> 6);
  10891. c1 = 128 + (code & 63);
  10892. return [c0, c1];
  10893. // 3 bytes
  10894. } else {
  10895. c0 = 224 + (code >> 12);
  10896. c1 = 128 + (code >> 6 & 63);
  10897. c2 = 128 + (code & 63);
  10898. return [c0, c1, c2];
  10899. }
  10900. }
  10901. /**
  10902. * 获取字符串的utf8编码字节串
  10903. * @param {string} string
  10904. * @return {array}
  10905. */
  10906. function getUTF8Bytes(string) {
  10907. var utf8codes = [];
  10908. for (var i = 0; i < string.length; i++) {
  10909. var code = string.charCodeAt(i);
  10910. var utf8 = unicodeFormat8(code);
  10911. for (var j = 0; j < utf8.length; j++) {
  10912. utf8codes.push(utf8[j]);
  10913. }
  10914. }
  10915. return utf8codes;
  10916. }
  10917. /**
  10918. * 二维码算法实现
  10919. * @param {string} data 要编码的信息字符串
  10920. * @param {num} errorCorrectLevel 纠错等级
  10921. */
  10922. function QRCodeAlg(data, errorCorrectLevel) {
  10923. this.typeNumber = -1; //版本
  10924. this.errorCorrectLevel = errorCorrectLevel;
  10925. this.modules = null; //二维矩阵,存放最终结果
  10926. this.moduleCount = 0; //矩阵大小
  10927. this.dataCache = null; //数据缓存
  10928. this.rsBlocks = null; //版本数据信息
  10929. this.totalDataCount = -1; //可使用的数据量
  10930. this.data = data;
  10931. this.utf8bytes = getUTF8Bytes(data);
  10932. this.make();
  10933. }
  10934. QRCodeAlg.prototype = {
  10935. constructor: QRCodeAlg,
  10936. /**
  10937. * 获取二维码矩阵大小
  10938. * @return {num} 矩阵大小
  10939. */
  10940. getModuleCount: function() {
  10941. return this.moduleCount;
  10942. },
  10943. /**
  10944. * 编码
  10945. */
  10946. make: function() {
  10947. this.getRightType();
  10948. this.dataCache = this.createData();
  10949. this.createQrcode();
  10950. },
  10951. /**
  10952. * 设置二位矩阵功能图形
  10953. * @param {bool} test 表示是否在寻找最好掩膜阶段
  10954. * @param {num} maskPattern 掩膜的版本
  10955. */
  10956. makeImpl: function(maskPattern) {
  10957. this.moduleCount = this.typeNumber * 4 + 17;
  10958. this.modules = new Array(this.moduleCount);
  10959. for (var row = 0; row < this.moduleCount; row++) {
  10960. this.modules[row] = new Array(this.moduleCount);
  10961. }
  10962. this.setupPositionProbePattern(0, 0);
  10963. this.setupPositionProbePattern(this.moduleCount - 7, 0);
  10964. this.setupPositionProbePattern(0, this.moduleCount - 7);
  10965. this.setupPositionAdjustPattern();
  10966. this.setupTimingPattern();
  10967. this.setupTypeInfo(true, maskPattern);
  10968. if (this.typeNumber >= 7) {
  10969. this.setupTypeNumber(true);
  10970. }
  10971. this.mapData(this.dataCache, maskPattern);
  10972. },
  10973. /**
  10974. * 设置二维码的位置探测图形
  10975. * @param {num} row 探测图形的中心横坐标
  10976. * @param {num} col 探测图形的中心纵坐标
  10977. */
  10978. setupPositionProbePattern: function(row, col) {
  10979. for (var r = -1; r <= 7; r++) {
  10980. if (row + r <= -1 || this.moduleCount <= row + r) continue;
  10981. for (var c = -1; c <= 7; c++) {
  10982. if (col + c <= -1 || this.moduleCount <= col + c) continue;
  10983. if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || (0 <= c && c <= 6 && (r == 0 || r == 6)) || (2 <= r && r <= 4 && 2 <= c && c <= 4)) {
  10984. this.modules[row + r][col + c] = true;
  10985. } else {
  10986. this.modules[row + r][col + c] = false;
  10987. }
  10988. }
  10989. }
  10990. },
  10991. /**
  10992. * 创建二维码
  10993. * @return {[type]} [description]
  10994. */
  10995. createQrcode: function() {
  10996. var minLostPoint = 0;
  10997. var pattern = 0;
  10998. var bestModules = null;
  10999. for (var i = 0; i < 8; i++) {
  11000. this.makeImpl(i);
  11001. var lostPoint = QRUtil.getLostPoint(this);
  11002. if (i == 0 || minLostPoint > lostPoint) {
  11003. minLostPoint = lostPoint;
  11004. pattern = i;
  11005. bestModules = this.modules;
  11006. }
  11007. }
  11008. this.modules = bestModules;
  11009. this.setupTypeInfo(false, pattern);
  11010. if (this.typeNumber >= 7) {
  11011. this.setupTypeNumber(false);
  11012. }
  11013. },
  11014. /**
  11015. * 设置定位图形
  11016. * @return {[type]} [description]
  11017. */
  11018. setupTimingPattern: function() {
  11019. for (var r = 8; r < this.moduleCount - 8; r++) {
  11020. if (this.modules[r][6] != null) {
  11021. continue;
  11022. }
  11023. this.modules[r][6] = (r % 2 == 0);
  11024. if (this.modules[6][r] != null) {
  11025. continue;
  11026. }
  11027. this.modules[6][r] = (r % 2 == 0);
  11028. }
  11029. },
  11030. /**
  11031. * 设置矫正图形
  11032. * @return {[type]} [description]
  11033. */
  11034. setupPositionAdjustPattern: function() {
  11035. var pos = QRUtil.getPatternPosition(this.typeNumber);
  11036. for (var i = 0; i < pos.length; i++) {
  11037. for (var j = 0; j < pos.length; j++) {
  11038. var row = pos[i];
  11039. var col = pos[j];
  11040. if (this.modules[row][col] != null) {
  11041. continue;
  11042. }
  11043. for (var r = -2; r <= 2; r++) {
  11044. for (var c = -2; c <= 2; c++) {
  11045. if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) {
  11046. this.modules[row + r][col + c] = true;
  11047. } else {
  11048. this.modules[row + r][col + c] = false;
  11049. }
  11050. }
  11051. }
  11052. }
  11053. }
  11054. },
  11055. /**
  11056. * 设置版本信息(7以上版本才有)
  11057. * @param {bool} test 是否处于判断最佳掩膜阶段
  11058. * @return {[type]} [description]
  11059. */
  11060. setupTypeNumber: function(test) {
  11061. var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
  11062. for (var i = 0; i < 18; i++) {
  11063. var mod = (!test && ((bits >> i) & 1) == 1);
  11064. this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
  11065. this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
  11066. }
  11067. },
  11068. /**
  11069. * 设置格式信息(纠错等级和掩膜版本)
  11070. * @param {bool} test
  11071. * @param {num} maskPattern 掩膜版本
  11072. * @return {}
  11073. */
  11074. setupTypeInfo: function(test, maskPattern) {
  11075. var data = (QRErrorCorrectLevel[this.errorCorrectLevel] << 3) | maskPattern;
  11076. var bits = QRUtil.getBCHTypeInfo(data);
  11077. // vertical
  11078. for (var i = 0; i < 15; i++) {
  11079. var mod = (!test && ((bits >> i) & 1) == 1);
  11080. if (i < 6) {
  11081. this.modules[i][8] = mod;
  11082. } else if (i < 8) {
  11083. this.modules[i + 1][8] = mod;
  11084. } else {
  11085. this.modules[this.moduleCount - 15 + i][8] = mod;
  11086. }
  11087. // horizontal
  11088. var mod = (!test && ((bits >> i) & 1) == 1);
  11089. if (i < 8) {
  11090. this.modules[8][this.moduleCount - i - 1] = mod;
  11091. } else if (i < 9) {
  11092. this.modules[8][15 - i - 1 + 1] = mod;
  11093. } else {
  11094. this.modules[8][15 - i - 1] = mod;
  11095. }
  11096. }
  11097. // fixed module
  11098. this.modules[this.moduleCount - 8][8] = (!test);
  11099. },
  11100. /**
  11101. * 数据编码
  11102. * @return {[type]} [description]
  11103. */
  11104. createData: function() {
  11105. var buffer = new QRBitBuffer();
  11106. var lengthBits = this.typeNumber > 9 ? 16 : 8;
  11107. buffer.put(4, 4); //添加模式
  11108. buffer.put(this.utf8bytes.length, lengthBits);
  11109. for (var i = 0, l = this.utf8bytes.length; i < l; i++) {
  11110. buffer.put(this.utf8bytes[i], 8);
  11111. }
  11112. if (buffer.length + 4 <= this.totalDataCount * 8) {
  11113. buffer.put(0, 4);
  11114. }
  11115. // padding
  11116. while (buffer.length % 8 != 0) {
  11117. buffer.putBit(false);
  11118. }
  11119. // padding
  11120. while (true) {
  11121. if (buffer.length >= this.totalDataCount * 8) {
  11122. break;
  11123. }
  11124. buffer.put(QRCodeAlg.PAD0, 8);
  11125. if (buffer.length >= this.totalDataCount * 8) {
  11126. break;
  11127. }
  11128. buffer.put(QRCodeAlg.PAD1, 8);
  11129. }
  11130. return this.createBytes(buffer);
  11131. },
  11132. /**
  11133. * 纠错码编码
  11134. * @param {buffer} buffer 数据编码
  11135. * @return {[type]}
  11136. */
  11137. createBytes: function(buffer) {
  11138. var offset = 0;
  11139. var maxDcCount = 0;
  11140. var maxEcCount = 0;
  11141. var length = this.rsBlock.length / 3;
  11142. var rsBlocks = new Array();
  11143. for (var i = 0; i < length; i++) {
  11144. var count = this.rsBlock[i * 3 + 0];
  11145. var totalCount = this.rsBlock[i * 3 + 1];
  11146. var dataCount = this.rsBlock[i * 3 + 2];
  11147. for (var j = 0; j < count; j++) {
  11148. rsBlocks.push([dataCount, totalCount]);
  11149. }
  11150. }
  11151. var dcdata = new Array(rsBlocks.length);
  11152. var ecdata = new Array(rsBlocks.length);
  11153. for (var r = 0; r < rsBlocks.length; r++) {
  11154. var dcCount = rsBlocks[r][0];
  11155. var ecCount = rsBlocks[r][1] - dcCount;
  11156. maxDcCount = Math.max(maxDcCount, dcCount);
  11157. maxEcCount = Math.max(maxEcCount, ecCount);
  11158. dcdata[r] = new Array(dcCount);
  11159. for (var i = 0; i < dcdata[r].length; i++) {
  11160. dcdata[r][i] = 0xff & buffer.buffer[i + offset];
  11161. }
  11162. offset += dcCount;
  11163. var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
  11164. var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
  11165. var modPoly = rawPoly.mod(rsPoly);
  11166. ecdata[r] = new Array(rsPoly.getLength() - 1);
  11167. for (var i = 0; i < ecdata[r].length; i++) {
  11168. var modIndex = i + modPoly.getLength() - ecdata[r].length;
  11169. ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;
  11170. }
  11171. }
  11172. var data = new Array(this.totalDataCount);
  11173. var index = 0;
  11174. for (var i = 0; i < maxDcCount; i++) {
  11175. for (var r = 0; r < rsBlocks.length; r++) {
  11176. if (i < dcdata[r].length) {
  11177. data[index++] = dcdata[r][i];
  11178. }
  11179. }
  11180. }
  11181. for (var i = 0; i < maxEcCount; i++) {
  11182. for (var r = 0; r < rsBlocks.length; r++) {
  11183. if (i < ecdata[r].length) {
  11184. data[index++] = ecdata[r][i];
  11185. }
  11186. }
  11187. }
  11188. return data;
  11189. },
  11190. /**
  11191. * 布置模块,构建最终信息
  11192. * @param {} data
  11193. * @param {} maskPattern
  11194. * @return {}
  11195. */
  11196. mapData: function(data, maskPattern) {
  11197. var inc = -1;
  11198. var row = this.moduleCount - 1;
  11199. var bitIndex = 7;
  11200. var byteIndex = 0;
  11201. for (var col = this.moduleCount - 1; col > 0; col -= 2) {
  11202. if (col == 6) col--;
  11203. while (true) {
  11204. for (var c = 0; c < 2; c++) {
  11205. if (this.modules[row][col - c] == null) {
  11206. var dark = false;
  11207. if (byteIndex < data.length) {
  11208. dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);
  11209. }
  11210. var mask = QRUtil.getMask(maskPattern, row, col - c);
  11211. if (mask) {
  11212. dark = !dark;
  11213. }
  11214. this.modules[row][col - c] = dark;
  11215. bitIndex--;
  11216. if (bitIndex == -1) {
  11217. byteIndex++;
  11218. bitIndex = 7;
  11219. }
  11220. }
  11221. }
  11222. row += inc;
  11223. if (row < 0 || this.moduleCount <= row) {
  11224. row -= inc;
  11225. inc = -inc;
  11226. break;
  11227. }
  11228. }
  11229. }
  11230. }
  11231. };
  11232. /**
  11233. * 填充字段
  11234. */
  11235. QRCodeAlg.PAD0 = 0xEC;
  11236. QRCodeAlg.PAD1 = 0x11;
  11237. //---------------------------------------------------------------------
  11238. // 纠错等级对应的编码
  11239. //---------------------------------------------------------------------
  11240. var QRErrorCorrectLevel = [1, 0, 3, 2];
  11241. //---------------------------------------------------------------------
  11242. // 掩膜版本
  11243. //---------------------------------------------------------------------
  11244. var QRMaskPattern = {
  11245. PATTERN000: 0,
  11246. PATTERN001: 1,
  11247. PATTERN010: 2,
  11248. PATTERN011: 3,
  11249. PATTERN100: 4,
  11250. PATTERN101: 5,
  11251. PATTERN110: 6,
  11252. PATTERN111: 7
  11253. };
  11254. //---------------------------------------------------------------------
  11255. // 工具类
  11256. //---------------------------------------------------------------------
  11257. var QRUtil = {
  11258. /*
  11259. 每个版本矫正图形的位置
  11260. */
  11261. PATTERN_POSITION_TABLE: [
  11262. [],
  11263. [6, 18],
  11264. [6, 22],
  11265. [6, 26],
  11266. [6, 30],
  11267. [6, 34],
  11268. [6, 22, 38],
  11269. [6, 24, 42],
  11270. [6, 26, 46],
  11271. [6, 28, 50],
  11272. [6, 30, 54],
  11273. [6, 32, 58],
  11274. [6, 34, 62],
  11275. [6, 26, 46, 66],
  11276. [6, 26, 48, 70],
  11277. [6, 26, 50, 74],
  11278. [6, 30, 54, 78],
  11279. [6, 30, 56, 82],
  11280. [6, 30, 58, 86],
  11281. [6, 34, 62, 90],
  11282. [6, 28, 50, 72, 94],
  11283. [6, 26, 50, 74, 98],
  11284. [6, 30, 54, 78, 102],
  11285. [6, 28, 54, 80, 106],
  11286. [6, 32, 58, 84, 110],
  11287. [6, 30, 58, 86, 114],
  11288. [6, 34, 62, 90, 118],
  11289. [6, 26, 50, 74, 98, 122],
  11290. [6, 30, 54, 78, 102, 126],
  11291. [6, 26, 52, 78, 104, 130],
  11292. [6, 30, 56, 82, 108, 134],
  11293. [6, 34, 60, 86, 112, 138],
  11294. [6, 30, 58, 86, 114, 142],
  11295. [6, 34, 62, 90, 118, 146],
  11296. [6, 30, 54, 78, 102, 126, 150],
  11297. [6, 24, 50, 76, 102, 128, 154],
  11298. [6, 28, 54, 80, 106, 132, 158],
  11299. [6, 32, 58, 84, 110, 136, 162],
  11300. [6, 26, 54, 82, 110, 138, 166],
  11301. [6, 30, 58, 86, 114, 142, 170]
  11302. ],
  11303. G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
  11304. G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
  11305. G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
  11306. /*
  11307. BCH编码格式信息
  11308. */
  11309. getBCHTypeInfo: function(data) {
  11310. var d = data << 10;
  11311. while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
  11312. d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)));
  11313. }
  11314. return ((data << 10) | d) ^ QRUtil.G15_MASK;
  11315. },
  11316. /*
  11317. BCH编码版本信息
  11318. */
  11319. getBCHTypeNumber: function(data) {
  11320. var d = data << 12;
  11321. while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
  11322. d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)));
  11323. }
  11324. return (data << 12) | d;
  11325. },
  11326. /*
  11327. 获取BCH位信息
  11328. */
  11329. getBCHDigit: function(data) {
  11330. var digit = 0;
  11331. while (data != 0) {
  11332. digit++;
  11333. data >>>= 1;
  11334. }
  11335. return digit;
  11336. },
  11337. /*
  11338. 获取版本对应的矫正图形位置
  11339. */
  11340. getPatternPosition: function(typeNumber) {
  11341. return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
  11342. },
  11343. /*
  11344. 掩膜算法
  11345. */
  11346. getMask: function(maskPattern, i, j) {
  11347. switch (maskPattern) {
  11348. case QRMaskPattern.PATTERN000:
  11349. return (i + j) % 2 == 0;
  11350. case QRMaskPattern.PATTERN001:
  11351. return i % 2 == 0;
  11352. case QRMaskPattern.PATTERN010:
  11353. return j % 3 == 0;
  11354. case QRMaskPattern.PATTERN011:
  11355. return (i + j) % 3 == 0;
  11356. case QRMaskPattern.PATTERN100:
  11357. return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
  11358. case QRMaskPattern.PATTERN101:
  11359. return (i * j) % 2 + (i * j) % 3 == 0;
  11360. case QRMaskPattern.PATTERN110:
  11361. return ((i * j) % 2 + (i * j) % 3) % 2 == 0;
  11362. case QRMaskPattern.PATTERN111:
  11363. return ((i * j) % 3 + (i + j) % 2) % 2 == 0;
  11364. default:
  11365. throw new Error("bad maskPattern:" + maskPattern);
  11366. }
  11367. },
  11368. /*
  11369. 获取RS的纠错多项式
  11370. */
  11371. getErrorCorrectPolynomial: function(errorCorrectLength) {
  11372. var a = new QRPolynomial([1], 0);
  11373. for (var i = 0; i < errorCorrectLength; i++) {
  11374. a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));
  11375. }
  11376. return a;
  11377. },
  11378. /*
  11379. 获取评价
  11380. */
  11381. getLostPoint: function(qrCode) {
  11382. var moduleCount = qrCode.getModuleCount(),
  11383. lostPoint = 0,
  11384. darkCount = 0;
  11385. for (var row = 0; row < moduleCount; row++) {
  11386. var sameCount = 0;
  11387. var head = qrCode.modules[row][0];
  11388. for (var col = 0; col < moduleCount; col++) {
  11389. var current = qrCode.modules[row][col];
  11390. //level 3 评价
  11391. if (col < moduleCount - 6) {
  11392. if (current && !qrCode.modules[row][col + 1] && qrCode.modules[row][col + 2] && qrCode.modules[row][col + 3] && qrCode.modules[row][col + 4] && !qrCode.modules[row][col + 5] && qrCode.modules[row][col + 6]) {
  11393. if (col < moduleCount - 10) {
  11394. if (qrCode.modules[row][col + 7] && qrCode.modules[row][col + 8] && qrCode.modules[row][col + 9] && qrCode.modules[row][col + 10]) {
  11395. lostPoint += 40;
  11396. }
  11397. } else if (col > 3) {
  11398. if (qrCode.modules[row][col - 1] && qrCode.modules[row][col - 2] && qrCode.modules[row][col - 3] && qrCode.modules[row][col - 4]) {
  11399. lostPoint += 40;
  11400. }
  11401. }
  11402. }
  11403. }
  11404. //level 2 评价
  11405. if ((row < moduleCount - 1) && (col < moduleCount - 1)) {
  11406. var count = 0;
  11407. if (current) count++;
  11408. if (qrCode.modules[row + 1][col]) count++;
  11409. if (qrCode.modules[row][col + 1]) count++;
  11410. if (qrCode.modules[row + 1][col + 1]) count++;
  11411. if (count == 0 || count == 4) {
  11412. lostPoint += 3;
  11413. }
  11414. }
  11415. //level 1 评价
  11416. if (head ^ current) {
  11417. sameCount++;
  11418. } else {
  11419. head = current;
  11420. if (sameCount >= 5) {
  11421. lostPoint += (3 + sameCount - 5);
  11422. }
  11423. sameCount = 1;
  11424. }
  11425. //level 4 评价
  11426. if (current) {
  11427. darkCount++;
  11428. }
  11429. }
  11430. }
  11431. for (var col = 0; col < moduleCount; col++) {
  11432. var sameCount = 0;
  11433. var head = qrCode.modules[0][col];
  11434. for (var row = 0; row < moduleCount; row++) {
  11435. var current = qrCode.modules[row][col];
  11436. //level 3 评价
  11437. if (row < moduleCount - 6) {
  11438. if (current && !qrCode.modules[row + 1][col] && qrCode.modules[row + 2][col] && qrCode.modules[row + 3][col] && qrCode.modules[row + 4][col] && !qrCode.modules[row + 5][col] && qrCode.modules[row + 6][col]) {
  11439. if (row < moduleCount - 10) {
  11440. if (qrCode.modules[row + 7][col] && qrCode.modules[row + 8][col] && qrCode.modules[row + 9][col] && qrCode.modules[row + 10][col]) {
  11441. lostPoint += 40;
  11442. }
  11443. } else if (row > 3) {
  11444. if (qrCode.modules[row - 1][col] && qrCode.modules[row - 2][col] && qrCode.modules[row - 3][col] && qrCode.modules[row - 4][col]) {
  11445. lostPoint += 40;
  11446. }
  11447. }
  11448. }
  11449. }
  11450. //level 1 评价
  11451. if (head ^ current) {
  11452. sameCount++;
  11453. } else {
  11454. head = current;
  11455. if (sameCount >= 5) {
  11456. lostPoint += (3 + sameCount - 5);
  11457. }
  11458. sameCount = 1;
  11459. }
  11460. }
  11461. }
  11462. // LEVEL4
  11463. var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
  11464. lostPoint += ratio * 10;
  11465. return lostPoint;
  11466. }
  11467. };
  11468. //---------------------------------------------------------------------
  11469. // QRMath使用的数学工具
  11470. //---------------------------------------------------------------------
  11471. var QRMath = {
  11472. /*
  11473. 将n转化为a^m
  11474. */
  11475. glog: function(n) {
  11476. if (n < 1) {
  11477. throw new Error("glog(" + n + ")");
  11478. }
  11479. return QRMath.LOG_TABLE[n];
  11480. },
  11481. /*
  11482. 将a^m转化为n
  11483. */
  11484. gexp: function(n) {
  11485. while (n < 0) {
  11486. n += 255;
  11487. }
  11488. while (n >= 256) {
  11489. n -= 255;
  11490. }
  11491. return QRMath.EXP_TABLE[n];
  11492. },
  11493. EXP_TABLE: new Array(256),
  11494. LOG_TABLE: new Array(256)
  11495. };
  11496. for (var i = 0; i < 8; i++) {
  11497. QRMath.EXP_TABLE[i] = 1 << i;
  11498. }
  11499. for (var i = 8; i < 256; i++) {
  11500. QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8];
  11501. }
  11502. for (var i = 0; i < 255; i++) {
  11503. QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;
  11504. }
  11505. //---------------------------------------------------------------------
  11506. // QRPolynomial 多项式
  11507. //---------------------------------------------------------------------
  11508. /**
  11509. * 多项式类
  11510. * @param {Array} num 系数
  11511. * @param {num} shift a^shift
  11512. */
  11513. function QRPolynomial(num, shift) {
  11514. if (num.length == undefined) {
  11515. throw new Error(num.length + "/" + shift);
  11516. }
  11517. var offset = 0;
  11518. while (offset < num.length && num[offset] == 0) {
  11519. offset++;
  11520. }
  11521. this.num = new Array(num.length - offset + shift);
  11522. for (var i = 0; i < num.length - offset; i++) {
  11523. this.num[i] = num[i + offset];
  11524. }
  11525. }
  11526. QRPolynomial.prototype = {
  11527. get: function(index) {
  11528. return this.num[index];
  11529. },
  11530. getLength: function() {
  11531. return this.num.length;
  11532. },
  11533. /**
  11534. * 多项式乘法
  11535. * @param {QRPolynomial} e 被乘多项式
  11536. * @return {[type]} [description]
  11537. */
  11538. multiply: function(e) {
  11539. var num = new Array(this.getLength() + e.getLength() - 1);
  11540. for (var i = 0; i < this.getLength(); i++) {
  11541. for (var j = 0; j < e.getLength(); j++) {
  11542. num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
  11543. }
  11544. }
  11545. return new QRPolynomial(num, 0);
  11546. },
  11547. /**
  11548. * 多项式模运算
  11549. * @param {QRPolynomial} e 模多项式
  11550. * @return {}
  11551. */
  11552. mod: function(e) {
  11553. var tl = this.getLength(),
  11554. el = e.getLength();
  11555. if (tl - el < 0) {
  11556. return this;
  11557. }
  11558. var num = new Array(tl);
  11559. for (var i = 0; i < tl; i++) {
  11560. num[i] = this.get(i);
  11561. }
  11562. while (num.length >= el) {
  11563. var ratio = QRMath.glog(num[0]) - QRMath.glog(e.get(0));
  11564. for (var i = 0; i < e.getLength(); i++) {
  11565. num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
  11566. }
  11567. while (num[0] == 0) {
  11568. num.shift();
  11569. }
  11570. }
  11571. return new QRPolynomial(num, 0);
  11572. }
  11573. };
  11574. //---------------------------------------------------------------------
  11575. // RS_BLOCK_TABLE
  11576. //---------------------------------------------------------------------
  11577. /*
  11578. 二维码各个版本信息[块数, 每块中的数据块数, 每块中的信息块数]
  11579. */
  11580. RS_BLOCK_TABLE = [
  11581. // L
  11582. // M
  11583. // Q
  11584. // H
  11585. // 1
  11586. [1, 26, 19],
  11587. [1, 26, 16],
  11588. [1, 26, 13],
  11589. [1, 26, 9],
  11590. // 2
  11591. [1, 44, 34],
  11592. [1, 44, 28],
  11593. [1, 44, 22],
  11594. [1, 44, 16],
  11595. // 3
  11596. [1, 70, 55],
  11597. [1, 70, 44],
  11598. [2, 35, 17],
  11599. [2, 35, 13],
  11600. // 4
  11601. [1, 100, 80],
  11602. [2, 50, 32],
  11603. [2, 50, 24],
  11604. [4, 25, 9],
  11605. // 5
  11606. [1, 134, 108],
  11607. [2, 67, 43],
  11608. [2, 33, 15, 2, 34, 16],
  11609. [2, 33, 11, 2, 34, 12],
  11610. // 6
  11611. [2, 86, 68],
  11612. [4, 43, 27],
  11613. [4, 43, 19],
  11614. [4, 43, 15],
  11615. // 7
  11616. [2, 98, 78],
  11617. [4, 49, 31],
  11618. [2, 32, 14, 4, 33, 15],
  11619. [4, 39, 13, 1, 40, 14],
  11620. // 8
  11621. [2, 121, 97],
  11622. [2, 60, 38, 2, 61, 39],
  11623. [4, 40, 18, 2, 41, 19],
  11624. [4, 40, 14, 2, 41, 15],
  11625. // 9
  11626. [2, 146, 116],
  11627. [3, 58, 36, 2, 59, 37],
  11628. [4, 36, 16, 4, 37, 17],
  11629. [4, 36, 12, 4, 37, 13],
  11630. // 10
  11631. [2, 86, 68, 2, 87, 69],
  11632. [4, 69, 43, 1, 70, 44],
  11633. [6, 43, 19, 2, 44, 20],
  11634. [6, 43, 15, 2, 44, 16],
  11635. // 11
  11636. [4, 101, 81],
  11637. [1, 80, 50, 4, 81, 51],
  11638. [4, 50, 22, 4, 51, 23],
  11639. [3, 36, 12, 8, 37, 13],
  11640. // 12
  11641. [2, 116, 92, 2, 117, 93],
  11642. [6, 58, 36, 2, 59, 37],
  11643. [4, 46, 20, 6, 47, 21],
  11644. [7, 42, 14, 4, 43, 15],
  11645. // 13
  11646. [4, 133, 107],
  11647. [8, 59, 37, 1, 60, 38],
  11648. [8, 44, 20, 4, 45, 21],
  11649. [12, 33, 11, 4, 34, 12],
  11650. // 14
  11651. [3, 145, 115, 1, 146, 116],
  11652. [4, 64, 40, 5, 65, 41],
  11653. [11, 36, 16, 5, 37, 17],
  11654. [11, 36, 12, 5, 37, 13],
  11655. // 15
  11656. [5, 109, 87, 1, 110, 88],
  11657. [5, 65, 41, 5, 66, 42],
  11658. [5, 54, 24, 7, 55, 25],
  11659. [11, 36, 12],
  11660. // 16
  11661. [5, 122, 98, 1, 123, 99],
  11662. [7, 73, 45, 3, 74, 46],
  11663. [15, 43, 19, 2, 44, 20],
  11664. [3, 45, 15, 13, 46, 16],
  11665. // 17
  11666. [1, 135, 107, 5, 136, 108],
  11667. [10, 74, 46, 1, 75, 47],
  11668. [1, 50, 22, 15, 51, 23],
  11669. [2, 42, 14, 17, 43, 15],
  11670. // 18
  11671. [5, 150, 120, 1, 151, 121],
  11672. [9, 69, 43, 4, 70, 44],
  11673. [17, 50, 22, 1, 51, 23],
  11674. [2, 42, 14, 19, 43, 15],
  11675. // 19
  11676. [3, 141, 113, 4, 142, 114],
  11677. [3, 70, 44, 11, 71, 45],
  11678. [17, 47, 21, 4, 48, 22],
  11679. [9, 39, 13, 16, 40, 14],
  11680. // 20
  11681. [3, 135, 107, 5, 136, 108],
  11682. [3, 67, 41, 13, 68, 42],
  11683. [15, 54, 24, 5, 55, 25],
  11684. [15, 43, 15, 10, 44, 16],
  11685. // 21
  11686. [4, 144, 116, 4, 145, 117],
  11687. [17, 68, 42],
  11688. [17, 50, 22, 6, 51, 23],
  11689. [19, 46, 16, 6, 47, 17],
  11690. // 22
  11691. [2, 139, 111, 7, 140, 112],
  11692. [17, 74, 46],
  11693. [7, 54, 24, 16, 55, 25],
  11694. [34, 37, 13],
  11695. // 23
  11696. [4, 151, 121, 5, 152, 122],
  11697. [4, 75, 47, 14, 76, 48],
  11698. [11, 54, 24, 14, 55, 25],
  11699. [16, 45, 15, 14, 46, 16],
  11700. // 24
  11701. [6, 147, 117, 4, 148, 118],
  11702. [6, 73, 45, 14, 74, 46],
  11703. [11, 54, 24, 16, 55, 25],
  11704. [30, 46, 16, 2, 47, 17],
  11705. // 25
  11706. [8, 132, 106, 4, 133, 107],
  11707. [8, 75, 47, 13, 76, 48],
  11708. [7, 54, 24, 22, 55, 25],
  11709. [22, 45, 15, 13, 46, 16],
  11710. // 26
  11711. [10, 142, 114, 2, 143, 115],
  11712. [19, 74, 46, 4, 75, 47],
  11713. [28, 50, 22, 6, 51, 23],
  11714. [33, 46, 16, 4, 47, 17],
  11715. // 27
  11716. [8, 152, 122, 4, 153, 123],
  11717. [22, 73, 45, 3, 74, 46],
  11718. [8, 53, 23, 26, 54, 24],
  11719. [12, 45, 15, 28, 46, 16],
  11720. // 28
  11721. [3, 147, 117, 10, 148, 118],
  11722. [3, 73, 45, 23, 74, 46],
  11723. [4, 54, 24, 31, 55, 25],
  11724. [11, 45, 15, 31, 46, 16],
  11725. // 29
  11726. [7, 146, 116, 7, 147, 117],
  11727. [21, 73, 45, 7, 74, 46],
  11728. [1, 53, 23, 37, 54, 24],
  11729. [19, 45, 15, 26, 46, 16],
  11730. // 30
  11731. [5, 145, 115, 10, 146, 116],
  11732. [19, 75, 47, 10, 76, 48],
  11733. [15, 54, 24, 25, 55, 25],
  11734. [23, 45, 15, 25, 46, 16],
  11735. // 31
  11736. [13, 145, 115, 3, 146, 116],
  11737. [2, 74, 46, 29, 75, 47],
  11738. [42, 54, 24, 1, 55, 25],
  11739. [23, 45, 15, 28, 46, 16],
  11740. // 32
  11741. [17, 145, 115],
  11742. [10, 74, 46, 23, 75, 47],
  11743. [10, 54, 24, 35, 55, 25],
  11744. [19, 45, 15, 35, 46, 16],
  11745. // 33
  11746. [17, 145, 115, 1, 146, 116],
  11747. [14, 74, 46, 21, 75, 47],
  11748. [29, 54, 24, 19, 55, 25],
  11749. [11, 45, 15, 46, 46, 16],
  11750. // 34
  11751. [13, 145, 115, 6, 146, 116],
  11752. [14, 74, 46, 23, 75, 47],
  11753. [44, 54, 24, 7, 55, 25],
  11754. [59, 46, 16, 1, 47, 17],
  11755. // 35
  11756. [12, 151, 121, 7, 152, 122],
  11757. [12, 75, 47, 26, 76, 48],
  11758. [39, 54, 24, 14, 55, 25],
  11759. [22, 45, 15, 41, 46, 16],
  11760. // 36
  11761. [6, 151, 121, 14, 152, 122],
  11762. [6, 75, 47, 34, 76, 48],
  11763. [46, 54, 24, 10, 55, 25],
  11764. [2, 45, 15, 64, 46, 16],
  11765. // 37
  11766. [17, 152, 122, 4, 153, 123],
  11767. [29, 74, 46, 14, 75, 47],
  11768. [49, 54, 24, 10, 55, 25],
  11769. [24, 45, 15, 46, 46, 16],
  11770. // 38
  11771. [4, 152, 122, 18, 153, 123],
  11772. [13, 74, 46, 32, 75, 47],
  11773. [48, 54, 24, 14, 55, 25],
  11774. [42, 45, 15, 32, 46, 16],
  11775. // 39
  11776. [20, 147, 117, 4, 148, 118],
  11777. [40, 75, 47, 7, 76, 48],
  11778. [43, 54, 24, 22, 55, 25],
  11779. [10, 45, 15, 67, 46, 16],
  11780. // 40
  11781. [19, 148, 118, 6, 149, 119],
  11782. [18, 75, 47, 31, 76, 48],
  11783. [34, 54, 24, 34, 55, 25],
  11784. [20, 45, 15, 61, 46, 16]
  11785. ];
  11786. /**
  11787. * 根据数据获取对应版本
  11788. * @return {[type]} [description]
  11789. */
  11790. QRCodeAlg.prototype.getRightType = function() {
  11791. for (var typeNumber = 1; typeNumber < 41; typeNumber++) {
  11792. var rsBlock = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + this.errorCorrectLevel];
  11793. if (rsBlock == undefined) {
  11794. throw new Error('bad rs block @ typeNumber:' + typeNumber + '/errorCorrectLevel:' + this.errorCorrectLevel);
  11795. }
  11796. var length = rsBlock.length / 3;
  11797. var totalDataCount = 0;
  11798. for (var i = 0; i < length; i++) {
  11799. var count = rsBlock[i * 3 + 0];
  11800. var dataCount = rsBlock[i * 3 + 2];
  11801. totalDataCount += dataCount * count;
  11802. }
  11803. var lengthBytes = typeNumber > 9 ? 2 : 1;
  11804. if (this.utf8bytes.length + lengthBytes < totalDataCount || typeNumber == 40) {
  11805. this.typeNumber = typeNumber;
  11806. this.rsBlock = rsBlock;
  11807. this.totalDataCount = totalDataCount;
  11808. break;
  11809. }
  11810. }
  11811. };
  11812. // ---------------------------------------------------------------------
  11813. // QRBitBuffer
  11814. // ---------------------------------------------------------------------
  11815. function QRBitBuffer() {
  11816. this.buffer = new Array();
  11817. this.length = 0;
  11818. }
  11819. QRBitBuffer.prototype = {
  11820. get: function(index) {
  11821. var bufIndex = Math.floor(index / 8);
  11822. return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1);
  11823. },
  11824. put: function(num, length) {
  11825. for (var i = 0; i < length; i++) {
  11826. this.putBit(((num >>> (length - i - 1)) & 1));
  11827. }
  11828. },
  11829. putBit: function(bit) {
  11830. var bufIndex = Math.floor(this.length / 8);
  11831. if (this.buffer.length <= bufIndex) {
  11832. this.buffer.push(0);
  11833. }
  11834. if (bit) {
  11835. this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));
  11836. }
  11837. this.length++;
  11838. }
  11839. };
  11840. $.fn.qrcode = function QRCodePlugin(option) {
  11841. return this.each(function() {
  11842. $(this).append(new QRCode(option));
  11843. });
  11844. };
  11845. module.exports = UI.qrcode = QRCode;
  11846. /***/ },
  11847. /* 27 */
  11848. /***/ function(module, exports, __webpack_require__) {
  11849. 'use strict';
  11850. var $ = __webpack_require__(1);
  11851. var UI = __webpack_require__(2);
  11852. /**
  11853. * @via https://github.com/uikit/uikit/blob/master/src/js/addons/sticky.js
  11854. * @license https://github.com/uikit/uikit/blob/master/LICENSE.md
  11855. */
  11856. // Sticky Class
  11857. var Sticky = function(element, options) {
  11858. var _this = this;
  11859. this.options = $.extend({}, Sticky.DEFAULTS, options);
  11860. this.$element = $(element);
  11861. this.sticked = null;
  11862. this.inited = null;
  11863. this.$holder = undefined;
  11864. this.$window = $(window).
  11865. on('scroll.sticky.amui',
  11866. UI.utils.debounce($.proxy(this.checkPosition, this), 10)).
  11867. on('resize.sticky.amui orientationchange.sticky.amui',
  11868. UI.utils.debounce(function() {
  11869. _this.reset(true, function() {
  11870. _this.checkPosition();
  11871. });
  11872. }, 50)).
  11873. on('load.sticky.amui', $.proxy(this.checkPosition, this));
  11874. // the `.offset()` is diff between jQuery & Zepto.js
  11875. // jQuery: return `top` and `left`
  11876. // Zepto.js: return `top`, `left`, `width`, `height`
  11877. this.offset = this.$element.offset();
  11878. this.init();
  11879. };
  11880. Sticky.DEFAULTS = {
  11881. top: 0,
  11882. bottom: 0,
  11883. animation: '',
  11884. className: {
  11885. sticky: 'am-sticky',
  11886. resetting: 'am-sticky-resetting',
  11887. stickyBtm: 'am-sticky-bottom',
  11888. animationRev: 'am-animation-reverse'
  11889. }
  11890. };
  11891. Sticky.prototype.init = function() {
  11892. var result = this.check();
  11893. if (!result) {
  11894. return false;
  11895. }
  11896. var $element = this.$element;
  11897. var $elementMargin = '';
  11898. $.each($element.css(
  11899. ['marginTop', 'marginRight', 'marginBottom', 'marginLeft']),
  11900. function(name, value) {
  11901. return $elementMargin += ' ' + value;
  11902. });
  11903. var $holder = $('<div class="am-sticky-placeholder"></div>').css({
  11904. height: $element.css('position') !== 'absolute' ?
  11905. $element.outerHeight() : '',
  11906. float: $element.css('float') != 'none' ? $element.css('float') : '',
  11907. margin: $elementMargin
  11908. });
  11909. this.$holder = $element.css('margin', 0).wrap($holder).parent();
  11910. this.inited = 1;
  11911. return true;
  11912. };
  11913. Sticky.prototype.reset = function(force, cb) {
  11914. var options = this.options;
  11915. var $element = this.$element;
  11916. var animation = (options.animation) ?
  11917. ' am-animation-' + options.animation : '';
  11918. var complete = function() {
  11919. $element.css({position: '', top: '', width: '', left: '', margin: 0});
  11920. $element.removeClass([
  11921. animation,
  11922. options.className.animationRev,
  11923. options.className.sticky,
  11924. options.className.resetting
  11925. ].join(' '));
  11926. this.animating = false;
  11927. this.sticked = false;
  11928. this.offset = $element.offset();
  11929. cb && cb();
  11930. }.bind(this);
  11931. $element.addClass(options.className.resetting);
  11932. if (!force && options.animation && UI.support.animation) {
  11933. this.animating = true;
  11934. $element.removeClass(animation).one(UI.support.animation.end, function() {
  11935. complete();
  11936. }).width(); // force redraw
  11937. $element.addClass(animation + ' ' + options.className.animationRev);
  11938. } else {
  11939. complete();
  11940. }
  11941. };
  11942. Sticky.prototype.check = function() {
  11943. if (!this.$element.is(':visible')) {
  11944. return false;
  11945. }
  11946. var media = this.options.media;
  11947. if (media) {
  11948. switch (typeof(media)) {
  11949. case 'number':
  11950. if (window.innerWidth < media) {
  11951. return false;
  11952. }
  11953. break;
  11954. case 'string':
  11955. if (window.matchMedia && !window.matchMedia(media).matches) {
  11956. return false;
  11957. }
  11958. break;
  11959. }
  11960. }
  11961. return true;
  11962. };
  11963. Sticky.prototype.checkPosition = function() {
  11964. if (!this.inited) {
  11965. var initialized = this.init();
  11966. if (!initialized) {
  11967. return;
  11968. }
  11969. }
  11970. var options = this.options;
  11971. var scrollTop = this.$window.scrollTop();
  11972. var offsetTop = options.top;
  11973. var offsetBottom = options.bottom;
  11974. var $element = this.$element;
  11975. var animation = (options.animation) ?
  11976. ' am-animation-' + options.animation : '';
  11977. var className = [options.className.sticky, animation].join(' ');
  11978. if (typeof offsetBottom == 'function') {
  11979. offsetBottom = offsetBottom(this.$element);
  11980. }
  11981. var checkResult = (scrollTop > this.$holder.offset().top);
  11982. if (!this.sticked && checkResult) {
  11983. $element.addClass(className);
  11984. } else if (this.sticked && !checkResult) {
  11985. this.reset();
  11986. }
  11987. this.$holder.css({
  11988. height: $element.is(':visible') && $element.css('position') !== 'absolute' ?
  11989. $element.outerHeight() : ''
  11990. });
  11991. if (checkResult) {
  11992. $element.css({
  11993. top: offsetTop,
  11994. left: this.$holder.offset().left,
  11995. width: this.$holder.width()
  11996. });
  11997. /*
  11998. if (offsetBottom) {
  11999. // (底部边距 + 元素高度 > 窗口高度) 时定位到底部
  12000. if ((offsetBottom + this.offset.height > $(window).height()) &&
  12001. (scrollTop + $(window).height() >= scrollHeight - offsetBottom)) {
  12002. $element.addClass(options.className.stickyBtm).
  12003. css({top: $(window).height() - offsetBottom - this.offset.height});
  12004. } else {
  12005. $element.removeClass(options.className.stickyBtm).css({top: offsetTop});
  12006. }
  12007. }
  12008. */
  12009. }
  12010. this.sticked = checkResult;
  12011. };
  12012. // Sticky Plugin
  12013. UI.plugin('sticky', Sticky);
  12014. // Init code
  12015. $(window).on('load', function() {
  12016. $('[data-am-sticky]').sticky();
  12017. });
  12018. module.exports = Sticky;
  12019. /***/ },
  12020. /* 28 */
  12021. /***/ function(module, exports, __webpack_require__) {
  12022. 'use strict';
  12023. var $ = __webpack_require__(1);
  12024. var UI = __webpack_require__(2);
  12025. var Hammer = __webpack_require__(3);
  12026. var supportTransition = UI.support.transition;
  12027. var animation = UI.support.animation;
  12028. /**
  12029. * @via https://github.com/twbs/bootstrap/blob/master/js/tab.js
  12030. * @copyright 2011-2014 Twitter, Inc.
  12031. * @license MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  12032. */
  12033. /**
  12034. * Tabs
  12035. * @param {HTMLElement} element
  12036. * @param {Object} options
  12037. * @constructor
  12038. */
  12039. var Tabs = function(element, options) {
  12040. this.$element = $(element);
  12041. this.options = $.extend({}, Tabs.DEFAULTS, options || {});
  12042. this.transitioning = this.activeIndex = null;
  12043. this.refresh();
  12044. this.init();
  12045. };
  12046. Tabs.DEFAULTS = {
  12047. selector: {
  12048. nav: '> .am-tabs-nav',
  12049. content: '> .am-tabs-bd',
  12050. panel: '> .am-tab-panel'
  12051. },
  12052. activeClass: 'am-active'
  12053. };
  12054. Tabs.prototype.refresh = function() {
  12055. var selector = this.options.selector;
  12056. this.$tabNav = this.$element.find(selector.nav);
  12057. this.$navs = this.$tabNav.find('a');
  12058. this.$content = this.$element.find(selector.content);
  12059. this.$tabPanels = this.$content.find(selector.panel);
  12060. var $active = this.$tabNav.find('> .' + this.options.activeClass);
  12061. // Activate the first Tab when no active Tab or multiple active Tabs
  12062. if ($active.length !== 1) {
  12063. this.open(0);
  12064. } else {
  12065. this.activeIndex = this.$navs.index($active.children('a'));
  12066. }
  12067. };
  12068. Tabs.prototype.init = function() {
  12069. var _this = this;
  12070. var options = this.options;
  12071. this.$element.on('click.tabs.amui', options.selector.nav + ' a', function(e) {
  12072. e.preventDefault();
  12073. _this.open($(this));
  12074. });
  12075. // TODO: nested Tabs touch events
  12076. if (!options.noSwipe) {
  12077. if (!this.$content.length) {
  12078. return this;
  12079. }
  12080. var hammer = new Hammer.Manager(this.$content[0]);
  12081. var swipe = new Hammer.Swipe({
  12082. direction: Hammer.DIRECTION_HORIZONTAL
  12083. // threshold: 40
  12084. });
  12085. hammer.add(swipe);
  12086. hammer.on('swipeleft', UI.utils.debounce(function(e) {
  12087. e.preventDefault();
  12088. _this.goTo('next');
  12089. }, 100));
  12090. hammer.on('swiperight', UI.utils.debounce(function(e) {
  12091. e.preventDefault();
  12092. _this.goTo('prev');
  12093. }, 100));
  12094. this._hammer = hammer;
  12095. }
  12096. };
  12097. /**
  12098. * Open $nav tab
  12099. * @param {jQuery|HTMLElement|Number} $nav
  12100. * @returns {Tabs}
  12101. */
  12102. Tabs.prototype.open = function($nav) {
  12103. var activeClass = this.options.activeClass;
  12104. var activeIndex = typeof $nav === 'number' ? $nav : this.$navs.index($($nav));
  12105. $nav = typeof $nav === 'number' ? this.$navs.eq(activeIndex) : $($nav);
  12106. if (!$nav ||
  12107. !$nav.length ||
  12108. this.transitioning ||
  12109. $nav.parent('li').hasClass(activeClass)) {
  12110. return;
  12111. }
  12112. var $tabNav = this.$tabNav;
  12113. var href = $nav.attr('href');
  12114. var regexHash = /^#.+$/;
  12115. var $target = regexHash.test(href) && this.$content.find(href) ||
  12116. this.$tabPanels.eq(activeIndex);
  12117. var previous = $tabNav.find('.' + activeClass + ' a')[0];
  12118. var e = $.Event('open.tabs.amui', {
  12119. relatedTarget: previous
  12120. });
  12121. $nav.trigger(e);
  12122. if (e.isDefaultPrevented()) {
  12123. return;
  12124. }
  12125. // activate Tab nav
  12126. this.activate($nav.closest('li'), $tabNav);
  12127. // activate Tab content
  12128. this.activate($target, this.$content, function() {
  12129. $nav.trigger({
  12130. type: 'opened.tabs.amui',
  12131. relatedTarget: previous
  12132. });
  12133. });
  12134. this.activeIndex = activeIndex;
  12135. };
  12136. Tabs.prototype.activate = function($element, $container, callback) {
  12137. this.transitioning = true;
  12138. var activeClass = this.options.activeClass;
  12139. var $active = $container.find('> .' + activeClass);
  12140. var transition = callback && supportTransition && !!$active.length;
  12141. $active.removeClass(activeClass + ' am-in');
  12142. $element.addClass(activeClass);
  12143. if (transition) {
  12144. $element.redraw(); // reflow for transition
  12145. $element.addClass('am-in');
  12146. } else {
  12147. $element.removeClass('am-fade');
  12148. }
  12149. var complete = $.proxy(function complete() {
  12150. callback && callback();
  12151. this.transitioning = false;
  12152. }, this);
  12153. transition && !this.$content.is('.am-tabs-bd-ofv') ?
  12154. $active.one(supportTransition.end, complete) : complete();
  12155. };
  12156. /**
  12157. * Go to `next` or `prev` tab
  12158. * @param {String} direction - `next` or `prev`
  12159. */
  12160. Tabs.prototype.goTo = function(direction) {
  12161. var navIndex = this.activeIndex;
  12162. var isNext = direction === 'next';
  12163. var spring = isNext ? 'am-animation-right-spring' :
  12164. 'am-animation-left-spring';
  12165. if ((isNext && navIndex + 1 >= this.$navs.length) || // last one
  12166. (!isNext && navIndex === 0)) { // first one
  12167. var $panel = this.$tabPanels.eq(navIndex);
  12168. animation && $panel.addClass(spring).on(animation.end, function() {
  12169. $panel.removeClass(spring);
  12170. });
  12171. } else {
  12172. this.open(isNext ? navIndex + 1 : navIndex - 1);
  12173. }
  12174. };
  12175. Tabs.prototype.destroy = function() {
  12176. this.$element.off('.tabs.amui');
  12177. Hammer.off(this.$content[0], 'swipeleft swiperight');
  12178. this._hammer && this._hammer.destroy();
  12179. $.removeData(this.$element, 'amui.tabs');
  12180. };
  12181. // Plugin
  12182. function Plugin(option) {
  12183. var args = Array.prototype.slice.call(arguments, 1);
  12184. var methodReturn;
  12185. this.each(function() {
  12186. var $this = $(this);
  12187. var $tabs = $this.is('.am-tabs') && $this || $this.closest('.am-tabs');
  12188. var data = $tabs.data('amui.tabs');
  12189. var options = $.extend({}, UI.utils.parseOptions($this.data('amTabs')),
  12190. $.isPlainObject(option) && option);
  12191. if (!data) {
  12192. $tabs.data('amui.tabs', (data = new Tabs($tabs[0], options)));
  12193. }
  12194. if (typeof option === 'string') {
  12195. if (option === 'open' && $this.is('.am-tabs-nav a')) {
  12196. data.open($this);
  12197. } else {
  12198. methodReturn = typeof data[option] === 'function' ?
  12199. data[option].apply(data, args) : data[option];
  12200. }
  12201. }
  12202. });
  12203. return methodReturn === undefined ? this : methodReturn;
  12204. }
  12205. $.fn.tabs = Plugin;
  12206. // Init code
  12207. UI.ready(function(context) {
  12208. $('[data-am-tabs]', context).tabs();
  12209. });
  12210. $(document).on('click.tabs.amui.data-api', '[data-am-tabs] .am-tabs-nav a',
  12211. function(e) {
  12212. e.preventDefault();
  12213. Plugin.call($(this), 'open');
  12214. });
  12215. module.exports = UI.tabs = Tabs;
  12216. // TODO: 1. Ajax 支持
  12217. // 2. touch 事件处理逻辑优化
  12218. /***/ },
  12219. /* 29 */
  12220. /***/ function(module, exports, __webpack_require__) {
  12221. 'use strict';
  12222. var $ = __webpack_require__(1);
  12223. var UI = __webpack_require__(2);
  12224. /**
  12225. * UCheck
  12226. * @via https://github.com/designmodo/Flat-UI/blob/8ef98df23ba7f5033e596a9bd05b53b535a9fe99/js/radiocheck.js
  12227. * @license CC BY 3.0 & MIT
  12228. * @param {HTMLElement} element
  12229. * @param {object} options
  12230. * @constructor
  12231. */
  12232. var UCheck = function(element, options) {
  12233. this.options = $.extend({}, UCheck.DEFAULTS, options);
  12234. // this.options = $.extend({}, UCheck.DEFAULTS, this.$element.data(), options);
  12235. this.$element = $(element);
  12236. this.init();
  12237. };
  12238. UCheck.DEFAULTS = {
  12239. checkboxClass: 'am-ucheck-checkbox',
  12240. radioClass: 'am-ucheck-radio',
  12241. checkboxTpl: '<span class="am-ucheck-icons">' +
  12242. '<i class="am-icon-unchecked"></i><i class="am-icon-checked"></i></span>',
  12243. radioTpl: '<span class="am-ucheck-icons">' +
  12244. '<i class="am-icon-unchecked"></i><i class="am-icon-checked"></i></span>'
  12245. };
  12246. UCheck.prototype.init = function() {
  12247. var $element = this.$element;
  12248. var element = $element[0];
  12249. var options = this.options;
  12250. if (element.type === 'checkbox') {
  12251. $element.addClass(options.checkboxClass)
  12252. .after(options.checkboxTpl);
  12253. } else if (element.type === 'radio') {
  12254. $element.addClass(options.radioClass)
  12255. .after(options.radioTpl);
  12256. }
  12257. };
  12258. UCheck.prototype.check = function() {
  12259. this.$element
  12260. .prop('checked', true)
  12261. .trigger('change.ucheck.amui')
  12262. .trigger('checked.ucheck.amui');
  12263. },
  12264. UCheck.prototype.uncheck = function() {
  12265. this.$element
  12266. .prop('checked', false)
  12267. // trigger `change` event for form validation, etc.
  12268. // @see https://forum.jquery.com/topic/should-chk-prop-checked-true-trigger-change-event
  12269. .trigger('change')
  12270. .trigger('unchecked.ucheck.amui');
  12271. },
  12272. UCheck.prototype.toggle = function() {
  12273. this.$element.
  12274. prop('checked', function(i, value) {
  12275. return !value;
  12276. })
  12277. .trigger('change.ucheck.amui')
  12278. .trigger('toggled.ucheck.amui');
  12279. },
  12280. UCheck.prototype.disable = function() {
  12281. this.$element
  12282. .prop('disabled', true)
  12283. .trigger('change.ucheck.amui')
  12284. .trigger('disabled.ucheck.amui');
  12285. },
  12286. UCheck.prototype.enable = function() {
  12287. this.$element.prop('disabled', false);
  12288. this.$element.trigger('change.ucheck.amui').trigger('enabled.ucheck.amui');
  12289. },
  12290. UCheck.prototype.destroy = function() {
  12291. this.$element
  12292. .removeData('amui.ucheck')
  12293. .removeClass(this.options.checkboxClass + ' ' + this.options.radioClass)
  12294. .next('.am-ucheck-icons')
  12295. .remove()
  12296. .end()
  12297. .trigger('destroyed.ucheck.amui');
  12298. };
  12299. UI.plugin('uCheck', UCheck, {
  12300. after: function() {
  12301. // Adding 'am-nohover' class for touch devices
  12302. if (UI.support.touch) {
  12303. this.parent().hover(function() {
  12304. $(this).addClass('am-nohover');
  12305. }, function() {
  12306. $(this).removeClass('am-nohover');
  12307. });
  12308. }
  12309. }
  12310. });
  12311. UI.ready(function(context) {
  12312. $('[data-am-ucheck]', context).uCheck();
  12313. });
  12314. module.exports = UCheck;
  12315. // TODO: 与表单验证结合使用的情况
  12316. /***/ },
  12317. /* 30 */
  12318. /***/ function(module, exports, __webpack_require__) {
  12319. 'use strict';
  12320. var $ = __webpack_require__(1);
  12321. var UI = __webpack_require__(2);
  12322. var Validator = function(element, options) {
  12323. this.options = $.extend({}, Validator.DEFAULTS, options);
  12324. this.options.patterns = $.extend({}, Validator.patterns,
  12325. this.options.patterns);
  12326. var locales = this.options.locales;
  12327. !Validator.validationMessages[locales] && (this.options.locales = 'zh_CN');
  12328. this.$element = $(element);
  12329. this.init();
  12330. };
  12331. Validator.DEFAULTS = {
  12332. debug: false,
  12333. locales: 'zh_CN',
  12334. H5validation: false,
  12335. H5inputType: ['email', 'url', 'number'],
  12336. patterns: {},
  12337. patternClassPrefix: 'js-pattern-',
  12338. activeClass: 'am-active',
  12339. inValidClass: 'am-field-error',
  12340. validClass: 'am-field-valid',
  12341. validateOnSubmit: true,
  12342. alwaysRevalidate: false,
  12343. // Elements to validate with allValid (only validating visible elements)
  12344. // :input: selects all input, textarea, select and button elements.
  12345. // @since 2.5: move `:visible` to `ignore` option (became to `:hidden`)
  12346. allFields: ':input:not(:submit, :button, :disabled, .am-novalidate)',
  12347. // ignored elements
  12348. // @since 2.5
  12349. ignore: ':hidden:not([data-am-selected], .am-validate)',
  12350. // Custom events
  12351. customEvents: 'validate',
  12352. // Keyboard events
  12353. keyboardFields: ':input:not(:submit, :button, :disabled, .am-novalidate)',
  12354. keyboardEvents: 'focusout, change', // keyup, focusin
  12355. // bind `keyup` event to active field
  12356. activeKeyup: false,
  12357. textareaMaxlenthKeyup: true,
  12358. // Mouse events
  12359. pointerFields: 'input[type="range"]:not(:disabled, .am-novalidate), ' +
  12360. 'input[type="radio"]:not(:disabled, .am-novalidate), ' +
  12361. 'input[type="checkbox"]:not(:disabled, .am-novalidate), ' +
  12362. 'select:not(:disabled, .am-novalidate), ' +
  12363. 'option:not(:disabled, .am-novalidate)',
  12364. pointerEvents: 'click',
  12365. onValid: function(validity) {
  12366. },
  12367. onInValid: function(validity) {
  12368. },
  12369. markValid: function(validity) {
  12370. // this is Validator instance
  12371. var options = this.options;
  12372. var $field = $(validity.field);
  12373. var $parent = $field.closest('.am-form-group');
  12374. $field.addClass(options.validClass).removeClass(options.inValidClass);
  12375. $parent.addClass('am-form-success').removeClass('am-form-error');
  12376. options.onValid.call(this, validity);
  12377. },
  12378. markInValid: function(validity) {
  12379. var options = this.options;
  12380. var $field = $(validity.field);
  12381. var $parent = $field.closest('.am-form-group');
  12382. $field.addClass(options.inValidClass + ' ' + options.activeClass).
  12383. removeClass(options.validClass);
  12384. $parent.addClass('am-form-error').removeClass('am-form-success');
  12385. options.onInValid.call(this, validity);
  12386. },
  12387. validate: function(validity) {
  12388. // return validity;
  12389. },
  12390. submit: null
  12391. };
  12392. Validator.VERSION = '2.7.2';
  12393. /* jshint -W101 */
  12394. Validator.patterns = {
  12395. email: /^((([a-zA-Z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-zA-Z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/,
  12396. url: /^(https?|ftp):\/\/(((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/,
  12397. // Number, including positive, negative, and floating decimal
  12398. number: /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/,
  12399. dateISO: /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/,
  12400. integer: /^-?\d+$/
  12401. };
  12402. /* jshint +W101 */
  12403. Validator.validationMessages = {
  12404. zh_CN: {
  12405. valueMissing: '请填写(选择)此字段',
  12406. customError: {
  12407. tooShort: '至少填写 %s 个字符',
  12408. checkedOverflow: '至多选择 %s 项',
  12409. checkedUnderflow: '至少选择 %s 项'
  12410. },
  12411. patternMismatch: '请按照要求的格式填写',
  12412. rangeOverflow: '请填写小于等于 %s 的值',
  12413. rangeUnderflow: '请填写大于等于 %s 的值',
  12414. stepMismatch: '',
  12415. tooLong: '至多填写 %s 个字符',
  12416. typeMismatch: '请按照要求的类型填写'
  12417. }
  12418. };
  12419. Validator.ERROR_MAP = {
  12420. tooShort: 'minlength',
  12421. checkedOverflow: 'maxchecked',
  12422. checkedUnderflow: 'minchecked',
  12423. rangeOverflow: 'max',
  12424. rangeUnderflow: 'min',
  12425. tooLong: 'maxlength'
  12426. };
  12427. // TODO: 考虑表单元素不是 form 子元素的情形
  12428. // TODO: change/click/focusout 同时触发时处理重复
  12429. // TODO: 显示提示信息
  12430. Validator.prototype.init = function() {
  12431. var _this = this;
  12432. var $element = this.$element;
  12433. var options = this.options;
  12434. // using H5 form validation if option set and supported
  12435. if (options.H5validation && UI.support.formValidation) {
  12436. return false;
  12437. }
  12438. // disable HTML5 form validation
  12439. $element.attr('novalidate', 'novalidate');
  12440. function regexToPattern(regex) {
  12441. var pattern = regex.toString();
  12442. return pattern.substring(1, pattern.length - 1);
  12443. }
  12444. // add pattern to H5 input type
  12445. $.each(options.H5inputType, function(i, type) {
  12446. var $field = $element.find('input[type=' + type + ']');
  12447. if (!$field.attr('pattern') &&
  12448. !$field.is('[class*=' + options.patternClassPrefix + ']')) {
  12449. $field.attr('pattern', regexToPattern(options.patterns[type]));
  12450. }
  12451. });
  12452. // add pattern to .js-pattern-xx
  12453. $.each(options.patterns, function(key, value) {
  12454. var $field = $element.find('.' + options.patternClassPrefix + key);
  12455. !$field.attr('pattern') && $field.attr('pattern', regexToPattern(value));
  12456. });
  12457. $element.on('submit.validator.amui', function(e) {
  12458. // user custom submit handler
  12459. if (typeof options.submit === 'function') {
  12460. return options.submit.call(_this, e);
  12461. }
  12462. if (options.validateOnSubmit) {
  12463. var formValidity = _this.isFormValid();
  12464. // sync validate, return result
  12465. if ($.type(formValidity) === 'boolean') {
  12466. return formValidity;
  12467. }
  12468. if ($element.data('amui.checked')) {
  12469. return true;
  12470. } else {
  12471. $.when(formValidity).then(function() {
  12472. // done, submit form
  12473. $element.data('amui.checked', true).submit();
  12474. }, function() {
  12475. // fail
  12476. $element.data('amui.checked', false).
  12477. find('.' + options.inValidClass).eq(0).focus();
  12478. });
  12479. return false;
  12480. }
  12481. }
  12482. });
  12483. function bindEvents(fields, eventFlags, debounce) {
  12484. var events = eventFlags.split(',');
  12485. var validate = function(e) {
  12486. // console.log(e.type);
  12487. _this.validate(this);
  12488. };
  12489. if (debounce) {
  12490. validate = UI.utils.debounce(validate, debounce);
  12491. }
  12492. $.each(events, function(i, event) {
  12493. $element.on(event + '.validator.amui', fields, validate);
  12494. });
  12495. }
  12496. bindEvents(':input', options.customEvents);
  12497. bindEvents(options.keyboardFields, options.keyboardEvents);
  12498. bindEvents(options.pointerFields, options.pointerEvents);
  12499. if (options.textareaMaxlenthKeyup) {
  12500. bindEvents('textarea[maxlength]', 'keyup', 50);
  12501. }
  12502. if (options.activeKeyup) {
  12503. bindEvents('.am-active', 'keyup', 50);
  12504. }
  12505. /*if (options.errorMessage === 'tooltip') {
  12506. this.$tooltip = $('<div></div>', {
  12507. 'class': 'am-validator-message',
  12508. id: UI.utils.generateGUID('am-validator-message')
  12509. });
  12510. $(document.body).append(this.$tooltip);
  12511. }*/
  12512. };
  12513. Validator.prototype.isValid = function(field) {
  12514. var $field = $(field);
  12515. var options = this.options;
  12516. // valid field not has been validated
  12517. if ($field.data('validity') === undefined || options.alwaysRevalidate) {
  12518. this.validate(field);
  12519. }
  12520. return $field.data('validity') && $field.data('validity').valid;
  12521. };
  12522. Validator.prototype.validate = function(field) {
  12523. var _this = this;
  12524. var $element = this.$element;
  12525. var options = this.options;
  12526. var $field = $(field);
  12527. // Validate equal, e.g. confirm password
  12528. var equalTo = $field.data('equalTo');
  12529. if (equalTo) {
  12530. $field.attr('pattern', '^' + $element.find(equalTo).val() + '$');
  12531. }
  12532. var pattern = $field.attr('pattern') || false;
  12533. var re = new RegExp(pattern);
  12534. var $radioGroup = null;
  12535. var $checkboxGroup = null;
  12536. // if checkbox, return `:chcked` length
  12537. // NOTE: checkbox and radio should have name attribute
  12538. var value = ($field.is('[type=checkbox]')) ?
  12539. ($checkboxGroup = $element.find('input[name="' + field.name + '"]')).
  12540. filter(':checked').length : ($field.is('[type=radio]') ?
  12541. ($radioGroup = this.$element.find('input[name="' + field.name + '"]')).
  12542. filter(':checked').length > 0 : $field.val());
  12543. // if checkbox, valid the first input of checkbox group
  12544. $field = ($checkboxGroup && $checkboxGroup.length) ?
  12545. $checkboxGroup.first() : $field;
  12546. var required = ($field.attr('required') !== undefined) &&
  12547. ($field.attr('required') !== 'false');
  12548. var maxLength = parseInt($field.attr('maxlength'), 10);
  12549. var minLength = parseInt($field.attr('minlength'), 10);
  12550. var min = Number($field.attr('min'));
  12551. var max = Number($field.attr('max'));
  12552. var validity = this.createValidity({field: $field[0], valid: true});
  12553. // Debug
  12554. if (options.debug && window.console) {
  12555. console.log('Validate: value -> [' + value + ', regex -> [' + re +
  12556. '], required -> ' + required);
  12557. console.log('Regex test: ' + re.test(value) + ', Pattern: ' + pattern);
  12558. }
  12559. // check value length
  12560. if (!isNaN(maxLength) && value.length > maxLength) {
  12561. validity.valid = false;
  12562. validity.tooLong = true;
  12563. }
  12564. if (!isNaN(minLength) && value.length < minLength) {
  12565. validity.valid = false;
  12566. validity.customError = 'tooShort';
  12567. }
  12568. // check minimum and maximum
  12569. // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input
  12570. // TODO: 日期验证最小值和最大值 min/max
  12571. if (!isNaN(min) && Number(value) < min) {
  12572. validity.valid = false;
  12573. validity.rangeUnderflow = true;
  12574. }
  12575. if (!isNaN(max) && Number(value) > max) {
  12576. validity.valid = false;
  12577. validity.rangeOverflow = true;
  12578. }
  12579. // check required
  12580. if (required && !value) {
  12581. validity.valid = false;
  12582. validity.valueMissing = true;
  12583. } else if (($checkboxGroup || $field.is('select[multiple="multiple"]')) &&
  12584. value) {
  12585. // check checkboxes / multiple select with `minchecked`/`maxchecked` attr
  12586. // var $multipleField = $checkboxGroup ? $checkboxGroup.first() : $field;
  12587. // if is select[multiple="multiple"], return selected length
  12588. value = $checkboxGroup ? value : value.length;
  12589. // at least checked
  12590. var minChecked = parseInt($field.attr('minchecked'), 10);
  12591. // at most checked
  12592. var maxChecked = parseInt($field.attr('maxchecked'), 10);
  12593. if (!isNaN(minChecked) && value < minChecked) {
  12594. // console.log('At least [%d] items checked!', maxChecked);
  12595. validity.valid = false;
  12596. validity.customError = 'checkedUnderflow';
  12597. }
  12598. if (!isNaN(maxChecked) && value > maxChecked) {
  12599. // console.log('At most [%d] items checked!', maxChecked);
  12600. validity.valid = false;
  12601. validity.customError = 'checkedOverflow';
  12602. }
  12603. } else if (pattern && !re.test(value) && value) { // check pattern
  12604. validity.valid = false;
  12605. validity.patternMismatch = true;
  12606. }
  12607. var validateComplete = function(validity) {
  12608. this.markField(validity);
  12609. var event = $.Event('validated.field.validator.amui');
  12610. event.validity = validity;
  12611. $field.trigger(event).data('validity', validity);
  12612. // validate the radios/checkboxes with the same name
  12613. var $fields = $radioGroup || $checkboxGroup;
  12614. if ($fields) {
  12615. $fields.not($field).data('validity', validity).each(function() {
  12616. validity.field = this;
  12617. _this.markField(validity);
  12618. });
  12619. }
  12620. return validity;
  12621. };
  12622. // Run custom validate
  12623. // NOTE: async custom validate should return Deferred project
  12624. var customValidate;
  12625. (typeof options.validate === 'function') &&
  12626. (customValidate = options.validate.call(this, validity));
  12627. // Deferred
  12628. if (customValidate) {
  12629. var dfd = new $.Deferred();
  12630. $field.data('amui.dfdValidity', dfd.promise());
  12631. return $.when(customValidate).always(function(validity) {
  12632. dfd[validity.valid ? 'resolve' : 'reject'](validity);
  12633. validateComplete.call(_this, validity);
  12634. });
  12635. }
  12636. validateComplete.call(this, validity);
  12637. };
  12638. Validator.prototype.markField = function(validity) {
  12639. var options = this.options;
  12640. var flag = 'mark' + (validity.valid ? '' : 'In') + 'Valid';
  12641. options[flag] && options[flag].call(this, validity);
  12642. };
  12643. // check all fields in the form are valid
  12644. Validator.prototype.validateForm = function() {
  12645. var _this = this;
  12646. var $element = this.$element;
  12647. var options = this.options;
  12648. var $allFields = $element.find(options.allFields).not(options.ignore);
  12649. var radioNames = [];
  12650. var valid = true;
  12651. var formValidity = [];
  12652. var $inValidFields = $([]);
  12653. var promises = [];
  12654. // for async validate
  12655. var async = false;
  12656. $element.trigger('validate.form.validator.amui');
  12657. // Filter radio with the same name and keep only one,
  12658. // since they will be checked as a group by validate()
  12659. var $filteredFields = $allFields.filter(function(index) {
  12660. var name;
  12661. if (this.tagName === 'INPUT' && this.type === 'radio') {
  12662. name = this.name;
  12663. if (radioNames[name] === true) {
  12664. return false;
  12665. }
  12666. radioNames[name] = true;
  12667. }
  12668. return true;
  12669. });
  12670. $filteredFields.each(function() {
  12671. var $this = $(this);
  12672. var fieldValid = _this.isValid(this);
  12673. var fieldValidity = $this.data('validity');
  12674. valid = !!fieldValid && valid;
  12675. formValidity.push(fieldValidity);
  12676. if (!fieldValid) {
  12677. $inValidFields = $inValidFields.add($(this), $element);
  12678. }
  12679. // async validity
  12680. var promise = $this.data('amui.dfdValidity');
  12681. if (promise) {
  12682. promises.push(promise);
  12683. async = true;
  12684. } else {
  12685. // convert sync validity to Promise
  12686. var dfd = new $.Deferred();
  12687. promises.push(dfd.promise());
  12688. dfd[fieldValid ? 'resolve' : 'reject'](fieldValidity);
  12689. }
  12690. });
  12691. // NOTE: If there are async validity, the valid may be not exact result.
  12692. var validity = {
  12693. valid: valid,
  12694. $invalidFields: $inValidFields,
  12695. validity: formValidity,
  12696. promises: promises,
  12697. async: async
  12698. };
  12699. $element.trigger('validated.form.validator.amui', validity);
  12700. return validity;
  12701. };
  12702. Validator.prototype.isFormValid = function() {
  12703. var _this = this;
  12704. var formValidity = this.validateForm();
  12705. var triggerValid = function(type) {
  12706. _this.$element.trigger(type + '.validator.amui');
  12707. };
  12708. if (formValidity.async) {
  12709. var masterDfd = new $.Deferred();
  12710. $.when.apply(null, formValidity.promises).then(function() {
  12711. masterDfd.resolve();
  12712. triggerValid('valid');
  12713. }, function() {
  12714. masterDfd.reject();
  12715. triggerValid('invalid');
  12716. });
  12717. return masterDfd.promise();
  12718. } else {
  12719. if (!formValidity.valid) {
  12720. var $first = formValidity.$invalidFields.first();
  12721. // Selected plugin support
  12722. // @since 2.5
  12723. if ($first.is('[data-am-selected]')) {
  12724. $first = $first.next('.am-selected').find('.am-selected-btn');
  12725. }
  12726. $first.focus();
  12727. triggerValid('invalid');
  12728. return false;
  12729. }
  12730. triggerValid('valid');
  12731. return true;
  12732. }
  12733. };
  12734. // customErrors:
  12735. // 1. tooShort
  12736. // 2. checkedOverflow
  12737. // 3. checkedUnderflow
  12738. Validator.prototype.createValidity = function(validity) {
  12739. return $.extend({
  12740. customError: validity.customError || false,
  12741. patternMismatch: validity.patternMismatch || false,
  12742. rangeOverflow: validity.rangeOverflow || false, // higher than maximum
  12743. rangeUnderflow: validity.rangeUnderflow || false, // lower than minimum
  12744. stepMismatch: validity.stepMismatch || false,
  12745. tooLong: validity.tooLong || false,
  12746. // value is not in the correct syntax
  12747. typeMismatch: validity.typeMismatch || false,
  12748. valid: validity.valid || true,
  12749. // Returns true if the element has no value but is a required field
  12750. valueMissing: validity.valueMissing || false
  12751. }, validity);
  12752. };
  12753. Validator.prototype.getValidationMessage = function(validity) {
  12754. var messages = Validator.validationMessages[this.options.locales];
  12755. var error;
  12756. var message;
  12757. var placeholder = '%s';
  12758. var $field = $(validity.field);
  12759. if ($field.is('[type="checkbox"]') || $field.is('[type="radio"]')) {
  12760. $field = this.$element.find('[name=' + $field.attr('name') + ']').first();
  12761. }
  12762. // get error name
  12763. $.each(validity, function(key, val) {
  12764. // skip `field` and `valid`
  12765. if (key === 'field' || key === 'valid') {
  12766. return key;
  12767. }
  12768. // Amaze UI custom error type
  12769. if (key === 'customError' && val) {
  12770. error = val;
  12771. messages = messages.customError;
  12772. return false;
  12773. }
  12774. // W3C specs error type
  12775. if (val === true) {
  12776. error = key;
  12777. return false;
  12778. }
  12779. });
  12780. message = messages[error] || undefined;
  12781. if (message && Validator.ERROR_MAP[error]) {
  12782. message = message.replace(placeholder,
  12783. $field.attr(Validator.ERROR_MAP[error]) || '规定的');
  12784. }
  12785. return message;
  12786. };
  12787. // remove valid mark
  12788. Validator.prototype.removeMark = function() {
  12789. this.$element
  12790. .find('.am-form-success, .am-form-error, .' + this.options.inValidClass +
  12791. ', .' + this.options.validClass)
  12792. .removeClass([
  12793. 'am-form-success',
  12794. 'am-form-error',
  12795. this.options.inValidClass,
  12796. this.options.validClass
  12797. ].join(' '));
  12798. };
  12799. // @since 2.5
  12800. Validator.prototype.destroy = function() {
  12801. this.removeMark();
  12802. // Remove data
  12803. // - Validator.prototype.init -> $element.data('amui.checked')
  12804. // - Validator.prototype.validateForm
  12805. // - Validator.prototype.isValid
  12806. this.$element.removeData('amui.validator amui.checked')
  12807. .off('.validator.amui')
  12808. .find(this.options.allFields).removeData('validity amui.dfdValidity');
  12809. };
  12810. UI.plugin('validator', Validator);
  12811. // init code
  12812. UI.ready(function(context) {
  12813. $('[data-am-validator]', context).validator();
  12814. });
  12815. module.exports = Validator;
  12816. /***/ },
  12817. /* 31 */
  12818. /***/ function(module, exports, __webpack_require__) {
  12819. 'use strict';
  12820. var UI = __webpack_require__(2);
  12821. var cookie = {
  12822. get: function(name) {
  12823. var cookieName = encodeURIComponent(name) + '=';
  12824. var cookieStart = document.cookie.indexOf(cookieName);
  12825. var cookieValue = null;
  12826. var cookieEnd;
  12827. if (cookieStart > -1) {
  12828. cookieEnd = document.cookie.indexOf(';', cookieStart);
  12829. if (cookieEnd == -1) {
  12830. cookieEnd = document.cookie.length;
  12831. }
  12832. cookieValue = decodeURIComponent(document.cookie.substring(cookieStart +
  12833. cookieName.length, cookieEnd));
  12834. }
  12835. return cookieValue;
  12836. },
  12837. set: function(name, value, expires, path, domain, secure) {
  12838. var cookieText = encodeURIComponent(name) + '=' +
  12839. encodeURIComponent(value);
  12840. if (expires instanceof Date) {
  12841. cookieText += '; expires=' + expires.toUTCString();
  12842. }
  12843. if (path) {
  12844. cookieText += '; path=' + path;
  12845. }
  12846. if (domain) {
  12847. cookieText += '; domain=' + domain;
  12848. }
  12849. if (secure) {
  12850. cookieText += '; secure';
  12851. }
  12852. document.cookie = cookieText;
  12853. },
  12854. unset: function(name, path, domain, secure) {
  12855. this.set(name, '', new Date(0), path, domain, secure);
  12856. }
  12857. };
  12858. UI.utils = UI.utils || {};
  12859. module.exports = UI.utils.cookie = cookie;
  12860. /***/ },
  12861. /* 32 */
  12862. /***/ function(module, exports, __webpack_require__) {
  12863. 'use strict';
  12864. /**
  12865. * @see https://github.com/sindresorhus/screenfull.js
  12866. * @license MIT © Sindre Sorhus
  12867. */
  12868. var UI = __webpack_require__(2);
  12869. var screenfull = (function() {
  12870. var keyboardAllowed = typeof Element !== 'undefined' &&
  12871. 'ALLOW_KEYBOARD_INPUT' in Element;
  12872. var fn = (function() {
  12873. var val;
  12874. var valLength;
  12875. var fnMap = [
  12876. [
  12877. 'requestFullscreen',
  12878. 'exitFullscreen',
  12879. 'fullscreenElement',
  12880. 'fullscreenEnabled',
  12881. 'fullscreenchange',
  12882. 'fullscreenerror'
  12883. ],
  12884. // new WebKit
  12885. [
  12886. 'webkitRequestFullscreen',
  12887. 'webkitExitFullscreen',
  12888. 'webkitFullscreenElement',
  12889. 'webkitFullscreenEnabled',
  12890. 'webkitfullscreenchange',
  12891. 'webkitfullscreenerror'
  12892. ],
  12893. // old WebKit (Safari 5.1)
  12894. [
  12895. 'webkitRequestFullScreen',
  12896. 'webkitCancelFullScreen',
  12897. 'webkitCurrentFullScreenElement',
  12898. 'webkitCancelFullScreen',
  12899. 'webkitfullscreenchange',
  12900. 'webkitfullscreenerror'
  12901. ],
  12902. [
  12903. 'mozRequestFullScreen',
  12904. 'mozCancelFullScreen',
  12905. 'mozFullScreenElement',
  12906. 'mozFullScreenEnabled',
  12907. 'mozfullscreenchange',
  12908. 'mozfullscreenerror'
  12909. ],
  12910. [
  12911. 'msRequestFullscreen',
  12912. 'msExitFullscreen',
  12913. 'msFullscreenElement',
  12914. 'msFullscreenEnabled',
  12915. 'MSFullscreenChange',
  12916. 'MSFullscreenError'
  12917. ]
  12918. ];
  12919. var i = 0;
  12920. var l = fnMap.length;
  12921. var ret = {};
  12922. for (; i < l; i++) {
  12923. val = fnMap[i];
  12924. if (val && val[1] in document) {
  12925. for (i = 0, valLength = val.length; i < valLength; i++) {
  12926. ret[fnMap[0][i]] = val[i];
  12927. }
  12928. return ret;
  12929. }
  12930. }
  12931. return false;
  12932. })();
  12933. var screenfull = {
  12934. request: function(elem) {
  12935. var request = fn.requestFullscreen;
  12936. elem = elem || document.documentElement;
  12937. // Work around Safari 5.1 bug: reports support for
  12938. // keyboard in fullscreen even though it doesn't.
  12939. // Browser sniffing, since the alternative with
  12940. // setTimeout is even worse.
  12941. if (/5\.1[\.\d]* Safari/.test(navigator.userAgent)) {
  12942. elem[request]();
  12943. } else {
  12944. elem[request](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT);
  12945. }
  12946. },
  12947. exit: function() {
  12948. document[fn.exitFullscreen]();
  12949. },
  12950. toggle: function(elem) {
  12951. if (this.isFullscreen) {
  12952. this.exit();
  12953. } else {
  12954. this.request(elem);
  12955. }
  12956. },
  12957. raw: fn
  12958. };
  12959. if (!fn) {
  12960. return false;
  12961. }
  12962. Object.defineProperties(screenfull, {
  12963. isFullscreen: {
  12964. get: function() {
  12965. return !!document[fn.fullscreenElement];
  12966. }
  12967. },
  12968. element: {
  12969. enumerable: true,
  12970. get: function() {
  12971. return document[fn.fullscreenElement];
  12972. }
  12973. },
  12974. enabled: {
  12975. enumerable: true,
  12976. get: function() {
  12977. // Coerce to boolean in case of old WebKit
  12978. return !!document[fn.fullscreenEnabled];
  12979. }
  12980. }
  12981. });
  12982. screenfull.VERSION = '3.0.0';
  12983. return screenfull;
  12984. })();
  12985. module.exports = UI.fullscreen = screenfull;
  12986. /***/ },
  12987. /* 33 */
  12988. /***/ function(module, exports, __webpack_require__) {
  12989. 'use strict';
  12990. var $ = __webpack_require__(1);
  12991. var UI = __webpack_require__(2);
  12992. UI.support.geolocation = window.navigator && window.navigator.geolocation;
  12993. var geo = UI.support.geolocation;
  12994. var Geolocation = function(options) {
  12995. this.options = options || {};
  12996. };
  12997. Geolocation.MESSAGES = {
  12998. unsupportedBrowser: 'Browser does not support location services',
  12999. permissionDenied: 'You have rejected access to your location',
  13000. positionUnavailable: 'Unable to determine your location',
  13001. timeout: 'Service timeout has been reached'
  13002. };
  13003. Geolocation.ERROR_CODE = {
  13004. 0: 'unsupportedBrowser',
  13005. 1: 'permissionDenied',
  13006. 2: 'positionUnavailable',
  13007. 3: 'timeout'
  13008. };
  13009. Geolocation.prototype.get = function(options) {
  13010. var _this = this;
  13011. options = $.extend({}, this.options, options);
  13012. var deferred = new $.Deferred();
  13013. if (geo) {
  13014. this.watchID = geo.getCurrentPosition(function(position) {
  13015. deferred.resolve.call(_this, position);
  13016. }, function(error) {
  13017. deferred.reject(Geolocation.MESSAGES[Geolocation.ERROR_CODE[error.code]]);
  13018. }, options);
  13019. } else {
  13020. deferred.reject(Geolocation.MESSAGES.unsupportedBrowser);
  13021. }
  13022. return deferred.promise();
  13023. };
  13024. Geolocation.prototype.watch = function(options) {
  13025. if (!geo) {
  13026. return;
  13027. }
  13028. options = $.extend({}, this.options, options);
  13029. if (!$.isFunction(options.done)) {
  13030. return;
  13031. }
  13032. this.clearWatch();
  13033. var fail = $.isFunction(options.fail) ? options.fail : null;
  13034. this.watchID = geo.watchPosition(options.done, fail, options);
  13035. return this.watchID;
  13036. };
  13037. Geolocation.prototype.clearWatch = function() {
  13038. if (!geo || !this.watchID) {
  13039. return;
  13040. }
  13041. geo.clearWatch(this.watchID);
  13042. this.watchID = null;
  13043. };
  13044. module.exports = UI.Geolocation = Geolocation;
  13045. /***/ },
  13046. /* 34 */
  13047. /***/ function(module, exports, __webpack_require__) {
  13048. /* WEBPACK VAR INJECTION */(function(global) {'use strict';
  13049. var UI = __webpack_require__(2);
  13050. /**
  13051. * store.js
  13052. * @see https://github.com/marcuswestin/store.js
  13053. * @license https://github.com/marcuswestin/store.js/blob/master/LICENSE
  13054. */
  13055. var store = {};
  13056. var win = (typeof window != 'undefined' ? window : global);
  13057. var localStorageName = 'localStorage';
  13058. var storage;
  13059. store.disabled = false;
  13060. store.version = '1.3.20';
  13061. store.set = function(key, value) {
  13062. };
  13063. store.get = function(key, defaultVal) {
  13064. };
  13065. store.has = function(key) {
  13066. return store.get(key) !== undefined;
  13067. };
  13068. store.remove = function(key) {
  13069. };
  13070. store.clear = function() {
  13071. };
  13072. store.transact = function(key, defaultVal, transactionFn) {
  13073. if (transactionFn == null) {
  13074. transactionFn = defaultVal;
  13075. defaultVal = null;
  13076. }
  13077. if (defaultVal == null) {
  13078. defaultVal = {};
  13079. }
  13080. var val = store.get(key, defaultVal);
  13081. transactionFn(val);
  13082. store.set(key, val);
  13083. };
  13084. store.getAll = function() {
  13085. };
  13086. store.forEach = function() {
  13087. };
  13088. store.serialize = function(value) {
  13089. return JSON.stringify(value);
  13090. };
  13091. store.deserialize = function(value) {
  13092. if (typeof value != 'string') {
  13093. return undefined;
  13094. }
  13095. try {
  13096. return JSON.parse(value);
  13097. } catch (e) {
  13098. return value || undefined;
  13099. }
  13100. };
  13101. // Functions to encapsulate questionable FireFox 3.6.13 behavior
  13102. // when about.config::dom.storage.enabled === false
  13103. // See https://github.com/marcuswestin/store.js/issues#issue/13
  13104. function isLocalStorageNameSupported() {
  13105. try {
  13106. return (localStorageName in win && win[localStorageName]);
  13107. } catch (err) {
  13108. return false;
  13109. }
  13110. }
  13111. if (isLocalStorageNameSupported()) {
  13112. storage = win[localStorageName];
  13113. store.set = function(key, val) {
  13114. if (val === undefined) {
  13115. return store.remove(key);
  13116. }
  13117. storage.setItem(key, store.serialize(val));
  13118. return val;
  13119. };
  13120. store.get = function(key, defaultVal) {
  13121. var val = store.deserialize(storage.getItem(key));
  13122. return (val === undefined ? defaultVal : val);
  13123. };
  13124. store.remove = function(key) {
  13125. storage.removeItem(key);
  13126. };
  13127. store.clear = function() {
  13128. storage.clear();
  13129. };
  13130. store.getAll = function() {
  13131. var ret = {};
  13132. store.forEach(function(key, val) {
  13133. ret[key] = val;
  13134. });
  13135. return ret;
  13136. };
  13137. store.forEach = function(callback) {
  13138. for (var i = 0; i < storage.length; i++) {
  13139. var key = storage.key(i);
  13140. callback(key, store.get(key));
  13141. }
  13142. };
  13143. }
  13144. try {
  13145. var testKey = '__storejs__';
  13146. store.set(testKey, testKey);
  13147. if (store.get(testKey) != testKey) {
  13148. store.disabled = true;
  13149. }
  13150. store.remove(testKey);
  13151. } catch (e) {
  13152. store.disabled = true;
  13153. }
  13154. store.enabled = !store.disabled;
  13155. module.exports = UI.store = store;
  13156. /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
  13157. /***/ },
  13158. /* 35 */
  13159. /***/ function(module, exports, __webpack_require__) {
  13160. 'use strict';
  13161. var $ = __webpack_require__(1);
  13162. var UI = __webpack_require__(2);
  13163. __webpack_require__(7);
  13164. function accordionInit() {
  13165. var $accordion = $('[data-am-widget="accordion"]');
  13166. var selector = {
  13167. item: '.am-accordion-item',
  13168. title: '.am-accordion-title',
  13169. body: '.am-accordion-bd',
  13170. disabled: '.am-disabled'
  13171. };
  13172. $accordion.each(function(i, item) {
  13173. var options = UI.utils.parseOptions($(item).attr('data-am-accordion'));
  13174. var $title = $(item).find(selector.title);
  13175. $title.on('click.accordion.amui', function() {
  13176. var $collapse = $(this).next(selector.body);
  13177. var $parent = $(this).parent(selector.item);
  13178. var data = $collapse.data('amui.collapse');
  13179. if ($parent.is(selector.disabled)) {
  13180. return;
  13181. }
  13182. $parent.toggleClass('am-active');
  13183. if (!data) {
  13184. $collapse.collapse();
  13185. } else {
  13186. $collapse.collapse('toggle');
  13187. }
  13188. !options.multiple &&
  13189. $(item).children('.am-active').
  13190. not($parent).not(selector.disabled).removeClass('am-active').
  13191. find(selector.body + '.am-in').collapse('close');
  13192. });
  13193. });
  13194. }
  13195. // Init on DOM ready
  13196. $(accordionInit);
  13197. module.exports = UI.accordion = {
  13198. VERSION: '2.1.0',
  13199. init: accordionInit
  13200. };
  13201. /***/ },
  13202. /* 36 */
  13203. /***/ function(module, exports) {
  13204. 'use strict';
  13205. module.exports = {
  13206. VERSION: '2.0.1'
  13207. };
  13208. /***/ },
  13209. /* 37 */
  13210. /***/ function(module, exports, __webpack_require__) {
  13211. 'use strict';
  13212. var $ = __webpack_require__(1);
  13213. var UI = __webpack_require__(2);
  13214. function duoshuoInit() {
  13215. var $dsThread = $('.ds-thread');
  13216. var dsShortName = $dsThread.parent('[data-am-widget="duoshuo"]').
  13217. attr('data-ds-short-name');
  13218. var dsSrc = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
  13219. '//static.duoshuo.com/embed.js';
  13220. if (!$dsThread.length || !dsShortName) {
  13221. return;
  13222. }
  13223. window.duoshuoQuery = {
  13224. short_name: dsShortName
  13225. };
  13226. // 已经有多说脚本
  13227. if ($('script[src="' + dsSrc + '"]').length) {
  13228. return;
  13229. }
  13230. var $dsJS = $('<script>', {
  13231. async: true,
  13232. type: 'text/javascript',
  13233. src: dsSrc,
  13234. charset: 'utf-8'
  13235. });
  13236. $('body').append($dsJS);
  13237. }
  13238. $(window).on('load', duoshuoInit);
  13239. module.exports = UI.duoshuo = {
  13240. VERSION: '2.0.1',
  13241. init: duoshuoInit
  13242. };
  13243. /***/ },
  13244. /* 38 */
  13245. /***/ function(module, exports, __webpack_require__) {
  13246. 'use strict';
  13247. var $ = __webpack_require__(1);
  13248. var UI = __webpack_require__(2);
  13249. __webpack_require__(20);
  13250. /**
  13251. * Is Images zoomable
  13252. * @return {Boolean}
  13253. */
  13254. $.isImgZoomAble = function(element) {
  13255. var t = new Image();
  13256. t.src = element.src;
  13257. var zoomAble = ($(element).width() < t.width);
  13258. if (zoomAble) {
  13259. $(element).closest('.am-figure').addClass('am-figure-zoomable');
  13260. }
  13261. return zoomAble;
  13262. };
  13263. function figureInit() {
  13264. $('.am-figure').each(function(i, item) {
  13265. var options = UI.utils.parseOptions($(item).attr('data-am-figure'));
  13266. var $item = $(item);
  13267. var data;
  13268. if (options.pureview) {
  13269. if (options.pureview === 'auto') {
  13270. var zoomAble = $.isImgZoomAble($item.find('img')[0]);
  13271. zoomAble && $item.pureview();
  13272. } else {
  13273. $item.addClass('am-figure-zoomable').pureview();
  13274. }
  13275. }
  13276. data = $item.data('amui.pureview');
  13277. if (data) {
  13278. $item.on('click', ':not(img)', function() {
  13279. data.open(0);
  13280. });
  13281. }
  13282. });
  13283. }
  13284. $(window).on('load', figureInit);
  13285. module.exports = UI.figure = {
  13286. VERSION: '2.0.3',
  13287. init: figureInit
  13288. };
  13289. /***/ },
  13290. /* 39 */
  13291. /***/ function(module, exports, __webpack_require__) {
  13292. 'use strict';
  13293. var $ = __webpack_require__(1);
  13294. var UI = __webpack_require__(2);
  13295. __webpack_require__(15);
  13296. var addToHS = __webpack_require__(4);
  13297. var cookie = __webpack_require__(31);
  13298. function footerInit() {
  13299. // modal mode
  13300. $('.am-footer-ysp').on('click', function() {
  13301. $('#am-footer-modal').modal();
  13302. });
  13303. var options = UI.utils.parseOptions($('.am-footer').data('amFooter'));
  13304. options.addToHS && addToHS();
  13305. // switch mode
  13306. // switch to desktop
  13307. $('[data-rel="desktop"]').on('click', function(e) {
  13308. e.preventDefault();
  13309. if (window.AMPlatform) { // front end
  13310. window.AMPlatform.util.goDesktop();
  13311. } else { // back end
  13312. cookie.set('allmobilize', 'desktop', '', '/');
  13313. window.location = window.location;
  13314. }
  13315. });
  13316. }
  13317. $(footerInit);
  13318. module.exports = UI.footer = {
  13319. VERSION: '3.1.2',
  13320. init: footerInit
  13321. };
  13322. /***/ },
  13323. /* 40 */
  13324. /***/ function(module, exports, __webpack_require__) {
  13325. 'use strict';
  13326. var $ = __webpack_require__(1);
  13327. var UI = __webpack_require__(2);
  13328. __webpack_require__(20);
  13329. function galleryInit() {
  13330. var $gallery = $('[data-am-widget="gallery"]');
  13331. $gallery.each(function() {
  13332. var options = UI.utils.parseOptions($(this).attr('data-am-gallery'));
  13333. if (options.pureview) {
  13334. (typeof options.pureview === 'object') ?
  13335. $(this).pureview(options.pureview) : $(this).pureview();
  13336. }
  13337. });
  13338. }
  13339. $(galleryInit);
  13340. module.exports = UI.gallery = {
  13341. VERSION: '3.0.0',
  13342. init: galleryInit
  13343. };
  13344. /***/ },
  13345. /* 41 */
  13346. /***/ function(module, exports, __webpack_require__) {
  13347. 'use strict';
  13348. var $ = __webpack_require__(1);
  13349. var UI = __webpack_require__(2);
  13350. __webpack_require__(23);
  13351. function goTopInit() {
  13352. var $goTop = $('[data-am-widget="gotop"]');
  13353. var $fixed = $goTop.filter('.am-gotop-fixed');
  13354. var $win = $(window);
  13355. if ($goTop.data('init')) {
  13356. return;
  13357. }
  13358. $goTop.find('a').on('click', function(e) {
  13359. e.preventDefault();
  13360. $win.smoothScroll();
  13361. });
  13362. function checkPosition() {
  13363. $fixed[($win.scrollTop() > 50 ? 'add' : 'remove') + 'Class']('am-active');
  13364. }
  13365. checkPosition();
  13366. $win.on('scroll.gotop.amui', UI.utils.debounce(checkPosition, 100));
  13367. $goTop.data('init', true);
  13368. }
  13369. $(goTopInit);
  13370. module.exports = UI.gotop = {
  13371. VERSION: '4.0.2',
  13372. init: goTopInit
  13373. };
  13374. /***/ },
  13375. /* 42 */
  13376. /***/ function(module, exports, __webpack_require__) {
  13377. 'use strict';
  13378. var $ = __webpack_require__(1);
  13379. var UI = __webpack_require__(2);
  13380. function headerInit() {
  13381. $('[data-am-widget="header"]').each(function() {
  13382. if ($(this).hasClass('am-header-fixed')) {
  13383. $('body').addClass('am-with-fixed-header');
  13384. return false;
  13385. }
  13386. });
  13387. }
  13388. $(headerInit);
  13389. module.exports = UI.header = {
  13390. VERSION: '2.0.0',
  13391. init: headerInit
  13392. };
  13393. /***/ },
  13394. /* 43 */
  13395. /***/ function(module, exports, __webpack_require__) {
  13396. 'use strict';
  13397. var UI = __webpack_require__(2);
  13398. module.exports = UI.intro = {
  13399. VERSION: '4.0.2',
  13400. init: function() {}
  13401. };
  13402. /***/ },
  13403. /* 44 */
  13404. /***/ function(module, exports, __webpack_require__) {
  13405. 'use strict';
  13406. var UI = __webpack_require__(2);
  13407. module.exports = UI.listNews = {
  13408. VERSION: '4.0.0',
  13409. init: function() {}
  13410. };
  13411. /***/ },
  13412. /* 45 */
  13413. /***/ function(module, exports, __webpack_require__) {
  13414. /* jshint strict: false, maxlen: 200 */
  13415. /* global BMap */
  13416. var $ = __webpack_require__(1);
  13417. var UI = __webpack_require__(2);
  13418. function addMapApi(callback) {
  13419. var $mapApi0 = $('<script />', {
  13420. id: 'am-map-api-0'
  13421. });
  13422. $('body').append($mapApi0);
  13423. $mapApi0.on('load', function() {
  13424. console.log('load');
  13425. var $mapApi1 = $('<script/>', {
  13426. id: 'am-map-api-1'
  13427. });
  13428. $('body').append($mapApi1);
  13429. $mapApi1.on('load', function() {
  13430. var script = document.createElement('script');
  13431. script.textContent = '(' + callback.toString() + ')();';
  13432. $('body')[0].appendChild(script);
  13433. }).attr('src', 'http://api.map.baidu.com/getscript' +
  13434. '?type=quick&file=feature' +
  13435. '&ak=WVAXZ05oyNRXS5egLImmentg&t=20140109092002');
  13436. }).attr('src', 'http://api.map.baidu.com/getscript' +
  13437. '?type=quick&file=api&ak=WVAXZ05oyNRXS5egLImmentg&t=20140109092002');
  13438. // jQuery 中 `load` 事件触发有问题,动态设置 src 属性才会触发 `load` 事件
  13439. // $mapApi0 = $('<script />', {src: 'xxx'}); 这样的写法在 Zepto.js 中则没有问题
  13440. }
  13441. function addBdMap() {
  13442. // 如果使用 $ 选择符,minify 以后会报错: $ is undefined
  13443. // 即使传入 $ 也无效,改为使用原生方法
  13444. // 这个函数作为 callback 会插入到 body 以后才执行,应该是 $ 引用错误导致
  13445. var content = document.querySelector('.am-map');
  13446. var defaultLng = 116.331398; // 经度默认值
  13447. var defaultLat = 39.897445; // 纬度默认值
  13448. var name = content.getAttribute('data-name');
  13449. var address = content.getAttribute('data-address');
  13450. var lng = content.getAttribute('data-longitude') || defaultLng;
  13451. var lat = content.getAttribute('data-latitude') || defaultLat;
  13452. var setZoom = content.getAttribute('data-setZoom') || 17;
  13453. var icon = content.getAttribute('data-icon');
  13454. var map = new BMap.Map('bd-map');
  13455. // 实例化一个地理坐标点
  13456. var point = new BMap.Point(lng, lat);
  13457. // 设初始化地图, options: 3-18
  13458. map.centerAndZoom(point, setZoom);
  13459. // 添加地图缩放控件
  13460. if (content.getAttribute('data-zoomControl')) {
  13461. map.addControl(new BMap.ZoomControl());
  13462. }
  13463. // 添加比例尺控件
  13464. if (content.getAttribute('data-scaleControl')) {
  13465. map.addControl(new BMap.ScaleControl());
  13466. }
  13467. // 创建标准与自定义 icon
  13468. var marker = new BMap.Marker(point);
  13469. if (icon) {
  13470. marker.setIcon(new BMap.Icon(icon, new BMap.Size(40, 40)));
  13471. }
  13472. var opts = {
  13473. width: 200, // 信息窗口宽度
  13474. // height: 'auto', // 信息窗口高度
  13475. title: name // 信息窗口标题
  13476. };
  13477. // 创建信息窗口对象
  13478. var infoWindow = new BMap.InfoWindow('地址:' + address, opts);
  13479. // 创建地址解析器实例
  13480. var myGeo = new BMap.Geocoder();
  13481. // 判断有没有使用经纬度
  13482. if (lng == defaultLng && lat == defaultLat) {
  13483. // 使用地址反解析来设置地图
  13484. // 将地址解析结果显示在地图上,并调整地图视野
  13485. myGeo.getPoint(address, function(point) {
  13486. if (point) {
  13487. map.centerAndZoom(point, setZoom);
  13488. marker.setPosition(point);
  13489. map.addOverlay(marker);
  13490. map.openInfoWindow(infoWindow, point); // 开启信息窗口
  13491. }
  13492. }, '');
  13493. } else {
  13494. // 使用经纬度来设置地图
  13495. myGeo.getLocation(point, function(result) {
  13496. map.centerAndZoom(point, setZoom);
  13497. marker.setPosition(point);
  13498. map.addOverlay(marker);
  13499. if (address) {
  13500. map.openInfoWindow(infoWindow, point); // 开启信息窗口
  13501. } else {
  13502. map.openInfoWindow(new BMap.InfoWindow(address, opts), point); // 开启信息窗口
  13503. }
  13504. });
  13505. }
  13506. }
  13507. var mapInit = function() {
  13508. $('.am-map').length && addMapApi(addBdMap);
  13509. };
  13510. $(mapInit);
  13511. module.exports = UI.map = {
  13512. VERSION: '2.0.2',
  13513. init: mapInit
  13514. };
  13515. /***/ },
  13516. /* 46 */
  13517. /***/ function(module, exports, __webpack_require__) {
  13518. 'use strict';
  13519. var $ = __webpack_require__(1);
  13520. var UI = __webpack_require__(2);
  13521. function mechatInit() {
  13522. if (!$('#mechat').length) {
  13523. return;
  13524. }
  13525. var $mechat = $('[data-am-widget="mechat"]');
  13526. var unitid = $mechat.data('am-mechat-unitid');
  13527. var $mechatData = $('<script>', {
  13528. charset: 'utf-8',
  13529. src: 'http://mechatim.com/js/unit/button.js?id=' + unitid
  13530. });
  13531. $('body').append($mechatData);
  13532. }
  13533. // Lazy load
  13534. $(window).on('load', mechatInit);
  13535. module.exports = UI.mechat = {
  13536. VERSION: '2.0.1',
  13537. init: mechatInit
  13538. };
  13539. /***/ },
  13540. /* 47 */
  13541. /***/ function(module, exports, __webpack_require__) {
  13542. 'use strict';
  13543. var $ = __webpack_require__(1);
  13544. var UI = __webpack_require__(2);
  13545. var IScroll = __webpack_require__(14);
  13546. __webpack_require__(16);
  13547. __webpack_require__(7);
  13548. var menuInit = function() {
  13549. var $menus = $('[data-am-widget="menu"]');
  13550. $menus.find('.am-menu-nav .am-parent > a').on('click', function(e) {
  13551. e.preventDefault();
  13552. var $clicked = $(this);
  13553. var $parent = $clicked.parent();
  13554. var $subMenu = $clicked.next('.am-menu-sub');
  13555. $parent.toggleClass('am-open');
  13556. $subMenu.collapse('toggle');
  13557. $parent.siblings('.am-parent').removeClass('am-open')
  13558. .children('.am-menu-sub.am-in').collapse('close');
  13559. });
  13560. // Dropdown/slideDown menu
  13561. $menus.
  13562. filter('[data-am-menu-collapse]').
  13563. find('> .am-menu-toggle').
  13564. on('click', function(e) {
  13565. e.preventDefault();
  13566. var $this = $(this);
  13567. var $nav = $this.next('.am-menu-nav');
  13568. $this.toggleClass('am-active');
  13569. $nav.collapse('toggle');
  13570. });
  13571. // OffCanvas menu
  13572. $menus.
  13573. filter('[data-am-menu-offcanvas]').
  13574. find('> .am-menu-toggle').
  13575. on('click', function(e) {
  13576. e.preventDefault();
  13577. var $this = $(this);
  13578. var $nav = $this.next('.am-offcanvas');
  13579. $this.toggleClass('am-active');
  13580. $nav.offCanvas('open');
  13581. });
  13582. // Close offCanvas when link clicked
  13583. var autoCloseOffCanvas = '.am-offcanvas[data-dismiss-on="click"]';
  13584. var $autoCloseOffCanvas = $(autoCloseOffCanvas);
  13585. $autoCloseOffCanvas.find('a').not('.am-parent>a').on('click', function(e) {
  13586. $(this).parents(autoCloseOffCanvas).offCanvas('close');
  13587. });
  13588. // one theme
  13589. $menus.filter('.am-menu-one').each(function(index) {
  13590. var $this = $(this);
  13591. var $wrap = $('<div class="am-menu-nav-sub-wrap"></div>');
  13592. var allWidth = 0;
  13593. var $nav = $this.find('.am-menu-nav');
  13594. var $navTopItem = $nav.children('li');
  13595. var prevIndex;
  13596. $navTopItem.filter('.am-parent').each(function(index) {
  13597. $(this).attr('data-rel', '#am-menu-sub-' + index);
  13598. $(this).
  13599. find('.am-menu-sub').
  13600. attr('id', 'am-menu-sub-' + index).
  13601. appendTo($wrap);
  13602. });
  13603. $this.append($wrap);
  13604. $nav.wrap('<div class="am-menu-nav-wrap" id="am-menu-' + index + '">');
  13605. // $navTopItem.eq(0).addClass('am-active');
  13606. // 计算出所有 li 宽度
  13607. $navTopItem.each(function(i) {
  13608. allWidth += parseFloat($(this).css('width'));
  13609. });
  13610. $nav.width(allWidth);
  13611. var menuScroll = new IScroll('#am-menu-' + index, {
  13612. eventPassthrough: true,
  13613. scrollX: true,
  13614. scrollY: false,
  13615. preventDefault: false
  13616. });
  13617. $navTopItem.on('click', function() {
  13618. var $clicked = $(this);
  13619. $clicked.addClass('am-active').siblings().removeClass('am-active');
  13620. $wrap.find('.am-menu-sub.am-in').collapse('close');
  13621. if ($clicked.is('.am-parent')) {
  13622. !$clicked.hasClass('.am-open') &&
  13623. $wrap.find($clicked.attr('data-rel')).collapse('open');
  13624. } else {
  13625. $clicked.siblings().removeClass('am-open');
  13626. }
  13627. // 第一次调用,没有prevIndex
  13628. if (prevIndex === undefined) {
  13629. prevIndex = $(this).index() ? 0 : 1;
  13630. }
  13631. // 判断方向
  13632. var dir = $(this).index() > prevIndex;
  13633. var target = $(this)[dir ? 'next' : 'prev']();
  13634. // 点击的按钮,显示一半
  13635. var offset = target.offset() || $(this).offset();
  13636. var within = $this.offset();
  13637. // 父类左边距
  13638. var listOffset;
  13639. var parentLeft = parseInt($this.css('padding-left'));
  13640. if (dir ? offset.left + offset.width > within.left + within.width :
  13641. offset.left < within.left) {
  13642. listOffset = $nav.offset();
  13643. menuScroll.scrollTo(dir ?
  13644. within.width - offset.left + listOffset.left -
  13645. offset.width - parentLeft :
  13646. listOffset.left - offset.left, 0, 400);
  13647. }
  13648. prevIndex = $(this).index();
  13649. });
  13650. $this.on('touchmove', function(event) {
  13651. event.preventDefault();
  13652. });
  13653. });
  13654. };
  13655. $(menuInit);
  13656. module.exports = UI.menu = {
  13657. VERSION: '4.0.3',
  13658. init: menuInit
  13659. };
  13660. /***/ },
  13661. /* 48 */
  13662. /***/ function(module, exports, __webpack_require__) {
  13663. 'use strict';
  13664. var $ = __webpack_require__(1);
  13665. var UI = __webpack_require__(2);
  13666. var share = __webpack_require__(25);
  13667. var QRCode = __webpack_require__(26);
  13668. __webpack_require__(15);
  13669. function navbarInit() {
  13670. var $navBar = $('[data-am-widget="navbar"]');
  13671. if (!$navBar.length) {
  13672. return;
  13673. }
  13674. var $win = $(window);
  13675. var $body = $('body');
  13676. var $navBarNav = $navBar.find('.am-navbar-nav');
  13677. var $navItems = $navBar.find('li');
  13678. var navItemsCounter = $navItems.length;
  13679. var configItems = $navBarNav.attr('class') &&
  13680. parseInt($navBarNav.attr('class').
  13681. match(/am-avg-sm-(\d+)/)[1]) || 3;
  13682. var navMinWidth = 60; // 每个 li 最小宽度
  13683. var offsetWidth = 16;
  13684. var $share = $navItems.filter('[data-am-navbar-share]');
  13685. var $qrcode = $navItems.filter('[data-am-navbar-qrcode]');
  13686. var activeStatus = 'am-active';
  13687. var $moreActions = $('<ul class="am-navbar-actions"></ul>', {
  13688. id: UI.utils.generateGUID('am-navbar-actions')
  13689. });
  13690. var $moreLink = $('<li class="am-navbar-labels am-navbar-more">' +
  13691. '<a href="javascript: void(0);">' +
  13692. '<span class="am-icon-angle-up"></span>' +
  13693. '<span class="am-navbar-label">更多</span></a></li>');
  13694. // 如果有 Fix 的工具栏则设置 body 的 padding-bottom
  13695. if ($navBar.css('position') == 'fixed') {
  13696. $body.addClass('am-with-fixed-navbar');
  13697. }
  13698. if ($qrcode.length) {
  13699. var qrId = 'am-navbar-qrcode';
  13700. $qrModal = $('#' + qrId);
  13701. if (!$qrModal.length) {
  13702. var qrImg = $qrcode.attr('data-am-navbar-qrcode');
  13703. var $qrModal = $('<div class="am-modal am-modal-no-btn" id="">' +
  13704. '<div class="am-modal-dialog">' +
  13705. '<div class="am-modal-bd"></div></div>' +
  13706. '</div>', {
  13707. id: qrId
  13708. });
  13709. var $qrContainer = $qrModal.find('.am-modal-bd');
  13710. // 判断上传自定义的二维码没有,否则生成二维码
  13711. if (qrImg) {
  13712. $qrContainer.html('<img src="' + qrImg + '"/>');
  13713. } else {
  13714. var qrnode = new QRCode({
  13715. render: 'canvas',
  13716. correctLevel: 0,
  13717. text: window.location.href,
  13718. width: 200,
  13719. height: 200,
  13720. background: '#fff',
  13721. foreground: '#000'
  13722. });
  13723. $qrContainer.html(qrnode);
  13724. }
  13725. $body.append($qrModal);
  13726. }
  13727. $qrcode.on('click', function(e) {
  13728. e.preventDefault();
  13729. $qrModal.modal();
  13730. });
  13731. }
  13732. if (navItemsCounter > configItems && navItemsCounter > calcSuiteItems()) {
  13733. initActions();
  13734. }
  13735. // console.log('NavItems: %d, config: %d, best: %d',
  13736. // navItemsCounter, configItems, calcSuiteItems());
  13737. function initActions() {
  13738. $navBarNav.append($moreLink);
  13739. $navBarNav.
  13740. find('li').
  13741. not('.am-navbar-more').
  13742. slice(calcSuiteItems() - 1).
  13743. appendTo($moreActions);
  13744. // Append more actions
  13745. $navBar.append($moreActions);
  13746. }
  13747. function checkNavBarItems() {
  13748. if (calcSuiteItems() >= navItemsCounter) {
  13749. // 显示所有链接,隐藏 more
  13750. $moreLink.hide();
  13751. $moreActions.find('li').insertBefore($moreLink);
  13752. return;
  13753. }
  13754. !$navBar.find('.am-navbar-actions').length && initActions();
  13755. $moreLink.show();
  13756. if ($navBarNav.find('li').length < calcSuiteItems()) {
  13757. $moreActions.find('li').
  13758. slice(0, calcSuiteItems() - $navBarNav.find('li').length).
  13759. insertBefore($moreLink);
  13760. } else if ($navBarNav.find('li').length > calcSuiteItems()) {
  13761. if ($moreActions.find('li').length) {
  13762. $navBarNav.find('li').not($moreLink).slice(calcSuiteItems() - 1).
  13763. insertBefore($moreActions.find('li').first());
  13764. } else {
  13765. $navBarNav.find('li').not($moreLink).slice(calcSuiteItems() - 1).
  13766. appendTo($moreActions);
  13767. }
  13768. }
  13769. }
  13770. /**
  13771. * 计算最适合显示的条目个数
  13772. * @returns {number}
  13773. */
  13774. function calcSuiteItems() {
  13775. return Math.floor(($win.width() - offsetWidth) / navMinWidth);
  13776. }
  13777. $navBar.on('click.navbar.amui', '.am-navbar-more', function(e) {
  13778. e.preventDefault();
  13779. $moreLink[$moreActions.hasClass(activeStatus) ?
  13780. 'removeClass' : 'addClass'](activeStatus);
  13781. $moreActions.toggleClass(activeStatus);
  13782. });
  13783. if ($share.length) {
  13784. $share.on('click.navbar.amui', function(e) {
  13785. e.preventDefault();
  13786. share.toggle();
  13787. });
  13788. }
  13789. $win.on('resize.navbar.amui orientationchange.navbar.amui',
  13790. UI.utils.debounce(checkNavBarItems, 150));
  13791. }
  13792. // DOMContent ready
  13793. $(navbarInit);
  13794. module.exports = UI.navbar = {
  13795. VERSION: '2.0.2',
  13796. init: navbarInit
  13797. };
  13798. /***/ },
  13799. /* 49 */
  13800. /***/ function(module, exports, __webpack_require__) {
  13801. 'use strict';
  13802. var UI = __webpack_require__(2);
  13803. module.exports = UI.pagination = {
  13804. VERSION: '3.0.1'
  13805. };
  13806. /***/ },
  13807. /* 50 */
  13808. /***/ function(module, exports, __webpack_require__) {
  13809. 'use strict';
  13810. var $ = __webpack_require__(1);
  13811. var UI = __webpack_require__(2);
  13812. var IScroll = __webpack_require__(14);
  13813. __webpack_require__(20);
  13814. /**
  13815. * 表格滚动
  13816. * @param {number} index ID 标识,多个 paragraph 里面多个 table
  13817. */
  13818. $.fn.scrollTable = function(index) {
  13819. var $this = $(this);
  13820. var $parent;
  13821. $this.wrap('<div class="am-paragraph-table-container" ' +
  13822. 'id="am-paragraph-table-' + index + '">' +
  13823. '<div class="am-paragraph-table-scroller"></div></div>');
  13824. $parent = $this.parent();
  13825. $parent.width($this.width());
  13826. $parent.height($this.height());
  13827. new IScroll('#am-paragraph-table-' + index, {
  13828. eventPassthrough: true,
  13829. scrollX: true,
  13830. scrollY: false,
  13831. preventDefault: false
  13832. });
  13833. };
  13834. function paragraphInit() {
  13835. var $paragraph = $('[data-am-widget="paragraph"]');
  13836. $paragraph.each(function(index) {
  13837. var $this = $(this);
  13838. var options = UI.utils.parseOptions($this.attr('data-am-paragraph'));
  13839. var $index = index;
  13840. if (options.pureview) {
  13841. $this.pureview();
  13842. }
  13843. if (options.tableScrollable) {
  13844. $this.find('table').each(function(index) {
  13845. if ($(this).width() > $(window).width()) {
  13846. $(this).scrollTable($index + '-' + index);
  13847. }
  13848. });
  13849. }
  13850. });
  13851. }
  13852. $(window).on('load', paragraphInit);
  13853. module.exports = UI.paragraph = {
  13854. VERSION: '2.0.1',
  13855. init: paragraphInit
  13856. };
  13857. /***/ },
  13858. /* 51 */
  13859. /***/ function(module, exports, __webpack_require__) {
  13860. 'use strict';
  13861. var $ = __webpack_require__(1);
  13862. var UI = __webpack_require__(2);
  13863. __webpack_require__(11);
  13864. function sliderInit() {
  13865. var $sliders = $('[data-am-widget="slider"]');
  13866. $sliders.not('.am-slider-manual').each(function(i, item) {
  13867. var options = UI.utils.parseOptions($(item).attr('data-am-slider'));
  13868. $(item).flexslider(options);
  13869. });
  13870. }
  13871. $(sliderInit);
  13872. module.exports = UI.slider = {
  13873. VERSION: '3.0.1',
  13874. init: sliderInit
  13875. };
  13876. /***/ },
  13877. /* 52 */
  13878. /***/ function(module, exports, __webpack_require__) {
  13879. 'use strict';
  13880. var $ = __webpack_require__(1);
  13881. var UI = __webpack_require__(2);
  13882. __webpack_require__(28);
  13883. function tabsInit() {
  13884. $('[data-am-widget="tabs"]').each(function() {
  13885. var options = $(this).data('amTabsNoswipe') ? {noSwipe: 1} : {};
  13886. $(this).tabs(options);
  13887. });
  13888. }
  13889. $(tabsInit);
  13890. module.exports = UI.tab = {
  13891. VERSION: '4.0.1',
  13892. init: tabsInit
  13893. };
  13894. /***/ },
  13895. /* 53 */
  13896. /***/ function(module, exports, __webpack_require__) {
  13897. 'use strict';
  13898. var UI = __webpack_require__(2);
  13899. module.exports = UI.titlebar = {
  13900. VERSION: '4.0.1'
  13901. };
  13902. /***/ },
  13903. /* 54 */
  13904. /***/ function(module, exports, __webpack_require__) {
  13905. 'use strict';
  13906. var $ = __webpack_require__(1);
  13907. var UI = __webpack_require__(2);
  13908. var isWeChat = window.navigator.userAgent.indexOf('MicroMessenger') > -1;
  13909. /* global wx,alert */
  13910. function appendWeChatSDK(callback) {
  13911. var $weChatSDK = $('<script/>', {
  13912. id: 'wechat-sdk'
  13913. });
  13914. $('body').append($weChatSDK);
  13915. $weChatSDK.on('load', function() {
  13916. callback && callback();
  13917. }).attr('src', 'http://res.wx.qq.com/open/js/jweixin-1.0.0.js');
  13918. }
  13919. function payHandler() {
  13920. var $paymentBtn = $('[data-am-widget="wechatpay"]');
  13921. if (!isWeChat) {
  13922. $paymentBtn.hide();
  13923. return false;
  13924. }
  13925. $paymentBtn.on('click', '.am-wechatpay-btn', function(e) {
  13926. e.preventDefault();
  13927. var options = UI.utils.parseOptions($(this).parent().data('wechatPay'));
  13928. // console.log(options);
  13929. // alert('pay button clicked');
  13930. if (!window.wx) {
  13931. alert('没有微信 JS SDK');
  13932. return;
  13933. }
  13934. wx.checkJsApi({
  13935. jsApiList: ['chooseWXPay'],
  13936. success: function(res) {
  13937. if (res.checkResult.chooseWXPay) {
  13938. wx.chooseWXPay(options);
  13939. } else {
  13940. alert('微信版本不支持支付接口或没有开启!');
  13941. }
  13942. },
  13943. fail: function() {
  13944. alert('调用 checkJsApi 接口时发生错误!');
  13945. }
  13946. });
  13947. });
  13948. }
  13949. var payInit = payHandler;
  13950. // Init on DOM ready
  13951. $(payInit);
  13952. module.exports = UI.pay = {
  13953. VERSION: '1.0.0',
  13954. init: payInit
  13955. };
  13956. /***/ }
  13957. /******/ ])
  13958. });
  13959. ;