amazeui.js 447 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445
  1. /*! Amaze UI v2.5.2 | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-01-26T11:06:52+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. /* jshint -W040 */
  109. var $ = __webpack_require__(1);
  110. if (typeof $ === 'undefined') {
  111. throw new Error('Amaze UI 2.x requires jQuery :-(\n' +
  112. '\u7231\u4e0a\u4e00\u5339\u91ce\u9a6c\uff0c\u53ef\u4f60' +
  113. '\u7684\u5bb6\u91cc\u6ca1\u6709\u8349\u539f\u2026');
  114. }
  115. var UI = $.AMUI || {};
  116. var $win = $(window);
  117. var doc = window.document;
  118. var $html = $('html');
  119. UI.VERSION = '2.5.2';
  120. UI.support = {};
  121. UI.support.transition = (function() {
  122. var transitionEnd = (function() {
  123. // https://developer.mozilla.org/en-US/docs/Web/Events/transitionend#Browser_compatibility
  124. var element = doc.body || doc.documentElement;
  125. var transEndEventNames = {
  126. WebkitTransition: 'webkitTransitionEnd',
  127. MozTransition: 'transitionend',
  128. OTransition: 'oTransitionEnd otransitionend',
  129. transition: 'transitionend'
  130. };
  131. for (var name in transEndEventNames) {
  132. if (element.style[name] !== undefined) {
  133. return transEndEventNames[name];
  134. }
  135. }
  136. })();
  137. return transitionEnd && {end: transitionEnd};
  138. })();
  139. UI.support.animation = (function() {
  140. var animationEnd = (function() {
  141. var element = doc.body || doc.documentElement;
  142. var animEndEventNames = {
  143. WebkitAnimation: 'webkitAnimationEnd',
  144. MozAnimation: 'animationend',
  145. OAnimation: 'oAnimationEnd oanimationend',
  146. animation: 'animationend'
  147. };
  148. for (var name in animEndEventNames) {
  149. if (element.style[name] !== undefined) {
  150. return animEndEventNames[name];
  151. }
  152. }
  153. })();
  154. return animationEnd && {end: animationEnd};
  155. })();
  156. /* jshint -W069 */
  157. UI.support.touch = (
  158. ('ontouchstart' in window &&
  159. navigator.userAgent.toLowerCase().match(/mobile|tablet/)) ||
  160. (window.DocumentTouch && document instanceof window.DocumentTouch) ||
  161. (window.navigator['msPointerEnabled'] &&
  162. window.navigator['msMaxTouchPoints'] > 0) || //IE 10
  163. (window.navigator['pointerEnabled'] &&
  164. window.navigator['maxTouchPoints'] > 0) || //IE >=11
  165. false);
  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. * @param {function} func Function to be debounced
  176. * @param {number} wait Function execution threshold in milliseconds
  177. * @param {bool} immediate Whether the function should be called at
  178. * the beginning of the delay instead of the
  179. * end. Default is false.
  180. * @desc Executes a function when it stops being invoked for n seconds
  181. * @via _.debounce() http://underscorejs.org
  182. */
  183. UI.utils.debounce = function(func, wait, immediate) {
  184. var timeout;
  185. return function() {
  186. var context = this;
  187. var args = arguments;
  188. var later = function() {
  189. timeout = null;
  190. if (!immediate) {
  191. func.apply(context, args);
  192. }
  193. };
  194. var callNow = immediate && !timeout;
  195. clearTimeout(timeout);
  196. timeout = setTimeout(later, wait);
  197. if (callNow) {
  198. func.apply(context, args);
  199. }
  200. };
  201. };
  202. UI.utils.isInView = function(element, options) {
  203. var $element = $(element);
  204. var visible = !!($element.width() || $element.height()) &&
  205. $element.css('display') !== 'none';
  206. if (!visible) {
  207. return false;
  208. }
  209. var windowLeft = $win.scrollLeft();
  210. var windowTop = $win.scrollTop();
  211. var offset = $element.offset();
  212. var left = offset.left;
  213. var top = offset.top;
  214. options = $.extend({topOffset: 0, leftOffset: 0}, options);
  215. return (top + $element.height() >= windowTop &&
  216. top - options.topOffset <= windowTop + $win.height() &&
  217. left + $element.width() >= windowLeft &&
  218. left - options.leftOffset <= windowLeft + $win.width());
  219. };
  220. /* jshint -W054 */
  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. /* jshint +W054 */
  238. UI.utils.generateGUID = function(namespace) {
  239. var uid = namespace + '-' || 'am-';
  240. do {
  241. uid += Math.random().toString(36).substring(2, 7);
  242. } while (document.getElementById(uid));
  243. return uid;
  244. };
  245. // @see https://davidwalsh.name/get-absolute-url
  246. UI.utils.getAbsoluteUrl = (function() {
  247. var a;
  248. return function(url) {
  249. if (!a) {
  250. a = document.createElement('a');
  251. }
  252. a.href = url;
  253. return a.href;
  254. };
  255. })();
  256. /**
  257. * Plugin AMUI Component to jQuery
  258. *
  259. * @param {String} name - plugin name
  260. * @param {Function} Component - plugin constructor
  261. * @param {Object} [pluginOption]
  262. * @param {String} pluginOption.dataOptions
  263. * @param {Function} pluginOption.methodCall - custom method call
  264. * @param {Function} pluginOption.before
  265. * @param {Function} pluginOption.after
  266. * @since v2.4.1
  267. */
  268. UI.plugin = function UIPlugin(name, Component, pluginOption) {
  269. var old = $.fn[name];
  270. pluginOption = pluginOption || {};
  271. $.fn[name] = function(option) {
  272. var allArgs = Array.prototype.slice.call(arguments, 0);
  273. var args = allArgs.slice(1);
  274. var propReturn;
  275. var $set = this.each(function() {
  276. var $this = $(this);
  277. var dataName = 'amui.' + name;
  278. var dataOptionsName = pluginOption.dataOptions || ('data-am-' + name);
  279. var instance = $this.data(dataName);
  280. var options = $.extend({},
  281. UI.utils.parseOptions($this.attr(dataOptionsName)),
  282. typeof option === 'object' && option);
  283. if (!instance && option === 'destroy') {
  284. return;
  285. }
  286. if (!instance) {
  287. $this.data(dataName, (instance = new Component(this, options)));
  288. }
  289. // custom method call
  290. if (pluginOption.methodCall) {
  291. pluginOption.methodCall.call($this, allArgs, instance);
  292. } else {
  293. // before method call
  294. pluginOption.before &&
  295. pluginOption.before.call($this, allArgs, instance);
  296. if (typeof option === 'string') {
  297. propReturn = typeof instance[option] === 'function' ?
  298. instance[option].apply(instance, args) : instance[option];
  299. }
  300. // after method call
  301. pluginOption.after && pluginOption.after.call($this, allArgs, instance);
  302. }
  303. });
  304. return (propReturn === undefined) ? $set : propReturn;
  305. };
  306. $.fn[name].Constructor = Component;
  307. // no conflict
  308. $.fn[name].noConflict = function() {
  309. $.fn[name] = old;
  310. return this;
  311. };
  312. UI[name] = Component;
  313. };
  314. // http://blog.alexmaccaw.com/css-transitions
  315. $.fn.emulateTransitionEnd = function(duration) {
  316. var called = false;
  317. var $el = this;
  318. $(this).one(UI.support.transition.end, function() {
  319. called = true;
  320. });
  321. var callback = function() {
  322. if (!called) {
  323. $($el).trigger(UI.support.transition.end);
  324. }
  325. $el.transitionEndTimmer = undefined;
  326. };
  327. this.transitionEndTimmer = setTimeout(callback, duration);
  328. return this;
  329. };
  330. $.fn.redraw = function() {
  331. return this.each(function() {
  332. /* jshint unused:false */
  333. var redraw = this.offsetHeight;
  334. });
  335. };
  336. /* jshint unused:true */
  337. $.fn.transitionEnd = function(callback) {
  338. var endEvent = UI.support.transition.end;
  339. var dom = this;
  340. function fireCallBack(e) {
  341. callback.call(this, e);
  342. endEvent && dom.off(endEvent, fireCallBack);
  343. }
  344. if (callback && endEvent) {
  345. dom.on(endEvent, fireCallBack);
  346. }
  347. return this;
  348. };
  349. $.fn.removeClassRegEx = function() {
  350. return this.each(function(regex) {
  351. var classes = $(this).attr('class');
  352. if (!classes || !regex) {
  353. return false;
  354. }
  355. var classArray = [];
  356. classes = classes.split(' ');
  357. for (var i = 0, len = classes.length; i < len; i++) {
  358. if (!classes[i].match(regex)) {
  359. classArray.push(classes[i]);
  360. }
  361. }
  362. $(this).attr('class', classArray.join(' '));
  363. });
  364. };
  365. //
  366. $.fn.alterClass = function(removals, additions) {
  367. var self = this;
  368. if (removals.indexOf('*') === -1) {
  369. // Use native jQuery methods if there is no wildcard matching
  370. self.removeClass(removals);
  371. return !additions ? self : self.addClass(additions);
  372. }
  373. var classPattern = new RegExp('\\s' +
  374. removals.
  375. replace(/\*/g, '[A-Za-z0-9-_]+').
  376. split(' ').
  377. join('\\s|\\s') +
  378. '\\s', 'g');
  379. self.each(function(i, it) {
  380. var cn = ' ' + it.className + ' ';
  381. while (classPattern.test(cn)) {
  382. cn = cn.replace(classPattern, ' ');
  383. }
  384. it.className = $.trim(cn);
  385. });
  386. return !additions ? self : self.addClass(additions);
  387. };
  388. // handle multiple browsers for requestAnimationFrame()
  389. // http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
  390. // https://github.com/gnarf/jquery-requestAnimationFrame
  391. UI.utils.rAF = (function() {
  392. return window.requestAnimationFrame ||
  393. window.webkitRequestAnimationFrame ||
  394. window.mozRequestAnimationFrame ||
  395. window.oRequestAnimationFrame ||
  396. // if all else fails, use setTimeout
  397. function(callback) {
  398. return window.setTimeout(callback, 1000 / 60); // shoot for 60 fps
  399. };
  400. })();
  401. // handle multiple browsers for cancelAnimationFrame()
  402. UI.utils.cancelAF = (function() {
  403. return window.cancelAnimationFrame ||
  404. window.webkitCancelAnimationFrame ||
  405. window.mozCancelAnimationFrame ||
  406. window.oCancelAnimationFrame ||
  407. function(id) {
  408. window.clearTimeout(id);
  409. };
  410. })();
  411. // via http://davidwalsh.name/detect-scrollbar-width
  412. UI.utils.measureScrollbar = function() {
  413. if (document.body.clientWidth >= window.innerWidth) {
  414. return 0;
  415. }
  416. // if ($html.width() >= window.innerWidth) return;
  417. // var scrollbarWidth = window.innerWidth - $html.width();
  418. var $measure = $('<div ' +
  419. 'style="width: 100px;height: 100px;overflow: scroll;' +
  420. 'position: absolute;top: -9999px;"></div>');
  421. $(document.body).append($measure);
  422. var scrollbarWidth = $measure[0].offsetWidth - $measure[0].clientWidth;
  423. $measure.remove();
  424. return scrollbarWidth;
  425. };
  426. UI.utils.imageLoader = function($image, callback) {
  427. function loaded() {
  428. callback($image[0]);
  429. }
  430. function bindLoad() {
  431. this.one('load', loaded);
  432. if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) {
  433. var src = this.attr('src');
  434. var param = src.match(/\?/) ? '&' : '?';
  435. param += 'random=' + (new Date()).getTime();
  436. this.attr('src', src + param);
  437. }
  438. }
  439. if (!$image.attr('src')) {
  440. loaded();
  441. return;
  442. }
  443. if ($image[0].complete || $image[0].readyState === 4) {
  444. loaded();
  445. } else {
  446. bindLoad.call($image);
  447. }
  448. };
  449. /**
  450. * https://github.com/cho45/micro-template.js
  451. * (c) cho45 http://cho45.github.com/mit-license
  452. */
  453. /* jshint -W109 */
  454. UI.template = function(id, data) {
  455. var me = UI.template;
  456. if (!me.cache[id]) {
  457. me.cache[id] = (function() {
  458. var name = id;
  459. var string = /^[\w\-]+$/.test(id) ?
  460. me.get(id) : (name = 'template(string)', id); // no warnings
  461. var line = 1;
  462. var body = ('try { ' + (me.variable ?
  463. 'var ' + me.variable + ' = this.stash;' : 'with (this.stash) { ') +
  464. "this.ret += '" +
  465. string.
  466. replace(/<%/g, '\x11').replace(/%>/g, '\x13'). // if you want other tag, just edit this line
  467. replace(/'(?![^\x11\x13]+?\x13)/g, '\\x27').
  468. replace(/^\s*|\s*$/g, '').
  469. replace(/\n/g, function() {
  470. return "';\nthis.line = " + (++line) + "; this.ret += '\\n";
  471. }).
  472. replace(/\x11-(.+?)\x13/g, "' + ($1) + '").
  473. replace(/\x11=(.+?)\x13/g, "' + this.escapeHTML($1) + '").
  474. replace(/\x11(.+?)\x13/g, "'; $1; this.ret += '") +
  475. "'; " + (me.variable ? "" : "}") + "return this.ret;" +
  476. "} catch (e) { throw 'TemplateError: ' + e + ' (on " + name +
  477. "' + ' line ' + this.line + ')'; } " +
  478. "//@ sourceURL=" + name + "\n" // source map
  479. ).replace(/this\.ret \+= '';/g, '');
  480. /* jshint -W054 */
  481. var func = new Function(body);
  482. var map = {
  483. '&': '&amp;',
  484. '<': '&lt;',
  485. '>': '&gt;',
  486. '\x22': '&#x22;',
  487. '\x27': '&#x27;'
  488. };
  489. var escapeHTML = function(string) {
  490. return ('' + string).replace(/[&<>\'\"]/g, function(_) {
  491. return map[_];
  492. });
  493. };
  494. return function(stash) {
  495. return func.call(me.context = {
  496. escapeHTML: escapeHTML,
  497. line: 1,
  498. ret: '',
  499. stash: stash
  500. });
  501. };
  502. })();
  503. }
  504. return data ? me.cache[id](data) : me.cache[id];
  505. };
  506. /* jshint +W109 */
  507. /* jshint +W054 */
  508. UI.template.cache = {};
  509. UI.template.get = function(id) {
  510. if (id) {
  511. var element = document.getElementById(id);
  512. return element && element.innerHTML || '';
  513. }
  514. };
  515. // Dom mutation watchers
  516. UI.DOMWatchers = [];
  517. UI.DOMReady = false;
  518. UI.ready = function(callback) {
  519. UI.DOMWatchers.push(callback);
  520. if (UI.DOMReady) {
  521. // console.log('Ready call');
  522. callback(document);
  523. }
  524. };
  525. UI.DOMObserve = function(elements, options, callback) {
  526. var Observer = UI.support.mutationobserver;
  527. if (!Observer) {
  528. return;
  529. }
  530. options = $.isPlainObject(options) ?
  531. options : {childList: true, subtree: true};
  532. callback = typeof callback === 'function' && callback || function() {
  533. };
  534. $(elements).each(function() {
  535. var element = this;
  536. var $element = $(element);
  537. if ($element.data('am.observer')) {
  538. return;
  539. }
  540. try {
  541. var observer = new Observer(UI.utils.debounce(
  542. function(mutations, instance) {
  543. callback.call(element, mutations, instance);
  544. // trigger this event manually if MutationObserver not supported
  545. $element.trigger('changed.dom.amui');
  546. }, 50));
  547. observer.observe(element, options);
  548. $element.data('am.observer', observer);
  549. } catch (e) {
  550. }
  551. });
  552. };
  553. $.fn.DOMObserve = function(options, callback) {
  554. return this.each(function() {
  555. UI.DOMObserve(this, options, callback);
  556. });
  557. };
  558. if (UI.support.touch) {
  559. $html.addClass('am-touch');
  560. }
  561. $(document).on('changed.dom.amui', function(e) {
  562. var element = e.target;
  563. // TODO: just call changed element's watcher
  564. // every watcher callback should have a key
  565. // use like this: <div data-am-observe='key1, key2'>
  566. // get keys via $(element).data('amObserve')
  567. // call functions store with these keys
  568. $.each(UI.DOMWatchers, function(i, watcher) {
  569. watcher(element);
  570. });
  571. });
  572. $(function() {
  573. var $body = $('body');
  574. UI.DOMReady = true;
  575. // Run default init
  576. $.each(UI.DOMWatchers, function(i, watcher) {
  577. watcher(document);
  578. });
  579. // watches DOM
  580. UI.DOMObserve('[data-am-observe]');
  581. $html.removeClass('no-js').addClass('js');
  582. UI.support.animation && $html.addClass('cssanimations');
  583. // iOS standalone mode
  584. if (window.navigator.standalone) {
  585. $html.addClass('am-standalone');
  586. }
  587. $('.am-topbar-fixed-top').length &&
  588. $body.addClass('am-with-topbar-fixed-top');
  589. $('.am-topbar-fixed-bottom').length &&
  590. $body.addClass('am-with-topbar-fixed-bottom');
  591. // Remove responsive classes in .am-layout
  592. var $layout = $('.am-layout');
  593. $layout.find('[class*="md-block-grid"]').alterClass('md-block-grid-*');
  594. $layout.find('[class*="lg-block-grid"]').alterClass('lg-block-grid');
  595. // widgets not in .am-layout
  596. $('[data-am-widget]').each(function() {
  597. var $widget = $(this);
  598. // console.log($widget.parents('.am-layout').length)
  599. if ($widget.parents('.am-layout').length === 0) {
  600. $widget.addClass('am-no-layout');
  601. }
  602. });
  603. });
  604. module.exports = UI;
  605. /***/ },
  606. /* 3 */
  607. /***/ function(module, exports, __webpack_require__) {
  608. /*! Hammer.JS - v2.0.4 - 2014-09-28
  609. * http://hammerjs.github.io/
  610. *
  611. * Copyright (c) 2014 Jorik Tangelder;
  612. * Licensed under the MIT license */
  613. 'use strict';
  614. var $ = __webpack_require__(1);
  615. var UI = __webpack_require__(2);
  616. var VENDOR_PREFIXES = ['', 'webkit', 'moz', 'MS', 'ms', 'o'];
  617. var TEST_ELEMENT = document.createElement('div');
  618. var TYPE_FUNCTION = 'function';
  619. var round = Math.round;
  620. var abs = Math.abs;
  621. var now = Date.now;
  622. /**
  623. * set a timeout with a given scope
  624. * @param {Function} fn
  625. * @param {Number} timeout
  626. * @param {Object} context
  627. * @returns {number}
  628. */
  629. function setTimeoutContext(fn, timeout, context) {
  630. return setTimeout(bindFn(fn, context), timeout);
  631. }
  632. /**
  633. * if the argument is an array, we want to execute the fn on each entry
  634. * if it aint an array we don't want to do a thing.
  635. * this is used by all the methods that accept a single and array argument.
  636. * @param {*|Array} arg
  637. * @param {String} fn
  638. * @param {Object} [context]
  639. * @returns {Boolean}
  640. */
  641. function invokeArrayArg(arg, fn, context) {
  642. if (Array.isArray(arg)) {
  643. each(arg, context[fn], context);
  644. return true;
  645. }
  646. return false;
  647. }
  648. /**
  649. * walk objects and arrays
  650. * @param {Object} obj
  651. * @param {Function} iterator
  652. * @param {Object} context
  653. */
  654. function each(obj, iterator, context) {
  655. var i;
  656. if (!obj) {
  657. return;
  658. }
  659. if (obj.forEach) {
  660. obj.forEach(iterator, context);
  661. } else if (obj.length !== undefined) {
  662. i = 0;
  663. while (i < obj.length) {
  664. iterator.call(context, obj[i], i, obj);
  665. i++;
  666. }
  667. } else {
  668. for (i in obj) {
  669. obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
  670. }
  671. }
  672. }
  673. /**
  674. * extend object.
  675. * means that properties in dest will be overwritten by the ones in src.
  676. * @param {Object} dest
  677. * @param {Object} src
  678. * @param {Boolean} [merge]
  679. * @returns {Object} dest
  680. */
  681. function extend(dest, src, merge) {
  682. var keys = Object.keys(src);
  683. var i = 0;
  684. while (i < keys.length) {
  685. if (!merge || (merge && dest[keys[i]] === undefined)) {
  686. dest[keys[i]] = src[keys[i]];
  687. }
  688. i++;
  689. }
  690. return dest;
  691. }
  692. /**
  693. * merge the values from src in the dest.
  694. * means that properties that exist in dest will not be overwritten by src
  695. * @param {Object} dest
  696. * @param {Object} src
  697. * @returns {Object} dest
  698. */
  699. function merge(dest, src) {
  700. return extend(dest, src, true);
  701. }
  702. /**
  703. * simple class inheritance
  704. * @param {Function} child
  705. * @param {Function} base
  706. * @param {Object} [properties]
  707. */
  708. function inherit(child, base, properties) {
  709. var baseP = base.prototype,
  710. childP;
  711. childP = child.prototype = Object.create(baseP);
  712. childP.constructor = child;
  713. childP._super = baseP;
  714. if (properties) {
  715. extend(childP, properties);
  716. }
  717. }
  718. /**
  719. * simple function bind
  720. * @param {Function} fn
  721. * @param {Object} context
  722. * @returns {Function}
  723. */
  724. function bindFn(fn, context) {
  725. return function boundFn() {
  726. return fn.apply(context, arguments);
  727. };
  728. }
  729. /**
  730. * let a boolean value also be a function that must return a boolean
  731. * this first item in args will be used as the context
  732. * @param {Boolean|Function} val
  733. * @param {Array} [args]
  734. * @returns {Boolean}
  735. */
  736. function boolOrFn(val, args) {
  737. if (typeof val == TYPE_FUNCTION) {
  738. return val.apply(args ? args[0] || undefined : undefined, args);
  739. }
  740. return val;
  741. }
  742. /**
  743. * use the val2 when val1 is undefined
  744. * @param {*} val1
  745. * @param {*} val2
  746. * @returns {*}
  747. */
  748. function ifUndefined(val1, val2) {
  749. return (val1 === undefined) ? val2 : val1;
  750. }
  751. /**
  752. * addEventListener with multiple events at once
  753. * @param {EventTarget} target
  754. * @param {String} types
  755. * @param {Function} handler
  756. */
  757. function addEventListeners(target, types, handler) {
  758. each(splitStr(types), function(type) {
  759. target.addEventListener(type, handler, false);
  760. });
  761. }
  762. /**
  763. * removeEventListener with multiple events at once
  764. * @param {EventTarget} target
  765. * @param {String} types
  766. * @param {Function} handler
  767. */
  768. function removeEventListeners(target, types, handler) {
  769. each(splitStr(types), function(type) {
  770. target.removeEventListener(type, handler, false);
  771. });
  772. }
  773. /**
  774. * find if a node is in the given parent
  775. * @method hasParent
  776. * @param {HTMLElement} node
  777. * @param {HTMLElement} parent
  778. * @return {Boolean} found
  779. */
  780. function hasParent(node, parent) {
  781. while (node) {
  782. if (node == parent) {
  783. return true;
  784. }
  785. node = node.parentNode;
  786. }
  787. return false;
  788. }
  789. /**
  790. * small indexOf wrapper
  791. * @param {String} str
  792. * @param {String} find
  793. * @returns {Boolean} found
  794. */
  795. function inStr(str, find) {
  796. return str.indexOf(find) > -1;
  797. }
  798. /**
  799. * split string on whitespace
  800. * @param {String} str
  801. * @returns {Array} words
  802. */
  803. function splitStr(str) {
  804. return str.trim().split(/\s+/g);
  805. }
  806. /**
  807. * find if a array contains the object using indexOf or a simple polyFill
  808. * @param {Array} src
  809. * @param {String} find
  810. * @param {String} [findByKey]
  811. * @return {Boolean|Number} false when not found, or the index
  812. */
  813. function inArray(src, find, findByKey) {
  814. if (src.indexOf && !findByKey) {
  815. return src.indexOf(find);
  816. } else {
  817. var i = 0;
  818. while (i < src.length) {
  819. if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {
  820. return i;
  821. }
  822. i++;
  823. }
  824. return -1;
  825. }
  826. }
  827. /**
  828. * convert array-like objects to real arrays
  829. * @param {Object} obj
  830. * @returns {Array}
  831. */
  832. function toArray(obj) {
  833. return Array.prototype.slice.call(obj, 0);
  834. }
  835. /**
  836. * unique array with objects based on a key (like 'id') or just by the array's value
  837. * @param {Array} src [{id:1},{id:2},{id:1}]
  838. * @param {String} [key]
  839. * @param {Boolean} [sort=False]
  840. * @returns {Array} [{id:1},{id:2}]
  841. */
  842. function uniqueArray(src, key, sort) {
  843. var results = [];
  844. var values = [];
  845. var i = 0;
  846. while (i < src.length) {
  847. var val = key ? src[i][key] : src[i];
  848. if (inArray(values, val) < 0) {
  849. results.push(src[i]);
  850. }
  851. values[i] = val;
  852. i++;
  853. }
  854. if (sort) {
  855. if (!key) {
  856. results = results.sort();
  857. } else {
  858. results = results.sort(function sortUniqueArray(a, b) {
  859. return a[key] > b[key];
  860. });
  861. }
  862. }
  863. return results;
  864. }
  865. /**
  866. * get the prefixed property
  867. * @param {Object} obj
  868. * @param {String} property
  869. * @returns {String|Undefined} prefixed
  870. */
  871. function prefixed(obj, property) {
  872. var prefix, prop;
  873. var camelProp = property[0].toUpperCase() + property.slice(1);
  874. var i = 0;
  875. while (i < VENDOR_PREFIXES.length) {
  876. prefix = VENDOR_PREFIXES[i];
  877. prop = (prefix) ? prefix + camelProp : property;
  878. if (prop in obj) {
  879. return prop;
  880. }
  881. i++;
  882. }
  883. return undefined;
  884. }
  885. /**
  886. * get a unique id
  887. * @returns {number} uniqueId
  888. */
  889. var _uniqueId = 1;
  890. function uniqueId() {
  891. return _uniqueId++;
  892. }
  893. /**
  894. * get the window object of an element
  895. * @param {HTMLElement} element
  896. * @returns {DocumentView|Window}
  897. */
  898. function getWindowForElement(element) {
  899. var doc = element.ownerDocument;
  900. return (doc.defaultView || doc.parentWindow);
  901. }
  902. var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
  903. var SUPPORT_TOUCH = ('ontouchstart' in window);
  904. var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined;
  905. var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
  906. var INPUT_TYPE_TOUCH = 'touch';
  907. var INPUT_TYPE_PEN = 'pen';
  908. var INPUT_TYPE_MOUSE = 'mouse';
  909. var INPUT_TYPE_KINECT = 'kinect';
  910. var COMPUTE_INTERVAL = 25;
  911. var INPUT_START = 1;
  912. var INPUT_MOVE = 2;
  913. var INPUT_END = 4;
  914. var INPUT_CANCEL = 8;
  915. var DIRECTION_NONE = 1;
  916. var DIRECTION_LEFT = 2;
  917. var DIRECTION_RIGHT = 4;
  918. var DIRECTION_UP = 8;
  919. var DIRECTION_DOWN = 16;
  920. var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
  921. var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
  922. var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
  923. var PROPS_XY = ['x', 'y'];
  924. var PROPS_CLIENT_XY = ['clientX', 'clientY'];
  925. /**
  926. * create new input type manager
  927. * @param {Manager} manager
  928. * @param {Function} callback
  929. * @returns {Input}
  930. * @constructor
  931. */
  932. function Input(manager, callback) {
  933. var self = this;
  934. this.manager = manager;
  935. this.callback = callback;
  936. this.element = manager.element;
  937. this.target = manager.options.inputTarget;
  938. // smaller wrapper around the handler, for the scope and the enabled state of the manager,
  939. // so when disabled the input events are completely bypassed.
  940. this.domHandler = function(ev) {
  941. if (boolOrFn(manager.options.enable, [manager])) {
  942. self.handler(ev);
  943. }
  944. };
  945. this.init();
  946. }
  947. Input.prototype = {
  948. /**
  949. * should handle the inputEvent data and trigger the callback
  950. * @virtual
  951. */
  952. handler: function() {
  953. },
  954. /**
  955. * bind the events
  956. */
  957. init: function() {
  958. this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
  959. this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
  960. this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
  961. },
  962. /**
  963. * unbind the events
  964. */
  965. destroy: function() {
  966. this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
  967. this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
  968. this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
  969. }
  970. };
  971. /**
  972. * create new input type manager
  973. * called by the Manager constructor
  974. * @param {Hammer} manager
  975. * @returns {Input}
  976. */
  977. function createInputInstance(manager) {
  978. var Type;
  979. var inputClass = manager.options.inputClass;
  980. if (inputClass) {
  981. Type = inputClass;
  982. } else if (SUPPORT_POINTER_EVENTS) {
  983. Type = PointerEventInput;
  984. } else if (SUPPORT_ONLY_TOUCH) {
  985. Type = TouchInput;
  986. } else if (!SUPPORT_TOUCH) {
  987. Type = MouseInput;
  988. } else {
  989. Type = TouchMouseInput;
  990. }
  991. return new (Type)(manager, inputHandler);
  992. }
  993. /**
  994. * handle input events
  995. * @param {Manager} manager
  996. * @param {String} eventType
  997. * @param {Object} input
  998. */
  999. function inputHandler(manager, eventType, input) {
  1000. var pointersLen = input.pointers.length;
  1001. var changedPointersLen = input.changedPointers.length;
  1002. var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0));
  1003. var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0));
  1004. input.isFirst = !!isFirst;
  1005. input.isFinal = !!isFinal;
  1006. if (isFirst) {
  1007. manager.session = {};
  1008. }
  1009. // source event is the normalized value of the domEvents
  1010. // like 'touchstart, mouseup, pointerdown'
  1011. input.eventType = eventType;
  1012. // compute scale, rotation etc
  1013. computeInputData(manager, input);
  1014. // emit secret event
  1015. manager.emit('hammer.input', input);
  1016. manager.recognize(input);
  1017. manager.session.prevInput = input;
  1018. }
  1019. /**
  1020. * extend the data with some usable properties like scale, rotate, velocity etc
  1021. * @param {Object} manager
  1022. * @param {Object} input
  1023. */
  1024. function computeInputData(manager, input) {
  1025. var session = manager.session;
  1026. var pointers = input.pointers;
  1027. var pointersLength = pointers.length;
  1028. // store the first input to calculate the distance and direction
  1029. if (!session.firstInput) {
  1030. session.firstInput = simpleCloneInputData(input);
  1031. }
  1032. // to compute scale and rotation we need to store the multiple touches
  1033. if (pointersLength > 1 && !session.firstMultiple) {
  1034. session.firstMultiple = simpleCloneInputData(input);
  1035. } else if (pointersLength === 1) {
  1036. session.firstMultiple = false;
  1037. }
  1038. var firstInput = session.firstInput;
  1039. var firstMultiple = session.firstMultiple;
  1040. var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;
  1041. var center = input.center = getCenter(pointers);
  1042. input.timeStamp = now();
  1043. input.deltaTime = input.timeStamp - firstInput.timeStamp;
  1044. input.angle = getAngle(offsetCenter, center);
  1045. input.distance = getDistance(offsetCenter, center);
  1046. computeDeltaXY(session, input);
  1047. input.offsetDirection = getDirection(input.deltaX, input.deltaY);
  1048. input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
  1049. input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;
  1050. computeIntervalInputData(session, input);
  1051. // find the correct target
  1052. var target = manager.element;
  1053. if (hasParent(input.srcEvent.target, target)) {
  1054. target = input.srcEvent.target;
  1055. }
  1056. input.target = target;
  1057. }
  1058. function computeDeltaXY(session, input) {
  1059. var center = input.center;
  1060. var offset = session.offsetDelta || {};
  1061. var prevDelta = session.prevDelta || {};
  1062. var prevInput = session.prevInput || {};
  1063. if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
  1064. prevDelta = session.prevDelta = {
  1065. x: prevInput.deltaX || 0,
  1066. y: prevInput.deltaY || 0
  1067. };
  1068. offset = session.offsetDelta = {
  1069. x: center.x,
  1070. y: center.y
  1071. };
  1072. }
  1073. input.deltaX = prevDelta.x + (center.x - offset.x);
  1074. input.deltaY = prevDelta.y + (center.y - offset.y);
  1075. }
  1076. /**
  1077. * velocity is calculated every x ms
  1078. * @param {Object} session
  1079. * @param {Object} input
  1080. */
  1081. function computeIntervalInputData(session, input) {
  1082. var last = session.lastInterval || input,
  1083. deltaTime = input.timeStamp - last.timeStamp,
  1084. velocity, velocityX, velocityY, direction;
  1085. if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {
  1086. var deltaX = last.deltaX - input.deltaX;
  1087. var deltaY = last.deltaY - input.deltaY;
  1088. var v = getVelocity(deltaTime, deltaX, deltaY);
  1089. velocityX = v.x;
  1090. velocityY = v.y;
  1091. velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;
  1092. direction = getDirection(deltaX, deltaY);
  1093. session.lastInterval = input;
  1094. } else {
  1095. // use latest velocity info if it doesn't overtake a minimum period
  1096. velocity = last.velocity;
  1097. velocityX = last.velocityX;
  1098. velocityY = last.velocityY;
  1099. direction = last.direction;
  1100. }
  1101. input.velocity = velocity;
  1102. input.velocityX = velocityX;
  1103. input.velocityY = velocityY;
  1104. input.direction = direction;
  1105. }
  1106. /**
  1107. * create a simple clone from the input used for storage of firstInput and firstMultiple
  1108. * @param {Object} input
  1109. * @returns {Object} clonedInputData
  1110. */
  1111. function simpleCloneInputData(input) {
  1112. // make a simple copy of the pointers because we will get a reference if we don't
  1113. // we only need clientXY for the calculations
  1114. var pointers = [];
  1115. var i = 0;
  1116. while (i < input.pointers.length) {
  1117. pointers[i] = {
  1118. clientX: round(input.pointers[i].clientX),
  1119. clientY: round(input.pointers[i].clientY)
  1120. };
  1121. i++;
  1122. }
  1123. return {
  1124. timeStamp: now(),
  1125. pointers: pointers,
  1126. center: getCenter(pointers),
  1127. deltaX: input.deltaX,
  1128. deltaY: input.deltaY
  1129. };
  1130. }
  1131. /**
  1132. * get the center of all the pointers
  1133. * @param {Array} pointers
  1134. * @return {Object} center contains `x` and `y` properties
  1135. */
  1136. function getCenter(pointers) {
  1137. var pointersLength = pointers.length;
  1138. // no need to loop when only one touch
  1139. if (pointersLength === 1) {
  1140. return {
  1141. x: round(pointers[0].clientX),
  1142. y: round(pointers[0].clientY)
  1143. };
  1144. }
  1145. var x = 0, y = 0, i = 0;
  1146. while (i < pointersLength) {
  1147. x += pointers[i].clientX;
  1148. y += pointers[i].clientY;
  1149. i++;
  1150. }
  1151. return {
  1152. x: round(x / pointersLength),
  1153. y: round(y / pointersLength)
  1154. };
  1155. }
  1156. /**
  1157. * calculate the velocity between two points. unit is in px per ms.
  1158. * @param {Number} deltaTime
  1159. * @param {Number} x
  1160. * @param {Number} y
  1161. * @return {Object} velocity `x` and `y`
  1162. */
  1163. function getVelocity(deltaTime, x, y) {
  1164. return {
  1165. x: x / deltaTime || 0,
  1166. y: y / deltaTime || 0
  1167. };
  1168. }
  1169. /**
  1170. * get the direction between two points
  1171. * @param {Number} x
  1172. * @param {Number} y
  1173. * @return {Number} direction
  1174. */
  1175. function getDirection(x, y) {
  1176. if (x === y) {
  1177. return DIRECTION_NONE;
  1178. }
  1179. if (abs(x) >= abs(y)) {
  1180. return x > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
  1181. }
  1182. return y > 0 ? DIRECTION_UP : DIRECTION_DOWN;
  1183. }
  1184. /**
  1185. * calculate the absolute distance between two points
  1186. * @param {Object} p1 {x, y}
  1187. * @param {Object} p2 {x, y}
  1188. * @param {Array} [props] containing x and y keys
  1189. * @return {Number} distance
  1190. */
  1191. function getDistance(p1, p2, props) {
  1192. if (!props) {
  1193. props = PROPS_XY;
  1194. }
  1195. var x = p2[props[0]] - p1[props[0]],
  1196. y = p2[props[1]] - p1[props[1]];
  1197. return Math.sqrt((x * x) + (y * y));
  1198. }
  1199. /**
  1200. * calculate the angle between two coordinates
  1201. * @param {Object} p1
  1202. * @param {Object} p2
  1203. * @param {Array} [props] containing x and y keys
  1204. * @return {Number} angle
  1205. */
  1206. function getAngle(p1, p2, props) {
  1207. if (!props) {
  1208. props = PROPS_XY;
  1209. }
  1210. var x = p2[props[0]] - p1[props[0]],
  1211. y = p2[props[1]] - p1[props[1]];
  1212. return Math.atan2(y, x) * 180 / Math.PI;
  1213. }
  1214. /**
  1215. * calculate the rotation degrees between two pointersets
  1216. * @param {Array} start array of pointers
  1217. * @param {Array} end array of pointers
  1218. * @return {Number} rotation
  1219. */
  1220. function getRotation(start, end) {
  1221. return getAngle(end[1], end[0], PROPS_CLIENT_XY) - getAngle(start[1], start[0], PROPS_CLIENT_XY);
  1222. }
  1223. /**
  1224. * calculate the scale factor between two pointersets
  1225. * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
  1226. * @param {Array} start array of pointers
  1227. * @param {Array} end array of pointers
  1228. * @return {Number} scale
  1229. */
  1230. function getScale(start, end) {
  1231. return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
  1232. }
  1233. var MOUSE_INPUT_MAP = {
  1234. mousedown: INPUT_START,
  1235. mousemove: INPUT_MOVE,
  1236. mouseup: INPUT_END
  1237. };
  1238. var MOUSE_ELEMENT_EVENTS = 'mousedown';
  1239. var MOUSE_WINDOW_EVENTS = 'mousemove mouseup';
  1240. /**
  1241. * Mouse events input
  1242. * @constructor
  1243. * @extends Input
  1244. */
  1245. function MouseInput() {
  1246. this.evEl = MOUSE_ELEMENT_EVENTS;
  1247. this.evWin = MOUSE_WINDOW_EVENTS;
  1248. this.allow = true; // used by Input.TouchMouse to disable mouse events
  1249. this.pressed = false; // mousedown state
  1250. Input.apply(this, arguments);
  1251. }
  1252. inherit(MouseInput, Input, {
  1253. /**
  1254. * handle mouse events
  1255. * @param {Object} ev
  1256. */
  1257. handler: function MEhandler(ev) {
  1258. var eventType = MOUSE_INPUT_MAP[ev.type];
  1259. // on start we want to have the left mouse button down
  1260. if (eventType & INPUT_START && ev.button === 0) {
  1261. this.pressed = true;
  1262. }
  1263. if (eventType & INPUT_MOVE && ev.which !== 1) {
  1264. eventType = INPUT_END;
  1265. }
  1266. // mouse must be down, and mouse events are allowed (see the TouchMouse input)
  1267. if (!this.pressed || !this.allow) {
  1268. return;
  1269. }
  1270. if (eventType & INPUT_END) {
  1271. this.pressed = false;
  1272. }
  1273. this.callback(this.manager, eventType, {
  1274. pointers: [ev],
  1275. changedPointers: [ev],
  1276. pointerType: INPUT_TYPE_MOUSE,
  1277. srcEvent: ev
  1278. });
  1279. }
  1280. });
  1281. var POINTER_INPUT_MAP = {
  1282. pointerdown: INPUT_START,
  1283. pointermove: INPUT_MOVE,
  1284. pointerup: INPUT_END,
  1285. pointercancel: INPUT_CANCEL,
  1286. pointerout: INPUT_CANCEL
  1287. };
  1288. // in IE10 the pointer types is defined as an enum
  1289. var IE10_POINTER_TYPE_ENUM = {
  1290. 2: INPUT_TYPE_TOUCH,
  1291. 3: INPUT_TYPE_PEN,
  1292. 4: INPUT_TYPE_MOUSE,
  1293. 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816
  1294. };
  1295. var POINTER_ELEMENT_EVENTS = 'pointerdown';
  1296. var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel';
  1297. // IE10 has prefixed support, and case-sensitive
  1298. if (window.MSPointerEvent) {
  1299. POINTER_ELEMENT_EVENTS = 'MSPointerDown';
  1300. POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';
  1301. }
  1302. /**
  1303. * Pointer events input
  1304. * @constructor
  1305. * @extends Input
  1306. */
  1307. function PointerEventInput() {
  1308. this.evEl = POINTER_ELEMENT_EVENTS;
  1309. this.evWin = POINTER_WINDOW_EVENTS;
  1310. Input.apply(this, arguments);
  1311. this.store = (this.manager.session.pointerEvents = []);
  1312. }
  1313. inherit(PointerEventInput, Input, {
  1314. /**
  1315. * handle mouse events
  1316. * @param {Object} ev
  1317. */
  1318. handler: function PEhandler(ev) {
  1319. var store = this.store;
  1320. var removePointer = false;
  1321. var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
  1322. var eventType = POINTER_INPUT_MAP[eventTypeNormalized];
  1323. var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;
  1324. var isTouch = (pointerType == INPUT_TYPE_TOUCH);
  1325. // get index of the event in the store
  1326. var storeIndex = inArray(store, ev.pointerId, 'pointerId');
  1327. // start and mouse must be down
  1328. if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {
  1329. if (storeIndex < 0) {
  1330. store.push(ev);
  1331. storeIndex = store.length - 1;
  1332. }
  1333. } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
  1334. removePointer = true;
  1335. }
  1336. // it not found, so the pointer hasn't been down (so it's probably a hover)
  1337. if (storeIndex < 0) {
  1338. return;
  1339. }
  1340. // update the event in the store
  1341. store[storeIndex] = ev;
  1342. this.callback(this.manager, eventType, {
  1343. pointers: store,
  1344. changedPointers: [ev],
  1345. pointerType: pointerType,
  1346. srcEvent: ev
  1347. });
  1348. if (removePointer) {
  1349. // remove from the store
  1350. store.splice(storeIndex, 1);
  1351. }
  1352. }
  1353. });
  1354. var SINGLE_TOUCH_INPUT_MAP = {
  1355. touchstart: INPUT_START,
  1356. touchmove: INPUT_MOVE,
  1357. touchend: INPUT_END,
  1358. touchcancel: INPUT_CANCEL
  1359. };
  1360. var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';
  1361. var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';
  1362. /**
  1363. * Touch events input
  1364. * @constructor
  1365. * @extends Input
  1366. */
  1367. function SingleTouchInput() {
  1368. this.evTarget = SINGLE_TOUCH_TARGET_EVENTS;
  1369. this.evWin = SINGLE_TOUCH_WINDOW_EVENTS;
  1370. this.started = false;
  1371. Input.apply(this, arguments);
  1372. }
  1373. inherit(SingleTouchInput, Input, {
  1374. handler: function TEhandler(ev) {
  1375. var type = SINGLE_TOUCH_INPUT_MAP[ev.type];
  1376. // should we handle the touch events?
  1377. if (type === INPUT_START) {
  1378. this.started = true;
  1379. }
  1380. if (!this.started) {
  1381. return;
  1382. }
  1383. var touches = normalizeSingleTouches.call(this, ev, type);
  1384. // when done, reset the started state
  1385. if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {
  1386. this.started = false;
  1387. }
  1388. this.callback(this.manager, type, {
  1389. pointers: touches[0],
  1390. changedPointers: touches[1],
  1391. pointerType: INPUT_TYPE_TOUCH,
  1392. srcEvent: ev
  1393. });
  1394. }
  1395. });
  1396. /**
  1397. * @this {TouchInput}
  1398. * @param {Object} ev
  1399. * @param {Number} type flag
  1400. * @returns {undefined|Array} [all, changed]
  1401. */
  1402. function normalizeSingleTouches(ev, type) {
  1403. var all = toArray(ev.touches);
  1404. var changed = toArray(ev.changedTouches);
  1405. if (type & (INPUT_END | INPUT_CANCEL)) {
  1406. all = uniqueArray(all.concat(changed), 'identifier', true);
  1407. }
  1408. return [all, changed];
  1409. }
  1410. var TOUCH_INPUT_MAP = {
  1411. touchstart: INPUT_START,
  1412. touchmove: INPUT_MOVE,
  1413. touchend: INPUT_END,
  1414. touchcancel: INPUT_CANCEL
  1415. };
  1416. var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
  1417. /**
  1418. * Multi-user touch events input
  1419. * @constructor
  1420. * @extends Input
  1421. */
  1422. function TouchInput() {
  1423. this.evTarget = TOUCH_TARGET_EVENTS;
  1424. this.targetIds = {};
  1425. Input.apply(this, arguments);
  1426. }
  1427. inherit(TouchInput, Input, {
  1428. handler: function MTEhandler(ev) {
  1429. var type = TOUCH_INPUT_MAP[ev.type];
  1430. var touches = getTouches.call(this, ev, type);
  1431. if (!touches) {
  1432. return;
  1433. }
  1434. this.callback(this.manager, type, {
  1435. pointers: touches[0],
  1436. changedPointers: touches[1],
  1437. pointerType: INPUT_TYPE_TOUCH,
  1438. srcEvent: ev
  1439. });
  1440. }
  1441. });
  1442. /**
  1443. * @this {TouchInput}
  1444. * @param {Object} ev
  1445. * @param {Number} type flag
  1446. * @returns {undefined|Array} [all, changed]
  1447. */
  1448. function getTouches(ev, type) {
  1449. var allTouches = toArray(ev.touches);
  1450. var targetIds = this.targetIds;
  1451. // when there is only one touch, the process can be simplified
  1452. if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {
  1453. targetIds[allTouches[0].identifier] = true;
  1454. return [allTouches, allTouches];
  1455. }
  1456. var i,
  1457. targetTouches,
  1458. changedTouches = toArray(ev.changedTouches),
  1459. changedTargetTouches = [],
  1460. target = this.target;
  1461. // get target touches from touches
  1462. targetTouches = allTouches.filter(function(touch) {
  1463. return hasParent(touch.target, target);
  1464. });
  1465. // collect touches
  1466. if (type === INPUT_START) {
  1467. i = 0;
  1468. while (i < targetTouches.length) {
  1469. targetIds[targetTouches[i].identifier] = true;
  1470. i++;
  1471. }
  1472. }
  1473. // filter changed touches to only contain touches that exist in the collected target ids
  1474. i = 0;
  1475. while (i < changedTouches.length) {
  1476. if (targetIds[changedTouches[i].identifier]) {
  1477. changedTargetTouches.push(changedTouches[i]);
  1478. }
  1479. // cleanup removed touches
  1480. if (type & (INPUT_END | INPUT_CANCEL)) {
  1481. delete targetIds[changedTouches[i].identifier];
  1482. }
  1483. i++;
  1484. }
  1485. if (!changedTargetTouches.length) {
  1486. return;
  1487. }
  1488. return [
  1489. // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
  1490. uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true),
  1491. changedTargetTouches
  1492. ];
  1493. }
  1494. /**
  1495. * Combined touch and mouse input
  1496. *
  1497. * Touch has a higher priority then mouse, and while touching no mouse events are allowed.
  1498. * This because touch devices also emit mouse events while doing a touch.
  1499. *
  1500. * @constructor
  1501. * @extends Input
  1502. */
  1503. function TouchMouseInput() {
  1504. Input.apply(this, arguments);
  1505. var handler = bindFn(this.handler, this);
  1506. this.touch = new TouchInput(this.manager, handler);
  1507. this.mouse = new MouseInput(this.manager, handler);
  1508. }
  1509. inherit(TouchMouseInput, Input, {
  1510. /**
  1511. * handle mouse and touch events
  1512. * @param {Hammer} manager
  1513. * @param {String} inputEvent
  1514. * @param {Object} inputData
  1515. */
  1516. handler: function TMEhandler(manager, inputEvent, inputData) {
  1517. var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH),
  1518. isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE);
  1519. // when we're in a touch event, so block all upcoming mouse events
  1520. // most mobile browser also emit mouseevents, right after touchstart
  1521. if (isTouch) {
  1522. this.mouse.allow = false;
  1523. } else if (isMouse && !this.mouse.allow) {
  1524. return;
  1525. }
  1526. // reset the allowMouse when we're done
  1527. if (inputEvent & (INPUT_END | INPUT_CANCEL)) {
  1528. this.mouse.allow = true;
  1529. }
  1530. this.callback(manager, inputEvent, inputData);
  1531. },
  1532. /**
  1533. * remove the event listeners
  1534. */
  1535. destroy: function destroy() {
  1536. this.touch.destroy();
  1537. this.mouse.destroy();
  1538. }
  1539. });
  1540. var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
  1541. var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;
  1542. // magical touchAction value
  1543. var TOUCH_ACTION_COMPUTE = 'compute';
  1544. var TOUCH_ACTION_AUTO = 'auto';
  1545. var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented
  1546. var TOUCH_ACTION_NONE = 'none';
  1547. var TOUCH_ACTION_PAN_X = 'pan-x';
  1548. var TOUCH_ACTION_PAN_Y = 'pan-y';
  1549. /**
  1550. * Touch Action
  1551. * sets the touchAction property or uses the js alternative
  1552. * @param {Manager} manager
  1553. * @param {String} value
  1554. * @constructor
  1555. */
  1556. function TouchAction(manager, value) {
  1557. this.manager = manager;
  1558. this.set(value);
  1559. }
  1560. TouchAction.prototype = {
  1561. /**
  1562. * set the touchAction value on the element or enable the polyfill
  1563. * @param {String} value
  1564. */
  1565. set: function(value) {
  1566. // find out the touch-action by the event handlers
  1567. if (value == TOUCH_ACTION_COMPUTE) {
  1568. value = this.compute();
  1569. }
  1570. if (NATIVE_TOUCH_ACTION) {
  1571. this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;
  1572. }
  1573. this.actions = value.toLowerCase().trim();
  1574. },
  1575. /**
  1576. * just re-set the touchAction value
  1577. */
  1578. update: function() {
  1579. this.set(this.manager.options.touchAction);
  1580. },
  1581. /**
  1582. * compute the value for the touchAction property based on the recognizer's settings
  1583. * @returns {String} value
  1584. */
  1585. compute: function() {
  1586. var actions = [];
  1587. each(this.manager.recognizers, function(recognizer) {
  1588. if (boolOrFn(recognizer.options.enable, [recognizer])) {
  1589. actions = actions.concat(recognizer.getTouchAction());
  1590. }
  1591. });
  1592. return cleanTouchActions(actions.join(' '));
  1593. },
  1594. /**
  1595. * this method is called on each input cycle and provides the preventing of the browser behavior
  1596. * @param {Object} input
  1597. */
  1598. preventDefaults: function(input) {
  1599. // not needed with native support for the touchAction property
  1600. if (NATIVE_TOUCH_ACTION) {
  1601. return;
  1602. }
  1603. var srcEvent = input.srcEvent;
  1604. var direction = input.offsetDirection;
  1605. // if the touch action did prevented once this session
  1606. if (this.manager.session.prevented) {
  1607. srcEvent.preventDefault();
  1608. return;
  1609. }
  1610. var actions = this.actions;
  1611. var hasNone = inStr(actions, TOUCH_ACTION_NONE);
  1612. var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);
  1613. var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
  1614. if (hasNone ||
  1615. (hasPanY && direction & DIRECTION_HORIZONTAL) ||
  1616. (hasPanX && direction & DIRECTION_VERTICAL)) {
  1617. return this.preventSrc(srcEvent);
  1618. }
  1619. },
  1620. /**
  1621. * call preventDefault to prevent the browser's default behavior (scrolling in most cases)
  1622. * @param {Object} srcEvent
  1623. */
  1624. preventSrc: function(srcEvent) {
  1625. this.manager.session.prevented = true;
  1626. srcEvent.preventDefault();
  1627. }
  1628. };
  1629. /**
  1630. * when the touchActions are collected they are not a valid value, so we need to clean things up. *
  1631. * @param {String} actions
  1632. * @returns {*}
  1633. */
  1634. function cleanTouchActions(actions) {
  1635. // none
  1636. if (inStr(actions, TOUCH_ACTION_NONE)) {
  1637. return TOUCH_ACTION_NONE;
  1638. }
  1639. var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
  1640. var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);
  1641. // pan-x and pan-y can be combined
  1642. if (hasPanX && hasPanY) {
  1643. return TOUCH_ACTION_PAN_X + ' ' + TOUCH_ACTION_PAN_Y;
  1644. }
  1645. // pan-x OR pan-y
  1646. if (hasPanX || hasPanY) {
  1647. return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;
  1648. }
  1649. // manipulation
  1650. if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {
  1651. return TOUCH_ACTION_MANIPULATION;
  1652. }
  1653. return TOUCH_ACTION_AUTO;
  1654. }
  1655. /**
  1656. * Recognizer flow explained; *
  1657. * All recognizers have the initial state of POSSIBLE when a input session starts.
  1658. * The definition of a input session is from the first input until the last input, with all it's movement in it. *
  1659. * Example session for mouse-input: mousedown -> mousemove -> mouseup
  1660. *
  1661. * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed
  1662. * which determines with state it should be.
  1663. *
  1664. * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to
  1665. * POSSIBLE to give it another change on the next cycle.
  1666. *
  1667. * Possible
  1668. * |
  1669. * +-----+---------------+
  1670. * | |
  1671. * +-----+-----+ |
  1672. * | | |
  1673. * Failed Cancelled |
  1674. * +-------+------+
  1675. * | |
  1676. * Recognized Began
  1677. * |
  1678. * Changed
  1679. * |
  1680. * Ended/Recognized
  1681. */
  1682. var STATE_POSSIBLE = 1;
  1683. var STATE_BEGAN = 2;
  1684. var STATE_CHANGED = 4;
  1685. var STATE_ENDED = 8;
  1686. var STATE_RECOGNIZED = STATE_ENDED;
  1687. var STATE_CANCELLED = 16;
  1688. var STATE_FAILED = 32;
  1689. /**
  1690. * Recognizer
  1691. * Every recognizer needs to extend from this class.
  1692. * @constructor
  1693. * @param {Object} options
  1694. */
  1695. function Recognizer(options) {
  1696. this.id = uniqueId();
  1697. this.manager = null;
  1698. this.options = merge(options || {}, this.defaults);
  1699. // default is enable true
  1700. this.options.enable = ifUndefined(this.options.enable, true);
  1701. this.state = STATE_POSSIBLE;
  1702. this.simultaneous = {};
  1703. this.requireFail = [];
  1704. }
  1705. Recognizer.prototype = {
  1706. /**
  1707. * @virtual
  1708. * @type {Object}
  1709. */
  1710. defaults: {},
  1711. /**
  1712. * set options
  1713. * @param {Object} options
  1714. * @return {Recognizer}
  1715. */
  1716. set: function(options) {
  1717. extend(this.options, options);
  1718. // also update the touchAction, in case something changed about the directions/enabled state
  1719. this.manager && this.manager.touchAction.update();
  1720. return this;
  1721. },
  1722. /**
  1723. * recognize simultaneous with an other recognizer.
  1724. * @param {Recognizer} otherRecognizer
  1725. * @returns {Recognizer} this
  1726. */
  1727. recognizeWith: function(otherRecognizer) {
  1728. if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {
  1729. return this;
  1730. }
  1731. var simultaneous = this.simultaneous;
  1732. otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
  1733. if (!simultaneous[otherRecognizer.id]) {
  1734. simultaneous[otherRecognizer.id] = otherRecognizer;
  1735. otherRecognizer.recognizeWith(this);
  1736. }
  1737. return this;
  1738. },
  1739. /**
  1740. * drop the simultaneous link. it doesnt remove the link on the other recognizer.
  1741. * @param {Recognizer} otherRecognizer
  1742. * @returns {Recognizer} this
  1743. */
  1744. dropRecognizeWith: function(otherRecognizer) {
  1745. if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {
  1746. return this;
  1747. }
  1748. otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
  1749. delete this.simultaneous[otherRecognizer.id];
  1750. return this;
  1751. },
  1752. /**
  1753. * recognizer can only run when an other is failing
  1754. * @param {Recognizer} otherRecognizer
  1755. * @returns {Recognizer} this
  1756. */
  1757. requireFailure: function(otherRecognizer) {
  1758. if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {
  1759. return this;
  1760. }
  1761. var requireFail = this.requireFail;
  1762. otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
  1763. if (inArray(requireFail, otherRecognizer) === -1) {
  1764. requireFail.push(otherRecognizer);
  1765. otherRecognizer.requireFailure(this);
  1766. }
  1767. return this;
  1768. },
  1769. /**
  1770. * drop the requireFailure link. it does not remove the link on the other recognizer.
  1771. * @param {Recognizer} otherRecognizer
  1772. * @returns {Recognizer} this
  1773. */
  1774. dropRequireFailure: function(otherRecognizer) {
  1775. if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {
  1776. return this;
  1777. }
  1778. otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
  1779. var index = inArray(this.requireFail, otherRecognizer);
  1780. if (index > -1) {
  1781. this.requireFail.splice(index, 1);
  1782. }
  1783. return this;
  1784. },
  1785. /**
  1786. * has require failures boolean
  1787. * @returns {boolean}
  1788. */
  1789. hasRequireFailures: function() {
  1790. return this.requireFail.length > 0;
  1791. },
  1792. /**
  1793. * if the recognizer can recognize simultaneous with an other recognizer
  1794. * @param {Recognizer} otherRecognizer
  1795. * @returns {Boolean}
  1796. */
  1797. canRecognizeWith: function(otherRecognizer) {
  1798. return !!this.simultaneous[otherRecognizer.id];
  1799. },
  1800. /**
  1801. * You should use `tryEmit` instead of `emit` directly to check
  1802. * that all the needed recognizers has failed before emitting.
  1803. * @param {Object} input
  1804. */
  1805. emit: function(input) {
  1806. var self = this;
  1807. var state = this.state;
  1808. function emit(withState) {
  1809. self.manager.emit(self.options.event + (withState ? stateStr(state) : ''), input);
  1810. }
  1811. // 'panstart' and 'panmove'
  1812. if (state < STATE_ENDED) {
  1813. emit(true);
  1814. }
  1815. emit(); // simple 'eventName' events
  1816. // panend and pancancel
  1817. if (state >= STATE_ENDED) {
  1818. emit(true);
  1819. }
  1820. },
  1821. /**
  1822. * Check that all the require failure recognizers has failed,
  1823. * if true, it emits a gesture event,
  1824. * otherwise, setup the state to FAILED.
  1825. * @param {Object} input
  1826. */
  1827. tryEmit: function(input) {
  1828. if (this.canEmit()) {
  1829. return this.emit(input);
  1830. }
  1831. // it's failing anyway
  1832. this.state = STATE_FAILED;
  1833. },
  1834. /**
  1835. * can we emit?
  1836. * @returns {boolean}
  1837. */
  1838. canEmit: function() {
  1839. var i = 0;
  1840. while (i < this.requireFail.length) {
  1841. if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {
  1842. return false;
  1843. }
  1844. i++;
  1845. }
  1846. return true;
  1847. },
  1848. /**
  1849. * update the recognizer
  1850. * @param {Object} inputData
  1851. */
  1852. recognize: function(inputData) {
  1853. // make a new copy of the inputData
  1854. // so we can change the inputData without messing up the other recognizers
  1855. var inputDataClone = extend({}, inputData);
  1856. // is is enabled and allow recognizing?
  1857. if (!boolOrFn(this.options.enable, [this, inputDataClone])) {
  1858. this.reset();
  1859. this.state = STATE_FAILED;
  1860. return;
  1861. }
  1862. // reset when we've reached the end
  1863. if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {
  1864. this.state = STATE_POSSIBLE;
  1865. }
  1866. this.state = this.process(inputDataClone);
  1867. // the recognizer has recognized a gesture
  1868. // so trigger an event
  1869. if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {
  1870. this.tryEmit(inputDataClone);
  1871. }
  1872. },
  1873. /**
  1874. * return the state of the recognizer
  1875. * the actual recognizing happens in this method
  1876. * @virtual
  1877. * @param {Object} inputData
  1878. * @returns {Const} STATE
  1879. */
  1880. process: function(inputData) {
  1881. }, // jshint ignore:line
  1882. /**
  1883. * return the preferred touch-action
  1884. * @virtual
  1885. * @returns {Array}
  1886. */
  1887. getTouchAction: function() {
  1888. },
  1889. /**
  1890. * called when the gesture isn't allowed to recognize
  1891. * like when another is being recognized or it is disabled
  1892. * @virtual
  1893. */
  1894. reset: function() {
  1895. }
  1896. };
  1897. /**
  1898. * get a usable string, used as event postfix
  1899. * @param {Const} state
  1900. * @returns {String} state
  1901. */
  1902. function stateStr(state) {
  1903. if (state & STATE_CANCELLED) {
  1904. return 'cancel';
  1905. } else if (state & STATE_ENDED) {
  1906. return 'end';
  1907. } else if (state & STATE_CHANGED) {
  1908. return 'move';
  1909. } else if (state & STATE_BEGAN) {
  1910. return 'start';
  1911. }
  1912. return '';
  1913. }
  1914. /**
  1915. * direction cons to string
  1916. * @param {Const} direction
  1917. * @returns {String}
  1918. */
  1919. function directionStr(direction) {
  1920. if (direction == DIRECTION_DOWN) {
  1921. return 'down';
  1922. } else if (direction == DIRECTION_UP) {
  1923. return 'up';
  1924. } else if (direction == DIRECTION_LEFT) {
  1925. return 'left';
  1926. } else if (direction == DIRECTION_RIGHT) {
  1927. return 'right';
  1928. }
  1929. return '';
  1930. }
  1931. /**
  1932. * get a recognizer by name if it is bound to a manager
  1933. * @param {Recognizer|String} otherRecognizer
  1934. * @param {Recognizer} recognizer
  1935. * @returns {Recognizer}
  1936. */
  1937. function getRecognizerByNameIfManager(otherRecognizer, recognizer) {
  1938. var manager = recognizer.manager;
  1939. if (manager) {
  1940. return manager.get(otherRecognizer);
  1941. }
  1942. return otherRecognizer;
  1943. }
  1944. /**
  1945. * This recognizer is just used as a base for the simple attribute recognizers.
  1946. * @constructor
  1947. * @extends Recognizer
  1948. */
  1949. function AttrRecognizer() {
  1950. Recognizer.apply(this, arguments);
  1951. }
  1952. inherit(AttrRecognizer, Recognizer, {
  1953. /**
  1954. * @namespace
  1955. * @memberof AttrRecognizer
  1956. */
  1957. defaults: {
  1958. /**
  1959. * @type {Number}
  1960. * @default 1
  1961. */
  1962. pointers: 1
  1963. },
  1964. /**
  1965. * Used to check if it the recognizer receives valid input, like input.distance > 10.
  1966. * @memberof AttrRecognizer
  1967. * @param {Object} input
  1968. * @returns {Boolean} recognized
  1969. */
  1970. attrTest: function(input) {
  1971. var optionPointers = this.options.pointers;
  1972. return optionPointers === 0 || input.pointers.length === optionPointers;
  1973. },
  1974. /**
  1975. * Process the input and return the state for the recognizer
  1976. * @memberof AttrRecognizer
  1977. * @param {Object} input
  1978. * @returns {*} State
  1979. */
  1980. process: function(input) {
  1981. var state = this.state;
  1982. var eventType = input.eventType;
  1983. var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);
  1984. var isValid = this.attrTest(input);
  1985. // on cancel input and we've recognized before, return STATE_CANCELLED
  1986. if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {
  1987. return state | STATE_CANCELLED;
  1988. } else if (isRecognized || isValid) {
  1989. if (eventType & INPUT_END) {
  1990. return state | STATE_ENDED;
  1991. } else if (!(state & STATE_BEGAN)) {
  1992. return STATE_BEGAN;
  1993. }
  1994. return state | STATE_CHANGED;
  1995. }
  1996. return STATE_FAILED;
  1997. }
  1998. });
  1999. /**
  2000. * Pan
  2001. * Recognized when the pointer is down and moved in the allowed direction.
  2002. * @constructor
  2003. * @extends AttrRecognizer
  2004. */
  2005. function PanRecognizer() {
  2006. AttrRecognizer.apply(this, arguments);
  2007. this.pX = null;
  2008. this.pY = null;
  2009. }
  2010. inherit(PanRecognizer, AttrRecognizer, {
  2011. /**
  2012. * @namespace
  2013. * @memberof PanRecognizer
  2014. */
  2015. defaults: {
  2016. event: 'pan',
  2017. threshold: 10,
  2018. pointers: 1,
  2019. direction: DIRECTION_ALL
  2020. },
  2021. getTouchAction: function() {
  2022. var direction = this.options.direction;
  2023. var actions = [];
  2024. if (direction & DIRECTION_HORIZONTAL) {
  2025. actions.push(TOUCH_ACTION_PAN_Y);
  2026. }
  2027. if (direction & DIRECTION_VERTICAL) {
  2028. actions.push(TOUCH_ACTION_PAN_X);
  2029. }
  2030. return actions;
  2031. },
  2032. directionTest: function(input) {
  2033. var options = this.options;
  2034. var hasMoved = true;
  2035. var distance = input.distance;
  2036. var direction = input.direction;
  2037. var x = input.deltaX;
  2038. var y = input.deltaY;
  2039. // lock to axis?
  2040. if (!(direction & options.direction)) {
  2041. if (options.direction & DIRECTION_HORIZONTAL) {
  2042. direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT;
  2043. hasMoved = x != this.pX;
  2044. distance = Math.abs(input.deltaX);
  2045. } else {
  2046. direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN;
  2047. hasMoved = y != this.pY;
  2048. distance = Math.abs(input.deltaY);
  2049. }
  2050. }
  2051. input.direction = direction;
  2052. return hasMoved && distance > options.threshold && direction & options.direction;
  2053. },
  2054. attrTest: function(input) {
  2055. return AttrRecognizer.prototype.attrTest.call(this, input) &&
  2056. (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input)));
  2057. },
  2058. emit: function(input) {
  2059. this.pX = input.deltaX;
  2060. this.pY = input.deltaY;
  2061. var direction = directionStr(input.direction);
  2062. if (direction) {
  2063. this.manager.emit(this.options.event + direction, input);
  2064. }
  2065. this._super.emit.call(this, input);
  2066. }
  2067. });
  2068. /**
  2069. * Pinch
  2070. * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).
  2071. * @constructor
  2072. * @extends AttrRecognizer
  2073. */
  2074. function PinchRecognizer() {
  2075. AttrRecognizer.apply(this, arguments);
  2076. }
  2077. inherit(PinchRecognizer, AttrRecognizer, {
  2078. /**
  2079. * @namespace
  2080. * @memberof PinchRecognizer
  2081. */
  2082. defaults: {
  2083. event: 'pinch',
  2084. threshold: 0,
  2085. pointers: 2
  2086. },
  2087. getTouchAction: function() {
  2088. return [TOUCH_ACTION_NONE];
  2089. },
  2090. attrTest: function(input) {
  2091. return this._super.attrTest.call(this, input) &&
  2092. (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);
  2093. },
  2094. emit: function(input) {
  2095. this._super.emit.call(this, input);
  2096. if (input.scale !== 1) {
  2097. var inOut = input.scale < 1 ? 'in' : 'out';
  2098. this.manager.emit(this.options.event + inOut, input);
  2099. }
  2100. }
  2101. });
  2102. /**
  2103. * Press
  2104. * Recognized when the pointer is down for x ms without any movement.
  2105. * @constructor
  2106. * @extends Recognizer
  2107. */
  2108. function PressRecognizer() {
  2109. Recognizer.apply(this, arguments);
  2110. this._timer = null;
  2111. this._input = null;
  2112. }
  2113. inherit(PressRecognizer, Recognizer, {
  2114. /**
  2115. * @namespace
  2116. * @memberof PressRecognizer
  2117. */
  2118. defaults: {
  2119. event: 'press',
  2120. pointers: 1,
  2121. time: 500, // minimal time of the pointer to be pressed
  2122. threshold: 5 // a minimal movement is ok, but keep it low
  2123. },
  2124. getTouchAction: function() {
  2125. return [TOUCH_ACTION_AUTO];
  2126. },
  2127. process: function(input) {
  2128. var options = this.options;
  2129. var validPointers = input.pointers.length === options.pointers;
  2130. var validMovement = input.distance < options.threshold;
  2131. var validTime = input.deltaTime > options.time;
  2132. this._input = input;
  2133. // we only allow little movement
  2134. // and we've reached an end event, so a tap is possible
  2135. if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) {
  2136. this.reset();
  2137. } else if (input.eventType & INPUT_START) {
  2138. this.reset();
  2139. this._timer = setTimeoutContext(function() {
  2140. this.state = STATE_RECOGNIZED;
  2141. this.tryEmit();
  2142. }, options.time, this);
  2143. } else if (input.eventType & INPUT_END) {
  2144. return STATE_RECOGNIZED;
  2145. }
  2146. return STATE_FAILED;
  2147. },
  2148. reset: function() {
  2149. clearTimeout(this._timer);
  2150. },
  2151. emit: function(input) {
  2152. if (this.state !== STATE_RECOGNIZED) {
  2153. return;
  2154. }
  2155. if (input && (input.eventType & INPUT_END)) {
  2156. this.manager.emit(this.options.event + 'up', input);
  2157. } else {
  2158. this._input.timeStamp = now();
  2159. this.manager.emit(this.options.event, this._input);
  2160. }
  2161. }
  2162. });
  2163. /**
  2164. * Rotate
  2165. * Recognized when two or more pointer are moving in a circular motion.
  2166. * @constructor
  2167. * @extends AttrRecognizer
  2168. */
  2169. function RotateRecognizer() {
  2170. AttrRecognizer.apply(this, arguments);
  2171. }
  2172. inherit(RotateRecognizer, AttrRecognizer, {
  2173. /**
  2174. * @namespace
  2175. * @memberof RotateRecognizer
  2176. */
  2177. defaults: {
  2178. event: 'rotate',
  2179. threshold: 0,
  2180. pointers: 2
  2181. },
  2182. getTouchAction: function() {
  2183. return [TOUCH_ACTION_NONE];
  2184. },
  2185. attrTest: function(input) {
  2186. return this._super.attrTest.call(this, input) &&
  2187. (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);
  2188. }
  2189. });
  2190. /**
  2191. * Swipe
  2192. * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.
  2193. * @constructor
  2194. * @extends AttrRecognizer
  2195. */
  2196. function SwipeRecognizer() {
  2197. AttrRecognizer.apply(this, arguments);
  2198. }
  2199. inherit(SwipeRecognizer, AttrRecognizer, {
  2200. /**
  2201. * @namespace
  2202. * @memberof SwipeRecognizer
  2203. */
  2204. defaults: {
  2205. event: 'swipe',
  2206. threshold: 10,
  2207. velocity: 0.65,
  2208. direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,
  2209. pointers: 1
  2210. },
  2211. getTouchAction: function() {
  2212. return PanRecognizer.prototype.getTouchAction.call(this);
  2213. },
  2214. attrTest: function(input) {
  2215. var direction = this.options.direction;
  2216. var velocity;
  2217. if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {
  2218. velocity = input.velocity;
  2219. } else if (direction & DIRECTION_HORIZONTAL) {
  2220. velocity = input.velocityX;
  2221. } else if (direction & DIRECTION_VERTICAL) {
  2222. velocity = input.velocityY;
  2223. }
  2224. return this._super.attrTest.call(this, input) &&
  2225. direction & input.direction &&
  2226. input.distance > this.options.threshold &&
  2227. abs(velocity) > this.options.velocity && input.eventType & INPUT_END;
  2228. },
  2229. emit: function(input) {
  2230. var direction = directionStr(input.direction);
  2231. if (direction) {
  2232. this.manager.emit(this.options.event + direction, input);
  2233. }
  2234. this.manager.emit(this.options.event, input);
  2235. }
  2236. });
  2237. /**
  2238. * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur
  2239. * between the given interval and position. The delay option can be used to recognize multi-taps without firing
  2240. * a single tap.
  2241. *
  2242. * The eventData from the emitted event contains the property `tapCount`, which contains the amount of
  2243. * multi-taps being recognized.
  2244. * @constructor
  2245. * @extends Recognizer
  2246. */
  2247. function TapRecognizer() {
  2248. Recognizer.apply(this, arguments);
  2249. // previous time and center,
  2250. // used for tap counting
  2251. this.pTime = false;
  2252. this.pCenter = false;
  2253. this._timer = null;
  2254. this._input = null;
  2255. this.count = 0;
  2256. }
  2257. inherit(TapRecognizer, Recognizer, {
  2258. /**
  2259. * @namespace
  2260. * @memberof PinchRecognizer
  2261. */
  2262. defaults: {
  2263. event: 'tap',
  2264. pointers: 1,
  2265. taps: 1,
  2266. interval: 300, // max time between the multi-tap taps
  2267. time: 250, // max time of the pointer to be down (like finger on the screen)
  2268. threshold: 2, // a minimal movement is ok, but keep it low
  2269. posThreshold: 10 // a multi-tap can be a bit off the initial position
  2270. },
  2271. getTouchAction: function() {
  2272. return [TOUCH_ACTION_MANIPULATION];
  2273. },
  2274. process: function(input) {
  2275. var options = this.options;
  2276. var validPointers = input.pointers.length === options.pointers;
  2277. var validMovement = input.distance < options.threshold;
  2278. var validTouchTime = input.deltaTime < options.time;
  2279. this.reset();
  2280. if ((input.eventType & INPUT_START) && (this.count === 0)) {
  2281. return this.failTimeout();
  2282. }
  2283. // we only allow little movement
  2284. // and we've reached an end event, so a tap is possible
  2285. if (validMovement && validTouchTime && validPointers) {
  2286. if (input.eventType != INPUT_END) {
  2287. return this.failTimeout();
  2288. }
  2289. var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true;
  2290. var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;
  2291. this.pTime = input.timeStamp;
  2292. this.pCenter = input.center;
  2293. if (!validMultiTap || !validInterval) {
  2294. this.count = 1;
  2295. } else {
  2296. this.count += 1;
  2297. }
  2298. this._input = input;
  2299. // if tap count matches we have recognized it,
  2300. // else it has began recognizing...
  2301. var tapCount = this.count % options.taps;
  2302. if (tapCount === 0) {
  2303. // no failing requirements, immediately trigger the tap event
  2304. // or wait as long as the multitap interval to trigger
  2305. if (!this.hasRequireFailures()) {
  2306. return STATE_RECOGNIZED;
  2307. } else {
  2308. this._timer = setTimeoutContext(function() {
  2309. this.state = STATE_RECOGNIZED;
  2310. this.tryEmit();
  2311. }, options.interval, this);
  2312. return STATE_BEGAN;
  2313. }
  2314. }
  2315. }
  2316. return STATE_FAILED;
  2317. },
  2318. failTimeout: function() {
  2319. this._timer = setTimeoutContext(function() {
  2320. this.state = STATE_FAILED;
  2321. }, this.options.interval, this);
  2322. return STATE_FAILED;
  2323. },
  2324. reset: function() {
  2325. clearTimeout(this._timer);
  2326. },
  2327. emit: function() {
  2328. if (this.state == STATE_RECOGNIZED) {
  2329. this._input.tapCount = this.count;
  2330. this.manager.emit(this.options.event, this._input);
  2331. }
  2332. }
  2333. });
  2334. /**
  2335. * Simple way to create an manager with a default set of recognizers.
  2336. * @param {HTMLElement} element
  2337. * @param {Object} [options]
  2338. * @constructor
  2339. */
  2340. function Hammer(element, options) {
  2341. options = options || {};
  2342. options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);
  2343. return new Manager(element, options);
  2344. }
  2345. /**
  2346. * @const {string}
  2347. */
  2348. Hammer.VERSION = '2.0.4';
  2349. /**
  2350. * default settings
  2351. * @namespace
  2352. */
  2353. Hammer.defaults = {
  2354. /**
  2355. * set if DOM events are being triggered.
  2356. * But this is slower and unused by simple implementations, so disabled by default.
  2357. * @type {Boolean}
  2358. * @default false
  2359. */
  2360. domEvents: false,
  2361. /**
  2362. * The value for the touchAction property/fallback.
  2363. * When set to `compute` it will magically set the correct value based on the added recognizers.
  2364. * @type {String}
  2365. * @default compute
  2366. */
  2367. touchAction: TOUCH_ACTION_COMPUTE,
  2368. /**
  2369. * @type {Boolean}
  2370. * @default true
  2371. */
  2372. enable: true,
  2373. /**
  2374. * EXPERIMENTAL FEATURE -- can be removed/changed
  2375. * Change the parent input target element.
  2376. * If Null, then it is being set the to main element.
  2377. * @type {Null|EventTarget}
  2378. * @default null
  2379. */
  2380. inputTarget: null,
  2381. /**
  2382. * force an input class
  2383. * @type {Null|Function}
  2384. * @default null
  2385. */
  2386. inputClass: null,
  2387. /**
  2388. * Default recognizer setup when calling `Hammer()`
  2389. * When creating a new Manager these will be skipped.
  2390. * @type {Array}
  2391. */
  2392. preset: [
  2393. // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]
  2394. [RotateRecognizer, {enable: false}],
  2395. [PinchRecognizer, {enable: false}, ['rotate']],
  2396. [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}],
  2397. [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']],
  2398. [TapRecognizer],
  2399. [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']],
  2400. [PressRecognizer]
  2401. ],
  2402. /**
  2403. * Some CSS properties can be used to improve the working of Hammer.
  2404. * Add them to this method and they will be set when creating a new Manager.
  2405. * @namespace
  2406. */
  2407. cssProps: {
  2408. /**
  2409. * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.
  2410. * @type {String}
  2411. * @default 'none'
  2412. */
  2413. userSelect: 'none',
  2414. /**
  2415. * Disable the Windows Phone grippers when pressing an element.
  2416. * @type {String}
  2417. * @default 'none'
  2418. */
  2419. touchSelect: 'none',
  2420. /**
  2421. * Disables the default callout shown when you touch and hold a touch target.
  2422. * On iOS, when you touch and hold a touch target such as a link, Safari displays
  2423. * a callout containing information about the link. This property allows you to disable that callout.
  2424. * @type {String}
  2425. * @default 'none'
  2426. */
  2427. touchCallout: 'none',
  2428. /**
  2429. * Specifies whether zooming is enabled. Used by IE10>
  2430. * @type {String}
  2431. * @default 'none'
  2432. */
  2433. contentZooming: 'none',
  2434. /**
  2435. * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.
  2436. * @type {String}
  2437. * @default 'none'
  2438. */
  2439. userDrag: 'none',
  2440. /**
  2441. * Overrides the highlight color shown when the user taps a link or a JavaScript
  2442. * clickable element in iOS. This property obeys the alpha value, if specified.
  2443. * @type {String}
  2444. * @default 'rgba(0,0,0,0)'
  2445. */
  2446. tapHighlightColor: 'rgba(0,0,0,0)'
  2447. }
  2448. };
  2449. var STOP = 1;
  2450. var FORCED_STOP = 2;
  2451. /**
  2452. * Manager
  2453. * @param {HTMLElement} element
  2454. * @param {Object} [options]
  2455. * @constructor
  2456. */
  2457. function Manager(element, options) {
  2458. options = options || {};
  2459. this.options = merge(options, Hammer.defaults);
  2460. this.options.inputTarget = this.options.inputTarget || element;
  2461. this.handlers = {};
  2462. this.session = {};
  2463. this.recognizers = [];
  2464. this.element = element;
  2465. this.input = createInputInstance(this);
  2466. this.touchAction = new TouchAction(this, this.options.touchAction);
  2467. toggleCssProps(this, true);
  2468. each(options.recognizers, function(item) {
  2469. var recognizer = this.add(new (item[0])(item[1]));
  2470. item[2] && recognizer.recognizeWith(item[2]);
  2471. item[3] && recognizer.requireFailure(item[3]);
  2472. }, this);
  2473. }
  2474. Manager.prototype = {
  2475. /**
  2476. * set options
  2477. * @param {Object} options
  2478. * @returns {Manager}
  2479. */
  2480. set: function(options) {
  2481. extend(this.options, options);
  2482. // Options that need a little more setup
  2483. if (options.touchAction) {
  2484. this.touchAction.update();
  2485. }
  2486. if (options.inputTarget) {
  2487. // Clean up existing event listeners and reinitialize
  2488. this.input.destroy();
  2489. this.input.target = options.inputTarget;
  2490. this.input.init();
  2491. }
  2492. return this;
  2493. },
  2494. /**
  2495. * stop recognizing for this session.
  2496. * This session will be discarded, when a new [input]start event is fired.
  2497. * When forced, the recognizer cycle is stopped immediately.
  2498. * @param {Boolean} [force]
  2499. */
  2500. stop: function(force) {
  2501. this.session.stopped = force ? FORCED_STOP : STOP;
  2502. },
  2503. /**
  2504. * run the recognizers!
  2505. * called by the inputHandler function on every movement of the pointers (touches)
  2506. * it walks through all the recognizers and tries to detect the gesture that is being made
  2507. * @param {Object} inputData
  2508. */
  2509. recognize: function(inputData) {
  2510. var session = this.session;
  2511. if (session.stopped) {
  2512. return;
  2513. }
  2514. // run the touch-action polyfill
  2515. this.touchAction.preventDefaults(inputData);
  2516. var recognizer;
  2517. var recognizers = this.recognizers;
  2518. // this holds the recognizer that is being recognized.
  2519. // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED
  2520. // if no recognizer is detecting a thing, it is set to `null`
  2521. var curRecognizer = session.curRecognizer;
  2522. // reset when the last recognizer is recognized
  2523. // or when we're in a new session
  2524. if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) {
  2525. curRecognizer = session.curRecognizer = null;
  2526. }
  2527. var i = 0;
  2528. while (i < recognizers.length) {
  2529. recognizer = recognizers[i];
  2530. // find out if we are allowed try to recognize the input for this one.
  2531. // 1. allow if the session is NOT forced stopped (see the .stop() method)
  2532. // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one
  2533. // that is being recognized.
  2534. // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.
  2535. // this can be setup with the `recognizeWith()` method on the recognizer.
  2536. if (session.stopped !== FORCED_STOP && ( // 1
  2537. !curRecognizer || recognizer == curRecognizer || // 2
  2538. recognizer.canRecognizeWith(curRecognizer))) { // 3
  2539. recognizer.recognize(inputData);
  2540. } else {
  2541. recognizer.reset();
  2542. }
  2543. // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the
  2544. // current active recognizer. but only if we don't already have an active recognizer
  2545. if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {
  2546. curRecognizer = session.curRecognizer = recognizer;
  2547. }
  2548. i++;
  2549. }
  2550. },
  2551. /**
  2552. * get a recognizer by its event name.
  2553. * @param {Recognizer|String} recognizer
  2554. * @returns {Recognizer|Null}
  2555. */
  2556. get: function(recognizer) {
  2557. if (recognizer instanceof Recognizer) {
  2558. return recognizer;
  2559. }
  2560. var recognizers = this.recognizers;
  2561. for (var i = 0; i < recognizers.length; i++) {
  2562. if (recognizers[i].options.event == recognizer) {
  2563. return recognizers[i];
  2564. }
  2565. }
  2566. return null;
  2567. },
  2568. /**
  2569. * add a recognizer to the manager
  2570. * existing recognizers with the same event name will be removed
  2571. * @param {Recognizer} recognizer
  2572. * @returns {Recognizer|Manager}
  2573. */
  2574. add: function(recognizer) {
  2575. if (invokeArrayArg(recognizer, 'add', this)) {
  2576. return this;
  2577. }
  2578. // remove existing
  2579. var existing = this.get(recognizer.options.event);
  2580. if (existing) {
  2581. this.remove(existing);
  2582. }
  2583. this.recognizers.push(recognizer);
  2584. recognizer.manager = this;
  2585. this.touchAction.update();
  2586. return recognizer;
  2587. },
  2588. /**
  2589. * remove a recognizer by name or instance
  2590. * @param {Recognizer|String} recognizer
  2591. * @returns {Manager}
  2592. */
  2593. remove: function(recognizer) {
  2594. if (invokeArrayArg(recognizer, 'remove', this)) {
  2595. return this;
  2596. }
  2597. var recognizers = this.recognizers;
  2598. recognizer = this.get(recognizer);
  2599. recognizers.splice(inArray(recognizers, recognizer), 1);
  2600. this.touchAction.update();
  2601. return this;
  2602. },
  2603. /**
  2604. * bind event
  2605. * @param {String} events
  2606. * @param {Function} handler
  2607. * @returns {EventEmitter} this
  2608. */
  2609. on: function(events, handler) {
  2610. var handlers = this.handlers;
  2611. each(splitStr(events), function(event) {
  2612. handlers[event] = handlers[event] || [];
  2613. handlers[event].push(handler);
  2614. });
  2615. return this;
  2616. },
  2617. /**
  2618. * unbind event, leave emit blank to remove all handlers
  2619. * @param {String} events
  2620. * @param {Function} [handler]
  2621. * @returns {EventEmitter} this
  2622. */
  2623. off: function(events, handler) {
  2624. var handlers = this.handlers;
  2625. each(splitStr(events), function(event) {
  2626. if (!handler) {
  2627. delete handlers[event];
  2628. } else {
  2629. handlers[event].splice(inArray(handlers[event], handler), 1);
  2630. }
  2631. });
  2632. return this;
  2633. },
  2634. /**
  2635. * emit event to the listeners
  2636. * @param {String} event
  2637. * @param {Object} data
  2638. */
  2639. emit: function(event, data) {
  2640. // we also want to trigger dom events
  2641. if (this.options.domEvents) {
  2642. triggerDomEvent(event, data);
  2643. }
  2644. // no handlers, so skip it all
  2645. var handlers = this.handlers[event] && this.handlers[event].slice();
  2646. if (!handlers || !handlers.length) {
  2647. return;
  2648. }
  2649. data.type = event;
  2650. data.preventDefault = function() {
  2651. data.srcEvent.preventDefault();
  2652. };
  2653. var i = 0;
  2654. while (i < handlers.length) {
  2655. handlers[i](data);
  2656. i++;
  2657. }
  2658. },
  2659. /**
  2660. * destroy the manager and unbinds all events
  2661. * it doesn't unbind dom events, that is the user own responsibility
  2662. */
  2663. destroy: function() {
  2664. this.element && toggleCssProps(this, false);
  2665. this.handlers = {};
  2666. this.session = {};
  2667. this.input.destroy();
  2668. this.element = null;
  2669. }
  2670. };
  2671. /**
  2672. * add/remove the css properties as defined in manager.options.cssProps
  2673. * @param {Manager} manager
  2674. * @param {Boolean} add
  2675. */
  2676. function toggleCssProps(manager, add) {
  2677. var element = manager.element;
  2678. each(manager.options.cssProps, function(value, name) {
  2679. element.style[prefixed(element.style, name)] = add ? value : '';
  2680. });
  2681. }
  2682. /**
  2683. * trigger dom event
  2684. * @param {String} event
  2685. * @param {Object} data
  2686. */
  2687. function triggerDomEvent(event, data) {
  2688. var gestureEvent = document.createEvent('Event');
  2689. gestureEvent.initEvent(event, true, true);
  2690. gestureEvent.gesture = data;
  2691. data.target.dispatchEvent(gestureEvent);
  2692. }
  2693. extend(Hammer, {
  2694. INPUT_START: INPUT_START,
  2695. INPUT_MOVE: INPUT_MOVE,
  2696. INPUT_END: INPUT_END,
  2697. INPUT_CANCEL: INPUT_CANCEL,
  2698. STATE_POSSIBLE: STATE_POSSIBLE,
  2699. STATE_BEGAN: STATE_BEGAN,
  2700. STATE_CHANGED: STATE_CHANGED,
  2701. STATE_ENDED: STATE_ENDED,
  2702. STATE_RECOGNIZED: STATE_RECOGNIZED,
  2703. STATE_CANCELLED: STATE_CANCELLED,
  2704. STATE_FAILED: STATE_FAILED,
  2705. DIRECTION_NONE: DIRECTION_NONE,
  2706. DIRECTION_LEFT: DIRECTION_LEFT,
  2707. DIRECTION_RIGHT: DIRECTION_RIGHT,
  2708. DIRECTION_UP: DIRECTION_UP,
  2709. DIRECTION_DOWN: DIRECTION_DOWN,
  2710. DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL,
  2711. DIRECTION_VERTICAL: DIRECTION_VERTICAL,
  2712. DIRECTION_ALL: DIRECTION_ALL,
  2713. Manager: Manager,
  2714. Input: Input,
  2715. TouchAction: TouchAction,
  2716. TouchInput: TouchInput,
  2717. MouseInput: MouseInput,
  2718. PointerEventInput: PointerEventInput,
  2719. TouchMouseInput: TouchMouseInput,
  2720. SingleTouchInput: SingleTouchInput,
  2721. Recognizer: Recognizer,
  2722. AttrRecognizer: AttrRecognizer,
  2723. Tap: TapRecognizer,
  2724. Pan: PanRecognizer,
  2725. Swipe: SwipeRecognizer,
  2726. Pinch: PinchRecognizer,
  2727. Rotate: RotateRecognizer,
  2728. Press: PressRecognizer,
  2729. on: addEventListeners,
  2730. off: removeEventListeners,
  2731. each: each,
  2732. merge: merge,
  2733. extend: extend,
  2734. inherit: inherit,
  2735. bindFn: bindFn,
  2736. prefixed: prefixed
  2737. });
  2738. // jquery.hammer.js
  2739. // This jQuery plugin is just a small wrapper around the Hammer() class.
  2740. // It also extends the Manager.emit method by triggering jQuery events.
  2741. // $(element).hammer(options).bind("pan", myPanHandler);
  2742. // The Hammer instance is stored at $element.data("hammer").
  2743. // https://github.com/hammerjs/jquery.hammer.js
  2744. (function($, Hammer) {
  2745. function hammerify(el, options) {
  2746. var $el = $(el);
  2747. if (!$el.data('hammer')) {
  2748. $el.data('hammer', new Hammer($el[0], options));
  2749. }
  2750. }
  2751. $.fn.hammer = function(options) {
  2752. return this.each(function() {
  2753. hammerify(this, options);
  2754. });
  2755. };
  2756. // extend the emit method to also trigger jQuery events
  2757. Hammer.Manager.prototype.emit = (function(originalEmit) {
  2758. return function(type, data) {
  2759. originalEmit.call(this, type, data);
  2760. $(this.element).trigger({
  2761. type: type,
  2762. gesture: data
  2763. });
  2764. };
  2765. })(Hammer.Manager.prototype.emit);
  2766. })($, Hammer);
  2767. module.exports = UI.Hammer = Hammer;
  2768. /***/ },
  2769. /* 4 */
  2770. /***/ function(module, exports, __webpack_require__) {
  2771. 'use strict';
  2772. var UI = __webpack_require__(2);
  2773. /* jshint -W101, -W106 */
  2774. /**
  2775. * Add to Homescreen v3.2.2
  2776. * (c) 2015 Matteo Spinelli
  2777. * @license: http://cubiq.org/license
  2778. */
  2779. // Check for addEventListener browser support (prevent errors in IE<9)
  2780. var _eventListener = 'addEventListener' in window;
  2781. // Check if document is loaded, needed by autostart
  2782. var _DOMReady = false;
  2783. if (document.readyState === 'complete') {
  2784. _DOMReady = true;
  2785. } else if (_eventListener) {
  2786. window.addEventListener('load', loaded, false);
  2787. }
  2788. function loaded() {
  2789. window.removeEventListener('load', loaded, false);
  2790. _DOMReady = true;
  2791. }
  2792. // regex used to detect if app has been added to the homescreen
  2793. var _reSmartURL = /\/ath(\/)?$/;
  2794. var _reQueryString = /([\?&]ath=[^&]*$|&ath=[^&]*(&))/;
  2795. // singleton
  2796. var _instance;
  2797. function ath(options) {
  2798. _instance = _instance || new ath.Class(options);
  2799. return _instance;
  2800. }
  2801. // message in all supported languages
  2802. ath.intl = {
  2803. en_us: {
  2804. ios: 'To add this web app to the home screen: tap %icon and then <strong>Add to Home Screen</strong>.',
  2805. 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>'
  2806. },
  2807. zh_cn: {
  2808. ios: '如要把应用程式加至主屏幕,请点击%icon, 然后<strong>加至主屏幕</strong>',
  2809. 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>'
  2810. },
  2811. zh_tw: {
  2812. ios: '如要把應用程式加至主屏幕, 請點擊%icon, 然後<strong>加至主屏幕</strong>.',
  2813. 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>'
  2814. }
  2815. };
  2816. // Add 2 characters language support (Android mostly)
  2817. for (var lang in ath.intl) {
  2818. ath.intl[lang.substr(0, 2)] = ath.intl[lang];
  2819. }
  2820. // default options
  2821. ath.defaults = {
  2822. appID: 'org.cubiq.addtohome', // local storage name (no need to change)
  2823. fontSize: 15, // base font size, used to properly resize the popup based on viewport scale factor
  2824. debug: false, // override browser checks
  2825. logging: false, // log reasons for showing or not showing to js console; defaults to true when debug is true
  2826. modal: false, // prevent further actions until the message is closed
  2827. mandatory: false, // you can't proceed if you don't add the app to the homescreen
  2828. autostart: true, // show the message automatically
  2829. skipFirstVisit: false, // show only to returning visitors (ie: skip the first time you visit)
  2830. startDelay: 1, // display the message after that many seconds from page load
  2831. lifespan: 15, // life of the message in seconds
  2832. displayPace: 1440, // minutes before the message is shown again (0: display every time, default 24 hours)
  2833. maxDisplayCount: 0, // absolute maximum number of times the message will be shown to the user (0: no limit)
  2834. icon: true, // add touch icon to the message
  2835. message: '', // the message can be customized
  2836. validLocation: [], // list of pages where the message will be shown (array of regexes)
  2837. onInit: null, // executed on instance creation
  2838. onShow: null, // executed when the message is shown
  2839. onRemove: null, // executed when the message is removed
  2840. onAdd: null, // when the application is launched the first time from the homescreen (guesstimate)
  2841. onPrivate: null, // executed if user is in private mode
  2842. privateModeOverride: false, // show the message even in private mode (very rude)
  2843. detectHomescreen: false // try to detect if the site has been added to the homescreen (false | true | 'hash' | 'queryString' | 'smartURL')
  2844. };
  2845. // browser info and capability
  2846. var _ua = window.navigator.userAgent;
  2847. var _nav = window.navigator;
  2848. _extend(ath, {
  2849. hasToken: document.location.hash == '#ath' || _reSmartURL.test(document.location.href) || _reQueryString.test(document.location.search),
  2850. isRetina: window.devicePixelRatio && window.devicePixelRatio > 1,
  2851. isIDevice: (/iphone|ipod|ipad/i).test(_ua),
  2852. isMobileChrome: _ua.indexOf('Android') > -1 && (/Chrome\/[.0-9]*/).test(_ua) && _ua.indexOf("Version") == -1,
  2853. isMobileIE: _ua.indexOf('Windows Phone') > -1,
  2854. language: _nav.language && _nav.language.toLowerCase().replace('-', '_') || ''
  2855. });
  2856. // falls back to en_us if language is unsupported
  2857. ath.language = ath.language && ath.language in ath.intl ? ath.language : 'en_us';
  2858. ath.isMobileSafari = ath.isIDevice && _ua.indexOf('Safari') > -1 && _ua.indexOf('CriOS') < 0;
  2859. ath.OS = ath.isIDevice ? 'ios' : ath.isMobileChrome ? 'android' : ath.isMobileIE ? 'windows' : 'unsupported';
  2860. ath.OSVersion = _ua.match(/(OS|Android) (\d+[_\.]\d+)/);
  2861. ath.OSVersion = ath.OSVersion && ath.OSVersion[2] ? +ath.OSVersion[2].replace('_', '.') : 0;
  2862. ath.isStandalone = 'standalone' in window.navigator && window.navigator.standalone;
  2863. ath.isTablet = (ath.isMobileSafari && _ua.indexOf('iPad') > -1) || (ath.isMobileChrome && _ua.indexOf('Mobile') < 0);
  2864. ath.isCompatible = (ath.isMobileSafari && ath.OSVersion >= 6) || ath.isMobileChrome; // TODO: add winphone
  2865. var _defaultSession = {
  2866. lastDisplayTime: 0, // last time we displayed the message
  2867. returningVisitor: false, // is this the first time you visit
  2868. displayCount: 0, // number of times the message has been shown
  2869. optedout: false, // has the user opted out
  2870. added: false // has been actually added to the homescreen
  2871. };
  2872. ath.removeSession = function(appID) {
  2873. try {
  2874. if (!localStorage) {
  2875. throw new Error('localStorage is not defined');
  2876. }
  2877. localStorage.removeItem(appID || ath.defaults.appID);
  2878. } catch (e) {
  2879. // we are most likely in private mode
  2880. }
  2881. };
  2882. ath.doLog = function(logStr) {
  2883. if (this.options.logging) {
  2884. console.log(logStr);
  2885. }
  2886. };
  2887. ath.Class = function(options) {
  2888. // class methods
  2889. this.doLog = ath.doLog;
  2890. // merge default options with user config
  2891. this.options = _extend({}, ath.defaults);
  2892. _extend(this.options, options);
  2893. // override defaults that are dependent on each other
  2894. if (this.options.debug) {
  2895. this.options.logging = true;
  2896. }
  2897. // IE<9 so exit (I hate you, really)
  2898. if (!_eventListener) {
  2899. return;
  2900. }
  2901. // normalize some options
  2902. this.options.mandatory = this.options.mandatory && ( 'standalone' in window.navigator || this.options.debug );
  2903. this.options.modal = this.options.modal || this.options.mandatory;
  2904. if (this.options.mandatory) {
  2905. this.options.startDelay = -0.5; // make the popup hasty
  2906. }
  2907. this.options.detectHomescreen = this.options.detectHomescreen === true ? 'hash' : this.options.detectHomescreen;
  2908. // setup the debug environment
  2909. if (this.options.debug) {
  2910. ath.isCompatible = true;
  2911. ath.OS = typeof this.options.debug == 'string' ? this.options.debug : ath.OS == 'unsupported' ? 'android' : ath.OS;
  2912. ath.OSVersion = ath.OS == 'ios' ? '8' : '4';
  2913. }
  2914. // the element the message will be appended to
  2915. this.container = document.documentElement;
  2916. // load session
  2917. this.session = this.getItem(this.options.appID);
  2918. this.session = this.session ? JSON.parse(this.session) : undefined;
  2919. // user most likely came from a direct link containing our token, we don't need it and we remove it
  2920. if (ath.hasToken && ( !ath.isCompatible || !this.session )) {
  2921. ath.hasToken = false;
  2922. _removeToken();
  2923. }
  2924. // the device is not supported
  2925. if (!ath.isCompatible) {
  2926. this.doLog("Add to homescreen: not displaying callout because device not supported");
  2927. return;
  2928. }
  2929. this.session = this.session || _defaultSession;
  2930. // check if we can use the local storage
  2931. try {
  2932. if (!localStorage) {
  2933. throw new Error('localStorage is not defined');
  2934. }
  2935. localStorage.setItem(this.options.appID, JSON.stringify(this.session));
  2936. ath.hasLocalStorage = true;
  2937. } catch (e) {
  2938. // we are most likely in private mode
  2939. ath.hasLocalStorage = false;
  2940. if (this.options.onPrivate) {
  2941. this.options.onPrivate.call(this);
  2942. }
  2943. }
  2944. // check if this is a valid location
  2945. var isValidLocation = !this.options.validLocation.length;
  2946. for (var i = this.options.validLocation.length; i--;) {
  2947. if (this.options.validLocation[i].test(document.location.href)) {
  2948. isValidLocation = true;
  2949. break;
  2950. }
  2951. }
  2952. // check compatibility with old versions of add to homescreen. Opt-out if an old session is found
  2953. if (this.getItem('addToHome')) {
  2954. this.optOut();
  2955. }
  2956. // critical errors:
  2957. if (this.session.optedout) {
  2958. this.doLog("Add to homescreen: not displaying callout because user opted out");
  2959. return;
  2960. }
  2961. if (this.session.added) {
  2962. this.doLog("Add to homescreen: not displaying callout because already added to the homescreen");
  2963. return;
  2964. }
  2965. if (!isValidLocation) {
  2966. this.doLog("Add to homescreen: not displaying callout because not a valid location");
  2967. return;
  2968. }
  2969. // check if the app is in stand alone mode
  2970. if (ath.isStandalone) {
  2971. // execute the onAdd event if we haven't already
  2972. if (!this.session.added) {
  2973. this.session.added = true;
  2974. this.updateSession();
  2975. if (this.options.onAdd && ath.hasLocalStorage) { // double check on localstorage to avoid multiple calls to the custom event
  2976. this.options.onAdd.call(this);
  2977. }
  2978. }
  2979. this.doLog("Add to homescreen: not displaying callout because in standalone mode");
  2980. return;
  2981. }
  2982. // (try to) check if the page has been added to the homescreen
  2983. if (this.options.detectHomescreen) {
  2984. // the URL has the token, we are likely coming from the homescreen
  2985. if (ath.hasToken) {
  2986. _removeToken(); // we don't actually need the token anymore, we remove it to prevent redistribution
  2987. // this is called the first time the user opens the app from the homescreen
  2988. if (!this.session.added) {
  2989. this.session.added = true;
  2990. this.updateSession();
  2991. if (this.options.onAdd && ath.hasLocalStorage) { // double check on localstorage to avoid multiple calls to the custom event
  2992. this.options.onAdd.call(this);
  2993. }
  2994. }
  2995. this.doLog("Add to homescreen: not displaying callout because URL has token, so we are likely coming from homescreen");
  2996. return;
  2997. }
  2998. // URL doesn't have the token, so add it
  2999. if (this.options.detectHomescreen == 'hash') {
  3000. history.replaceState('', window.document.title, document.location.href + '#ath');
  3001. } else if (this.options.detectHomescreen == 'smartURL') {
  3002. history.replaceState('', window.document.title, document.location.href.replace(/(\/)?$/, '/ath$1'));
  3003. } else {
  3004. history.replaceState('', window.document.title, document.location.href + (document.location.search ? '&' : '?' ) + 'ath=');
  3005. }
  3006. }
  3007. // check if this is a returning visitor
  3008. if (!this.session.returningVisitor) {
  3009. this.session.returningVisitor = true;
  3010. this.updateSession();
  3011. // we do not show the message if this is your first visit
  3012. if (this.options.skipFirstVisit) {
  3013. this.doLog("Add to homescreen: not displaying callout because skipping first visit");
  3014. return;
  3015. }
  3016. }
  3017. // we do no show the message in private mode
  3018. if (!this.options.privateModeOverride && !ath.hasLocalStorage) {
  3019. this.doLog("Add to homescreen: not displaying callout because browser is in private mode");
  3020. return;
  3021. }
  3022. // all checks passed, ready to display
  3023. this.ready = true;
  3024. if (this.options.onInit) {
  3025. this.options.onInit.call(this);
  3026. }
  3027. if (this.options.autostart) {
  3028. this.doLog("Add to homescreen: autostart displaying callout");
  3029. this.show();
  3030. }
  3031. };
  3032. ath.Class.prototype = {
  3033. // event type to method conversion
  3034. events: {
  3035. load: '_delayedShow',
  3036. error: '_delayedShow',
  3037. orientationchange: 'resize',
  3038. resize: 'resize',
  3039. scroll: 'resize',
  3040. click: 'remove',
  3041. touchmove: '_preventDefault',
  3042. transitionend: '_removeElements',
  3043. webkitTransitionEnd: '_removeElements',
  3044. MSTransitionEnd: '_removeElements'
  3045. },
  3046. handleEvent: function(e) {
  3047. var type = this.events[e.type];
  3048. if (type) {
  3049. this[type](e);
  3050. }
  3051. },
  3052. show: function(force) {
  3053. // in autostart mode wait for the document to be ready
  3054. if (this.options.autostart && !_DOMReady) {
  3055. setTimeout(this.show.bind(this), 50);
  3056. // we are not displaying callout because DOM not ready, but don't log that because
  3057. // it would log too frequently
  3058. return;
  3059. }
  3060. // message already on screen
  3061. if (this.shown) {
  3062. this.doLog("Add to homescreen: not displaying callout because already shown on screen");
  3063. return;
  3064. }
  3065. var now = Date.now();
  3066. var lastDisplayTime = this.session.lastDisplayTime;
  3067. if (force !== true) {
  3068. // this is needed if autostart is disabled and you programmatically call the show() method
  3069. if (!this.ready) {
  3070. this.doLog("Add to homescreen: not displaying callout because not ready");
  3071. return;
  3072. }
  3073. // we obey the display pace (prevent the message to popup too often)
  3074. if (now - lastDisplayTime < this.options.displayPace * 60000) {
  3075. this.doLog("Add to homescreen: not displaying callout because displayed recently");
  3076. return;
  3077. }
  3078. // obey the maximum number of display count
  3079. if (this.options.maxDisplayCount && this.session.displayCount >= this.options.maxDisplayCount) {
  3080. this.doLog("Add to homescreen: not displaying callout because displayed too many times already");
  3081. return;
  3082. }
  3083. }
  3084. this.shown = true;
  3085. // increment the display count
  3086. this.session.lastDisplayTime = now;
  3087. this.session.displayCount++;
  3088. this.updateSession();
  3089. // try to get the highest resolution application icon
  3090. if (!this.applicationIcon) {
  3091. if (ath.OS == 'ios') {
  3092. 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]');
  3093. } else {
  3094. this.applicationIcon = document.querySelector('head link[rel^="shortcut icon"][sizes="196x196"],head link[rel^=apple-touch-icon]');
  3095. }
  3096. }
  3097. var message = '';
  3098. if (typeof this.options.message == 'object' && ath.language in this.options.message) { // use custom language message
  3099. message = this.options.message[ath.language][ath.OS];
  3100. } else if (typeof this.options.message == 'object' && ath.OS in this.options.message) { // use custom os message
  3101. message = this.options.message[ath.OS];
  3102. } else if (this.options.message in ath.intl) { // you can force the locale
  3103. message = ath.intl[this.options.message][ath.OS];
  3104. } else if (this.options.message !== '') { // use a custom message
  3105. message = this.options.message;
  3106. } else if (ath.OS in ath.intl[ath.language]) { // otherwise we use our message
  3107. message = ath.intl[ath.language][ath.OS];
  3108. }
  3109. // add the action icon
  3110. message = '<p>' + message.replace('%icon', '<span class="ath-action-icon">icon</span>') + '</p>';
  3111. // create the message container
  3112. this.viewport = document.createElement('div');
  3113. this.viewport.className = 'ath-viewport';
  3114. if (this.options.modal) {
  3115. this.viewport.className += ' ath-modal';
  3116. }
  3117. if (this.options.mandatory) {
  3118. this.viewport.className += ' ath-mandatory';
  3119. }
  3120. this.viewport.style.position = 'absolute';
  3121. // create the actual message element
  3122. this.element = document.createElement('div');
  3123. this.element.className = 'ath-container ath-' + ath.OS + ' ath-' + ath.OS + (ath.OSVersion + '').substr(0, 1) + ' ath-' + (ath.isTablet ? 'tablet' : 'phone');
  3124. 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;';
  3125. this.element.style.webkitTransform = 'translate3d(0,-' + window.innerHeight + 'px,0)';
  3126. this.element.style.transform = 'translate3d(0,-' + window.innerHeight + 'px,0)';
  3127. // add the application icon
  3128. if (this.options.icon && this.applicationIcon) {
  3129. this.element.className += ' ath-icon';
  3130. this.img = document.createElement('img');
  3131. this.img.className = 'ath-application-icon';
  3132. this.img.addEventListener('load', this, false);
  3133. this.img.addEventListener('error', this, false);
  3134. this.img.src = this.applicationIcon.href;
  3135. this.element.appendChild(this.img);
  3136. }
  3137. this.element.innerHTML += message;
  3138. // we are not ready to show, place the message out of sight
  3139. this.viewport.style.left = '-99999em';
  3140. // attach all elements to the DOM
  3141. this.viewport.appendChild(this.element);
  3142. this.container.appendChild(this.viewport);
  3143. // if we don't have to wait for an image to load, show the message right away
  3144. if (this.img) {
  3145. this.doLog("Add to homescreen: not displaying callout because waiting for img to load");
  3146. } else {
  3147. this._delayedShow();
  3148. }
  3149. },
  3150. _delayedShow: function(e) {
  3151. setTimeout(this._show.bind(this), this.options.startDelay * 1000 + 500);
  3152. },
  3153. _show: function() {
  3154. var that = this;
  3155. // update the viewport size and orientation
  3156. this.updateViewport();
  3157. // reposition/resize the message on orientation change
  3158. window.addEventListener('resize', this, false);
  3159. window.addEventListener('scroll', this, false);
  3160. window.addEventListener('orientationchange', this, false);
  3161. if (this.options.modal) {
  3162. // lock any other interaction
  3163. document.addEventListener('touchmove', this, true);
  3164. }
  3165. // Enable closing after 1 second
  3166. if (!this.options.mandatory) {
  3167. setTimeout(function() {
  3168. that.element.addEventListener('click', that, true);
  3169. }, 1000);
  3170. }
  3171. // kick the animation
  3172. setTimeout(function() {
  3173. that.element.style.webkitTransitionDuration = '1.2s';
  3174. that.element.style.transitionDuration = '1.2s';
  3175. that.element.style.webkitTransform = 'translate3d(0,0,0)';
  3176. that.element.style.transform = 'translate3d(0,0,0)';
  3177. }, 0);
  3178. // set the destroy timer
  3179. if (this.options.lifespan) {
  3180. this.removeTimer = setTimeout(this.remove.bind(this), this.options.lifespan * 1000);
  3181. }
  3182. // fire the custom onShow event
  3183. if (this.options.onShow) {
  3184. this.options.onShow.call(this);
  3185. }
  3186. },
  3187. remove: function() {
  3188. clearTimeout(this.removeTimer);
  3189. // clear up the event listeners
  3190. if (this.img) {
  3191. this.img.removeEventListener('load', this, false);
  3192. this.img.removeEventListener('error', this, false);
  3193. }
  3194. window.removeEventListener('resize', this, false);
  3195. window.removeEventListener('scroll', this, false);
  3196. window.removeEventListener('orientationchange', this, false);
  3197. document.removeEventListener('touchmove', this, true);
  3198. this.element.removeEventListener('click', this, true);
  3199. // remove the message element on transition end
  3200. this.element.addEventListener('transitionend', this, false);
  3201. this.element.addEventListener('webkitTransitionEnd', this, false);
  3202. this.element.addEventListener('MSTransitionEnd', this, false);
  3203. // start the fade out animation
  3204. this.element.style.webkitTransitionDuration = '0.3s';
  3205. this.element.style.opacity = '0';
  3206. },
  3207. _removeElements: function() {
  3208. this.element.removeEventListener('transitionend', this, false);
  3209. this.element.removeEventListener('webkitTransitionEnd', this, false);
  3210. this.element.removeEventListener('MSTransitionEnd', this, false);
  3211. // remove the message from the DOM
  3212. this.container.removeChild(this.viewport);
  3213. this.shown = false;
  3214. // fire the custom onRemove event
  3215. if (this.options.onRemove) {
  3216. this.options.onRemove.call(this);
  3217. }
  3218. },
  3219. updateViewport: function() {
  3220. if (!this.shown) {
  3221. return;
  3222. }
  3223. this.viewport.style.width = window.innerWidth + 'px';
  3224. this.viewport.style.height = window.innerHeight + 'px';
  3225. this.viewport.style.left = window.scrollX + 'px';
  3226. this.viewport.style.top = window.scrollY + 'px';
  3227. var clientWidth = document.documentElement.clientWidth;
  3228. this.orientation = clientWidth > document.documentElement.clientHeight ? 'landscape' : 'portrait';
  3229. var screenWidth = ath.OS == 'ios' ? this.orientation == 'portrait' ? screen.width : screen.height : screen.width;
  3230. this.scale = screen.width > clientWidth ? 1 : screenWidth / window.innerWidth;
  3231. this.element.style.fontSize = this.options.fontSize / this.scale + 'px';
  3232. },
  3233. resize: function() {
  3234. clearTimeout(this.resizeTimer);
  3235. this.resizeTimer = setTimeout(this.updateViewport.bind(this), 100);
  3236. },
  3237. updateSession: function() {
  3238. if (ath.hasLocalStorage === false) {
  3239. return;
  3240. }
  3241. if (localStorage) {
  3242. localStorage.setItem(this.options.appID, JSON.stringify(this.session));
  3243. }
  3244. },
  3245. clearSession: function() {
  3246. this.session = _defaultSession;
  3247. this.updateSession();
  3248. },
  3249. getItem: function(item) {
  3250. try {
  3251. if (!localStorage) {
  3252. throw new Error('localStorage is not defined');
  3253. }
  3254. return localStorage.getItem(item);
  3255. } catch (e) {
  3256. // Preventing exception for some browsers when fetching localStorage key
  3257. ath.hasLocalStorage = false;
  3258. }
  3259. },
  3260. optOut: function() {
  3261. this.session.optedout = true;
  3262. this.updateSession();
  3263. },
  3264. optIn: function() {
  3265. this.session.optedout = false;
  3266. this.updateSession();
  3267. },
  3268. clearDisplayCount: function() {
  3269. this.session.displayCount = 0;
  3270. this.updateSession();
  3271. },
  3272. _preventDefault: function(e) {
  3273. e.preventDefault();
  3274. e.stopPropagation();
  3275. }
  3276. };
  3277. // utility
  3278. function _extend(target, obj) {
  3279. for (var i in obj) {
  3280. target[i] = obj[i];
  3281. }
  3282. return target;
  3283. }
  3284. function _removeToken() {
  3285. if (document.location.hash == '#ath') {
  3286. history.replaceState('', window.document.title, document.location.href.split('#')[0]);
  3287. }
  3288. if (_reSmartURL.test(document.location.href)) {
  3289. history.replaceState('', window.document.title, document.location.href.replace(_reSmartURL, '$1'));
  3290. }
  3291. if (_reQueryString.test(document.location.search)) {
  3292. history.replaceState('', window.document.title, document.location.href.replace(_reQueryString, '$2'));
  3293. }
  3294. }
  3295. /* jshint +W101, +W106 */
  3296. ath.VERSION = '3.2.2';
  3297. module.exports = UI.addToHomescreen = ath;
  3298. /***/ },
  3299. /* 5 */
  3300. /***/ function(module, exports, __webpack_require__) {
  3301. 'use strict';
  3302. var $ = __webpack_require__(1);
  3303. var UI = __webpack_require__(2);
  3304. /**
  3305. * @via https://github.com/Minwe/bootstrap/blob/master/js/alert.js
  3306. * @copyright Copyright 2013 Twitter, Inc.
  3307. * @license Apache 2.0
  3308. */
  3309. // Alert Class
  3310. // NOTE: removeElement option is unavailable now
  3311. var Alert = function(element, options) {
  3312. var _this = this;
  3313. this.options = $.extend({}, Alert.DEFAULTS, options);
  3314. this.$element = $(element);
  3315. this.$element
  3316. .addClass('am-fade am-in')
  3317. .on('click.alert.amui', '.am-close', function() {
  3318. _this.close();
  3319. });
  3320. };
  3321. Alert.DEFAULTS = {
  3322. removeElement: true
  3323. };
  3324. Alert.prototype.close = function() {
  3325. var $element = this.$element;
  3326. $element.trigger('close.alert.amui').removeClass('am-in');
  3327. function processAlert() {
  3328. $element.trigger('closed.alert.amui').remove();
  3329. }
  3330. UI.support.transition && $element.hasClass('am-fade') ?
  3331. $element
  3332. .one(UI.support.transition.end, processAlert)
  3333. .emulateTransitionEnd(200) :
  3334. processAlert();
  3335. };
  3336. // plugin
  3337. UI.plugin('alert', Alert);
  3338. // Init code
  3339. $(document).on('click.alert.amui.data-api', '[data-am-alert]', function(e) {
  3340. var $target = $(e.target);
  3341. $target.is('.am-close') && $(this).alert('close');
  3342. });
  3343. module.exports = Alert;
  3344. /***/ },
  3345. /* 6 */
  3346. /***/ function(module, exports, __webpack_require__) {
  3347. 'use strict';
  3348. var $ = __webpack_require__(1);
  3349. var UI = __webpack_require__(2);
  3350. /**
  3351. * @via https://github.com/twbs/bootstrap/blob/master/js/button.js
  3352. * @copyright (c) 2011-2014 Twitter, Inc
  3353. * @license The MIT License
  3354. */
  3355. var Button = function(element, options) {
  3356. this.$element = $(element);
  3357. this.options = $.extend({}, Button.DEFAULTS, options);
  3358. this.isLoading = false;
  3359. this.hasSpinner = false;
  3360. };
  3361. Button.DEFAULTS = {
  3362. loadingText: 'loading...',
  3363. disabledClassName: 'am-disabled',
  3364. spinner: undefined
  3365. };
  3366. Button.prototype.setState = function(state, stateText) {
  3367. var $element = this.$element;
  3368. var disabled = 'disabled';
  3369. var data = $element.data();
  3370. var options = this.options;
  3371. var val = $element.is('input') ? 'val' : 'html';
  3372. var stateClassName = 'am-btn-' + state + ' ' + options.disabledClassName;
  3373. state += 'Text';
  3374. if (!options.resetText) {
  3375. options.resetText = $element[val]();
  3376. }
  3377. // add spinner for element with html()
  3378. if (UI.support.animation && options.spinner &&
  3379. val === 'html' && !this.hasSpinner) {
  3380. options.loadingText = '<span class="am-icon-' + options.spinner +
  3381. ' am-icon-spin"></span>' + options.loadingText;
  3382. this.hasSpinner = true;
  3383. }
  3384. stateText = stateText ||
  3385. (data[state] === undefined ? options[state] : data[state]);
  3386. $element[val](stateText);
  3387. // push to event loop to allow forms to submit
  3388. setTimeout($.proxy(function() {
  3389. // TODO: add stateClass for other states
  3390. if (state === 'loadingText') {
  3391. $element.addClass(stateClassName).attr(disabled, disabled);
  3392. this.isLoading = true;
  3393. } else if (this.isLoading) {
  3394. $element.removeClass(stateClassName).removeAttr(disabled);
  3395. this.isLoading = false;
  3396. }
  3397. }, this), 0);
  3398. };
  3399. Button.prototype.toggle = function() {
  3400. var changed = true;
  3401. var $element = this.$element;
  3402. var $parent = this.$element.parent('[class*="am-btn-group"]');
  3403. if ($parent.length) {
  3404. var $input = this.$element.find('input');
  3405. if ($input.prop('type') == 'radio') {
  3406. if ($input.prop('checked') && $element.hasClass('am-active')) {
  3407. changed = false;
  3408. } else {
  3409. $parent.find('.am-active').removeClass('am-active');
  3410. }
  3411. }
  3412. if (changed) {
  3413. $input.prop('checked',
  3414. !$element.hasClass('am-active')).trigger('change');
  3415. }
  3416. }
  3417. if (changed) {
  3418. $element.toggleClass('am-active');
  3419. if (!$element.hasClass('am-active')) {
  3420. $element.blur();
  3421. }
  3422. }
  3423. };
  3424. UI.plugin('button', Button, {
  3425. dataOptions: 'data-am-loading',
  3426. methodCall: function(args, instance) {
  3427. if (args[0] === 'toggle') {
  3428. instance.toggle();
  3429. } else if (typeof args[0] === 'string') {
  3430. instance.setState.apply(instance, args);
  3431. }
  3432. }
  3433. });
  3434. // Init code
  3435. $(document).on('click.button.amui.data-api', '[data-am-button]', function(e) {
  3436. e.preventDefault();
  3437. var $btn = $(e.target);
  3438. if (!$btn.hasClass('am-btn')) {
  3439. $btn = $btn.closest('.am-btn');
  3440. }
  3441. $btn.button('toggle');
  3442. });
  3443. UI.ready(function(context) {
  3444. $('[data-am-loading]', context).button();
  3445. });
  3446. module.exports = UI.button = Button;
  3447. /***/ },
  3448. /* 7 */
  3449. /***/ function(module, exports, __webpack_require__) {
  3450. 'use strict';
  3451. var $ = __webpack_require__(1);
  3452. var UI = __webpack_require__(2);
  3453. /**
  3454. * @via https://github.com/twbs/bootstrap/blob/master/js/collapse.js
  3455. * @copyright (c) 2011-2014 Twitter, Inc
  3456. * @license The MIT License
  3457. */
  3458. var Collapse = function(element, options) {
  3459. this.$element = $(element);
  3460. this.options = $.extend({}, Collapse.DEFAULTS, options);
  3461. this.transitioning = null;
  3462. if (this.options.parent) {
  3463. this.$parent = $(this.options.parent);
  3464. }
  3465. if (this.options.toggle) {
  3466. this.toggle();
  3467. }
  3468. };
  3469. Collapse.DEFAULTS = {
  3470. toggle: true
  3471. };
  3472. Collapse.prototype.open = function() {
  3473. if (this.transitioning || this.$element.hasClass('am-in')) {
  3474. return;
  3475. }
  3476. var startEvent = $.Event('open.collapse.amui');
  3477. this.$element.trigger(startEvent);
  3478. if (startEvent.isDefaultPrevented()) {
  3479. return;
  3480. }
  3481. var actives = this.$parent && this.$parent.find('> .am-panel > .am-in');
  3482. if (actives && actives.length) {
  3483. var hasData = actives.data('amui.collapse');
  3484. if (hasData && hasData.transitioning) {
  3485. return;
  3486. }
  3487. Plugin.call(actives, 'close');
  3488. hasData || actives.data('amui.collapse', null);
  3489. }
  3490. this.$element
  3491. .removeClass('am-collapse')
  3492. .addClass('am-collapsing').height(0);
  3493. this.transitioning = 1;
  3494. var complete = function() {
  3495. this.$element
  3496. .removeClass('am-collapsing')
  3497. .addClass('am-collapse am-in')
  3498. .height('')
  3499. .trigger('opened.collapse.amui');
  3500. this.transitioning = 0;
  3501. };
  3502. if (!UI.support.transition) {
  3503. return complete.call(this);
  3504. }
  3505. var scrollHeight = this.$element[0].scrollHeight;
  3506. this.$element
  3507. .one(UI.support.transition.end, $.proxy(complete, this))
  3508. .emulateTransitionEnd(300)
  3509. .css({height: scrollHeight}); // 当折叠的容器有 padding 时,如果用 height() 只能设置内容的宽度
  3510. };
  3511. Collapse.prototype.close = function() {
  3512. if (this.transitioning || !this.$element.hasClass('am-in')) {
  3513. return;
  3514. }
  3515. var startEvent = $.Event('close.collapse.amui');
  3516. this.$element.trigger(startEvent);
  3517. if (startEvent.isDefaultPrevented()) {
  3518. return;
  3519. }
  3520. this.$element.height(this.$element.height()).redraw();
  3521. this.$element.addClass('am-collapsing').
  3522. removeClass('am-collapse am-in');
  3523. this.transitioning = 1;
  3524. var complete = function() {
  3525. this.transitioning = 0;
  3526. this.$element
  3527. .trigger('closed.collapse.amui')
  3528. .removeClass('am-collapsing')
  3529. .addClass('am-collapse');
  3530. // css({height: '0'});
  3531. };
  3532. if (!UI.support.transition) {
  3533. return complete.call(this);
  3534. }
  3535. this.$element.height(0)
  3536. .one(UI.support.transition.end, $.proxy(complete, this))
  3537. .emulateTransitionEnd(300);
  3538. };
  3539. Collapse.prototype.toggle = function() {
  3540. this[this.$element.hasClass('am-in') ? 'close' : 'open']();
  3541. };
  3542. // Collapse Plugin
  3543. function Plugin(option) {
  3544. return this.each(function() {
  3545. var $this = $(this);
  3546. var data = $this.data('amui.collapse');
  3547. var options = $.extend({}, Collapse.DEFAULTS,
  3548. UI.utils.options($this.attr('data-am-collapse')),
  3549. typeof option == 'object' && option);
  3550. if (!data && options.toggle && option === 'open') {
  3551. option = !option;
  3552. }
  3553. if (!data) {
  3554. $this.data('amui.collapse', (data = new Collapse(this, options)));
  3555. }
  3556. if (typeof option == 'string') {
  3557. data[option]();
  3558. }
  3559. });
  3560. }
  3561. $.fn.collapse = Plugin;
  3562. // Init code
  3563. $(document).on('click.collapse.amui.data-api', '[data-am-collapse]',
  3564. function(e) {
  3565. var href;
  3566. var $this = $(this);
  3567. var options = UI.utils.options($this.attr('data-am-collapse'));
  3568. var target = options.target ||
  3569. e.preventDefault() ||
  3570. (href = $this.attr('href')) &&
  3571. href.replace(/.*(?=#[^\s]+$)/, '');
  3572. var $target = $(target);
  3573. var data = $target.data('amui.collapse');
  3574. var option = data ? 'toggle' : options;
  3575. var parent = options.parent;
  3576. var $parent = parent && $(parent);
  3577. if (!data || !data.transitioning) {
  3578. if ($parent) {
  3579. // '[data-am-collapse*="{parent: \'' + parent + '"]
  3580. $parent.find('[data-am-collapse]').not($this).addClass('am-collapsed');
  3581. }
  3582. $this[$target.hasClass('am-in') ?
  3583. 'addClass' : 'removeClass']('am-collapsed');
  3584. }
  3585. Plugin.call($target, option);
  3586. });
  3587. module.exports = UI.collapse = Collapse;
  3588. // TODO: 更好的 target 选择方式
  3589. // 折叠的容器必须没有 border/padding 才能正常处理,否则动画会有一些小问题
  3590. // 寻找更好的未知高度 transition 动画解决方案,max-height 之类的就算了
  3591. /***/ },
  3592. /* 8 */
  3593. /***/ function(module, exports, __webpack_require__) {
  3594. 'use strict';
  3595. var $ = __webpack_require__(1);
  3596. var UI = __webpack_require__(2);
  3597. var $doc = $(document);
  3598. /**
  3599. * bootstrap-datepicker.js
  3600. * @via http://www.eyecon.ro/bootstrap-datepicker
  3601. * @license http://www.apache.org/licenses/LICENSE-2.0
  3602. */
  3603. var Datepicker = function(element, options) {
  3604. this.$element = $(element);
  3605. this.options = $.extend({}, Datepicker.DEFAULTS, options);
  3606. this.format = DPGlobal.parseFormat(this.options.format);
  3607. this.$element.data('date', this.options.date);
  3608. this.language = this.getLocale(this.options.locale);
  3609. this.theme = this.options.theme;
  3610. this.$picker = $(DPGlobal.template).appendTo('body').on({
  3611. click: $.proxy(this.click, this)
  3612. // mousedown: $.proxy(this.mousedown, this)
  3613. });
  3614. this.isInput = this.$element.is('input');
  3615. this.component = this.$element.is('.am-datepicker-date') ?
  3616. this.$element.find('.am-datepicker-add-on') : false;
  3617. if (this.isInput) {
  3618. this.$element.on({
  3619. 'click.datepicker.amui': $.proxy(this.open, this),
  3620. // blur: $.proxy(this.close, this),
  3621. 'keyup.datepicker.amui': $.proxy(this.update, this)
  3622. });
  3623. } else {
  3624. if (this.component) {
  3625. this.component.on('click.datepicker.amui', $.proxy(this.open, this));
  3626. } else {
  3627. this.$element.on('click.datepicker.amui', $.proxy(this.open, this));
  3628. }
  3629. }
  3630. this.minViewMode = this.options.minViewMode;
  3631. if (typeof this.minViewMode === 'string') {
  3632. switch (this.minViewMode) {
  3633. case 'months':
  3634. this.minViewMode = 1;
  3635. break;
  3636. case 'years':
  3637. this.minViewMode = 2;
  3638. break;
  3639. default:
  3640. this.minViewMode = 0;
  3641. break;
  3642. }
  3643. }
  3644. this.viewMode = this.options.viewMode;
  3645. if (typeof this.viewMode === 'string') {
  3646. switch (this.viewMode) {
  3647. case 'months':
  3648. this.viewMode = 1;
  3649. break;
  3650. case 'years':
  3651. this.viewMode = 2;
  3652. break;
  3653. default:
  3654. this.viewMode = 0;
  3655. break;
  3656. }
  3657. }
  3658. this.startViewMode = this.viewMode;
  3659. this.weekStart = ((this.options.weekStart ||
  3660. Datepicker.locales[this.language].weekStart || 0) % 7);
  3661. this.weekEnd = ((this.weekStart + 6) % 7);
  3662. this.onRender = this.options.onRender;
  3663. this.setTheme();
  3664. this.fillDow();
  3665. this.fillMonths();
  3666. this.update();
  3667. this.showMode();
  3668. };
  3669. Datepicker.DEFAULTS = {
  3670. locale: 'zh_CN',
  3671. format: 'yyyy-mm-dd',
  3672. weekStart: undefined,
  3673. viewMode: 0,
  3674. minViewMode: 0,
  3675. date: '',
  3676. theme: '',
  3677. autoClose: 1,
  3678. onRender: function(date) {
  3679. return '';
  3680. }
  3681. };
  3682. Datepicker.prototype.open = function(e) {
  3683. this.$picker.show();
  3684. this.height = this.component ?
  3685. this.component.outerHeight() : this.$element.outerHeight();
  3686. this.place();
  3687. $(window).on('resize.datepicker.amui', $.proxy(this.place, this));
  3688. if (e) {
  3689. e.stopPropagation();
  3690. e.preventDefault();
  3691. }
  3692. var that = this;
  3693. $doc.on('mousedown.datapicker.amui touchstart.datepicker.amui', function(ev) {
  3694. if ($(ev.target).closest('.am-datepicker').length === 0) {
  3695. that.close();
  3696. }
  3697. });
  3698. this.$element.trigger({
  3699. type: 'open.datepicker.amui',
  3700. date: this.date
  3701. });
  3702. };
  3703. Datepicker.prototype.close = function() {
  3704. this.$picker.hide();
  3705. $(window).off('resize.datepicker.amui', this.place);
  3706. this.viewMode = this.startViewMode;
  3707. this.showMode();
  3708. if (!this.isInput) {
  3709. $(document).off('mousedown.datapicker.amui touchstart.datepicker.amui',
  3710. this.close);
  3711. }
  3712. // this.set();
  3713. this.$element.trigger({
  3714. type: 'close.datepicker.amui',
  3715. date: this.date
  3716. });
  3717. };
  3718. Datepicker.prototype.set = function() {
  3719. var formatted = DPGlobal.formatDate(this.date, this.format);
  3720. var $input;
  3721. if (!this.isInput) {
  3722. if (this.component) {
  3723. $input = this.$element.find('input').attr('value', formatted);
  3724. }
  3725. this.$element.data('date', formatted);
  3726. } else {
  3727. $input = this.$element.attr('value', formatted);
  3728. }
  3729. // fixes https://github.com/amazeui/amazeui/issues/711
  3730. $input && $input.trigger('change');
  3731. };
  3732. Datepicker.prototype.setValue = function(newDate) {
  3733. if (typeof newDate === 'string') {
  3734. this.date = DPGlobal.parseDate(newDate, this.format);
  3735. } else {
  3736. this.date = new Date(newDate);
  3737. }
  3738. this.set();
  3739. this.viewDate = new Date(this.date.getFullYear(),
  3740. this.date.getMonth(), 1, 0, 0, 0, 0);
  3741. this.fill();
  3742. };
  3743. Datepicker.prototype.place = function() {
  3744. var offset = this.component ?
  3745. this.component.offset() : this.$element.offset();
  3746. var $width = this.component ?
  3747. this.component.width() : this.$element.width();
  3748. var top = offset.top + this.height;
  3749. var left = offset.left;
  3750. var right = $doc.width() - offset.left - $width;
  3751. var isOutView = this.isOutView();
  3752. this.$picker.removeClass('am-datepicker-right');
  3753. this.$picker.removeClass('am-datepicker-up');
  3754. if ($doc.width() > 640) {
  3755. if (isOutView.outRight) {
  3756. this.$picker.addClass('am-datepicker-right');
  3757. this.$picker.css({
  3758. top: top,
  3759. left: 'auto',
  3760. right: right
  3761. });
  3762. return;
  3763. }
  3764. if (isOutView.outBottom) {
  3765. this.$picker.addClass('am-datepicker-up');
  3766. top = offset.top - this.$picker.outerHeight(true);
  3767. }
  3768. } else {
  3769. left = 0;
  3770. }
  3771. this.$picker.css({
  3772. top: top,
  3773. left: left
  3774. });
  3775. };
  3776. Datepicker.prototype.update = function(newDate) {
  3777. this.date = DPGlobal.parseDate(
  3778. typeof newDate === 'string' ? newDate : (this.isInput ?
  3779. this.$element.prop('value') : this.$element.data('date')),
  3780. this.format
  3781. );
  3782. this.viewDate = new Date(this.date.getFullYear(),
  3783. this.date.getMonth(), 1, 0, 0, 0, 0);
  3784. this.fill();
  3785. };
  3786. // Days of week
  3787. Datepicker.prototype.fillDow = function() {
  3788. var dowCount = this.weekStart;
  3789. var html = '<tr>';
  3790. while (dowCount < this.weekStart + 7) {
  3791. // NOTE: do % then add 1
  3792. html += '<th class="am-datepicker-dow">' +
  3793. Datepicker.locales[this.language].daysMin[(dowCount++) % 7] +
  3794. '</th>';
  3795. }
  3796. html += '</tr>';
  3797. this.$picker.find('.am-datepicker-days thead').append(html);
  3798. };
  3799. Datepicker.prototype.fillMonths = function() {
  3800. var html = '';
  3801. var i = 0;
  3802. while (i < 12) {
  3803. html += '<span class="am-datepicker-month">' +
  3804. Datepicker.locales[this.language].monthsShort[i++] + '</span>';
  3805. }
  3806. this.$picker.find('.am-datepicker-months td').append(html);
  3807. };
  3808. Datepicker.prototype.fill = function() {
  3809. var d = new Date(this.viewDate);
  3810. var year = d.getFullYear();
  3811. var month = d.getMonth();
  3812. var currentDate = this.date.valueOf();
  3813. var prevMonth = new Date(year, month - 1, 28, 0, 0, 0, 0);
  3814. var day = DPGlobal
  3815. .getDaysInMonth(prevMonth.getFullYear(), prevMonth.getMonth());
  3816. var daysSelect = this.$picker
  3817. .find('.am-datepicker-days .am-datepicker-select');
  3818. if (this.language === 'zh_CN') {
  3819. daysSelect.text(year + Datepicker.locales[this.language].year[0] +
  3820. ' ' + Datepicker.locales[this.language].months[month]);
  3821. } else {
  3822. daysSelect.text(Datepicker.locales[this.language].months[month] +
  3823. ' ' + year);
  3824. }
  3825. prevMonth.setDate(day);
  3826. prevMonth.setDate(day - (prevMonth.getDay() - this.weekStart + 7) % 7);
  3827. var nextMonth = new Date(prevMonth);
  3828. nextMonth.setDate(nextMonth.getDate() + 42);
  3829. nextMonth = nextMonth.valueOf();
  3830. var html = [];
  3831. var className;
  3832. var prevY;
  3833. var prevM;
  3834. while (prevMonth.valueOf() < nextMonth) {
  3835. if (prevMonth.getDay() === this.weekStart) {
  3836. html.push('<tr>');
  3837. }
  3838. className = this.onRender(prevMonth, 0);
  3839. prevY = prevMonth.getFullYear();
  3840. prevM = prevMonth.getMonth();
  3841. if ((prevM < month && prevY === year) || prevY < year) {
  3842. className += ' am-datepicker-old';
  3843. } else if ((prevM > month && prevY === year) || prevY > year) {
  3844. className += ' am-datepicker-new';
  3845. }
  3846. if (prevMonth.valueOf() === currentDate) {
  3847. className += ' am-active';
  3848. }
  3849. html.push('<td class="am-datepicker-day ' +
  3850. className + '">' + prevMonth.getDate() + '</td>');
  3851. if (prevMonth.getDay() === this.weekEnd) {
  3852. html.push('</tr>');
  3853. }
  3854. prevMonth.setDate(prevMonth.getDate() + 1);
  3855. }
  3856. this.$picker.find('.am-datepicker-days tbody')
  3857. .empty().append(html.join(''));
  3858. var currentYear = this.date.getFullYear();
  3859. var months = this.$picker.find('.am-datepicker-months')
  3860. .find('.am-datepicker-select')
  3861. .text(year);
  3862. months = months.end()
  3863. .find('span').removeClass('am-active').removeClass('am-disabled');
  3864. var monthLen = 0;
  3865. while (monthLen < 12) {
  3866. if (this.onRender(d.setFullYear(year, monthLen), 1)) {
  3867. months.eq(monthLen).addClass('am-disabled');
  3868. }
  3869. monthLen++;
  3870. }
  3871. if (currentYear === year) {
  3872. months.eq(this.date.getMonth())
  3873. .removeClass('am-disabled')
  3874. .addClass('am-active');
  3875. }
  3876. html = '';
  3877. year = parseInt(year / 10, 10) * 10;
  3878. var yearCont = this.$picker
  3879. .find('.am-datepicker-years')
  3880. .find('.am-datepicker-select')
  3881. .text(year + '-' + (year + 9))
  3882. .end()
  3883. .find('td');
  3884. var yearClassName;
  3885. // fixes https://github.com/amazeui/amazeui/issues/770
  3886. // maybe not need now
  3887. var viewDate = new Date(this.viewDate);
  3888. year -= 1;
  3889. for (var i = -1; i < 11; i++) {
  3890. yearClassName = this.onRender(viewDate.setFullYear(year), 2);
  3891. html += '<span class="' + yearClassName + '' +
  3892. (i === -1 || i === 10 ? ' am-datepicker-old' : '') +
  3893. (currentYear === year ? ' am-active' : '') + '">' + year + '</span>';
  3894. year += 1;
  3895. }
  3896. yearCont.html(html);
  3897. };
  3898. Datepicker.prototype.click = function(event) {
  3899. event.stopPropagation();
  3900. event.preventDefault();
  3901. var month;
  3902. var year;
  3903. var $dayActive = this.$picker.find('.am-datepicker-days').find('.am-active');
  3904. var $months = this.$picker.find('.am-datepicker-months');
  3905. var $monthIndex = $months.find('.am-active').index();
  3906. var $target = $(event.target).closest('span, td, th');
  3907. if ($target.length === 1) {
  3908. switch ($target[0].nodeName.toLowerCase()) {
  3909. case 'th':
  3910. switch ($target[0].className) {
  3911. case 'am-datepicker-switch':
  3912. this.showMode(1);
  3913. break;
  3914. case 'am-datepicker-prev':
  3915. case 'am-datepicker-next':
  3916. this.viewDate['set' + DPGlobal.modes[this.viewMode].navFnc].call(
  3917. this.viewDate,
  3918. this.viewDate
  3919. ['get' + DPGlobal.modes[this.viewMode].navFnc]
  3920. .call(this.viewDate) +
  3921. DPGlobal.modes[this.viewMode].navStep *
  3922. ($target[0].className === 'am-datepicker-prev' ? -1 : 1)
  3923. );
  3924. this.fill();
  3925. this.set();
  3926. break;
  3927. }
  3928. break;
  3929. case 'span':
  3930. if ($target.is('.am-disabled')) {
  3931. return;
  3932. }
  3933. if ($target.is('.am-datepicker-month')) {
  3934. month = $target.parent().find('span').index($target);
  3935. if ($target.is('.am-active')) {
  3936. this.viewDate.setMonth(month, $dayActive.text());
  3937. } else {
  3938. this.viewDate.setMonth(month);
  3939. }
  3940. } else {
  3941. year = parseInt($target.text(), 10) || 0;
  3942. if ($target.is('.am-active')) {
  3943. this.viewDate.setFullYear(year, $monthIndex, $dayActive.text());
  3944. } else {
  3945. this.viewDate.setFullYear(year);
  3946. }
  3947. }
  3948. if (this.viewMode !== 0) {
  3949. this.date = new Date(this.viewDate);
  3950. this.$element.trigger({
  3951. type: 'changeDate.datepicker.amui',
  3952. date: this.date,
  3953. viewMode: DPGlobal.modes[this.viewMode].clsName
  3954. });
  3955. }
  3956. this.showMode(-1);
  3957. this.fill();
  3958. this.set();
  3959. break;
  3960. case 'td':
  3961. if ($target.is('.am-datepicker-day') && !$target.is('.am-disabled')) {
  3962. var day = parseInt($target.text(), 10) || 1;
  3963. month = this.viewDate.getMonth();
  3964. if ($target.is('.am-datepicker-old')) {
  3965. month -= 1;
  3966. } else if ($target.is('.am-datepicker-new')) {
  3967. month += 1;
  3968. }
  3969. year = this.viewDate.getFullYear();
  3970. this.date = new Date(year, month, day, 0, 0, 0, 0);
  3971. this.viewDate = new Date(year, month, Math.min(28, day), 0, 0, 0, 0);
  3972. this.fill();
  3973. this.set();
  3974. this.$element.trigger({
  3975. type: 'changeDate.datepicker.amui',
  3976. date: this.date,
  3977. viewMode: DPGlobal.modes[this.viewMode].clsName
  3978. });
  3979. this.options.autoClose && this.close();
  3980. }
  3981. break;
  3982. }
  3983. }
  3984. };
  3985. Datepicker.prototype.mousedown = function(event) {
  3986. event.stopPropagation();
  3987. event.preventDefault();
  3988. };
  3989. Datepicker.prototype.showMode = function(dir) {
  3990. if (dir) {
  3991. this.viewMode = Math.max(this.minViewMode,
  3992. Math.min(2, this.viewMode + dir));
  3993. }
  3994. this.$picker.find('>div').hide().
  3995. filter('.am-datepicker-' + DPGlobal.modes[this.viewMode].clsName).show();
  3996. };
  3997. Datepicker.prototype.isOutView = function() {
  3998. var offset = this.component ?
  3999. this.component.offset() : this.$element.offset();
  4000. var isOutView = {
  4001. outRight: false,
  4002. outBottom: false
  4003. };
  4004. var $picker = this.$picker;
  4005. var width = offset.left + $picker.outerWidth(true);
  4006. var height = offset.top + $picker.outerHeight(true) +
  4007. this.$element.innerHeight();
  4008. if (width > $doc.width()) {
  4009. isOutView.outRight = true;
  4010. }
  4011. if (height > $doc.height()) {
  4012. isOutView.outBottom = true;
  4013. }
  4014. return isOutView;
  4015. };
  4016. Datepicker.prototype.getLocale = function(locale) {
  4017. if (!locale) {
  4018. locale = navigator.language && navigator.language.split('-');
  4019. locale[1] = locale[1].toUpperCase();
  4020. locale = locale.join('_');
  4021. }
  4022. if (!Datepicker.locales[locale]) {
  4023. locale = 'en_US';
  4024. }
  4025. return locale;
  4026. };
  4027. Datepicker.prototype.setTheme = function() {
  4028. if (this.theme) {
  4029. this.$picker.addClass('am-datepicker-' + this.theme);
  4030. }
  4031. };
  4032. // Datepicker locales
  4033. Datepicker.locales = {
  4034. en_US: {
  4035. days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
  4036. 'Friday', 'Saturday'],
  4037. daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
  4038. daysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
  4039. months: ['January', 'February', 'March', 'April', 'May', 'June',
  4040. 'July', 'August', 'September', 'October', 'November', 'December'],
  4041. monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
  4042. 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
  4043. weekStart: 0
  4044. },
  4045. zh_CN: {
  4046. days: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
  4047. daysShort: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
  4048. daysMin: ['日', '一', '二', '三', '四', '五', '六'],
  4049. months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月',
  4050. '八月', '九月', '十月', '十一月', '十二月'],
  4051. monthsShort: ['一月', '二月', '三月', '四月', '五月', '六月',
  4052. '七月', '八月', '九月', '十月', '十一月', '十二月'],
  4053. weekStart: 1,
  4054. year: ['年']
  4055. }
  4056. };
  4057. var DPGlobal = {
  4058. modes: [
  4059. {
  4060. clsName: 'days',
  4061. navFnc: 'Month',
  4062. navStep: 1
  4063. },
  4064. {
  4065. clsName: 'months',
  4066. navFnc: 'FullYear',
  4067. navStep: 1
  4068. },
  4069. {
  4070. clsName: 'years',
  4071. navFnc: 'FullYear',
  4072. navStep: 10
  4073. }
  4074. ],
  4075. isLeapYear: function(year) {
  4076. return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
  4077. },
  4078. getDaysInMonth: function(year, month) {
  4079. return [31, (DPGlobal.isLeapYear(year) ? 29 : 28),
  4080. 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
  4081. },
  4082. parseFormat: function(format) {
  4083. var separator = format.match(/[.\/\-\s].*?/);
  4084. var parts = format.split(/\W+/);
  4085. if (!separator || !parts || parts.length === 0) {
  4086. throw new Error('Invalid date format.');
  4087. }
  4088. return {
  4089. separator: separator,
  4090. parts: parts
  4091. };
  4092. },
  4093. parseDate: function(date, format) {
  4094. var parts = date.split(format.separator);
  4095. var val;
  4096. date = new Date();
  4097. date.setHours(0);
  4098. date.setMinutes(0);
  4099. date.setSeconds(0);
  4100. date.setMilliseconds(0);
  4101. if (parts.length === format.parts.length) {
  4102. var year = date.getFullYear();
  4103. var day = date.getDate();
  4104. var month = date.getMonth();
  4105. for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
  4106. val = parseInt(parts[i], 10) || 1;
  4107. switch (format.parts[i]) {
  4108. case 'dd':
  4109. case 'd':
  4110. day = val;
  4111. date.setDate(val);
  4112. break;
  4113. case 'mm':
  4114. case 'm':
  4115. month = val - 1;
  4116. date.setMonth(val - 1);
  4117. break;
  4118. case 'yy':
  4119. year = 2000 + val;
  4120. date.setFullYear(2000 + val);
  4121. break;
  4122. case 'yyyy':
  4123. year = val;
  4124. date.setFullYear(val);
  4125. break;
  4126. }
  4127. }
  4128. date = new Date(year, month, day, 0, 0, 0);
  4129. }
  4130. return date;
  4131. },
  4132. formatDate: function(date, format) {
  4133. var val = {
  4134. d: date.getDate(),
  4135. m: date.getMonth() + 1,
  4136. yy: date.getFullYear().toString().substring(2),
  4137. yyyy: date.getFullYear()
  4138. };
  4139. var dateArray = [];
  4140. val.dd = (val.d < 10 ? '0' : '') + val.d;
  4141. val.mm = (val.m < 10 ? '0' : '') + val.m;
  4142. for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
  4143. dateArray.push(val[format.parts[i]]);
  4144. }
  4145. return dateArray.join(format.separator);
  4146. },
  4147. headTemplate: '<thead>' +
  4148. '<tr class="am-datepicker-header">' +
  4149. '<th class="am-datepicker-prev">' +
  4150. '<i class="am-datepicker-prev-icon"></i></th>' +
  4151. '<th colspan="5" class="am-datepicker-switch">' +
  4152. '<div class="am-datepicker-select"></div></th>' +
  4153. '<th class="am-datepicker-next"><i class="am-datepicker-next-icon"></i>' +
  4154. '</th></tr></thead>',
  4155. contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
  4156. };
  4157. DPGlobal.template = '<div class="am-datepicker am-datepicker-dropdown">' +
  4158. '<div class="am-datepicker-caret"></div>' +
  4159. '<div class="am-datepicker-days">' +
  4160. '<table class="am-datepicker-table">' +
  4161. DPGlobal.headTemplate +
  4162. '<tbody></tbody>' +
  4163. '</table>' +
  4164. '</div>' +
  4165. '<div class="am-datepicker-months">' +
  4166. '<table class="am-datepicker-table">' +
  4167. DPGlobal.headTemplate +
  4168. DPGlobal.contTemplate +
  4169. '</table>' +
  4170. '</div>' +
  4171. '<div class="am-datepicker-years">' +
  4172. '<table class="am-datepicker-table">' +
  4173. DPGlobal.headTemplate +
  4174. DPGlobal.contTemplate +
  4175. '</table>' +
  4176. '</div>' +
  4177. '</div>';
  4178. // jQuery plugin
  4179. UI.plugin('datepicker', Datepicker);
  4180. // Init code
  4181. UI.ready(function(context) {
  4182. $('[data-am-datepicker]').datepicker();
  4183. });
  4184. module.exports = UI.datepicker = Datepicker;
  4185. // TODO: 1. 载入动画
  4186. // 2. less 优化
  4187. /***/ },
  4188. /* 9 */
  4189. /***/ function(module, exports, __webpack_require__) {
  4190. 'use strict';
  4191. var $ = __webpack_require__(1);
  4192. var UI = __webpack_require__(2);
  4193. var $doc = $(document);
  4194. var transition = UI.support.transition;
  4195. var Dimmer = function() {
  4196. this.id = UI.utils.generateGUID('am-dimmer');
  4197. this.$element = $(Dimmer.DEFAULTS.tpl, {
  4198. id: this.id
  4199. });
  4200. this.inited = false;
  4201. this.scrollbarWidth = 0;
  4202. this.$used = $([]);
  4203. };
  4204. Dimmer.DEFAULTS = {
  4205. tpl: '<div class="am-dimmer" data-am-dimmer></div>'
  4206. };
  4207. Dimmer.prototype.init = function() {
  4208. if (!this.inited) {
  4209. $(document.body).append(this.$element);
  4210. this.inited = true;
  4211. $doc.trigger('init.dimmer.amui');
  4212. this.$element.on('touchmove.dimmer.amui', function(e) {
  4213. e.preventDefault();
  4214. });
  4215. }
  4216. return this;
  4217. };
  4218. Dimmer.prototype.open = function(relatedElement) {
  4219. if (!this.inited) {
  4220. this.init();
  4221. }
  4222. var $element = this.$element;
  4223. // 用于多重调用
  4224. if (relatedElement) {
  4225. this.$used = this.$used.add($(relatedElement));
  4226. }
  4227. this.checkScrollbar().setScrollbar();
  4228. $element.show().trigger('open.dimmer.amui');
  4229. transition && $element.off(transition.end);
  4230. setTimeout(function() {
  4231. $element.addClass('am-active');
  4232. }, 0);
  4233. return this;
  4234. };
  4235. Dimmer.prototype.close = function(relatedElement, force) {
  4236. this.$used = this.$used.not($(relatedElement));
  4237. if (!force && this.$used.length) {
  4238. return this;
  4239. }
  4240. var $element = this.$element;
  4241. $element.removeClass('am-active').trigger('close.dimmer.amui');
  4242. function complete() {
  4243. $element.hide();
  4244. this.resetScrollbar();
  4245. }
  4246. // transition ? $element.one(transition.end, $.proxy(complete, this)) :
  4247. complete.call(this);
  4248. return this;
  4249. };
  4250. Dimmer.prototype.checkScrollbar = function() {
  4251. this.scrollbarWidth = UI.utils.measureScrollbar();
  4252. return this;
  4253. };
  4254. Dimmer.prototype.setScrollbar = function() {
  4255. var $body = $(document.body);
  4256. var bodyPaddingRight = parseInt(($body.css('padding-right') || 0), 10);
  4257. if (this.scrollbarWidth) {
  4258. $body.css('padding-right', bodyPaddingRight + this.scrollbarWidth);
  4259. }
  4260. $body.addClass('am-dimmer-active');
  4261. return this;
  4262. };
  4263. Dimmer.prototype.resetScrollbar = function() {
  4264. $(document.body).css('padding-right', '').removeClass('am-dimmer-active');
  4265. return this;
  4266. };
  4267. module.exports = UI.dimmer = new Dimmer();
  4268. /***/ },
  4269. /* 10 */
  4270. /***/ function(module, exports, __webpack_require__) {
  4271. 'use strict';
  4272. var $ = __webpack_require__(1);
  4273. var UI = __webpack_require__(2);
  4274. var animation = UI.support.animation;
  4275. /**
  4276. * @via https://github.com/Minwe/bootstrap/blob/master/js/dropdown.js
  4277. * @copyright (c) 2011-2014 Twitter, Inc
  4278. * @license The MIT License
  4279. */
  4280. // var toggle = '[data-am-dropdown] > .am-dropdown-toggle';
  4281. var Dropdown = function(element, options) {
  4282. this.options = $.extend({}, Dropdown.DEFAULTS, options);
  4283. options = this.options;
  4284. this.$element = $(element);
  4285. this.$toggle = this.$element.find(options.selector.toggle);
  4286. this.$dropdown = this.$element.find(options.selector.dropdown);
  4287. this.$boundary = (options.boundary === window) ? $(window) :
  4288. this.$element.closest(options.boundary);
  4289. this.$justify = (options.justify && $(options.justify).length &&
  4290. $(options.justify)) || undefined;
  4291. !this.$boundary.length && (this.$boundary = $(window));
  4292. this.active = this.$element.hasClass('am-active') ? true : false;
  4293. this.animating = null;
  4294. this.events();
  4295. };
  4296. Dropdown.DEFAULTS = {
  4297. animation: 'am-animation-slide-top-fixed',
  4298. boundary: window,
  4299. justify: undefined,
  4300. selector: {
  4301. dropdown: '.am-dropdown-content',
  4302. toggle: '.am-dropdown-toggle'
  4303. },
  4304. trigger: 'click'
  4305. };
  4306. Dropdown.prototype.toggle = function() {
  4307. this.clear();
  4308. if (this.animating) {
  4309. return;
  4310. }
  4311. this[this.active ? 'close' : 'open']();
  4312. };
  4313. Dropdown.prototype.open = function(e) {
  4314. var $toggle = this.$toggle;
  4315. var $element = this.$element;
  4316. var $dropdown = this.$dropdown;
  4317. if ($toggle.is('.am-disabled, :disabled')) {
  4318. return;
  4319. }
  4320. if (this.active) {
  4321. return;
  4322. }
  4323. $element.trigger('open.dropdown.amui').addClass('am-active');
  4324. $toggle.trigger('focus');
  4325. this.checkDimensions();
  4326. var complete = $.proxy(function() {
  4327. $element.trigger('opened.dropdown.amui');
  4328. this.active = true;
  4329. this.animating = 0;
  4330. }, this);
  4331. if (animation) {
  4332. this.animating = 1;
  4333. $dropdown.addClass(this.options.animation).
  4334. on(animation.end + '.open.dropdown.amui', $.proxy(function() {
  4335. complete();
  4336. $dropdown.removeClass(this.options.animation);
  4337. }, this));
  4338. } else {
  4339. complete();
  4340. }
  4341. };
  4342. Dropdown.prototype.close = function() {
  4343. if (!this.active) {
  4344. return;
  4345. }
  4346. // fix #165
  4347. // var animationName = this.options.animation + ' am-animation-reverse';
  4348. var animationName = 'am-dropdown-animation';
  4349. var $element = this.$element;
  4350. var $dropdown = this.$dropdown;
  4351. $element.trigger('close.dropdown.amui');
  4352. var complete = $.proxy(function complete() {
  4353. $element.
  4354. removeClass('am-active').
  4355. trigger('closed.dropdown.amui');
  4356. this.active = false;
  4357. this.animating = 0;
  4358. this.$toggle.blur();
  4359. }, this);
  4360. if (animation) {
  4361. $dropdown.removeClass(this.options.animation);
  4362. $dropdown.addClass(animationName);
  4363. this.animating = 1;
  4364. // animation
  4365. $dropdown.one(animation.end + '.close.dropdown.amui', function() {
  4366. $dropdown.removeClass(animationName);
  4367. complete();
  4368. });
  4369. } else {
  4370. complete();
  4371. }
  4372. };
  4373. Dropdown.prototype.enable = function() {
  4374. this.$toggle.prop('disabled', false);
  4375. },
  4376. Dropdown.prototype.disable = function() {
  4377. this.$toggle.prop('disabled', true);
  4378. },
  4379. Dropdown.prototype.checkDimensions = function() {
  4380. if (!this.$dropdown.length) {
  4381. return;
  4382. }
  4383. var $dropdown = this.$dropdown;
  4384. var offset = $dropdown.offset();
  4385. var width = $dropdown.outerWidth();
  4386. var boundaryWidth = this.$boundary.width();
  4387. var boundaryOffset = $.isWindow(this.boundary) && this.$boundary.offset() ?
  4388. this.$boundary.offset().left : 0;
  4389. if (this.$justify) {
  4390. // jQuery.fn.width() is really...
  4391. $dropdown.css({'min-width': this.$justify.css('width')});
  4392. }
  4393. if ((width + (offset.left - boundaryOffset)) > boundaryWidth) {
  4394. this.$element.addClass('am-dropdown-flip');
  4395. }
  4396. };
  4397. Dropdown.prototype.clear = function() {
  4398. $('[data-am-dropdown]').not(this.$element).each(function() {
  4399. var data = $(this).data('amui.dropdown');
  4400. data && data.close();
  4401. });
  4402. };
  4403. Dropdown.prototype.events = function() {
  4404. var eventNS = 'dropdown.amui';
  4405. // triggers = this.options.trigger.split(' '),
  4406. var $toggle = this.$toggle;
  4407. $toggle.on('click.' + eventNS, $.proxy(function(e) {
  4408. e.preventDefault();
  4409. this.toggle();
  4410. }, this));
  4411. /*for (var i = triggers.length; i--;) {
  4412. var trigger = triggers[i];
  4413. if (trigger === 'click') {
  4414. $toggle.on('click.' + eventNS, $.proxy(this.toggle, this))
  4415. }
  4416. if (trigger === 'focus' || trigger === 'hover') {
  4417. var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin';
  4418. var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout';
  4419. this.$element.on(eventIn + '.' + eventNS, $.proxy(this.open, this))
  4420. .on(eventOut + '.' + eventNS, $.proxy(this.close, this));
  4421. }
  4422. }*/
  4423. $(document).on('keydown.dropdown.amui', $.proxy(function(e) {
  4424. e.keyCode === 27 && this.active && this.close();
  4425. }, this)).on('click.outer.dropdown.amui', $.proxy(function(e) {
  4426. // var $target = $(e.target);
  4427. if (this.active &&
  4428. (this.$element[0] === e.target || !this.$element.find(e.target).length)) {
  4429. this.close();
  4430. }
  4431. }, this));
  4432. };
  4433. // Dropdown Plugin
  4434. UI.plugin('dropdown', Dropdown);
  4435. // Init code
  4436. UI.ready(function(context) {
  4437. $('[data-am-dropdown]', context).dropdown();
  4438. });
  4439. $(document).on('click.dropdown.amui.data-api', '.am-dropdown form',
  4440. function(e) {
  4441. e.stopPropagation();
  4442. });
  4443. module.exports = UI.dropdown = Dropdown;
  4444. // TODO: 1. 处理链接 focus
  4445. // 2. 增加 mouseenter / mouseleave 选项
  4446. // 3. 宽度适应
  4447. /***/ },
  4448. /* 11 */
  4449. /***/ function(module, exports, __webpack_require__) {
  4450. /* WEBPACK VAR INJECTION */(function(setImmediate) {var $ = __webpack_require__(1);
  4451. var UI = __webpack_require__(2);
  4452. // MODIFIED:
  4453. // - LINE 226: add `<i></i>`
  4454. // - namespace
  4455. // - Init code
  4456. // TODO: start after x ms when pause on actions
  4457. /*
  4458. * jQuery FlexSlider v2.4.0
  4459. * Copyright 2012 WooThemes
  4460. * Contributing Author: Tyler Smith
  4461. */
  4462. // FlexSlider: Object Instance
  4463. $.flexslider = function(el, options) {
  4464. var slider = $(el);
  4465. // making variables public
  4466. slider.vars = $.extend({}, $.flexslider.defaults, options);
  4467. var namespace = slider.vars.namespace,
  4468. msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture,
  4469. touch = (( "ontouchstart" in window ) || msGesture || window.DocumentTouch && document instanceof DocumentTouch) && slider.vars.touch,
  4470. // depricating this idea, as devices are being released with both of these events
  4471. //eventType = (touch) ? "touchend" : "click",
  4472. eventType = "click touchend MSPointerUp keyup",
  4473. watchedEvent = "",
  4474. watchedEventClearTimer,
  4475. vertical = slider.vars.direction === "vertical",
  4476. reverse = slider.vars.reverse,
  4477. carousel = (slider.vars.itemWidth > 0),
  4478. fade = slider.vars.animation === "fade",
  4479. asNav = slider.vars.asNavFor !== "",
  4480. methods = {},
  4481. focused = true;
  4482. // Store a reference to the slider object
  4483. $.data(el, 'flexslider', slider);
  4484. // Private slider methods
  4485. methods = {
  4486. init: function() {
  4487. slider.animating = false;
  4488. // Get current slide and make sure it is a number
  4489. slider.currentSlide = parseInt((slider.vars.startAt ? slider.vars.startAt : 0), 10);
  4490. if (isNaN(slider.currentSlide)) {
  4491. slider.currentSlide = 0;
  4492. }
  4493. slider.animatingTo = slider.currentSlide;
  4494. slider.atEnd = (slider.currentSlide === 0 || slider.currentSlide === slider.last);
  4495. slider.containerSelector = slider.vars.selector.substr(0, slider.vars.selector.search(' '));
  4496. slider.slides = $(slider.vars.selector, slider);
  4497. slider.container = $(slider.containerSelector, slider);
  4498. slider.count = slider.slides.length;
  4499. // SYNC:
  4500. slider.syncExists = $(slider.vars.sync).length > 0;
  4501. // SLIDE:
  4502. if (slider.vars.animation === "slide") {
  4503. slider.vars.animation = "swing";
  4504. }
  4505. slider.prop = (vertical) ? "top" : "marginLeft";
  4506. slider.args = {};
  4507. // SLIDESHOW:
  4508. slider.manualPause = false;
  4509. slider.stopped = false;
  4510. //PAUSE WHEN INVISIBLE
  4511. slider.started = false;
  4512. slider.startTimeout = null;
  4513. // TOUCH/USECSS:
  4514. slider.transitions = !slider.vars.video && !fade && slider.vars.useCSS && (function() {
  4515. var obj = document.createElement('div'),
  4516. props = ['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];
  4517. for (var i in props) {
  4518. if (obj.style[props[i]] !== undefined) {
  4519. slider.pfx = props[i].replace('Perspective', '').toLowerCase();
  4520. slider.prop = "-" + slider.pfx + "-transform";
  4521. return true;
  4522. }
  4523. }
  4524. return false;
  4525. }());
  4526. slider.ensureAnimationEnd = '';
  4527. // CONTROLSCONTAINER:
  4528. if (slider.vars.controlsContainer !== "") slider.controlsContainer = $(slider.vars.controlsContainer).length > 0 && $(slider.vars.controlsContainer);
  4529. // MANUAL:
  4530. if (slider.vars.manualControls !== "") slider.manualControls = $(slider.vars.manualControls).length > 0 && $(slider.vars.manualControls);
  4531. // RANDOMIZE:
  4532. if (slider.vars.randomize) {
  4533. slider.slides.sort(function() {
  4534. return (Math.round(Math.random()) - 0.5);
  4535. });
  4536. slider.container.empty().append(slider.slides);
  4537. }
  4538. slider.doMath();
  4539. // INIT
  4540. slider.setup("init");
  4541. // CONTROLNAV:
  4542. if (slider.vars.controlNav) {
  4543. methods.controlNav.setup();
  4544. }
  4545. // DIRECTIONNAV:
  4546. if (slider.vars.directionNav) {
  4547. methods.directionNav.setup();
  4548. }
  4549. // KEYBOARD:
  4550. if (slider.vars.keyboard && ($(slider.containerSelector).length === 1 || slider.vars.multipleKeyboard)) {
  4551. $(document).bind('keyup', function(event) {
  4552. var keycode = event.keyCode;
  4553. if (!slider.animating && (keycode === 39 || keycode === 37)) {
  4554. var target = (keycode === 39) ? slider.getTarget('next') :
  4555. (keycode === 37) ? slider.getTarget('prev') : false;
  4556. slider.flexAnimate(target, slider.vars.pauseOnAction);
  4557. }
  4558. });
  4559. }
  4560. // MOUSEWHEEL:
  4561. if (slider.vars.mousewheel) {
  4562. slider.bind('mousewheel', function(event, delta, deltaX, deltaY) {
  4563. event.preventDefault();
  4564. var target = (delta < 0) ? slider.getTarget('next') : slider.getTarget('prev');
  4565. slider.flexAnimate(target, slider.vars.pauseOnAction);
  4566. });
  4567. }
  4568. // PAUSEPLAY
  4569. if (slider.vars.pausePlay) {
  4570. methods.pausePlay.setup();
  4571. }
  4572. //PAUSE WHEN INVISIBLE
  4573. if (slider.vars.slideshow && slider.vars.pauseInvisible) {
  4574. methods.pauseInvisible.init();
  4575. }
  4576. // SLIDSESHOW
  4577. if (slider.vars.slideshow) {
  4578. if (slider.vars.pauseOnHover) {
  4579. slider.hover(function() {
  4580. if (!slider.manualPlay && !slider.manualPause) {slider.pause();}
  4581. }, function() {
  4582. if (!slider.manualPause && !slider.manualPlay && !slider.stopped) {slider.play();}
  4583. });
  4584. }
  4585. // initialize animation
  4586. // If we're visible, or we don't use PageVisibility API
  4587. if (!slider.vars.pauseInvisible || !methods.pauseInvisible.isHidden()) {
  4588. (slider.vars.initDelay > 0) ? slider.startTimeout = setTimeout(slider.play, slider.vars.initDelay) : slider.play();
  4589. }
  4590. }
  4591. // ASNAV:
  4592. if (asNav) {methods.asNav.setup();}
  4593. // TOUCH
  4594. if (touch && slider.vars.touch) {methods.touch();}
  4595. // FADE&&SMOOTHHEIGHT || SLIDE:
  4596. if (!fade || (fade && slider.vars.smoothHeight)) {$(window).bind("resize orientationchange focus", methods.resize);}
  4597. slider.find("img").attr("draggable", "false");
  4598. // API: start() Callback
  4599. setTimeout(function() {
  4600. slider.vars.start(slider);
  4601. }, 200);
  4602. },
  4603. asNav: {
  4604. setup: function() {
  4605. slider.asNav = true;
  4606. slider.animatingTo = Math.floor(slider.currentSlide / slider.move);
  4607. slider.currentItem = slider.currentSlide;
  4608. slider.slides.removeClass(namespace + "active-slide").eq(slider.currentItem).addClass(namespace + "active-slide");
  4609. if (!msGesture) {
  4610. slider.slides.on(eventType, function(e) {
  4611. e.preventDefault();
  4612. var $slide = $(this),
  4613. target = $slide.index();
  4614. var posFromLeft = $slide.offset().left - $(slider).scrollLeft(); // Find position of slide relative to left of slider container
  4615. if (posFromLeft <= 0 && $slide.hasClass(namespace + 'active-slide')) {
  4616. slider.flexAnimate(slider.getTarget("prev"), true);
  4617. } else if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass(namespace + "active-slide")) {
  4618. slider.direction = (slider.currentItem < target) ? "next" : "prev";
  4619. slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);
  4620. }
  4621. });
  4622. } else {
  4623. el._slider = slider;
  4624. slider.slides.each(function() {
  4625. var that = this;
  4626. that._gesture = new MSGesture();
  4627. that._gesture.target = that;
  4628. that.addEventListener("MSPointerDown", function(e) {
  4629. e.preventDefault();
  4630. if (e.currentTarget._gesture) {
  4631. e.currentTarget._gesture.addPointer(e.pointerId);
  4632. }
  4633. }, false);
  4634. that.addEventListener("MSGestureTap", function(e) {
  4635. e.preventDefault();
  4636. var $slide = $(this),
  4637. target = $slide.index();
  4638. if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass('active')) {
  4639. slider.direction = (slider.currentItem < target) ? "next" : "prev";
  4640. slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);
  4641. }
  4642. });
  4643. });
  4644. }
  4645. }
  4646. },
  4647. controlNav: {
  4648. setup: function() {
  4649. if (!slider.manualControls) {
  4650. methods.controlNav.setupPaging();
  4651. } else { // MANUALCONTROLS:
  4652. methods.controlNav.setupManual();
  4653. }
  4654. },
  4655. setupPaging: function() {
  4656. var type = (slider.vars.controlNav === "thumbnails") ? 'control-thumbs' : 'control-paging',
  4657. j = 1,
  4658. item,
  4659. slide;
  4660. slider.controlNavScaffold = $('<ol class="' + namespace + 'control-nav ' + namespace + type + '"></ol>');
  4661. if (slider.pagingCount > 1) {
  4662. for (var i = 0; i < slider.pagingCount; i++) {
  4663. slide = slider.slides.eq(i);
  4664. item = (slider.vars.controlNav === "thumbnails") ? '<img src="' + slide.attr('data-thumb') + '"/>' : '<a>' + j + '</a>';
  4665. if ('thumbnails' === slider.vars.controlNav && true === slider.vars.thumbCaptions) {
  4666. var captn = slide.attr('data-thumbcaption');
  4667. if ('' != captn && undefined != captn) {item += '<span class="' + namespace + 'caption">' + captn + '</span>'};
  4668. }
  4669. // slider.controlNavScaffold.append('<li>' + item + '</li>');
  4670. slider.controlNavScaffold.append('<li>' + item + '<i></i></li>');
  4671. j++;
  4672. }
  4673. }
  4674. // CONTROLSCONTAINER:
  4675. (slider.controlsContainer) ? $(slider.controlsContainer).append(slider.controlNavScaffold) : slider.append(slider.controlNavScaffold);
  4676. methods.controlNav.set();
  4677. methods.controlNav.active();
  4678. slider.controlNavScaffold.delegate('a, img', eventType, function(event) {
  4679. event.preventDefault();
  4680. if (watchedEvent === "" || watchedEvent === event.type) {
  4681. var $this = $(this),
  4682. target = slider.controlNav.index($this);
  4683. if (!$this.hasClass(namespace + 'active')) {
  4684. slider.direction = (target > slider.currentSlide) ? "next" : "prev";
  4685. slider.flexAnimate(target, slider.vars.pauseOnAction);
  4686. }
  4687. }
  4688. // setup flags to prevent event duplication
  4689. if (watchedEvent === "") {
  4690. watchedEvent = event.type;
  4691. }
  4692. methods.setToClearWatchedEvent();
  4693. });
  4694. },
  4695. setupManual: function() {
  4696. slider.controlNav = slider.manualControls;
  4697. methods.controlNav.active();
  4698. slider.controlNav.bind(eventType, function(event) {
  4699. event.preventDefault();
  4700. if (watchedEvent === "" || watchedEvent === event.type) {
  4701. var $this = $(this),
  4702. target = slider.controlNav.index($this);
  4703. if (!$this.hasClass(namespace + 'active')) {
  4704. (target > slider.currentSlide) ? slider.direction = "next" : slider.direction = "prev";
  4705. slider.flexAnimate(target, slider.vars.pauseOnAction);
  4706. }
  4707. }
  4708. // setup flags to prevent event duplication
  4709. if (watchedEvent === "") {
  4710. watchedEvent = event.type;
  4711. }
  4712. methods.setToClearWatchedEvent();
  4713. });
  4714. },
  4715. set: function() {
  4716. var selector = (slider.vars.controlNav === "thumbnails") ? 'img' : 'a';
  4717. slider.controlNav = $('.' + namespace + 'control-nav li ' + selector, (slider.controlsContainer) ? slider.controlsContainer : slider);
  4718. },
  4719. active: function() {
  4720. slider.controlNav.removeClass(namespace + "active").eq(slider.animatingTo).addClass(namespace + "active");
  4721. },
  4722. update: function(action, pos) {
  4723. if (slider.pagingCount > 1 && action === "add") {
  4724. slider.controlNavScaffold.append($('<li><a>' + slider.count + '</a></li>'));
  4725. } else if (slider.pagingCount === 1) {
  4726. slider.controlNavScaffold.find('li').remove();
  4727. } else {
  4728. slider.controlNav.eq(pos).closest('li').remove();
  4729. }
  4730. methods.controlNav.set();
  4731. (slider.pagingCount > 1 && slider.pagingCount !== slider.controlNav.length) ? slider.update(pos, action) : methods.controlNav.active();
  4732. }
  4733. },
  4734. directionNav: {
  4735. setup: function() {
  4736. 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>');
  4737. // CONTROLSCONTAINER:
  4738. if (slider.controlsContainer) {
  4739. $(slider.controlsContainer).append(directionNavScaffold);
  4740. slider.directionNav = $('.' + namespace + 'direction-nav li a', slider.controlsContainer);
  4741. } else {
  4742. slider.append(directionNavScaffold);
  4743. slider.directionNav = $('.' + namespace + 'direction-nav li a', slider);
  4744. }
  4745. methods.directionNav.update();
  4746. slider.directionNav.bind(eventType, function(event) {
  4747. event.preventDefault();
  4748. var target;
  4749. if (watchedEvent === "" || watchedEvent === event.type) {
  4750. target = ($(this).hasClass(namespace + 'next')) ? slider.getTarget('next') : slider.getTarget('prev');
  4751. slider.flexAnimate(target, slider.vars.pauseOnAction);
  4752. }
  4753. // setup flags to prevent event duplication
  4754. if (watchedEvent === "") {
  4755. watchedEvent = event.type;
  4756. }
  4757. methods.setToClearWatchedEvent();
  4758. });
  4759. },
  4760. update: function() {
  4761. var disabledClass = namespace + 'disabled';
  4762. if (slider.pagingCount === 1) {
  4763. slider.directionNav.addClass(disabledClass).attr('tabindex', '-1');
  4764. } else if (!slider.vars.animationLoop) {
  4765. if (slider.animatingTo === 0) {
  4766. slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "prev").addClass(disabledClass).attr('tabindex', '-1');
  4767. } else if (slider.animatingTo === slider.last) {
  4768. slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "next").addClass(disabledClass).attr('tabindex', '-1');
  4769. } else {
  4770. slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');
  4771. }
  4772. } else {
  4773. slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');
  4774. }
  4775. }
  4776. },
  4777. pausePlay: {
  4778. setup: function() {
  4779. var pausePlayScaffold = $('<div class="' + namespace + 'pauseplay"><a></a></div>');
  4780. // CONTROLSCONTAINER:
  4781. if (slider.controlsContainer) {
  4782. slider.controlsContainer.append(pausePlayScaffold);
  4783. slider.pausePlay = $('.' + namespace + 'pauseplay a', slider.controlsContainer);
  4784. } else {
  4785. slider.append(pausePlayScaffold);
  4786. slider.pausePlay = $('.' + namespace + 'pauseplay a', slider);
  4787. }
  4788. methods.pausePlay.update((slider.vars.slideshow) ? namespace + 'pause' : namespace + 'play');
  4789. slider.pausePlay.bind(eventType, function(event) {
  4790. event.preventDefault();
  4791. if (watchedEvent === "" || watchedEvent === event.type) {
  4792. if ($(this).hasClass(namespace + 'pause')) {
  4793. slider.manualPause = true;
  4794. slider.manualPlay = false;
  4795. slider.pause();
  4796. } else {
  4797. slider.manualPause = false;
  4798. slider.manualPlay = true;
  4799. slider.play();
  4800. }
  4801. }
  4802. // setup flags to prevent event duplication
  4803. if (watchedEvent === "") {
  4804. watchedEvent = event.type;
  4805. }
  4806. methods.setToClearWatchedEvent();
  4807. });
  4808. },
  4809. update: function(state) {
  4810. (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);
  4811. }
  4812. },
  4813. touch: function() {
  4814. var startX,
  4815. startY,
  4816. offset,
  4817. cwidth,
  4818. dx,
  4819. startT,
  4820. scrolling = false,
  4821. localX = 0,
  4822. localY = 0,
  4823. accDx = 0;
  4824. if (!msGesture) {
  4825. el.addEventListener('touchstart', onTouchStart, false);
  4826. function onTouchStart(e) {
  4827. if (slider.animating) {
  4828. e.preventDefault();
  4829. } else if (( window.navigator.msPointerEnabled ) || e.touches.length === 1) {
  4830. slider.pause();
  4831. // CAROUSEL:
  4832. cwidth = (vertical) ? slider.h : slider.w;
  4833. startT = Number(new Date());
  4834. // CAROUSEL:
  4835. // Local vars for X and Y points.
  4836. localX = e.touches[0].pageX;
  4837. localY = e.touches[0].pageY;
  4838. offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :
  4839. (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
  4840. (carousel && slider.currentSlide === slider.last) ? slider.limit :
  4841. (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :
  4842. (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;
  4843. startX = (vertical) ? localY : localX;
  4844. startY = (vertical) ? localX : localY;
  4845. el.addEventListener('touchmove', onTouchMove, false);
  4846. el.addEventListener('touchend', onTouchEnd, false);
  4847. }
  4848. }
  4849. function onTouchMove(e) {
  4850. // Local vars for X and Y points.
  4851. localX = e.touches[0].pageX;
  4852. localY = e.touches[0].pageY;
  4853. dx = (vertical) ? startX - localY : startX - localX;
  4854. scrolling = (vertical) ? (Math.abs(dx) < Math.abs(localX - startY)) : (Math.abs(dx) < Math.abs(localY - startY));
  4855. var fxms = 500;
  4856. if (!scrolling || Number(new Date()) - startT > fxms) {
  4857. e.preventDefault();
  4858. if (!fade && slider.transitions) {
  4859. if (!slider.vars.animationLoop) {
  4860. dx = dx / ((slider.currentSlide === 0 && dx < 0 || slider.currentSlide === slider.last && dx > 0) ? (Math.abs(dx) / cwidth + 2) : 1);
  4861. }
  4862. slider.setProps(offset + dx, "setTouch");
  4863. }
  4864. }
  4865. }
  4866. function onTouchEnd(e) {
  4867. // finish the touch by undoing the touch session
  4868. el.removeEventListener('touchmove', onTouchMove, false);
  4869. if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {
  4870. var updateDx = (reverse) ? -dx : dx,
  4871. target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');
  4872. if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth / 2)) {
  4873. slider.flexAnimate(target, slider.vars.pauseOnAction);
  4874. } else {
  4875. if (!fade) {slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true);}
  4876. }
  4877. }
  4878. el.removeEventListener('touchend', onTouchEnd, false);
  4879. startX = null;
  4880. startY = null;
  4881. dx = null;
  4882. offset = null;
  4883. }
  4884. } else {
  4885. el.style.msTouchAction = "none";
  4886. el._gesture = new MSGesture();
  4887. el._gesture.target = el;
  4888. el.addEventListener("MSPointerDown", onMSPointerDown, false);
  4889. el._slider = slider;
  4890. el.addEventListener("MSGestureChange", onMSGestureChange, false);
  4891. el.addEventListener("MSGestureEnd", onMSGestureEnd, false);
  4892. function onMSPointerDown(e) {
  4893. e.stopPropagation();
  4894. if (slider.animating) {
  4895. e.preventDefault();
  4896. } else {
  4897. slider.pause();
  4898. el._gesture.addPointer(e.pointerId);
  4899. accDx = 0;
  4900. cwidth = (vertical) ? slider.h : slider.w;
  4901. startT = Number(new Date());
  4902. // CAROUSEL:
  4903. offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :
  4904. (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
  4905. (carousel && slider.currentSlide === slider.last) ? slider.limit :
  4906. (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :
  4907. (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;
  4908. }
  4909. }
  4910. function onMSGestureChange(e) {
  4911. e.stopPropagation();
  4912. var slider = e.target._slider;
  4913. if (!slider) {
  4914. return;
  4915. }
  4916. var transX = -e.translationX,
  4917. transY = -e.translationY;
  4918. //Accumulate translations.
  4919. accDx = accDx + ((vertical) ? transY : transX);
  4920. dx = accDx;
  4921. scrolling = (vertical) ? (Math.abs(accDx) < Math.abs(-transX)) : (Math.abs(accDx) < Math.abs(-transY));
  4922. if (e.detail === e.MSGESTURE_FLAG_INERTIA) {
  4923. setImmediate(function() {
  4924. el._gesture.stop();
  4925. });
  4926. return;
  4927. }
  4928. if (!scrolling || Number(new Date()) - startT > 500) {
  4929. e.preventDefault();
  4930. if (!fade && slider.transitions) {
  4931. if (!slider.vars.animationLoop) {
  4932. dx = accDx / ((slider.currentSlide === 0 && accDx < 0 || slider.currentSlide === slider.last && accDx > 0) ? (Math.abs(accDx) / cwidth + 2) : 1);
  4933. }
  4934. slider.setProps(offset + dx, "setTouch");
  4935. }
  4936. }
  4937. }
  4938. function onMSGestureEnd(e) {
  4939. e.stopPropagation();
  4940. var slider = e.target._slider;
  4941. if (!slider) {
  4942. return;
  4943. }
  4944. if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {
  4945. var updateDx = (reverse) ? -dx : dx,
  4946. target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');
  4947. if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth / 2)) {
  4948. slider.flexAnimate(target, slider.vars.pauseOnAction);
  4949. } else {
  4950. if (!fade) {slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true);}
  4951. }
  4952. }
  4953. startX = null;
  4954. startY = null;
  4955. dx = null;
  4956. offset = null;
  4957. accDx = 0;
  4958. }
  4959. }
  4960. },
  4961. resize: function() {
  4962. if (!slider.animating && slider.is(':visible')) {
  4963. if (!carousel) {slider.doMath()};
  4964. if (fade) {
  4965. // SMOOTH HEIGHT:
  4966. methods.smoothHeight();
  4967. } else if (carousel) { //CAROUSEL:
  4968. slider.slides.width(slider.computedW);
  4969. slider.update(slider.pagingCount);
  4970. slider.setProps();
  4971. }
  4972. else if (vertical) { //VERTICAL:
  4973. slider.viewport.height(slider.h);
  4974. slider.setProps(slider.h, "setTotal");
  4975. } else {
  4976. // SMOOTH HEIGHT:
  4977. if (slider.vars.smoothHeight) {methods.smoothHeight();}
  4978. slider.newSlides.width(slider.computedW);
  4979. slider.setProps(slider.computedW, "setTotal");
  4980. }
  4981. }
  4982. },
  4983. smoothHeight: function(dur) {
  4984. if (!vertical || fade) {
  4985. var $obj = (fade) ? slider : slider.viewport;
  4986. (dur) ? $obj.animate({"height": slider.slides.eq(slider.animatingTo).height()}, dur) : $obj.height(slider.slides.eq(slider.animatingTo).height());
  4987. }
  4988. },
  4989. sync: function(action) {
  4990. var $obj = $(slider.vars.sync).data("flexslider"),
  4991. target = slider.animatingTo;
  4992. switch (action) {
  4993. case "animate":
  4994. $obj.flexAnimate(target, slider.vars.pauseOnAction, false, true);
  4995. break;
  4996. case "play":
  4997. if (!$obj.playing && !$obj.asNav) {
  4998. $obj.play();
  4999. }
  5000. break;
  5001. case "pause":
  5002. $obj.pause();
  5003. break;
  5004. }
  5005. },
  5006. uniqueID: function($clone) {
  5007. // Append _clone to current level and children elements with id attributes
  5008. $clone.filter('[id]').add($clone.find('[id]')).each(function() {
  5009. var $this = $(this);
  5010. $this.attr('id', $this.attr('id') + '_clone');
  5011. });
  5012. return $clone;
  5013. },
  5014. pauseInvisible: {
  5015. visProp: null,
  5016. init: function() {
  5017. var visProp = methods.pauseInvisible.getHiddenProp();
  5018. if (visProp) {
  5019. var evtname = visProp.replace(/[H|h]idden/,'') + 'visibilitychange';
  5020. document.addEventListener(evtname, function() {
  5021. if (methods.pauseInvisible.isHidden()) {
  5022. if(slider.startTimeout) {
  5023. clearTimeout(slider.startTimeout); //If clock is ticking, stop timer and prevent from starting while invisible
  5024. } else {
  5025. slider.pause(); //Or just pause
  5026. }
  5027. }
  5028. else {
  5029. if(slider.started) {
  5030. slider.play(); //Initiated before, just play
  5031. } else {
  5032. if (slider.vars.initDelay > 0) {
  5033. setTimeout(slider.play, slider.vars.initDelay);
  5034. } else {
  5035. slider.play(); //Didn't init before: simply init or wait for it
  5036. }
  5037. }
  5038. }
  5039. });
  5040. }
  5041. },
  5042. isHidden: function() {
  5043. var prop = methods.pauseInvisible.getHiddenProp();
  5044. if (!prop) {
  5045. return false;
  5046. }
  5047. return document[prop];
  5048. },
  5049. getHiddenProp: function() {
  5050. var prefixes = ['webkit','moz','ms','o'];
  5051. // if 'hidden' is natively supported just return it
  5052. if ('hidden' in document) {
  5053. return 'hidden';
  5054. }
  5055. // otherwise loop over all the known prefixes until we find one
  5056. for (var i = 0; i < prefixes.length; i++ ) {
  5057. if ((prefixes[i] + 'Hidden') in document) {
  5058. return prefixes[i] + 'Hidden';
  5059. }
  5060. }
  5061. // otherwise it's not supported
  5062. return null;
  5063. }
  5064. },
  5065. setToClearWatchedEvent: function() {
  5066. clearTimeout(watchedEventClearTimer);
  5067. watchedEventClearTimer = setTimeout(function() {
  5068. watchedEvent = "";
  5069. }, 3000);
  5070. }
  5071. };
  5072. // public methods
  5073. slider.flexAnimate = function(target, pause, override, withSync, fromNav) {
  5074. if (!slider.vars.animationLoop && target !== slider.currentSlide) {
  5075. slider.direction = (target > slider.currentSlide) ? "next" : "prev";
  5076. }
  5077. if (asNav && slider.pagingCount === 1) slider.direction = (slider.currentItem < target) ? "next" : "prev";
  5078. if (!slider.animating && (slider.canAdvance(target, fromNav) || override) && slider.is(":visible")) {
  5079. if (asNav && withSync) {
  5080. var master = $(slider.vars.asNavFor).data('flexslider');
  5081. slider.atEnd = target === 0 || target === slider.count - 1;
  5082. master.flexAnimate(target, true, false, true, fromNav);
  5083. slider.direction = (slider.currentItem < target) ? "next" : "prev";
  5084. master.direction = slider.direction;
  5085. if (Math.ceil((target + 1) / slider.visible) - 1 !== slider.currentSlide && target !== 0) {
  5086. slider.currentItem = target;
  5087. slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide");
  5088. target = Math.floor(target / slider.visible);
  5089. } else {
  5090. slider.currentItem = target;
  5091. slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide");
  5092. return false;
  5093. }
  5094. }
  5095. slider.animating = true;
  5096. slider.animatingTo = target;
  5097. // SLIDESHOW:
  5098. if (pause) {slider.pause();}
  5099. // API: before() animation Callback
  5100. slider.vars.before(slider);
  5101. // SYNC:
  5102. if (slider.syncExists && !fromNav) {methods.sync("animate");}
  5103. // CONTROLNAV
  5104. if (slider.vars.controlNav) {methods.controlNav.active();}
  5105. // !CAROUSEL:
  5106. // CANDIDATE: slide active class (for add/remove slide)
  5107. if (!carousel) {slider.slides.removeClass(namespace + 'active-slide').eq(target).addClass(namespace + 'active-slide');}
  5108. // INFINITE LOOP:
  5109. // CANDIDATE: atEnd
  5110. slider.atEnd = target === 0 || target === slider.last;
  5111. // DIRECTIONNAV:
  5112. if (slider.vars.directionNav) {methods.directionNav.update();}
  5113. if (target === slider.last) {
  5114. // API: end() of cycle Callback
  5115. slider.vars.end(slider);
  5116. // SLIDESHOW && !INFINITE LOOP:
  5117. if (!slider.vars.animationLoop) {slider.pause();}
  5118. }
  5119. // SLIDE:
  5120. if (!fade) {
  5121. var dimension = (vertical) ? slider.slides.filter(':first').height() : slider.computedW,
  5122. margin, slideString, calcNext;
  5123. // INFINITE LOOP / REVERSE:
  5124. if (carousel) {
  5125. //margin = (slider.vars.itemWidth > slider.w) ? slider.vars.itemMargin * 2 : slider.vars.itemMargin;
  5126. margin = slider.vars.itemMargin;
  5127. calcNext = ((slider.itemW + margin) * slider.move) * slider.animatingTo;
  5128. slideString = (calcNext > slider.limit && slider.visible !== 1) ? slider.limit : calcNext;
  5129. } else if (slider.currentSlide === 0 && target === slider.count - 1 && slider.vars.animationLoop && slider.direction !== "next") {
  5130. slideString = (reverse) ? (slider.count + slider.cloneOffset) * dimension : 0;
  5131. } else if (slider.currentSlide === slider.last && target === 0 && slider.vars.animationLoop && slider.direction !== "prev") {
  5132. slideString = (reverse) ? 0 : (slider.count + 1) * dimension;
  5133. } else {
  5134. slideString = (reverse) ? ((slider.count - 1) - target + slider.cloneOffset) * dimension : (target + slider.cloneOffset) * dimension;
  5135. }
  5136. slider.setProps(slideString, "", slider.vars.animationSpeed);
  5137. if (slider.transitions) {
  5138. if (!slider.vars.animationLoop || !slider.atEnd) {
  5139. slider.animating = false;
  5140. slider.currentSlide = slider.animatingTo;
  5141. }
  5142. // Unbind previous transitionEnd events and re-bind new transitionEnd event
  5143. slider.container.unbind("webkitTransitionEnd transitionend");
  5144. slider.container.bind("webkitTransitionEnd transitionend", function() {
  5145. clearTimeout(slider.ensureAnimationEnd);
  5146. slider.wrapup(dimension);
  5147. });
  5148. // Insurance for the ever-so-fickle transitionEnd event
  5149. clearTimeout(slider.ensureAnimationEnd);
  5150. slider.ensureAnimationEnd = setTimeout(function() {
  5151. slider.wrapup(dimension);
  5152. }, slider.vars.animationSpeed + 100);
  5153. } else {
  5154. slider.container.animate(slider.args, slider.vars.animationSpeed, slider.vars.easing, function(){
  5155. slider.wrapup(dimension);
  5156. });
  5157. }
  5158. } else { // FADE:
  5159. if (!touch) {
  5160. //slider.slides.eq(slider.currentSlide).fadeOut(slider.vars.animationSpeed, slider.vars.easing);
  5161. //slider.slides.eq(target).fadeIn(slider.vars.animationSpeed, slider.vars.easing, slider.wrapup);
  5162. slider.slides.eq(slider.currentSlide).css({"zIndex": 1}).animate({"opacity": 0}, slider.vars.animationSpeed, slider.vars.easing);
  5163. slider.slides.eq(target).css({"zIndex": 2}).animate({"opacity": 1}, slider.vars.animationSpeed, slider.vars.easing, slider.wrapup);
  5164. } else {
  5165. slider.slides.eq(slider.currentSlide).css({
  5166. "opacity": 0,
  5167. "zIndex": 1
  5168. });
  5169. slider.slides.eq(target).css({"opacity": 1, "zIndex": 2});
  5170. slider.wrapup(dimension);
  5171. }
  5172. }
  5173. // SMOOTH HEIGHT:
  5174. if (slider.vars.smoothHeight) {methods.smoothHeight(slider.vars.animationSpeed)};
  5175. }
  5176. };
  5177. slider.wrapup = function(dimension) {
  5178. // SLIDE:
  5179. if (!fade && !carousel) {
  5180. if (slider.currentSlide === 0 && slider.animatingTo === slider.last && slider.vars.animationLoop) {
  5181. slider.setProps(dimension, "jumpEnd");
  5182. } else if (slider.currentSlide === slider.last && slider.animatingTo === 0 && slider.vars.animationLoop) {
  5183. slider.setProps(dimension, "jumpStart");
  5184. }
  5185. }
  5186. slider.animating = false;
  5187. slider.currentSlide = slider.animatingTo;
  5188. // API: after() animation Callback
  5189. slider.vars.after(slider);
  5190. };
  5191. // SLIDESHOW:
  5192. slider.animateSlides = function() {
  5193. if (!slider.animating && focused) {slider.flexAnimate(slider.getTarget("next"));}
  5194. };
  5195. // SLIDESHOW:
  5196. slider.pause = function() {
  5197. clearInterval(slider.animatedSlides);
  5198. slider.animatedSlides = null;
  5199. slider.playing = false;
  5200. // PAUSEPLAY:
  5201. if (slider.vars.pausePlay) {methods.pausePlay.update("play");}
  5202. // SYNC:
  5203. if (slider.syncExists) {methods.sync("pause");}
  5204. };
  5205. // SLIDESHOW:
  5206. slider.play = function() {
  5207. if (slider.playing) {clearInterval(slider.animatedSlides);}
  5208. slider.animatedSlides = slider.animatedSlides || setInterval(slider.animateSlides, slider.vars.slideshowSpeed);
  5209. slider.started = slider.playing = true;
  5210. // PAUSEPLAY:
  5211. if (slider.vars.pausePlay) {methods.pausePlay.update("pause");}
  5212. // SYNC:
  5213. if (slider.syncExists) {methods.sync("play");}
  5214. };
  5215. // STOP:
  5216. slider.stop = function() {
  5217. slider.pause();
  5218. slider.stopped = true;
  5219. };
  5220. slider.canAdvance = function(target, fromNav) {
  5221. // ASNAV:
  5222. var last = (asNav) ? slider.pagingCount - 1 : slider.last;
  5223. return (fromNav) ? true :
  5224. (asNav && slider.currentItem === slider.count - 1 && target === 0 && slider.direction === "prev") ? true :
  5225. (asNav && slider.currentItem === 0 && target === slider.pagingCount - 1 && slider.direction !== "next") ? false :
  5226. (target === slider.currentSlide && !asNav) ? false :
  5227. (slider.vars.animationLoop) ? true :
  5228. (slider.atEnd && slider.currentSlide === 0 && target === last && slider.direction !== "next") ? false :
  5229. (slider.atEnd && slider.currentSlide === last && target === 0 && slider.direction === "next") ? false :
  5230. true;
  5231. };
  5232. slider.getTarget = function(dir) {
  5233. slider.direction = dir;
  5234. if (dir === "next") {
  5235. return (slider.currentSlide === slider.last) ? 0 : slider.currentSlide + 1;
  5236. } else {
  5237. return (slider.currentSlide === 0) ? slider.last : slider.currentSlide - 1;
  5238. }
  5239. };
  5240. // SLIDE:
  5241. slider.setProps = function(pos, special, dur) {
  5242. var target = (function() {
  5243. var posCheck = (pos) ? pos : ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo,
  5244. posCalc = (function() {
  5245. if (carousel) {
  5246. return (special === "setTouch") ? pos :
  5247. (reverse && slider.animatingTo === slider.last) ? 0 :
  5248. (reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
  5249. (slider.animatingTo === slider.last) ? slider.limit : posCheck;
  5250. } else {
  5251. switch (special) {
  5252. case "setTotal":
  5253. return (reverse) ? ((slider.count - 1) - slider.currentSlide + slider.cloneOffset) * pos : (slider.currentSlide + slider.cloneOffset) * pos;
  5254. case "setTouch":
  5255. return (reverse) ? pos : pos;
  5256. case "jumpEnd":
  5257. return (reverse) ? pos : slider.count * pos;
  5258. case "jumpStart":
  5259. return (reverse) ? slider.count * pos : pos;
  5260. default:
  5261. return pos;
  5262. }
  5263. }
  5264. }());
  5265. return (posCalc * -1) + "px";
  5266. }());
  5267. if (slider.transitions) {
  5268. target = (vertical) ? "translate3d(0," + target + ",0)" : "translate3d(" + target + ",0,0)";
  5269. dur = (dur !== undefined) ? (dur / 1000) + "s" : "0s";
  5270. slider.container.css("-" + slider.pfx + "-transition-duration", dur);
  5271. slider.container.css("transition-duration", dur);
  5272. }
  5273. slider.args[slider.prop] = target;
  5274. if (slider.transitions || dur === undefined) {slider.container.css(slider.args);}
  5275. slider.container.css('transform', target);
  5276. };
  5277. slider.setup = function(type) {
  5278. // SLIDE:
  5279. if (!fade) {
  5280. var sliderOffset, arr;
  5281. if (type === "init") {
  5282. slider.viewport = $('<div class="' + namespace + 'viewport"></div>').css({
  5283. "overflow": "hidden",
  5284. "position": "relative"
  5285. }).appendTo(slider).append(slider.container);
  5286. // INFINITE LOOP:
  5287. slider.cloneCount = 0;
  5288. slider.cloneOffset = 0;
  5289. // REVERSE:
  5290. if (reverse) {
  5291. arr = $.makeArray(slider.slides).reverse();
  5292. slider.slides = $(arr);
  5293. slider.container.empty().append(slider.slides);
  5294. }
  5295. }
  5296. // INFINITE LOOP && !CAROUSEL:
  5297. if (slider.vars.animationLoop && !carousel) {
  5298. slider.cloneCount = 2;
  5299. slider.cloneOffset = 1;
  5300. // clear out old clones
  5301. if (type !== "init") { slider.container.find('.clone').remove(); }
  5302. slider.container.append(methods.uniqueID(slider.slides.first().clone().addClass('clone')).attr('aria-hidden', 'true'))
  5303. .prepend(methods.uniqueID(slider.slides.last().clone().addClass('clone')).attr('aria-hidden', 'true'));
  5304. }
  5305. slider.newSlides = $(slider.vars.selector, slider);
  5306. sliderOffset = (reverse) ? slider.count - 1 - slider.currentSlide + slider.cloneOffset : slider.currentSlide + slider.cloneOffset;
  5307. // VERTICAL:
  5308. if (vertical && !carousel) {
  5309. slider.container.height((slider.count + slider.cloneCount) * 200 + "%").css("position", "absolute").width("100%");
  5310. setTimeout(function() {
  5311. slider.newSlides.css({"display": "block"});
  5312. slider.doMath();
  5313. slider.viewport.height(slider.h);
  5314. slider.setProps(sliderOffset * slider.h, "init");
  5315. }, (type === "init") ? 100 : 0);
  5316. } else {
  5317. slider.container.width((slider.count + slider.cloneCount) * 200 + "%");
  5318. slider.setProps(sliderOffset * slider.computedW, "init");
  5319. setTimeout(function() {
  5320. slider.doMath();
  5321. slider.newSlides.css({
  5322. "width": slider.computedW,
  5323. "float": "left",
  5324. "display": "block"
  5325. });
  5326. // SMOOTH HEIGHT:
  5327. if (slider.vars.smoothHeight) {methods.smoothHeight();}
  5328. }, (type === "init") ? 100 : 0);
  5329. }
  5330. } else { // FADE:
  5331. slider.slides.css({
  5332. "width": "100%",
  5333. "float": "left",
  5334. "marginRight": "-100%",
  5335. "position": "relative"
  5336. });
  5337. if (type === "init") {
  5338. if (!touch) {
  5339. //slider.slides.eq(slider.currentSlide).fadeIn(slider.vars.animationSpeed, slider.vars.easing);
  5340. if (slider.vars.fadeFirstSlide == false) {
  5341. slider.slides.css({ "opacity": 0, "display": "block", "zIndex": 1 }).eq(slider.currentSlide).css({"zIndex": 2}).css({"opacity": 1});
  5342. } else {
  5343. slider.slides.css({ "opacity": 0, "display": "block", "zIndex": 1 }).eq(slider.currentSlide).css({"zIndex": 2}).animate({"opacity": 1},slider.vars.animationSpeed,slider.vars.easing);
  5344. }
  5345. } else {
  5346. 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});
  5347. }
  5348. }
  5349. // SMOOTH HEIGHT:
  5350. if (slider.vars.smoothHeight) {methods.smoothHeight();}
  5351. }
  5352. // !CAROUSEL:
  5353. // CANDIDATE: active slide
  5354. if (!carousel) {slider.slides.removeClass(namespace + "active-slide").eq(slider.currentSlide).addClass(namespace + "active-slide");}
  5355. //FlexSlider: init() Callback
  5356. slider.vars.init(slider);
  5357. };
  5358. slider.doMath = function() {
  5359. var slide = slider.slides.first(),
  5360. slideMargin = slider.vars.itemMargin,
  5361. minItems = slider.vars.minItems,
  5362. maxItems = slider.vars.maxItems;
  5363. slider.w = (slider.viewport === undefined) ? slider.width() : slider.viewport.width();
  5364. slider.h = slide.height();
  5365. slider.boxPadding = slide.outerWidth() - slide.width();
  5366. // CAROUSEL:
  5367. if (carousel) {
  5368. slider.itemT = slider.vars.itemWidth + slideMargin;
  5369. slider.minW = (minItems) ? minItems * slider.itemT : slider.w;
  5370. slider.maxW = (maxItems) ? (maxItems * slider.itemT) - slideMargin : slider.w;
  5371. slider.itemW = (slider.minW > slider.w) ? (slider.w - (slideMargin * (minItems - 1))) / minItems :
  5372. (slider.maxW < slider.w) ? (slider.w - (slideMargin * (maxItems - 1))) / maxItems :
  5373. (slider.vars.itemWidth > slider.w) ? slider.w : slider.vars.itemWidth;
  5374. slider.visible = Math.floor(slider.w / (slider.itemW));
  5375. slider.move = (slider.vars.move > 0 && slider.vars.move < slider.visible ) ? slider.vars.move : slider.visible;
  5376. slider.pagingCount = Math.ceil(((slider.count - slider.visible) / slider.move) + 1);
  5377. slider.last = slider.pagingCount - 1;
  5378. slider.limit = (slider.pagingCount === 1) ? 0 :
  5379. (slider.vars.itemWidth > slider.w) ? (slider.itemW * (slider.count - 1)) + (slideMargin * (slider.count - 1)) : ((slider.itemW + slideMargin) * slider.count) - slider.w - slideMargin;
  5380. } else {
  5381. slider.itemW = slider.w;
  5382. slider.pagingCount = slider.count;
  5383. slider.last = slider.count - 1;
  5384. }
  5385. slider.computedW = slider.itemW - slider.boxPadding;
  5386. };
  5387. slider.update = function(pos, action) {
  5388. slider.doMath();
  5389. // update currentSlide and slider.animatingTo if necessary
  5390. if (!carousel) {
  5391. if (pos < slider.currentSlide) {
  5392. slider.currentSlide += 1;
  5393. } else if (pos <= slider.currentSlide && pos !== 0) {
  5394. slider.currentSlide -= 1;
  5395. }
  5396. slider.animatingTo = slider.currentSlide;
  5397. }
  5398. // update controlNav
  5399. if (slider.vars.controlNav && !slider.manualControls) {
  5400. if ((action === "add" && !carousel) || slider.pagingCount > slider.controlNav.length) {
  5401. methods.controlNav.update("add");
  5402. } else if ((action === "remove" && !carousel) || slider.pagingCount < slider.controlNav.length) {
  5403. if (carousel && slider.currentSlide > slider.last) {
  5404. slider.currentSlide -= 1;
  5405. slider.animatingTo -= 1;
  5406. }
  5407. methods.controlNav.update("remove", slider.last);
  5408. }
  5409. }
  5410. // update directionNav
  5411. if (slider.vars.directionNav) {methods.directionNav.update();}
  5412. };
  5413. slider.addSlide = function(obj, pos) {
  5414. var $obj = $(obj);
  5415. slider.count += 1;
  5416. slider.last = slider.count - 1;
  5417. // append new slide
  5418. if (vertical && reverse) {
  5419. (pos !== undefined) ? slider.slides.eq(slider.count - pos).after($obj) : slider.container.prepend($obj);
  5420. } else {
  5421. (pos !== undefined) ? slider.slides.eq(pos).before($obj) : slider.container.append($obj);
  5422. }
  5423. // update currentSlide, animatingTo, controlNav, and directionNav
  5424. slider.update(pos, "add");
  5425. // update slider.slides
  5426. slider.slides = $(slider.vars.selector + ':not(.clone)', slider);
  5427. // re-setup the slider to accomdate new slide
  5428. slider.setup();
  5429. //FlexSlider: added() Callback
  5430. slider.vars.added(slider);
  5431. };
  5432. slider.removeSlide = function(obj) {
  5433. var pos = (isNaN(obj)) ? slider.slides.index($(obj)) : obj;
  5434. // update count
  5435. slider.count -= 1;
  5436. slider.last = slider.count - 1;
  5437. // remove slide
  5438. if (isNaN(obj)) {
  5439. $(obj, slider.slides).remove();
  5440. } else {
  5441. (vertical && reverse) ? slider.slides.eq(slider.last).remove() : slider.slides.eq(obj).remove();
  5442. }
  5443. // update currentSlide, animatingTo, controlNav, and directionNav
  5444. slider.doMath();
  5445. slider.update(pos, "remove");
  5446. // update slider.slides
  5447. slider.slides = $(slider.vars.selector + ':not(.clone)', slider);
  5448. // re-setup the slider to accomdate new slide
  5449. slider.setup();
  5450. // FlexSlider: removed() Callback
  5451. slider.vars.removed(slider);
  5452. };
  5453. //FlexSlider: Initialize
  5454. methods.init();
  5455. };
  5456. // Ensure the slider isn't focussed if the window loses focus.
  5457. $(window).blur(function(e) {
  5458. focused = false;
  5459. }).focus(function(e) {
  5460. focused = true;
  5461. });
  5462. // FlexSlider: Default Settings
  5463. $.flexslider.defaults = {
  5464. namespace: 'am-', // {NEW} String: Prefix string attached to the class of every element generated by the plugin
  5465. selector: '.am-slides > li', // {NEW} Selector: Must match a simple pattern. '{container} > {slide}' -- Ignore pattern at your own peril
  5466. animation: 'slide', // String: Select your animation type, 'fade' or 'slide'
  5467. easing: 'swing', // {NEW} String: Determines the easing method used in jQuery transitions. jQuery easing plugin is supported!
  5468. direction: 'horizontal', // String: Select the sliding direction, "horizontal" or "vertical"
  5469. reverse: false, // {NEW} Boolean: Reverse the animation direction
  5470. animationLoop: true, // Boolean: Should the animation loop? If false, directionNav will received "disable" classes at either end
  5471. smoothHeight: false, // {NEW} Boolean: Allow height of the slider to animate smoothly in horizontal mode
  5472. startAt: 0, // Integer: The slide that the slider should start on. Array notation (0 = first slide)
  5473. slideshow: true, // Boolean: Animate slider automatically
  5474. slideshowSpeed: 5000, // Integer: Set the speed of the slideshow cycling, in milliseconds
  5475. animationSpeed: 600, // Integer: Set the speed of animations, in milliseconds
  5476. initDelay: 0, // {NEW} Integer: Set an initialization delay, in milliseconds
  5477. randomize: false, // Boolean: Randomize slide order
  5478. fadeFirstSlide: true, // Boolean: Fade in the first slide when animation type is "fade"
  5479. thumbCaptions: false, // Boolean: Whether or not to put captions on thumbnails when using the "thumbnails" controlNav.
  5480. // Usability features
  5481. pauseOnAction: true, // Boolean: Pause the slideshow when interacting with control elements, highly recommended.
  5482. pauseOnHover: false, // Boolean: Pause the slideshow when hovering over slider, then resume when no longer hovering
  5483. pauseInvisible: true, // {NEW} Boolean: Pause the slideshow when tab is invisible, resume when visible. Provides better UX, lower CPU usage.
  5484. useCSS: true, // {NEW} Boolean: Slider will use CSS3 transitions if available
  5485. touch: true, // {NEW} Boolean: Allow touch swipe navigation of the slider on touch-enabled devices
  5486. video: false, // {NEW} Boolean: If using video in the slider, will prevent CSS3 3D Transforms to avoid graphical glitches
  5487. // Primary Controls
  5488. controlNav: true, // Boolean: Create navigation for paging control of each slide? Note: Leave true for manualControls usage
  5489. directionNav: true, // Boolean: Create navigation for previous/next navigation? (true/false)
  5490. prevText: ' ', // String: Set the text for the "previous" directionNav item
  5491. nextText: ' ', // String: Set the text for the "next" directionNav item
  5492. // Secondary Navigation
  5493. keyboard: true, // Boolean: Allow slider navigating via keyboard left/right keys
  5494. multipleKeyboard: false, // {NEW} Boolean: Allow keyboard navigation to affect multiple sliders. Default behavior cuts out keyboard navigation with more than one slider present.
  5495. mousewheel: false, // {UPDATED} Boolean: Requires jquery.mousewheel.js (https://github.com/brandonaaron/jquery-mousewheel) - Allows slider navigating via mousewheel
  5496. pausePlay: false, // Boolean: Create pause/play dynamic element
  5497. pauseText: 'Pause', // String: Set the text for the 'pause' pausePlay item
  5498. playText: 'Play', // String: Set the text for the 'play' pausePlay item
  5499. // Special properties
  5500. 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.
  5501. 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.
  5502. sync: '', // {NEW} Selector: Mirror the actions performed on this slider with another slider. Use with care.
  5503. asNavFor: '', // {NEW} Selector: Internal property exposed for turning the slider into a thumbnail navigation for another slider
  5504. // Carousel Options
  5505. itemWidth: 0, // {NEW} Integer: Box-model width of individual carousel items, including horizontal borders and padding.
  5506. itemMargin: 0, // {NEW} Integer: Margin between carousel items.
  5507. minItems: 1, // {NEW} Integer: Minimum number of carousel items that should be visible. Items will resize fluidly when below this.
  5508. maxItems: 0, // {NEW} Integer: Maxmimum number of carousel items that should be visible. Items will resize fluidly when above this limit.
  5509. move: 0, // {NEW} Integer: Number of carousel items that should move on animation. If 0, slider will move all visible items.
  5510. allowOneSlide: true, // {NEW} Boolean: Whether or not to allow a slider comprised of a single slide
  5511. // Callback API
  5512. start: function() {
  5513. }, // Callback: function(slider) - Fires when the slider loads the first slide
  5514. before: function() {
  5515. }, // Callback: function(slider) - Fires asynchronously with each slider animation
  5516. after: function() {
  5517. }, // Callback: function(slider) - Fires after each slider animation completes
  5518. end: function() {
  5519. }, // Callback: function(slider) - Fires when the slider reaches the last slide (asynchronous)
  5520. added: function() {
  5521. }, // {NEW} Callback: function(slider) - Fires after a slide is added
  5522. removed: function() {
  5523. }, // {NEW} Callback: function(slider) - Fires after a slide is removed
  5524. init: function() {
  5525. } // {NEW} Callback: function(slider) - Fires after the slider is initially setup
  5526. };
  5527. // FlexSlider: Plugin Function
  5528. $.fn.flexslider = function(options) {
  5529. var args = Array.prototype.slice.call(arguments, 1);
  5530. if (options === undefined) {options = {};}
  5531. if (typeof options === 'object') {
  5532. return this.each(function() {
  5533. var $this = $(this);
  5534. var selector = (options.selector) ? options.selector : '.am-slides > li';
  5535. var $slides = $this.find(selector);
  5536. if (($slides.length === 1 && options.allowOneSlide === true) || $slides.length === 0) {
  5537. $slides.fadeIn(400);
  5538. if (options.start) {options.start($this);}
  5539. } else if ($this.data('flexslider') === undefined) {
  5540. new $.flexslider(this, options);
  5541. }
  5542. });
  5543. } else {
  5544. // Helper strings to quickly pecdrform functions on the slider
  5545. var $slider = $(this).data('flexslider');
  5546. var methodReturn;
  5547. switch (options) {
  5548. case 'next':
  5549. $slider.flexAnimate($slider.getTarget('next'), true);
  5550. break;
  5551. case 'prev':
  5552. case 'previous':
  5553. $slider.flexAnimate($slider.getTarget('prev'), true);
  5554. break;
  5555. default:
  5556. if (typeof options === 'number') {
  5557. $slider.flexAnimate(options, true);
  5558. } else if (typeof options === 'string') {
  5559. methodReturn = (typeof $slider[options] === 'function') ?
  5560. $slider[options].apply($slider, args) : $slider[options];
  5561. }
  5562. }
  5563. return methodReturn === undefined ? this : methodReturn;
  5564. }
  5565. };
  5566. // Init code
  5567. UI.ready(function(context) {
  5568. $('[data-am-flexslider]', context).each(function(i, item) {
  5569. var $slider = $(item);
  5570. var options = UI.utils.parseOptions($slider.data('amFlexslider'));
  5571. options.before = function(slider) {
  5572. if (slider._pausedTimer) {
  5573. window.clearTimeout(slider._pausedTimer);
  5574. slider._pausedTimer = null;
  5575. }
  5576. };
  5577. options.after = function(slider) {
  5578. var pauseTime = slider.vars.playAfterPaused;
  5579. if (pauseTime && !isNaN(pauseTime) && !slider.playing) {
  5580. if (!slider.manualPause && !slider.manualPlay && !slider.stopped) {
  5581. slider._pausedTimer = window.setTimeout(function() {
  5582. slider.play();
  5583. }, pauseTime);
  5584. }
  5585. }
  5586. };
  5587. $slider.flexslider(options);
  5588. });
  5589. });
  5590. module.exports = $.flexslider;
  5591. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12).setImmediate))
  5592. /***/ },
  5593. /* 12 */
  5594. /***/ function(module, exports, __webpack_require__) {
  5595. /* WEBPACK VAR INJECTION */(function(setImmediate, clearImmediate) {var nextTick = __webpack_require__(13).nextTick;
  5596. var apply = Function.prototype.apply;
  5597. var slice = Array.prototype.slice;
  5598. var immediateIds = {};
  5599. var nextImmediateId = 0;
  5600. // DOM APIs, for completeness
  5601. exports.setTimeout = function() {
  5602. return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);
  5603. };
  5604. exports.setInterval = function() {
  5605. return new Timeout(apply.call(setInterval, window, arguments), clearInterval);
  5606. };
  5607. exports.clearTimeout =
  5608. exports.clearInterval = function(timeout) { timeout.close(); };
  5609. function Timeout(id, clearFn) {
  5610. this._id = id;
  5611. this._clearFn = clearFn;
  5612. }
  5613. Timeout.prototype.unref = Timeout.prototype.ref = function() {};
  5614. Timeout.prototype.close = function() {
  5615. this._clearFn.call(window, this._id);
  5616. };
  5617. // Does not start the time, just sets up the members needed.
  5618. exports.enroll = function(item, msecs) {
  5619. clearTimeout(item._idleTimeoutId);
  5620. item._idleTimeout = msecs;
  5621. };
  5622. exports.unenroll = function(item) {
  5623. clearTimeout(item._idleTimeoutId);
  5624. item._idleTimeout = -1;
  5625. };
  5626. exports._unrefActive = exports.active = function(item) {
  5627. clearTimeout(item._idleTimeoutId);
  5628. var msecs = item._idleTimeout;
  5629. if (msecs >= 0) {
  5630. item._idleTimeoutId = setTimeout(function onTimeout() {
  5631. if (item._onTimeout)
  5632. item._onTimeout();
  5633. }, msecs);
  5634. }
  5635. };
  5636. // That's not how node.js implements it but the exposed api is the same.
  5637. exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) {
  5638. var id = nextImmediateId++;
  5639. var args = arguments.length < 2 ? false : slice.call(arguments, 1);
  5640. immediateIds[id] = true;
  5641. nextTick(function onNextTick() {
  5642. if (immediateIds[id]) {
  5643. // fn.call() is faster so we optimize for the common use-case
  5644. // @see http://jsperf.com/call-apply-segu
  5645. if (args) {
  5646. fn.apply(null, args);
  5647. } else {
  5648. fn.call(null);
  5649. }
  5650. // Prevent ids from leaking
  5651. exports.clearImmediate(id);
  5652. }
  5653. });
  5654. return id;
  5655. };
  5656. exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) {
  5657. delete immediateIds[id];
  5658. };
  5659. /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12).setImmediate, __webpack_require__(12).clearImmediate))
  5660. /***/ },
  5661. /* 13 */
  5662. /***/ function(module, exports) {
  5663. // shim for using process in browser
  5664. var process = module.exports = {};
  5665. var queue = [];
  5666. var draining = false;
  5667. var currentQueue;
  5668. var queueIndex = -1;
  5669. function cleanUpNextTick() {
  5670. draining = false;
  5671. if (currentQueue.length) {
  5672. queue = currentQueue.concat(queue);
  5673. } else {
  5674. queueIndex = -1;
  5675. }
  5676. if (queue.length) {
  5677. drainQueue();
  5678. }
  5679. }
  5680. function drainQueue() {
  5681. if (draining) {
  5682. return;
  5683. }
  5684. var timeout = setTimeout(cleanUpNextTick);
  5685. draining = true;
  5686. var len = queue.length;
  5687. while(len) {
  5688. currentQueue = queue;
  5689. queue = [];
  5690. while (++queueIndex < len) {
  5691. if (currentQueue) {
  5692. currentQueue[queueIndex].run();
  5693. }
  5694. }
  5695. queueIndex = -1;
  5696. len = queue.length;
  5697. }
  5698. currentQueue = null;
  5699. draining = false;
  5700. clearTimeout(timeout);
  5701. }
  5702. process.nextTick = function (fun) {
  5703. var args = new Array(arguments.length - 1);
  5704. if (arguments.length > 1) {
  5705. for (var i = 1; i < arguments.length; i++) {
  5706. args[i - 1] = arguments[i];
  5707. }
  5708. }
  5709. queue.push(new Item(fun, args));
  5710. if (queue.length === 1 && !draining) {
  5711. setTimeout(drainQueue, 0);
  5712. }
  5713. };
  5714. // v8 likes predictible objects
  5715. function Item(fun, array) {
  5716. this.fun = fun;
  5717. this.array = array;
  5718. }
  5719. Item.prototype.run = function () {
  5720. this.fun.apply(null, this.array);
  5721. };
  5722. process.title = 'browser';
  5723. process.browser = true;
  5724. process.env = {};
  5725. process.argv = [];
  5726. process.version = ''; // empty string to avoid regexp issues
  5727. process.versions = {};
  5728. function noop() {}
  5729. process.on = noop;
  5730. process.addListener = noop;
  5731. process.once = noop;
  5732. process.off = noop;
  5733. process.removeListener = noop;
  5734. process.removeAllListeners = noop;
  5735. process.emit = noop;
  5736. process.binding = function (name) {
  5737. throw new Error('process.binding is not supported');
  5738. };
  5739. process.cwd = function () { return '/' };
  5740. process.chdir = function (dir) {
  5741. throw new Error('process.chdir is not supported');
  5742. };
  5743. process.umask = function() { return 0; };
  5744. /***/ },
  5745. /* 14 */
  5746. /***/ function(module, exports, __webpack_require__) {
  5747. 'use strict';
  5748. var UI = __webpack_require__(2);
  5749. /* jshint unused: false */
  5750. /* jshint -W101, -W116, -W109 */
  5751. /*! iScroll v5.1.3
  5752. * (c) 2008-2014 Matteo Spinelli
  5753. * http://cubiq.org/license
  5754. */
  5755. var rAF = window.requestAnimationFrame ||
  5756. window.webkitRequestAnimationFrame ||
  5757. window.mozRequestAnimationFrame ||
  5758. window.oRequestAnimationFrame ||
  5759. window.msRequestAnimationFrame ||
  5760. function(callback) {
  5761. window.setTimeout(callback, 1000 / 60);
  5762. };
  5763. var utils = (function() {
  5764. var me = {};
  5765. var _elementStyle = document.createElement('div').style;
  5766. var _vendor = (function() {
  5767. var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
  5768. transform,
  5769. i = 0,
  5770. l = vendors.length;
  5771. for (; i < l; i++) {
  5772. transform = vendors[i] + 'ransform';
  5773. if (transform in _elementStyle) return vendors[i].substr(0, vendors[i].length - 1);
  5774. }
  5775. return false;
  5776. })();
  5777. function _prefixStyle(style) {
  5778. if (_vendor === false) return false;
  5779. if (_vendor === '') return style;
  5780. return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
  5781. }
  5782. me.getTime = Date.now || function getTime() {
  5783. return new Date().getTime();
  5784. };
  5785. me.extend = function(target, obj) {
  5786. for (var i in obj) {
  5787. target[i] = obj[i];
  5788. }
  5789. };
  5790. me.addEvent = function(el, type, fn, capture) {
  5791. el.addEventListener(type, fn, !!capture);
  5792. };
  5793. me.removeEvent = function(el, type, fn, capture) {
  5794. el.removeEventListener(type, fn, !!capture);
  5795. };
  5796. me.prefixPointerEvent = function(pointerEvent) {
  5797. return window.MSPointerEvent ?
  5798. 'MSPointer' + pointerEvent.charAt(9).toUpperCase() + pointerEvent.substr(10) :
  5799. pointerEvent;
  5800. };
  5801. me.momentum = function(current, start, time, lowerMargin, wrapperSize, deceleration) {
  5802. var distance = current - start,
  5803. speed = Math.abs(distance) / time,
  5804. destination,
  5805. duration;
  5806. deceleration = deceleration === undefined ? 0.0006 : deceleration;
  5807. destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
  5808. duration = speed / deceleration;
  5809. if (destination < lowerMargin) {
  5810. destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
  5811. distance = Math.abs(destination - current);
  5812. duration = distance / speed;
  5813. } else if (destination > 0) {
  5814. destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
  5815. distance = Math.abs(current) + destination;
  5816. duration = distance / speed;
  5817. }
  5818. return {
  5819. destination: Math.round(destination),
  5820. duration: duration
  5821. };
  5822. };
  5823. var _transform = _prefixStyle('transform');
  5824. me.extend(me, {
  5825. hasTransform: _transform !== false,
  5826. hasPerspective: _prefixStyle('perspective') in _elementStyle,
  5827. hasTouch: 'ontouchstart' in window,
  5828. hasPointer: window.PointerEvent || window.MSPointerEvent, // IE10 is prefixed
  5829. hasTransition: _prefixStyle('transition') in _elementStyle
  5830. });
  5831. // This should find all Android browsers lower than build 535.19 (both stock browser and webview)
  5832. me.isBadAndroid = /Android /.test(window.navigator.appVersion) && !(/Chrome\/\d/.test(window.navigator.appVersion));
  5833. me.extend(me.style = {}, {
  5834. transform: _transform,
  5835. transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
  5836. transitionDuration: _prefixStyle('transitionDuration'),
  5837. transitionDelay: _prefixStyle('transitionDelay'),
  5838. transformOrigin: _prefixStyle('transformOrigin')
  5839. });
  5840. me.hasClass = function(e, c) {
  5841. var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
  5842. return re.test(e.className);
  5843. };
  5844. me.addClass = function(e, c) {
  5845. if (me.hasClass(e, c)) {
  5846. return;
  5847. }
  5848. var newclass = e.className.split(' ');
  5849. newclass.push(c);
  5850. e.className = newclass.join(' ');
  5851. };
  5852. me.removeClass = function(e, c) {
  5853. if (!me.hasClass(e, c)) {
  5854. return;
  5855. }
  5856. var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
  5857. e.className = e.className.replace(re, ' ');
  5858. };
  5859. me.offset = function(el) {
  5860. var left = -el.offsetLeft,
  5861. top = -el.offsetTop;
  5862. // jshint -W084
  5863. while (el = el.offsetParent) {
  5864. left -= el.offsetLeft;
  5865. top -= el.offsetTop;
  5866. }
  5867. // jshint +W084
  5868. return {
  5869. left: left,
  5870. top: top
  5871. };
  5872. };
  5873. me.preventDefaultException = function(el, exceptions) {
  5874. for (var i in exceptions) {
  5875. if (exceptions[i].test(el[i])) {
  5876. return true;
  5877. }
  5878. }
  5879. return false;
  5880. };
  5881. me.extend(me.eventType = {}, {
  5882. touchstart: 1,
  5883. touchmove: 1,
  5884. touchend: 1,
  5885. mousedown: 2,
  5886. mousemove: 2,
  5887. mouseup: 2,
  5888. pointerdown: 3,
  5889. pointermove: 3,
  5890. pointerup: 3,
  5891. MSPointerDown: 3,
  5892. MSPointerMove: 3,
  5893. MSPointerUp: 3
  5894. });
  5895. me.extend(me.ease = {}, {
  5896. quadratic: {
  5897. style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
  5898. fn: function(k) {
  5899. return k * ( 2 - k );
  5900. }
  5901. },
  5902. circular: {
  5903. 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)
  5904. fn: function(k) {
  5905. return Math.sqrt(1 - ( --k * k ));
  5906. }
  5907. },
  5908. back: {
  5909. style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
  5910. fn: function(k) {
  5911. var b = 4;
  5912. return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
  5913. }
  5914. },
  5915. bounce: {
  5916. style: '',
  5917. fn: function(k) {
  5918. if (( k /= 1 ) < ( 1 / 2.75 )) {
  5919. return 7.5625 * k * k;
  5920. } else if (k < ( 2 / 2.75 )) {
  5921. return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
  5922. } else if (k < ( 2.5 / 2.75 )) {
  5923. return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
  5924. } else {
  5925. return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
  5926. }
  5927. }
  5928. },
  5929. elastic: {
  5930. style: '',
  5931. fn: function(k) {
  5932. var f = 0.22,
  5933. e = 0.4;
  5934. if (k === 0) {
  5935. return 0;
  5936. }
  5937. if (k == 1) {
  5938. return 1;
  5939. }
  5940. return ( e * Math.pow(2, -10 * k) * Math.sin(( k - f / 4 ) * ( 2 * Math.PI ) / f) + 1 );
  5941. }
  5942. }
  5943. });
  5944. me.tap = function(e, eventName) {
  5945. var ev = document.createEvent('Event');
  5946. ev.initEvent(eventName, true, true);
  5947. ev.pageX = e.pageX;
  5948. ev.pageY = e.pageY;
  5949. e.target.dispatchEvent(ev);
  5950. };
  5951. me.click = function(e) {
  5952. var target = e.target,
  5953. ev;
  5954. if (!(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName)) {
  5955. ev = document.createEvent('MouseEvents');
  5956. ev.initMouseEvent('click', true, true, e.view, 1,
  5957. target.screenX, target.screenY, target.clientX, target.clientY,
  5958. e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
  5959. 0, null);
  5960. ev._constructed = true;
  5961. target.dispatchEvent(ev);
  5962. }
  5963. };
  5964. return me;
  5965. })();
  5966. function IScroll(el, options) {
  5967. this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
  5968. this.scroller = this.wrapper.children[0];
  5969. this.scrollerStyle = this.scroller.style; // cache style for better performance
  5970. this.options = {
  5971. // INSERT POINT: OPTIONS
  5972. startX: 0,
  5973. startY: 0,
  5974. scrollY: true,
  5975. directionLockThreshold: 5,
  5976. momentum: true,
  5977. bounce: true,
  5978. bounceTime: 600,
  5979. bounceEasing: '',
  5980. preventDefault: true,
  5981. preventDefaultException: {tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/},
  5982. HWCompositing: true,
  5983. useTransition: true,
  5984. useTransform: true
  5985. };
  5986. for (var i in options) {
  5987. this.options[i] = options[i];
  5988. }
  5989. // Normalize options
  5990. this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
  5991. this.options.useTransition = utils.hasTransition && this.options.useTransition;
  5992. this.options.useTransform = utils.hasTransform && this.options.useTransform;
  5993. this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
  5994. this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
  5995. // If you want eventPassthrough I have to lock one of the axes
  5996. this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
  5997. this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
  5998. // With eventPassthrough we also need lockDirection mechanism
  5999. this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
  6000. this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
  6001. this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
  6002. this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
  6003. if (this.options.tap === true) {
  6004. this.options.tap = 'tap';
  6005. }
  6006. // INSERT POINT: NORMALIZATION
  6007. // Some defaults
  6008. this.x = 0;
  6009. this.y = 0;
  6010. this.directionX = 0;
  6011. this.directionY = 0;
  6012. this._events = {};
  6013. // INSERT POINT: DEFAULTS
  6014. this._init();
  6015. this.refresh();
  6016. this.scrollTo(this.options.startX, this.options.startY);
  6017. this.enable();
  6018. }
  6019. IScroll.prototype = {
  6020. version: '5.1.3',
  6021. _init: function() {
  6022. this._initEvents();
  6023. // INSERT POINT: _init
  6024. },
  6025. destroy: function() {
  6026. this._initEvents(true);
  6027. this._execEvent('destroy');
  6028. },
  6029. _transitionEnd: function(e) {
  6030. if (e.target != this.scroller || !this.isInTransition) {
  6031. return;
  6032. }
  6033. this._transitionTime();
  6034. if (!this.resetPosition(this.options.bounceTime)) {
  6035. this.isInTransition = false;
  6036. this._execEvent('scrollEnd');
  6037. }
  6038. },
  6039. _start: function(e) {
  6040. // React to left mouse button only
  6041. if (utils.eventType[e.type] != 1) {
  6042. if (e.button !== 0) {
  6043. return;
  6044. }
  6045. }
  6046. if (!this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated)) {
  6047. return;
  6048. }
  6049. if (this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException)) {
  6050. e.preventDefault();
  6051. }
  6052. var point = e.touches ? e.touches[0] : e,
  6053. pos;
  6054. this.initiated = utils.eventType[e.type];
  6055. this.moved = false;
  6056. this.distX = 0;
  6057. this.distY = 0;
  6058. this.directionX = 0;
  6059. this.directionY = 0;
  6060. this.directionLocked = 0;
  6061. this._transitionTime();
  6062. this.startTime = utils.getTime();
  6063. if (this.options.useTransition && this.isInTransition) {
  6064. this.isInTransition = false;
  6065. pos = this.getComputedPosition();
  6066. this._translate(Math.round(pos.x), Math.round(pos.y));
  6067. this._execEvent('scrollEnd');
  6068. } else if (!this.options.useTransition && this.isAnimating) {
  6069. this.isAnimating = false;
  6070. this._execEvent('scrollEnd');
  6071. }
  6072. this.startX = this.x;
  6073. this.startY = this.y;
  6074. this.absStartX = this.x;
  6075. this.absStartY = this.y;
  6076. this.pointX = point.pageX;
  6077. this.pointY = point.pageY;
  6078. this._execEvent('beforeScrollStart');
  6079. },
  6080. _move: function(e) {
  6081. if (!this.enabled || utils.eventType[e.type] !== this.initiated) {
  6082. return;
  6083. }
  6084. if (this.options.preventDefault) { // increases performance on Android? TODO: check!
  6085. e.preventDefault();
  6086. }
  6087. var point = e.touches ? e.touches[0] : e,
  6088. deltaX = point.pageX - this.pointX,
  6089. deltaY = point.pageY - this.pointY,
  6090. timestamp = utils.getTime(),
  6091. newX, newY,
  6092. absDistX, absDistY;
  6093. this.pointX = point.pageX;
  6094. this.pointY = point.pageY;
  6095. this.distX += deltaX;
  6096. this.distY += deltaY;
  6097. absDistX = Math.abs(this.distX);
  6098. absDistY = Math.abs(this.distY);
  6099. // We need to move at least 10 pixels for the scrolling to initiate
  6100. if (timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10)) {
  6101. return;
  6102. }
  6103. // If you are scrolling in one direction lock the other
  6104. if (!this.directionLocked && !this.options.freeScroll) {
  6105. if (absDistX > absDistY + this.options.directionLockThreshold) {
  6106. this.directionLocked = 'h'; // lock horizontally
  6107. } else if (absDistY >= absDistX + this.options.directionLockThreshold) {
  6108. this.directionLocked = 'v'; // lock vertically
  6109. } else {
  6110. this.directionLocked = 'n'; // no lock
  6111. }
  6112. }
  6113. if (this.directionLocked == 'h') {
  6114. if (this.options.eventPassthrough == 'vertical') {
  6115. e.preventDefault();
  6116. } else if (this.options.eventPassthrough == 'horizontal') {
  6117. this.initiated = false;
  6118. return;
  6119. }
  6120. deltaY = 0;
  6121. } else if (this.directionLocked == 'v') {
  6122. if (this.options.eventPassthrough == 'horizontal') {
  6123. e.preventDefault();
  6124. } else if (this.options.eventPassthrough == 'vertical') {
  6125. this.initiated = false;
  6126. return;
  6127. }
  6128. deltaX = 0;
  6129. }
  6130. deltaX = this.hasHorizontalScroll ? deltaX : 0;
  6131. deltaY = this.hasVerticalScroll ? deltaY : 0;
  6132. newX = this.x + deltaX;
  6133. newY = this.y + deltaY;
  6134. // Slow down if outside of the boundaries
  6135. if (newX > 0 || newX < this.maxScrollX) {
  6136. newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
  6137. }
  6138. if (newY > 0 || newY < this.maxScrollY) {
  6139. newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
  6140. }
  6141. this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
  6142. this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
  6143. if (!this.moved) {
  6144. this._execEvent('scrollStart');
  6145. }
  6146. this.moved = true;
  6147. this._translate(newX, newY);
  6148. /* REPLACE START: _move */
  6149. if (timestamp - this.startTime > 300) {
  6150. this.startTime = timestamp;
  6151. this.startX = this.x;
  6152. this.startY = this.y;
  6153. }
  6154. /* REPLACE END: _move */
  6155. },
  6156. _end: function(e) {
  6157. if (!this.enabled || utils.eventType[e.type] !== this.initiated) {
  6158. return;
  6159. }
  6160. if (this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException)) {
  6161. e.preventDefault();
  6162. }
  6163. var point = e.changedTouches ? e.changedTouches[0] : e,
  6164. momentumX,
  6165. momentumY,
  6166. duration = utils.getTime() - this.startTime,
  6167. newX = Math.round(this.x),
  6168. newY = Math.round(this.y),
  6169. distanceX = Math.abs(newX - this.startX),
  6170. distanceY = Math.abs(newY - this.startY),
  6171. time = 0,
  6172. easing = '';
  6173. this.isInTransition = 0;
  6174. this.initiated = 0;
  6175. this.endTime = utils.getTime();
  6176. // reset if we are outside of the boundaries
  6177. if (this.resetPosition(this.options.bounceTime)) {
  6178. return;
  6179. }
  6180. this.scrollTo(newX, newY); // ensures that the last position is rounded
  6181. // we scrolled less than 10 pixels
  6182. if (!this.moved) {
  6183. if (this.options.tap) {
  6184. utils.tap(e, this.options.tap);
  6185. }
  6186. if (this.options.click) {
  6187. utils.click(e);
  6188. }
  6189. this._execEvent('scrollCancel');
  6190. return;
  6191. }
  6192. if (this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100) {
  6193. this._execEvent('flick');
  6194. return;
  6195. }
  6196. // start momentum animation if needed
  6197. if (this.options.momentum && duration < 300) {
  6198. momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : {
  6199. destination: newX,
  6200. duration: 0
  6201. };
  6202. momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : {
  6203. destination: newY,
  6204. duration: 0
  6205. };
  6206. newX = momentumX.destination;
  6207. newY = momentumY.destination;
  6208. time = Math.max(momentumX.duration, momentumY.duration);
  6209. this.isInTransition = 1;
  6210. }
  6211. // INSERT POINT: _end
  6212. if (newX != this.x || newY != this.y) {
  6213. // change easing function when scroller goes out of the boundaries
  6214. if (newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY) {
  6215. easing = utils.ease.quadratic;
  6216. }
  6217. this.scrollTo(newX, newY, time, easing);
  6218. return;
  6219. }
  6220. this._execEvent('scrollEnd');
  6221. },
  6222. _resize: function() {
  6223. var that = this;
  6224. clearTimeout(this.resizeTimeout);
  6225. this.resizeTimeout = setTimeout(function() {
  6226. that.refresh();
  6227. }, this.options.resizePolling);
  6228. },
  6229. resetPosition: function(time) {
  6230. var x = this.x,
  6231. y = this.y;
  6232. time = time || 0;
  6233. if (!this.hasHorizontalScroll || this.x > 0) {
  6234. x = 0;
  6235. } else if (this.x < this.maxScrollX) {
  6236. x = this.maxScrollX;
  6237. }
  6238. if (!this.hasVerticalScroll || this.y > 0) {
  6239. y = 0;
  6240. } else if (this.y < this.maxScrollY) {
  6241. y = this.maxScrollY;
  6242. }
  6243. if (x == this.x && y == this.y) {
  6244. return false;
  6245. }
  6246. this.scrollTo(x, y, time, this.options.bounceEasing);
  6247. return true;
  6248. },
  6249. disable: function() {
  6250. this.enabled = false;
  6251. },
  6252. enable: function() {
  6253. this.enabled = true;
  6254. },
  6255. refresh: function() {
  6256. var rf = this.wrapper.offsetHeight; // Force reflow
  6257. this.wrapperWidth = this.wrapper.clientWidth;
  6258. this.wrapperHeight = this.wrapper.clientHeight;
  6259. /* REPLACE START: refresh */
  6260. this.scrollerWidth = this.scroller.offsetWidth;
  6261. this.scrollerHeight = this.scroller.offsetHeight;
  6262. this.maxScrollX = this.wrapperWidth - this.scrollerWidth;
  6263. this.maxScrollY = this.wrapperHeight - this.scrollerHeight;
  6264. /* REPLACE END: refresh */
  6265. this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0;
  6266. this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0;
  6267. if (!this.hasHorizontalScroll) {
  6268. this.maxScrollX = 0;
  6269. this.scrollerWidth = this.wrapperWidth;
  6270. }
  6271. if (!this.hasVerticalScroll) {
  6272. this.maxScrollY = 0;
  6273. this.scrollerHeight = this.wrapperHeight;
  6274. }
  6275. this.endTime = 0;
  6276. this.directionX = 0;
  6277. this.directionY = 0;
  6278. this.wrapperOffset = utils.offset(this.wrapper);
  6279. this._execEvent('refresh');
  6280. this.resetPosition();
  6281. // INSERT POINT: _refresh
  6282. },
  6283. on: function(type, fn) {
  6284. if (!this._events[type]) {
  6285. this._events[type] = [];
  6286. }
  6287. this._events[type].push(fn);
  6288. },
  6289. off: function(type, fn) {
  6290. if (!this._events[type]) {
  6291. return;
  6292. }
  6293. var index = this._events[type].indexOf(fn);
  6294. if (index > -1) {
  6295. this._events[type].splice(index, 1);
  6296. }
  6297. },
  6298. _execEvent: function(type) {
  6299. if (!this._events[type]) {
  6300. return;
  6301. }
  6302. var i = 0,
  6303. l = this._events[type].length;
  6304. if (!l) {
  6305. return;
  6306. }
  6307. for (; i < l; i++) {
  6308. this._events[type][i].apply(this, [].slice.call(arguments, 1));
  6309. }
  6310. },
  6311. scrollBy: function(x, y, time, easing) {
  6312. x = this.x + x;
  6313. y = this.y + y;
  6314. time = time || 0;
  6315. this.scrollTo(x, y, time, easing);
  6316. },
  6317. scrollTo: function(x, y, time, easing) {
  6318. easing = easing || utils.ease.circular;
  6319. this.isInTransition = this.options.useTransition && time > 0;
  6320. if (!time || (this.options.useTransition && easing.style)) {
  6321. this._transitionTimingFunction(easing.style);
  6322. this._transitionTime(time);
  6323. this._translate(x, y);
  6324. } else {
  6325. this._animate(x, y, time, easing.fn);
  6326. }
  6327. },
  6328. scrollToElement: function(el, time, offsetX, offsetY, easing) {
  6329. el = el.nodeType ? el : this.scroller.querySelector(el);
  6330. if (!el) {
  6331. return;
  6332. }
  6333. var pos = utils.offset(el);
  6334. pos.left -= this.wrapperOffset.left;
  6335. pos.top -= this.wrapperOffset.top;
  6336. // if offsetX/Y are true we center the element to the screen
  6337. if (offsetX === true) {
  6338. offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
  6339. }
  6340. if (offsetY === true) {
  6341. offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
  6342. }
  6343. pos.left -= offsetX || 0;
  6344. pos.top -= offsetY || 0;
  6345. pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
  6346. pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top;
  6347. time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x - pos.left), Math.abs(this.y - pos.top)) : time;
  6348. this.scrollTo(pos.left, pos.top, time, easing);
  6349. },
  6350. _transitionTime: function(time) {
  6351. time = time || 0;
  6352. this.scrollerStyle[utils.style.transitionDuration] = time + 'ms';
  6353. if (!time && utils.isBadAndroid) {
  6354. this.scrollerStyle[utils.style.transitionDuration] = '0.001s';
  6355. }
  6356. // INSERT POINT: _transitionTime
  6357. },
  6358. _transitionTimingFunction: function(easing) {
  6359. this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
  6360. // INSERT POINT: _transitionTimingFunction
  6361. },
  6362. _translate: function(x, y) {
  6363. if (this.options.useTransform) {
  6364. /* REPLACE START: _translate */
  6365. this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
  6366. /* REPLACE END: _translate */
  6367. } else {
  6368. x = Math.round(x);
  6369. y = Math.round(y);
  6370. this.scrollerStyle.left = x + 'px';
  6371. this.scrollerStyle.top = y + 'px';
  6372. }
  6373. this.x = x;
  6374. this.y = y;
  6375. // INSERT POINT: _translate
  6376. },
  6377. _initEvents: function(remove) {
  6378. var eventType = remove ? utils.removeEvent : utils.addEvent,
  6379. target = this.options.bindToWrapper ? this.wrapper : window;
  6380. eventType(window, 'orientationchange', this);
  6381. eventType(window, 'resize', this);
  6382. if (this.options.click) {
  6383. eventType(this.wrapper, 'click', this, true);
  6384. }
  6385. if (!this.options.disableMouse) {
  6386. eventType(this.wrapper, 'mousedown', this);
  6387. eventType(target, 'mousemove', this);
  6388. eventType(target, 'mousecancel', this);
  6389. eventType(target, 'mouseup', this);
  6390. }
  6391. if (utils.hasPointer && !this.options.disablePointer) {
  6392. eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
  6393. eventType(target, utils.prefixPointerEvent('pointermove'), this);
  6394. eventType(target, utils.prefixPointerEvent('pointercancel'), this);
  6395. eventType(target, utils.prefixPointerEvent('pointerup'), this);
  6396. }
  6397. if (utils.hasTouch && !this.options.disableTouch) {
  6398. eventType(this.wrapper, 'touchstart', this);
  6399. eventType(target, 'touchmove', this);
  6400. eventType(target, 'touchcancel', this);
  6401. eventType(target, 'touchend', this);
  6402. }
  6403. eventType(this.scroller, 'transitionend', this);
  6404. eventType(this.scroller, 'webkitTransitionEnd', this);
  6405. eventType(this.scroller, 'oTransitionEnd', this);
  6406. eventType(this.scroller, 'MSTransitionEnd', this);
  6407. },
  6408. getComputedPosition: function() {
  6409. var matrix = window.getComputedStyle(this.scroller, null),
  6410. x, y;
  6411. if (this.options.useTransform) {
  6412. matrix = matrix[utils.style.transform].split(')')[0].split(', ');
  6413. x = +(matrix[12] || matrix[4]);
  6414. y = +(matrix[13] || matrix[5]);
  6415. } else {
  6416. x = +matrix.left.replace(/[^-\d.]/g, '');
  6417. y = +matrix.top.replace(/[^-\d.]/g, '');
  6418. }
  6419. return {x: x, y: y};
  6420. },
  6421. _animate: function(destX, destY, duration, easingFn) {
  6422. var that = this,
  6423. startX = this.x,
  6424. startY = this.y,
  6425. startTime = utils.getTime(),
  6426. destTime = startTime + duration;
  6427. function step() {
  6428. var now = utils.getTime(),
  6429. newX, newY,
  6430. easing;
  6431. if (now >= destTime) {
  6432. that.isAnimating = false;
  6433. that._translate(destX, destY);
  6434. if (!that.resetPosition(that.options.bounceTime)) {
  6435. that._execEvent('scrollEnd');
  6436. }
  6437. return;
  6438. }
  6439. now = ( now - startTime ) / duration;
  6440. easing = easingFn(now);
  6441. newX = ( destX - startX ) * easing + startX;
  6442. newY = ( destY - startY ) * easing + startY;
  6443. that._translate(newX, newY);
  6444. if (that.isAnimating) {
  6445. rAF(step);
  6446. }
  6447. }
  6448. this.isAnimating = true;
  6449. step();
  6450. },
  6451. handleEvent: function(e) {
  6452. switch (e.type) {
  6453. case 'touchstart':
  6454. case 'pointerdown':
  6455. case 'MSPointerDown':
  6456. case 'mousedown':
  6457. this._start(e);
  6458. break;
  6459. case 'touchmove':
  6460. case 'pointermove':
  6461. case 'MSPointerMove':
  6462. case 'mousemove':
  6463. this._move(e);
  6464. break;
  6465. case 'touchend':
  6466. case 'pointerup':
  6467. case 'MSPointerUp':
  6468. case 'mouseup':
  6469. case 'touchcancel':
  6470. case 'pointercancel':
  6471. case 'MSPointerCancel':
  6472. case 'mousecancel':
  6473. this._end(e);
  6474. break;
  6475. case 'orientationchange':
  6476. case 'resize':
  6477. this._resize();
  6478. break;
  6479. case 'transitionend':
  6480. case 'webkitTransitionEnd':
  6481. case 'oTransitionEnd':
  6482. case 'MSTransitionEnd':
  6483. this._transitionEnd(e);
  6484. break;
  6485. case 'wheel':
  6486. case 'DOMMouseScroll':
  6487. case 'mousewheel':
  6488. this._wheel(e);
  6489. break;
  6490. case 'keydown':
  6491. this._key(e);
  6492. break;
  6493. case 'click':
  6494. if (!e._constructed) {
  6495. e.preventDefault();
  6496. e.stopPropagation();
  6497. }
  6498. break;
  6499. }
  6500. }
  6501. };
  6502. IScroll.utils = utils;
  6503. module.exports = UI.iScroll = IScroll;
  6504. /* jshint unused: true */
  6505. /* jshint +W101, +W116, +W109 */
  6506. /***/ },
  6507. /* 15 */
  6508. /***/ function(module, exports, __webpack_require__) {
  6509. 'use strict';
  6510. var $ = __webpack_require__(1);
  6511. var UI = __webpack_require__(2);
  6512. var dimmer = __webpack_require__(9);
  6513. var $doc = $(document);
  6514. var supportTransition = UI.support.transition;
  6515. /**
  6516. * @reference https://github.com/nolimits4web/Framework7/blob/master/src/js/modals.js
  6517. * @license https://github.com/nolimits4web/Framework7/blob/master/LICENSE
  6518. */
  6519. var Modal = function(element, options) {
  6520. this.options = $.extend({}, Modal.DEFAULTS, options || {});
  6521. this.$element = $(element);
  6522. this.$dialog = this.$element.find('.am-modal-dialog');
  6523. if (!this.$element.attr('id')) {
  6524. this.$element.attr('id', UI.utils.generateGUID('am-modal'));
  6525. }
  6526. this.isPopup = this.$element.hasClass('am-popup');
  6527. this.isActions = this.$element.hasClass('am-modal-actions');
  6528. this.isPrompt = this.$element.hasClass('am-modal-prompt');
  6529. this.isLoading = this.$element.hasClass('am-modal-loading');
  6530. this.active = this.transitioning = this.relatedTarget = null;
  6531. this.dimmer = this.options.dimmer ? dimmer : {
  6532. open: function() {},
  6533. close: function() {}
  6534. };
  6535. this.events();
  6536. };
  6537. Modal.DEFAULTS = {
  6538. className: {
  6539. active: 'am-modal-active',
  6540. out: 'am-modal-out'
  6541. },
  6542. selector: {
  6543. modal: '.am-modal',
  6544. active: '.am-modal-active'
  6545. },
  6546. closeViaDimmer: true,
  6547. cancelable: true,
  6548. onConfirm: function() {
  6549. },
  6550. onCancel: function() {
  6551. },
  6552. closeOnCancel: true,
  6553. closeOnConfirm: true,
  6554. dimmer: true,
  6555. height: undefined,
  6556. width: undefined,
  6557. duration: 300, // must equal the CSS transition duration
  6558. transitionEnd: supportTransition && supportTransition.end + '.modal.amui'
  6559. };
  6560. Modal.prototype.toggle = function(relatedTarget) {
  6561. return this.active ? this.close() : this.open(relatedTarget);
  6562. };
  6563. Modal.prototype.open = function(relatedTarget) {
  6564. var $element = this.$element;
  6565. var options = this.options;
  6566. var isPopup = this.isPopup;
  6567. var width = options.width;
  6568. var height = options.height;
  6569. var style = {};
  6570. if (this.active) {
  6571. return;
  6572. }
  6573. if (!this.$element.length) {
  6574. return;
  6575. }
  6576. // callback hook
  6577. relatedTarget && (this.relatedTarget = relatedTarget);
  6578. // 判断如果还在动画,就先触发之前的closed事件
  6579. if (this.transitioning) {
  6580. clearTimeout($element.transitionEndTimmer);
  6581. $element.transitionEndTimmer = null;
  6582. $element.trigger(options.transitionEnd).off(options.transitionEnd);
  6583. }
  6584. isPopup && this.$element.show();
  6585. this.active = true;
  6586. $element.trigger($.Event('open.modal.amui', {relatedTarget: relatedTarget}));
  6587. this.dimmer.open($element);
  6588. $element.show().redraw();
  6589. // apply Modal width/height if set
  6590. if (!isPopup && !this.isActions) {
  6591. if (width) {
  6592. width = parseInt(width, 10);
  6593. style.width = width + 'px';
  6594. style.marginLeft = -parseInt(width / 2) + 'px';
  6595. }
  6596. if (height) {
  6597. height = parseInt(height, 10);
  6598. // style.height = height + 'px';
  6599. style.marginTop = -parseInt(height / 2) + 'px';
  6600. // the background color is styled to $dialog
  6601. // so the height should set to $dialog
  6602. this.$dialog.css({height: height + 'px'});
  6603. } else {
  6604. style.marginTop = -parseInt($element.height() / 2, 10) + 'px';
  6605. }
  6606. $element.css(style);
  6607. }
  6608. $element.
  6609. removeClass(options.className.out).
  6610. addClass(options.className.active);
  6611. this.transitioning = 1;
  6612. var complete = function() {
  6613. $element.trigger($.Event('opened.modal.amui',
  6614. {relatedTarget: relatedTarget}));
  6615. this.transitioning = 0;
  6616. // Prompt auto focus
  6617. if (this.isPrompt) {
  6618. this.$dialog.find('input').eq(0).focus();
  6619. }
  6620. };
  6621. if (!supportTransition) {
  6622. return complete.call(this);
  6623. }
  6624. $element.
  6625. one(options.transitionEnd, $.proxy(complete, this)).
  6626. emulateTransitionEnd(options.duration);
  6627. };
  6628. Modal.prototype.close = function(relatedTarget) {
  6629. if (!this.active) {
  6630. return;
  6631. }
  6632. var $element = this.$element;
  6633. var options = this.options;
  6634. var isPopup = this.isPopup;
  6635. // 判断如果还在动画,就先触发之前的opened事件
  6636. if (this.transitioning) {
  6637. clearTimeout($element.transitionEndTimmer);
  6638. $element.transitionEndTimmer = null;
  6639. $element.trigger(options.transitionEnd).off(options.transitionEnd);
  6640. this.dimmer.close($element, true);
  6641. }
  6642. this.$element.trigger($.Event('close.modal.amui',
  6643. {relatedTarget: relatedTarget}));
  6644. this.transitioning = 1;
  6645. var complete = function() {
  6646. $element.trigger('closed.modal.amui');
  6647. isPopup && $element.removeClass(options.className.out);
  6648. $element.hide();
  6649. this.transitioning = 0;
  6650. // 不强制关闭 Dimmer,以便多个 Modal 可以共享 Dimmer
  6651. this.dimmer.close($element, false);
  6652. this.active = false;
  6653. };
  6654. $element.removeClass(options.className.active).
  6655. addClass(options.className.out);
  6656. if (!supportTransition) {
  6657. return complete.call(this);
  6658. }
  6659. $element.one(options.transitionEnd, $.proxy(complete, this)).
  6660. emulateTransitionEnd(options.duration);
  6661. };
  6662. Modal.prototype.events = function() {
  6663. var options = this.options;
  6664. var _this = this;
  6665. var $element = this.$element;
  6666. var $ipt = $element.find('.am-modal-prompt-input');
  6667. var $confirm = $element.find('[data-am-modal-confirm]');
  6668. var $cancel = $element.find('[data-am-modal-cancel]');
  6669. var getData = function() {
  6670. var data = [];
  6671. $ipt.each(function() {
  6672. data.push($(this).val());
  6673. });
  6674. return (data.length === 0) ? undefined :
  6675. ((data.length === 1) ? data[0] : data);
  6676. };
  6677. // close via Esc key
  6678. if (this.options.cancelable) {
  6679. $element.on('keyup.modal.amui', function(e) {
  6680. if (_this.active && e.which === 27) {
  6681. $element.trigger('cancel.modal.amui');
  6682. _this.close();
  6683. }
  6684. });
  6685. }
  6686. // Close Modal when dimmer clicked
  6687. if (this.options.dimmer && this.options.closeViaDimmer && !this.isLoading) {
  6688. this.dimmer.$element.on('click.dimmer.modal.amui', function(e) {
  6689. _this.close();
  6690. });
  6691. }
  6692. // Close Modal when button clicked
  6693. $element.on('click.close.modal.amui', '[data-am-modal-close], .am-modal-btn', function(e) {
  6694. e.preventDefault();
  6695. var $this = $(this);
  6696. if ($this.is($confirm)) {
  6697. options.closeOnConfirm && _this.close();
  6698. } else if ($this.is($cancel)) {
  6699. options.closeOnCancel && _this.close();
  6700. } else {
  6701. _this.close();
  6702. }
  6703. });
  6704. $confirm.on('click.confirm.modal.amui',
  6705. function() {
  6706. $element.trigger($.Event('confirm.modal.amui', {
  6707. trigger: this
  6708. }));
  6709. });
  6710. $cancel.on('click.cancel.modal.amui', function() {
  6711. $element.trigger($.Event('cancel.modal.amui', {
  6712. trigger: this
  6713. }));
  6714. });
  6715. $element.on('confirm.modal.amui', function(e) {
  6716. e.data = getData();
  6717. _this.options.onConfirm.call(_this, e);
  6718. }).on('cancel.modal.amui', function(e) {
  6719. e.data = getData();
  6720. _this.options.onCancel.call(_this, e);
  6721. });
  6722. };
  6723. function Plugin(option, relatedTarget) {
  6724. return this.each(function() {
  6725. var $this = $(this);
  6726. var data = $this.data('amui.modal');
  6727. var options = typeof option == 'object' && option;
  6728. if (!data) {
  6729. $this.data('amui.modal', (data = new Modal(this, options)));
  6730. }
  6731. if (typeof option == 'string') {
  6732. data[option] && data[option](relatedTarget);
  6733. } else {
  6734. data.toggle(option && option.relatedTarget || undefined);
  6735. }
  6736. });
  6737. }
  6738. $.fn.modal = Plugin;
  6739. // Init
  6740. $doc.on('click.modal.amui.data-api', '[data-am-modal]', function() {
  6741. var $this = $(this);
  6742. var options = UI.utils.parseOptions($this.attr('data-am-modal'));
  6743. var $target = $(options.target ||
  6744. (this.href && this.href.replace(/.*(?=#[^\s]+$)/, '')));
  6745. var option = $target.data('amui.modal') ? 'toggle' : options;
  6746. Plugin.call($target, option, this);
  6747. });
  6748. module.exports = UI.modal = Modal;
  6749. /***/ },
  6750. /* 16 */
  6751. /***/ function(module, exports, __webpack_require__) {
  6752. 'use strict';
  6753. var $ = __webpack_require__(1);
  6754. var UI = __webpack_require__(2);
  6755. __webpack_require__(3);
  6756. var $win = $(window);
  6757. var $doc = $(document);
  6758. var scrollPos;
  6759. /**
  6760. * @via https://github.com/uikit/uikit/blob/master/src/js/offcanvas.js
  6761. * @license https://github.com/uikit/uikit/blob/master/LICENSE.md
  6762. */
  6763. var OffCanvas = function(element, options) {
  6764. this.$element = $(element);
  6765. this.options = $.extend({}, OffCanvas.DEFAULTS, options);
  6766. this.active = null;
  6767. this.bindEvents();
  6768. };
  6769. OffCanvas.DEFAULTS = {
  6770. duration: 300,
  6771. effect: 'overlay' // {push|overlay}, push is too expensive
  6772. };
  6773. OffCanvas.prototype.open = function(relatedElement) {
  6774. var _this = this;
  6775. var $element = this.$element;
  6776. if (!$element.length || $element.hasClass('am-active')) {
  6777. return;
  6778. }
  6779. var effect = this.options.effect;
  6780. var $html = $('html');
  6781. var $body = $('body');
  6782. var $bar = $element.find('.am-offcanvas-bar').first();
  6783. var dir = $bar.hasClass('am-offcanvas-bar-flip') ? -1 : 1;
  6784. $bar.addClass('am-offcanvas-bar-' + effect);
  6785. scrollPos = {x: window.scrollX, y: window.scrollY};
  6786. $element.addClass('am-active');
  6787. $body.css({
  6788. width: window.innerWidth,
  6789. height: $win.height()
  6790. }).addClass('am-offcanvas-page');
  6791. if (effect !== 'overlay') {
  6792. $body.css({
  6793. 'margin-left': $bar.outerWidth() * dir
  6794. }).width(); // force redraw
  6795. }
  6796. $html.css('margin-top', scrollPos.y * -1);
  6797. setTimeout(function() {
  6798. $bar.addClass('am-offcanvas-bar-active').width();
  6799. }, 0);
  6800. $element.trigger('open.offcanvas.amui');
  6801. this.active = 1;
  6802. // Close OffCanvas when none content area clicked
  6803. $element.on('click.offcanvas.amui', function(e) {
  6804. var $target = $(e.target);
  6805. if ($target.hasClass('am-offcanvas-bar')) {
  6806. return;
  6807. }
  6808. if ($target.parents('.am-offcanvas-bar').first().length) {
  6809. return;
  6810. }
  6811. // https://developer.mozilla.org/zh-CN/docs/DOM/event.stopImmediatePropagation
  6812. e.stopImmediatePropagation();
  6813. _this.close();
  6814. });
  6815. $html.on('keydown.offcanvas.amui', function(e) {
  6816. (e.keyCode === 27) && _this.close();
  6817. });
  6818. };
  6819. OffCanvas.prototype.close = function(relatedElement) {
  6820. var _this = this;
  6821. var $html = $('html');
  6822. var $body = $('body');
  6823. var $element = this.$element;
  6824. var $bar = $element.find('.am-offcanvas-bar').first();
  6825. if (!$element.length || !this.active || !$element.hasClass('am-active')) {
  6826. return;
  6827. }
  6828. $element.trigger('close.offcanvas.amui');
  6829. function complete() {
  6830. $body
  6831. .removeClass('am-offcanvas-page')
  6832. .css({
  6833. width: '',
  6834. height: '',
  6835. 'margin-left': '',
  6836. 'margin-right': ''
  6837. });
  6838. $element.removeClass('am-active');
  6839. $bar.removeClass('am-offcanvas-bar-active');
  6840. $html.css('margin-top', '');
  6841. window.scrollTo(scrollPos.x, scrollPos.y);
  6842. $element.trigger('closed.offcanvas.amui');
  6843. _this.active = 0;
  6844. }
  6845. if (UI.support.transition) {
  6846. setTimeout(function() {
  6847. $bar.removeClass('am-offcanvas-bar-active');
  6848. }, 0);
  6849. $body.css('margin-left', '').one(UI.support.transition.end, function() {
  6850. complete();
  6851. }).emulateTransitionEnd(this.options.duration);
  6852. } else {
  6853. complete();
  6854. }
  6855. $element.off('click.offcanvas.amui');
  6856. $html.off('.offcanvas.amui');
  6857. };
  6858. OffCanvas.prototype.bindEvents = function() {
  6859. var _this = this;
  6860. $doc.on('click.offcanvas.amui', '[data-am-dismiss="offcanvas"]', function(e) {
  6861. e.preventDefault();
  6862. _this.close();
  6863. });
  6864. $win.on('resize.offcanvas.amui orientationchange.offcanvas.amui',
  6865. function() {
  6866. _this.active && _this.close();
  6867. });
  6868. this.$element.hammer().on('swipeleft swipeleft', function(e) {
  6869. e.preventDefault();
  6870. _this.close();
  6871. });
  6872. return this;
  6873. };
  6874. function Plugin(option, relatedElement) {
  6875. var args = Array.prototype.slice.call(arguments, 1);
  6876. return this.each(function() {
  6877. var $this = $(this);
  6878. var data = $this.data('amui.offcanvas');
  6879. var options = $.extend({}, typeof option == 'object' && option);
  6880. if (!data) {
  6881. $this.data('amui.offcanvas', (data = new OffCanvas(this, options)));
  6882. (!option || typeof option == 'object') && data.open(relatedElement);
  6883. }
  6884. if (typeof option == 'string') {
  6885. data[option] && data[option].apply(data, args);
  6886. }
  6887. });
  6888. }
  6889. $.fn.offCanvas = Plugin;
  6890. // Init code
  6891. $doc.on('click.offcanvas.amui', '[data-am-offcanvas]', function(e) {
  6892. e.preventDefault();
  6893. var $this = $(this);
  6894. var options = UI.utils.parseOptions($this.data('amOffcanvas'));
  6895. var $target = $(options.target ||
  6896. (this.href && this.href.replace(/.*(?=#[^\s]+$)/, '')));
  6897. var option = $target.data('amui.offcanvas') ? 'open' : options;
  6898. Plugin.call($target, option, this);
  6899. });
  6900. module.exports = UI.offcanvas = OffCanvas;
  6901. // TODO: 优化动画效果
  6902. // http://dbushell.github.io/Responsive-Off-Canvas-Menu/step4.html
  6903. /***/ },
  6904. /* 17 */
  6905. /***/ function(module, exports, __webpack_require__) {
  6906. 'use strict';
  6907. var $ = __webpack_require__(1);
  6908. var UI = __webpack_require__(2);
  6909. /**
  6910. * @via https://github.com/manuelstofer/pinchzoom/blob/master/src/pinchzoom.js
  6911. * @license the MIT License.
  6912. */
  6913. var definePinchZoom = function($) {
  6914. /**
  6915. * Pinch zoom using jQuery
  6916. * @version 0.0.2
  6917. * @author Manuel Stofer <mst@rtp.ch>
  6918. * @param el
  6919. * @param options
  6920. * @constructor
  6921. */
  6922. var PinchZoom = function(el, options) {
  6923. this.el = $(el);
  6924. this.zoomFactor = 1;
  6925. this.lastScale = 1;
  6926. this.offset = {
  6927. x: 0,
  6928. y: 0
  6929. };
  6930. this.options = $.extend({}, this.defaults, options);
  6931. this.setupMarkup();
  6932. this.bindEvents();
  6933. this.update();
  6934. // default enable.
  6935. this.enable();
  6936. },
  6937. sum = function(a, b) {
  6938. return a + b;
  6939. },
  6940. isCloseTo = function(value, expected) {
  6941. return value > expected - 0.01 && value < expected + 0.01;
  6942. };
  6943. PinchZoom.prototype = {
  6944. defaults: {
  6945. tapZoomFactor: 2,
  6946. zoomOutFactor: 1.3,
  6947. animationDuration: 300,
  6948. animationInterval: 5,
  6949. maxZoom: 5,
  6950. minZoom: 0.5,
  6951. lockDragAxis: false,
  6952. use2d: false,
  6953. zoomStartEventName: 'pz_zoomstart',
  6954. zoomEndEventName: 'pz_zoomend',
  6955. dragStartEventName: 'pz_dragstart',
  6956. dragEndEventName: 'pz_dragend',
  6957. doubleTapEventName: 'pz_doubletap'
  6958. },
  6959. /**
  6960. * Event handler for 'dragstart'
  6961. * @param event
  6962. */
  6963. handleDragStart: function(event) {
  6964. this.el.trigger(this.options.dragStartEventName);
  6965. this.stopAnimation();
  6966. this.lastDragPosition = false;
  6967. this.hasInteraction = true;
  6968. this.handleDrag(event);
  6969. },
  6970. /**
  6971. * Event handler for 'drag'
  6972. * @param event
  6973. */
  6974. handleDrag: function(event) {
  6975. if (this.zoomFactor > 1.0) {
  6976. var touch = this.getTouches(event)[0];
  6977. this.drag(touch, this.lastDragPosition);
  6978. this.offset = this.sanitizeOffset(this.offset);
  6979. this.lastDragPosition = touch;
  6980. }
  6981. },
  6982. handleDragEnd: function() {
  6983. this.el.trigger(this.options.dragEndEventName);
  6984. this.end();
  6985. },
  6986. /**
  6987. * Event handler for 'zoomstart'
  6988. * @param event
  6989. */
  6990. handleZoomStart: function(event) {
  6991. this.el.trigger(this.options.zoomStartEventName);
  6992. this.stopAnimation();
  6993. this.lastScale = 1;
  6994. this.nthZoom = 0;
  6995. this.lastZoomCenter = false;
  6996. this.hasInteraction = true;
  6997. },
  6998. /**
  6999. * Event handler for 'zoom'
  7000. * @param event
  7001. */
  7002. handleZoom: function(event, newScale) {
  7003. // a relative scale factor is used
  7004. var touchCenter = this.getTouchCenter(this.getTouches(event)),
  7005. scale = newScale / this.lastScale;
  7006. this.lastScale = newScale;
  7007. // the first touch events are thrown away since they are not precise
  7008. this.nthZoom += 1;
  7009. if (this.nthZoom > 3) {
  7010. this.scale(scale, touchCenter);
  7011. this.drag(touchCenter, this.lastZoomCenter);
  7012. }
  7013. this.lastZoomCenter = touchCenter;
  7014. },
  7015. handleZoomEnd: function() {
  7016. this.el.trigger(this.options.zoomEndEventName);
  7017. this.end();
  7018. },
  7019. /**
  7020. * Event handler for 'doubletap'
  7021. * @param event
  7022. */
  7023. handleDoubleTap: function(event) {
  7024. var center = this.getTouches(event)[0],
  7025. zoomFactor = this.zoomFactor > 1 ? 1 : this.options.tapZoomFactor,
  7026. startZoomFactor = this.zoomFactor,
  7027. updateProgress = (function(progress) {
  7028. this.scaleTo(startZoomFactor + progress * (zoomFactor - startZoomFactor), center);
  7029. }).bind(this);
  7030. if (this.hasInteraction) {
  7031. return;
  7032. }
  7033. if (startZoomFactor > zoomFactor) {
  7034. center = this.getCurrentZoomCenter();
  7035. }
  7036. this.animate(this.options.animationDuration, this.options.animationInterval, updateProgress, this.swing);
  7037. this.el.trigger(this.options.doubleTapEventName);
  7038. },
  7039. /**
  7040. * Max / min values for the offset
  7041. * @param offset
  7042. * @return {Object} the sanitized offset
  7043. */
  7044. sanitizeOffset: function(offset) {
  7045. var maxX = (this.zoomFactor - 1) * this.getContainerX(),
  7046. maxY = (this.zoomFactor - 1) * this.getContainerY(),
  7047. maxOffsetX = Math.max(maxX, 0),
  7048. maxOffsetY = Math.max(maxY, 0),
  7049. minOffsetX = Math.min(maxX, 0),
  7050. minOffsetY = Math.min(maxY, 0);
  7051. return {
  7052. x: Math.min(Math.max(offset.x, minOffsetX), maxOffsetX),
  7053. y: Math.min(Math.max(offset.y, minOffsetY), maxOffsetY)
  7054. };
  7055. },
  7056. /**
  7057. * Scale to a specific zoom factor (not relative)
  7058. * @param zoomFactor
  7059. * @param center
  7060. */
  7061. scaleTo: function(zoomFactor, center) {
  7062. this.scale(zoomFactor / this.zoomFactor, center);
  7063. },
  7064. /**
  7065. * Scales the element from specified center
  7066. * @param scale
  7067. * @param center
  7068. */
  7069. scale: function(scale, center) {
  7070. scale = this.scaleZoomFactor(scale);
  7071. this.addOffset({
  7072. x: (scale - 1) * (center.x + this.offset.x),
  7073. y: (scale - 1) * (center.y + this.offset.y)
  7074. });
  7075. },
  7076. /**
  7077. * Scales the zoom factor relative to current state
  7078. * @param scale
  7079. * @return the actual scale (can differ because of max min zoom factor)
  7080. */
  7081. scaleZoomFactor: function(scale) {
  7082. var originalZoomFactor = this.zoomFactor;
  7083. this.zoomFactor *= scale;
  7084. this.zoomFactor = Math.min(this.options.maxZoom, Math.max(this.zoomFactor, this.options.minZoom));
  7085. return this.zoomFactor / originalZoomFactor;
  7086. },
  7087. /**
  7088. * Drags the element
  7089. * @param center
  7090. * @param lastCenter
  7091. */
  7092. drag: function(center, lastCenter) {
  7093. if (lastCenter) {
  7094. if (this.options.lockDragAxis) {
  7095. // lock scroll to position that was changed the most
  7096. if (Math.abs(center.x - lastCenter.x) > Math.abs(center.y - lastCenter.y)) {
  7097. this.addOffset({
  7098. x: -(center.x - lastCenter.x),
  7099. y: 0
  7100. });
  7101. }
  7102. else {
  7103. this.addOffset({
  7104. y: -(center.y - lastCenter.y),
  7105. x: 0
  7106. });
  7107. }
  7108. }
  7109. else {
  7110. this.addOffset({
  7111. y: -(center.y - lastCenter.y),
  7112. x: -(center.x - lastCenter.x)
  7113. });
  7114. }
  7115. }
  7116. },
  7117. /**
  7118. * Calculates the touch center of multiple touches
  7119. * @param touches
  7120. * @return {Object}
  7121. */
  7122. getTouchCenter: function(touches) {
  7123. return this.getVectorAvg(touches);
  7124. },
  7125. /**
  7126. * Calculates the average of multiple vectors (x, y values)
  7127. */
  7128. getVectorAvg: function(vectors) {
  7129. return {
  7130. x: vectors.map(function(v) {
  7131. return v.x;
  7132. }).reduce(sum) / vectors.length,
  7133. y: vectors.map(function(v) {
  7134. return v.y;
  7135. }).reduce(sum) / vectors.length
  7136. };
  7137. },
  7138. /**
  7139. * Adds an offset
  7140. * @param offset the offset to add
  7141. * @return return true when the offset change was accepted
  7142. */
  7143. addOffset: function(offset) {
  7144. this.offset = {
  7145. x: this.offset.x + offset.x,
  7146. y: this.offset.y + offset.y
  7147. };
  7148. },
  7149. sanitize: function() {
  7150. if (this.zoomFactor < this.options.zoomOutFactor) {
  7151. this.zoomOutAnimation();
  7152. } else if (this.isInsaneOffset(this.offset)) {
  7153. this.sanitizeOffsetAnimation();
  7154. }
  7155. },
  7156. /**
  7157. * Checks if the offset is ok with the current zoom factor
  7158. * @param offset
  7159. * @return {Boolean}
  7160. */
  7161. isInsaneOffset: function(offset) {
  7162. var sanitizedOffset = this.sanitizeOffset(offset);
  7163. return sanitizedOffset.x !== offset.x ||
  7164. sanitizedOffset.y !== offset.y;
  7165. },
  7166. /**
  7167. * Creates an animation moving to a sane offset
  7168. */
  7169. sanitizeOffsetAnimation: function() {
  7170. var targetOffset = this.sanitizeOffset(this.offset),
  7171. startOffset = {
  7172. x: this.offset.x,
  7173. y: this.offset.y
  7174. },
  7175. updateProgress = (function(progress) {
  7176. this.offset.x = startOffset.x + progress * (targetOffset.x - startOffset.x);
  7177. this.offset.y = startOffset.y + progress * (targetOffset.y - startOffset.y);
  7178. this.update();
  7179. }).bind(this);
  7180. this.animate(
  7181. this.options.animationDuration,
  7182. this.options.animationInterval,
  7183. updateProgress,
  7184. this.swing
  7185. );
  7186. },
  7187. /**
  7188. * Zooms back to the original position,
  7189. * (no offset and zoom factor 1)
  7190. */
  7191. zoomOutAnimation: function() {
  7192. var startZoomFactor = this.zoomFactor,
  7193. zoomFactor = 1,
  7194. center = this.getCurrentZoomCenter(),
  7195. updateProgress = (function(progress) {
  7196. this.scaleTo(startZoomFactor + progress * (zoomFactor - startZoomFactor), center);
  7197. }).bind(this);
  7198. this.animate(
  7199. this.options.animationDuration,
  7200. this.options.animationInterval,
  7201. updateProgress,
  7202. this.swing
  7203. );
  7204. },
  7205. /**
  7206. * Updates the aspect ratio
  7207. */
  7208. updateAspectRatio: function() {
  7209. // this.setContainerY(this.getContainerX() / this.getAspectRatio());
  7210. // @modified
  7211. this.setContainerY()
  7212. },
  7213. /**
  7214. * Calculates the initial zoom factor (for the element to fit into the container)
  7215. * @return the initial zoom factor
  7216. */
  7217. getInitialZoomFactor: function() {
  7218. // use .offsetWidth instead of width()
  7219. // because jQuery-width() return the original width but Zepto-width() will calculate width with transform.
  7220. // the same as .height()
  7221. return this.container[0].offsetWidth / this.el[0].offsetWidth;
  7222. },
  7223. /**
  7224. * Calculates the aspect ratio of the element
  7225. * @return the aspect ratio
  7226. */
  7227. getAspectRatio: function() {
  7228. return this.el[0].offsetWidth / this.el[0].offsetHeight;
  7229. },
  7230. /**
  7231. * Calculates the virtual zoom center for the current offset and zoom factor
  7232. * (used for reverse zoom)
  7233. * @return {Object} the current zoom center
  7234. */
  7235. getCurrentZoomCenter: function() {
  7236. // uses following formula to calculate the zoom center x value
  7237. // offset_left / offset_right = zoomcenter_x / (container_x - zoomcenter_x)
  7238. var length = this.container[0].offsetWidth * this.zoomFactor,
  7239. offsetLeft = this.offset.x,
  7240. offsetRight = length - offsetLeft - this.container[0].offsetWidth,
  7241. widthOffsetRatio = offsetLeft / offsetRight,
  7242. centerX = widthOffsetRatio * this.container[0].offsetWidth / (widthOffsetRatio + 1),
  7243. // the same for the zoomcenter y
  7244. height = this.container[0].offsetHeight * this.zoomFactor,
  7245. offsetTop = this.offset.y,
  7246. offsetBottom = height - offsetTop - this.container[0].offsetHeight,
  7247. heightOffsetRatio = offsetTop / offsetBottom,
  7248. centerY = heightOffsetRatio * this.container[0].offsetHeight / (heightOffsetRatio + 1);
  7249. // prevents division by zero
  7250. if (offsetRight === 0) {
  7251. centerX = this.container[0].offsetWidth;
  7252. }
  7253. if (offsetBottom === 0) {
  7254. centerY = this.container[0].offsetHeight;
  7255. }
  7256. return {
  7257. x: centerX,
  7258. y: centerY
  7259. };
  7260. },
  7261. canDrag: function() {
  7262. return !isCloseTo(this.zoomFactor, 1);
  7263. },
  7264. /**
  7265. * Returns the touches of an event relative to the container offset
  7266. * @param event
  7267. * @return array touches
  7268. */
  7269. getTouches: function(event) {
  7270. var position = this.container.offset();
  7271. return Array.prototype.slice.call(event.touches).map(function(touch) {
  7272. return {
  7273. x: touch.pageX - position.left,
  7274. y: touch.pageY - position.top
  7275. };
  7276. });
  7277. },
  7278. /**
  7279. * Animation loop
  7280. * does not support simultaneous animations
  7281. * @param duration
  7282. * @param interval
  7283. * @param framefn
  7284. * @param timefn
  7285. * @param callback
  7286. */
  7287. animate: function(duration, interval, framefn, timefn, callback) {
  7288. var startTime = new Date().getTime(),
  7289. renderFrame = (function() {
  7290. if (!this.inAnimation) {
  7291. return;
  7292. }
  7293. var frameTime = new Date().getTime() - startTime,
  7294. progress = frameTime / duration;
  7295. if (frameTime >= duration) {
  7296. framefn(1);
  7297. if (callback) {
  7298. callback();
  7299. }
  7300. this.update();
  7301. this.stopAnimation();
  7302. this.update();
  7303. } else {
  7304. if (timefn) {
  7305. progress = timefn(progress);
  7306. }
  7307. framefn(progress);
  7308. this.update();
  7309. setTimeout(renderFrame, interval);
  7310. }
  7311. }).bind(this);
  7312. this.inAnimation = true;
  7313. renderFrame();
  7314. },
  7315. /**
  7316. * Stops the animation
  7317. */
  7318. stopAnimation: function() {
  7319. this.inAnimation = false;
  7320. },
  7321. /**
  7322. * Swing timing function for animations
  7323. * @param p
  7324. * @return {Number}
  7325. */
  7326. swing: function(p) {
  7327. return -Math.cos(p * Math.PI) / 2 + 0.5;
  7328. },
  7329. getContainerX: function() {
  7330. // return this.container[0].offsetWidth;
  7331. // @modified
  7332. return window.innerWidth
  7333. },
  7334. getContainerY: function() {
  7335. // return this.container[0].offsetHeight;
  7336. // @modified
  7337. return window.innerHeight
  7338. },
  7339. setContainerY: function(y) {
  7340. // return this.container.height(y);
  7341. // @modified
  7342. var t = window.innerHeight;
  7343. return this.el.css({height: t}), this.container.height(t);
  7344. },
  7345. /**
  7346. * Creates the expected html structure
  7347. */
  7348. setupMarkup: function() {
  7349. this.container = $('<div class="pinch-zoom-container"></div>');
  7350. this.el.before(this.container);
  7351. this.container.append(this.el);
  7352. this.container.css({
  7353. 'overflow': 'hidden',
  7354. 'position': 'relative'
  7355. });
  7356. // Zepto doesn't recognize `webkitTransform..` style
  7357. this.el.css({
  7358. '-webkit-transform-origin': '0% 0%',
  7359. '-moz-transform-origin': '0% 0%',
  7360. '-ms-transform-origin': '0% 0%',
  7361. '-o-transform-origin': '0% 0%',
  7362. 'transform-origin': '0% 0%',
  7363. 'position': 'absolute'
  7364. });
  7365. },
  7366. end: function() {
  7367. this.hasInteraction = false;
  7368. this.sanitize();
  7369. this.update();
  7370. },
  7371. /**
  7372. * Binds all required event listeners
  7373. */
  7374. bindEvents: function() {
  7375. detectGestures(this.container.get(0), this);
  7376. // Zepto and jQuery both know about `on`
  7377. $(window).on('resize', this.update.bind(this));
  7378. $(this.el).find('img').on('load', this.update.bind(this));
  7379. },
  7380. /**
  7381. * Updates the css values according to the current zoom factor and offset
  7382. */
  7383. update: function() {
  7384. if (this.updatePlaned) {
  7385. return;
  7386. }
  7387. this.updatePlaned = true;
  7388. setTimeout((function() {
  7389. this.updatePlaned = false;
  7390. this.updateAspectRatio();
  7391. var zoomFactor = this.getInitialZoomFactor() * this.zoomFactor,
  7392. offsetX = -this.offset.x / zoomFactor,
  7393. offsetY = -this.offset.y / zoomFactor,
  7394. transform3d = 'scale3d(' + zoomFactor + ', ' + zoomFactor + ',1) ' +
  7395. 'translate3d(' + offsetX + 'px,' + offsetY + 'px,0px)',
  7396. transform2d = 'scale(' + zoomFactor + ', ' + zoomFactor + ') ' +
  7397. 'translate(' + offsetX + 'px,' + offsetY + 'px)',
  7398. removeClone = (function() {
  7399. if (this.clone) {
  7400. this.clone.remove();
  7401. delete this.clone;
  7402. }
  7403. }).bind(this);
  7404. // Scale 3d and translate3d are faster (at least on ios)
  7405. // but they also reduce the quality.
  7406. // PinchZoom uses the 3d transformations during interactions
  7407. // after interactions it falls back to 2d transformations
  7408. if (!this.options.use2d || this.hasInteraction || this.inAnimation) {
  7409. this.is3d = true;
  7410. removeClone();
  7411. this.el.css({
  7412. '-webkit-transform': transform3d,
  7413. '-o-transform': transform2d,
  7414. '-ms-transform': transform2d,
  7415. '-moz-transform': transform2d,
  7416. 'transform': transform3d
  7417. });
  7418. } else {
  7419. // When changing from 3d to 2d transform webkit has some glitches.
  7420. // To avoid this, a copy of the 3d transformed element is displayed in the
  7421. // foreground while the element is converted from 3d to 2d transform
  7422. if (this.is3d) {
  7423. this.clone = this.el.clone();
  7424. this.clone.css('pointer-events', 'none');
  7425. this.clone.appendTo(this.container);
  7426. setTimeout(removeClone, 200);
  7427. }
  7428. this.el.css({
  7429. '-webkit-transform': transform2d,
  7430. '-o-transform': transform2d,
  7431. '-ms-transform': transform2d,
  7432. '-moz-transform': transform2d,
  7433. 'transform': transform2d
  7434. });
  7435. this.is3d = false;
  7436. }
  7437. }).bind(this), 0);
  7438. },
  7439. /**
  7440. * Enables event handling for gestures
  7441. */
  7442. enable: function() {
  7443. this.enabled = true;
  7444. },
  7445. /**
  7446. * Disables event handling for gestures
  7447. */
  7448. disable: function() {
  7449. this.enabled = false;
  7450. }
  7451. };
  7452. var detectGestures = function(el, target) {
  7453. var interaction = null,
  7454. fingers = 0,
  7455. lastTouchStart = null,
  7456. startTouches = null,
  7457. setInteraction = function(newInteraction, event) {
  7458. if (interaction !== newInteraction) {
  7459. if (interaction && !newInteraction) {
  7460. switch (interaction) {
  7461. case "zoom":
  7462. target.handleZoomEnd(event);
  7463. break;
  7464. case 'drag':
  7465. target.handleDragEnd(event);
  7466. break;
  7467. }
  7468. }
  7469. switch (newInteraction) {
  7470. case 'zoom':
  7471. target.handleZoomStart(event);
  7472. break;
  7473. case 'drag':
  7474. target.handleDragStart(event);
  7475. break;
  7476. }
  7477. }
  7478. interaction = newInteraction;
  7479. },
  7480. updateInteraction = function(event) {
  7481. if (fingers === 2) {
  7482. setInteraction('zoom');
  7483. } else if (fingers === 1 && target.canDrag()) {
  7484. setInteraction('drag', event);
  7485. } else {
  7486. setInteraction(null, event);
  7487. }
  7488. },
  7489. targetTouches = function(touches) {
  7490. return Array.prototype.slice.call(touches).map(function(touch) {
  7491. return {
  7492. x: touch.pageX,
  7493. y: touch.pageY
  7494. };
  7495. });
  7496. },
  7497. getDistance = function(a, b) {
  7498. var x, y;
  7499. x = a.x - b.x;
  7500. y = a.y - b.y;
  7501. return Math.sqrt(x * x + y * y);
  7502. },
  7503. calculateScale = function(startTouches, endTouches) {
  7504. var startDistance = getDistance(startTouches[0], startTouches[1]),
  7505. endDistance = getDistance(endTouches[0], endTouches[1]);
  7506. return endDistance / startDistance;
  7507. },
  7508. cancelEvent = function(event) {
  7509. event.stopPropagation();
  7510. event.preventDefault();
  7511. },
  7512. detectDoubleTap = function(event) {
  7513. var time = (new Date()).getTime();
  7514. if (fingers > 1) {
  7515. lastTouchStart = null;
  7516. }
  7517. if (time - lastTouchStart < 300) {
  7518. cancelEvent(event);
  7519. target.handleDoubleTap(event);
  7520. switch (interaction) {
  7521. case "zoom":
  7522. target.handleZoomEnd(event);
  7523. break;
  7524. case 'drag':
  7525. target.handleDragEnd(event);
  7526. break;
  7527. }
  7528. }
  7529. if (fingers === 1) {
  7530. lastTouchStart = time;
  7531. }
  7532. },
  7533. firstMove = true;
  7534. el.addEventListener('touchstart', function(event) {
  7535. if (target.enabled) {
  7536. firstMove = true;
  7537. fingers = event.touches.length;
  7538. detectDoubleTap(event);
  7539. }
  7540. });
  7541. el.addEventListener('touchmove', function(event) {
  7542. if (target.enabled) {
  7543. if (firstMove) {
  7544. updateInteraction(event);
  7545. if (interaction) {
  7546. cancelEvent(event);
  7547. }
  7548. startTouches = targetTouches(event.touches);
  7549. } else {
  7550. switch (interaction) {
  7551. case 'zoom':
  7552. target.handleZoom(event, calculateScale(startTouches, targetTouches(event.touches)));
  7553. break;
  7554. case 'drag':
  7555. target.handleDrag(event);
  7556. break;
  7557. }
  7558. if (interaction) {
  7559. cancelEvent(event);
  7560. target.update();
  7561. }
  7562. }
  7563. firstMove = false;
  7564. }
  7565. });
  7566. el.addEventListener('touchend', function(event) {
  7567. if (target.enabled) {
  7568. fingers = event.touches.length;
  7569. updateInteraction(event);
  7570. }
  7571. });
  7572. };
  7573. return PinchZoom;
  7574. };
  7575. module.exports = UI.pichzoom = definePinchZoom($);
  7576. /***/ },
  7577. /* 18 */
  7578. /***/ function(module, exports, __webpack_require__) {
  7579. 'use strict';
  7580. var $ = __webpack_require__(1);
  7581. var UI = __webpack_require__(2);
  7582. var $w = $(window);
  7583. /**
  7584. * @reference https://github.com/nolimits4web/Framework7/blob/master/src/js/modals.js
  7585. * @license https://github.com/nolimits4web/Framework7/blob/master/LICENSE
  7586. */
  7587. var Popover = function(element, options) {
  7588. this.options = $.extend({}, Popover.DEFAULTS, options);
  7589. this.$element = $(element);
  7590. this.active = null;
  7591. this.$popover = (this.options.target && $(this.options.target)) || null;
  7592. this.init();
  7593. this._bindEvents();
  7594. };
  7595. Popover.DEFAULTS = {
  7596. theme: null,
  7597. trigger: 'click',
  7598. content: '',
  7599. open: false,
  7600. target: null,
  7601. tpl: '<div class="am-popover">' +
  7602. '<div class="am-popover-inner"></div>' +
  7603. '<div class="am-popover-caret"></div></div>'
  7604. };
  7605. Popover.prototype.init = function() {
  7606. var _this = this;
  7607. var $element = this.$element;
  7608. var $popover;
  7609. if (!this.options.target) {
  7610. this.$popover = this.getPopover();
  7611. this.setContent();
  7612. }
  7613. $popover = this.$popover;
  7614. $popover.appendTo($('body'));
  7615. this.sizePopover();
  7616. function sizePopover() {
  7617. _this.sizePopover();
  7618. }
  7619. // TODO: 监听页面内容变化,重新调整位置
  7620. $element.on('open.popover.amui', function() {
  7621. $(window).on('resize.popover.amui', UI.utils.debounce(sizePopover, 50));
  7622. });
  7623. $element.on('close.popover.amui', function() {
  7624. $(window).off('resize.popover.amui', sizePopover);
  7625. });
  7626. this.options.open && this.open();
  7627. };
  7628. Popover.prototype.sizePopover = function sizePopover() {
  7629. var $element = this.$element;
  7630. var $popover = this.$popover;
  7631. if (!$popover || !$popover.length) {
  7632. return;
  7633. }
  7634. var popWidth = $popover.outerWidth();
  7635. var popHeight = $popover.outerHeight();
  7636. var $popCaret = $popover.find('.am-popover-caret');
  7637. var popCaretSize = ($popCaret.outerWidth() / 2) || 8;
  7638. // 取不到 $popCaret.outerHeight() 的值,所以直接加 8
  7639. var popTotalHeight = popHeight + 8; // $popCaret.outerHeight();
  7640. var triggerWidth = $element.outerWidth();
  7641. var triggerHeight = $element.outerHeight();
  7642. var triggerOffset = $element.offset();
  7643. var triggerRect = $element[0].getBoundingClientRect();
  7644. var winHeight = $w.height();
  7645. var winWidth = $w.width();
  7646. var popTop = 0;
  7647. var popLeft = 0;
  7648. var diff = 0;
  7649. var spacing = 2;
  7650. var popPosition = 'top';
  7651. $popover.css({left: '', top: ''}).removeClass('am-popover-left ' +
  7652. 'am-popover-right am-popover-top am-popover-bottom');
  7653. // $popCaret.css({left: '', top: ''});
  7654. if (popTotalHeight - spacing < triggerRect.top + spacing) {
  7655. // Popover on the top of trigger
  7656. popTop = triggerOffset.top - popTotalHeight - spacing;
  7657. } else if (popTotalHeight <
  7658. winHeight - triggerRect.top - triggerRect.height) {
  7659. // On bottom
  7660. popPosition = 'bottom';
  7661. popTop = triggerOffset.top + triggerHeight + popCaretSize + spacing;
  7662. } else { // On middle
  7663. popPosition = 'middle';
  7664. popTop = triggerHeight / 2 + triggerOffset.top - popHeight / 2;
  7665. }
  7666. // Horizontal Position
  7667. if (popPosition === 'top' || popPosition === 'bottom') {
  7668. popLeft = triggerWidth / 2 + triggerOffset.left - popWidth / 2;
  7669. diff = popLeft;
  7670. if (popLeft < 5) {
  7671. popLeft = 5;
  7672. }
  7673. if (popLeft + popWidth > winWidth) {
  7674. popLeft = (winWidth - popWidth - 20);
  7675. // console.log('left %d, win %d, popw %d', popLeft, winWidth, popWidth);
  7676. }
  7677. if (popPosition === 'top') {
  7678. // This is the Popover position, NOT caret position
  7679. // Popover on the Top of trigger, caret on the bottom of Popover
  7680. $popover.addClass('am-popover-top');
  7681. }
  7682. if (popPosition === 'bottom') {
  7683. $popover.addClass('am-popover-bottom');
  7684. }
  7685. diff = diff - popLeft;
  7686. // $popCaret.css({left: (popWidth / 2 - popCaretSize + diff) + 'px'});
  7687. } else if (popPosition === 'middle') {
  7688. popLeft = triggerOffset.left - popWidth - popCaretSize;
  7689. $popover.addClass('am-popover-left');
  7690. if (popLeft < 5) {
  7691. popLeft = triggerOffset.left + triggerWidth + popCaretSize;
  7692. $popover.removeClass('am-popover-left').addClass('am-popover-right');
  7693. }
  7694. if (popLeft + popWidth > winWidth) {
  7695. popLeft = winWidth - popWidth - 5;
  7696. $popover.removeClass('am-popover-left').addClass('am-popover-right');
  7697. }
  7698. // $popCaret.css({top: (popHeight / 2 - popCaretSize / 2) + 'px'});
  7699. }
  7700. // Apply position style
  7701. $popover.css({top: popTop + 'px', left: popLeft + 'px'});
  7702. };
  7703. Popover.prototype.toggle = function() {
  7704. return this[this.active ? 'close' : 'open']();
  7705. };
  7706. Popover.prototype.open = function() {
  7707. var $popover = this.$popover;
  7708. this.$element.trigger('open.popover.amui');
  7709. this.sizePopover();
  7710. $popover.show().addClass('am-active');
  7711. this.active = true;
  7712. };
  7713. Popover.prototype.close = function() {
  7714. var $popover = this.$popover;
  7715. this.$element.trigger('close.popover.amui');
  7716. $popover
  7717. .removeClass('am-active')
  7718. .trigger('closed.popover.amui')
  7719. .hide();
  7720. this.active = false;
  7721. };
  7722. Popover.prototype.getPopover = function() {
  7723. var uid = UI.utils.generateGUID('am-popover');
  7724. var theme = [];
  7725. if (this.options.theme) {
  7726. $.each(this.options.theme.split(' '), function(i, item) {
  7727. theme.push('am-popover-' + $.trim(item));
  7728. });
  7729. }
  7730. return $(this.options.tpl).attr('id', uid).addClass(theme.join(' '));
  7731. };
  7732. Popover.prototype.setContent = function(content) {
  7733. content = content || this.options.content;
  7734. this.$popover && this.$popover.find('.am-popover-inner')
  7735. .empty().html(content);
  7736. };
  7737. Popover.prototype._bindEvents = function() {
  7738. var eventNS = 'popover.amui';
  7739. var triggers = this.options.trigger.split(' ');
  7740. for (var i = triggers.length; i--;) {
  7741. var trigger = triggers[i];
  7742. if (trigger === 'click') {
  7743. this.$element.on('click.' + eventNS, $.proxy(this.toggle, this));
  7744. } else { // hover or focus
  7745. var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin';
  7746. var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout';
  7747. this.$element.on(eventIn + '.' + eventNS, $.proxy(this.open, this));
  7748. this.$element.on(eventOut + '.' + eventNS, $.proxy(this.close, this));
  7749. }
  7750. }
  7751. };
  7752. Popover.prototype.destroy = function() {
  7753. this.$element.off('.popover.amui').removeData('amui.popover');
  7754. this.$popover.remove();
  7755. };
  7756. UI.plugin('popover', Popover);
  7757. // Init code
  7758. UI.ready(function(context) {
  7759. $('[data-am-popover]', context).popover();
  7760. });
  7761. module.exports = Popover;
  7762. // TODO: 允许用户定义位置
  7763. /***/ },
  7764. /* 19 */
  7765. /***/ function(module, exports, __webpack_require__) {
  7766. 'use strict';
  7767. var UI = __webpack_require__(2);
  7768. var Progress = (function() {
  7769. /**
  7770. * NProgress (c) 2013, Rico Sta. Cruz
  7771. * @via http://ricostacruz.com/nprogress
  7772. */
  7773. var NProgress = {};
  7774. NProgress.version = '0.2.0';
  7775. var Settings = NProgress.settings = {
  7776. minimum: 0.08,
  7777. easing: 'ease',
  7778. positionUsing: '',
  7779. speed: 200,
  7780. trickle: true,
  7781. trickleRate: 0.02,
  7782. trickleSpeed: 800,
  7783. showSpinner: true,
  7784. parent: 'body',
  7785. barSelector: '[role="nprogress-bar"]',
  7786. spinnerSelector: '[role="nprogress-spinner"]',
  7787. template: '<div class="nprogress-bar" role="nprogress-bar">' +
  7788. '<div class="nprogress-peg"></div></div>' +
  7789. '<div class="nprogress-spinner" role="nprogress-spinner">' +
  7790. '<div class="nprogress-spinner-icon"></div></div>'
  7791. };
  7792. /**
  7793. * Updates configuration.
  7794. *
  7795. * NProgress.configure({
  7796. * minimum: 0.1
  7797. * });
  7798. */
  7799. NProgress.configure = function(options) {
  7800. var key, value;
  7801. for (key in options) {
  7802. value = options[key];
  7803. if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value;
  7804. }
  7805. return this;
  7806. };
  7807. /**
  7808. * Last number.
  7809. */
  7810. NProgress.status = null;
  7811. /**
  7812. * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.
  7813. *
  7814. * NProgress.set(0.4);
  7815. * NProgress.set(1.0);
  7816. */
  7817. NProgress.set = function(n) {
  7818. var started = NProgress.isStarted();
  7819. n = clamp(n, Settings.minimum, 1);
  7820. NProgress.status = (n === 1 ? null : n);
  7821. var progress = NProgress.render(!started),
  7822. bar = progress.querySelector(Settings.barSelector),
  7823. speed = Settings.speed,
  7824. ease = Settings.easing;
  7825. progress.offsetWidth; /* Repaint */
  7826. queue(function(next) {
  7827. // Set positionUsing if it hasn't already been set
  7828. if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS();
  7829. // Add transition
  7830. css(bar, barPositionCSS(n, speed, ease));
  7831. if (n === 1) {
  7832. // Fade out
  7833. css(progress, {
  7834. transition: 'none',
  7835. opacity: 1
  7836. });
  7837. progress.offsetWidth; /* Repaint */
  7838. setTimeout(function() {
  7839. css(progress, {
  7840. transition: 'all ' + speed + 'ms linear',
  7841. opacity: 0
  7842. });
  7843. setTimeout(function() {
  7844. NProgress.remove();
  7845. next();
  7846. }, speed);
  7847. }, speed);
  7848. } else {
  7849. setTimeout(next, speed);
  7850. }
  7851. });
  7852. return this;
  7853. };
  7854. NProgress.isStarted = function() {
  7855. return typeof NProgress.status === 'number';
  7856. };
  7857. /**
  7858. * Shows the progress bar.
  7859. * This is the same as setting the status to 0%, except that it doesn't go backwards.
  7860. *
  7861. * NProgress.start();
  7862. *
  7863. */
  7864. NProgress.start = function() {
  7865. if (!NProgress.status) NProgress.set(0);
  7866. var work = function() {
  7867. setTimeout(function() {
  7868. if (!NProgress.status) return;
  7869. NProgress.trickle();
  7870. work();
  7871. }, Settings.trickleSpeed);
  7872. };
  7873. if (Settings.trickle) work();
  7874. return this;
  7875. };
  7876. /**
  7877. * Hides the progress bar.
  7878. * This is the *sort of* the same as setting the status to 100%, with the
  7879. * difference being `done()` makes some placebo effect of some realistic motion.
  7880. *
  7881. * NProgress.done();
  7882. *
  7883. * If `true` is passed, it will show the progress bar even if its hidden.
  7884. *
  7885. * NProgress.done(true);
  7886. */
  7887. NProgress.done = function(force) {
  7888. if (!force && !NProgress.status) return this;
  7889. return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);
  7890. };
  7891. /**
  7892. * Increments by a random amount.
  7893. */
  7894. NProgress.inc = function(amount) {
  7895. var n = NProgress.status;
  7896. if (!n) {
  7897. return NProgress.start();
  7898. } else {
  7899. if (typeof amount !== 'number') {
  7900. amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);
  7901. }
  7902. n = clamp(n + amount, 0, 0.994);
  7903. return NProgress.set(n);
  7904. }
  7905. };
  7906. NProgress.trickle = function() {
  7907. return NProgress.inc(Math.random() * Settings.trickleRate);
  7908. };
  7909. /**
  7910. * Waits for all supplied jQuery promises and
  7911. * increases the progress as the promises resolve.
  7912. *
  7913. * @param $promise jQUery Promise
  7914. */
  7915. (function() {
  7916. var initial = 0, current = 0;
  7917. NProgress.promise = function($promise) {
  7918. if (!$promise || $promise.state() === "resolved") {
  7919. return this;
  7920. }
  7921. if (current === 0) {
  7922. NProgress.start();
  7923. }
  7924. initial++;
  7925. current++;
  7926. $promise.always(function() {
  7927. current--;
  7928. if (current === 0) {
  7929. initial = 0;
  7930. NProgress.done();
  7931. } else {
  7932. NProgress.set((initial - current) / initial);
  7933. }
  7934. });
  7935. return this;
  7936. };
  7937. })();
  7938. /**
  7939. * (Internal) renders the progress bar markup based on the `template`
  7940. * setting.
  7941. */
  7942. NProgress.render = function(fromStart) {
  7943. if (NProgress.isRendered()) return document.getElementById('nprogress');
  7944. addClass(document.documentElement, 'nprogress-busy');
  7945. var progress = document.createElement('div');
  7946. progress.id = 'nprogress';
  7947. progress.innerHTML = Settings.template;
  7948. var bar = progress.querySelector(Settings.barSelector),
  7949. perc = fromStart ? '-100' : toBarPerc(NProgress.status || 0),
  7950. parent = document.querySelector(Settings.parent),
  7951. spinner;
  7952. css(bar, {
  7953. transition: 'all 0 linear',
  7954. transform: 'translate3d(' + perc + '%,0,0)'
  7955. });
  7956. if (!Settings.showSpinner) {
  7957. spinner = progress.querySelector(Settings.spinnerSelector);
  7958. spinner && removeElement(spinner);
  7959. }
  7960. if (parent != document.body) {
  7961. addClass(parent, 'nprogress-custom-parent');
  7962. }
  7963. parent.appendChild(progress);
  7964. return progress;
  7965. };
  7966. /**
  7967. * Removes the element. Opposite of render().
  7968. */
  7969. NProgress.remove = function() {
  7970. removeClass(document.documentElement, 'nprogress-busy');
  7971. removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent');
  7972. var progress = document.getElementById('nprogress');
  7973. progress && removeElement(progress);
  7974. };
  7975. /**
  7976. * Checks if the progress bar is rendered.
  7977. */
  7978. NProgress.isRendered = function() {
  7979. return !!document.getElementById('nprogress');
  7980. };
  7981. /**
  7982. * Determine which positioning CSS rule to use.
  7983. */
  7984. NProgress.getPositioningCSS = function() {
  7985. // Sniff on document.body.style
  7986. var bodyStyle = document.body.style;
  7987. // Sniff prefixes
  7988. var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :
  7989. ('MozTransform' in bodyStyle) ? 'Moz' :
  7990. ('msTransform' in bodyStyle) ? 'ms' :
  7991. ('OTransform' in bodyStyle) ? 'O' : '';
  7992. if (vendorPrefix + 'Perspective' in bodyStyle) {
  7993. // Modern browsers with 3D support, e.g. Webkit, IE10
  7994. return 'translate3d';
  7995. } else if (vendorPrefix + 'Transform' in bodyStyle) {
  7996. // Browsers without 3D support, e.g. IE9
  7997. return 'translate';
  7998. } else {
  7999. // Browsers without translate() support, e.g. IE7-8
  8000. return 'margin';
  8001. }
  8002. };
  8003. /**
  8004. * Helpers
  8005. */
  8006. function clamp(n, min, max) {
  8007. if (n < min) return min;
  8008. if (n > max) return max;
  8009. return n;
  8010. }
  8011. /**
  8012. * (Internal) converts a percentage (`0..1`) to a bar translateX
  8013. * percentage (`-100%..0%`).
  8014. */
  8015. function toBarPerc(n) {
  8016. return (-1 + n) * 100;
  8017. }
  8018. /**
  8019. * (Internal) returns the correct CSS for changing the bar's
  8020. * position given an n percentage, and speed and ease from Settings
  8021. */
  8022. function barPositionCSS(n, speed, ease) {
  8023. var barCSS;
  8024. if (Settings.positionUsing === 'translate3d') {
  8025. barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };
  8026. } else if (Settings.positionUsing === 'translate') {
  8027. barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };
  8028. } else {
  8029. barCSS = { 'margin-left': toBarPerc(n)+'%' };
  8030. }
  8031. barCSS.transition = 'all '+speed+'ms '+ease;
  8032. return barCSS;
  8033. }
  8034. /**
  8035. * (Internal) Queues a function to be executed.
  8036. */
  8037. var queue = (function() {
  8038. var pending = [];
  8039. function next() {
  8040. var fn = pending.shift();
  8041. if (fn) {
  8042. fn(next);
  8043. }
  8044. }
  8045. return function(fn) {
  8046. pending.push(fn);
  8047. if (pending.length == 1) next();
  8048. };
  8049. })();
  8050. /**
  8051. * (Internal) Applies css properties to an element, similar to the jQuery
  8052. * css method.
  8053. *
  8054. * While this helper does assist with vendor prefixed property names, it
  8055. * does not perform any manipulation of values prior to setting styles.
  8056. */
  8057. var css = (function() {
  8058. var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ],
  8059. cssProps = {};
  8060. function camelCase(string) {
  8061. return string.replace(/^-ms-/, 'ms-').replace(/-([\da-z])/gi, function(match, letter) {
  8062. return letter.toUpperCase();
  8063. });
  8064. }
  8065. function getVendorProp(name) {
  8066. var style = document.body.style;
  8067. if (name in style) return name;
  8068. var i = cssPrefixes.length,
  8069. capName = name.charAt(0).toUpperCase() + name.slice(1),
  8070. vendorName;
  8071. while (i--) {
  8072. vendorName = cssPrefixes[i] + capName;
  8073. if (vendorName in style) return vendorName;
  8074. }
  8075. return name;
  8076. }
  8077. function getStyleProp(name) {
  8078. name = camelCase(name);
  8079. return cssProps[name] || (cssProps[name] = getVendorProp(name));
  8080. }
  8081. function applyCss(element, prop, value) {
  8082. prop = getStyleProp(prop);
  8083. element.style[prop] = value;
  8084. }
  8085. return function(element, properties) {
  8086. var args = arguments,
  8087. prop,
  8088. value;
  8089. if (args.length == 2) {
  8090. for (prop in properties) {
  8091. value = properties[prop];
  8092. if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value);
  8093. }
  8094. } else {
  8095. applyCss(element, args[1], args[2]);
  8096. }
  8097. }
  8098. })();
  8099. /**
  8100. * (Internal) Determines if an element or space separated list of class names contains a class name.
  8101. */
  8102. function hasClass(element, name) {
  8103. var list = typeof element == 'string' ? element : classList(element);
  8104. return list.indexOf(' ' + name + ' ') >= 0;
  8105. }
  8106. /**
  8107. * (Internal) Adds a class to an element.
  8108. */
  8109. function addClass(element, name) {
  8110. var oldList = classList(element),
  8111. newList = oldList + name;
  8112. if (hasClass(oldList, name)) return;
  8113. // Trim the opening space.
  8114. element.className = newList.substring(1);
  8115. }
  8116. /**
  8117. * (Internal) Removes a class from an element.
  8118. */
  8119. function removeClass(element, name) {
  8120. var oldList = classList(element),
  8121. newList;
  8122. if (!hasClass(element, name)) return;
  8123. // Replace the class name.
  8124. newList = oldList.replace(' ' + name + ' ', ' ');
  8125. // Trim the opening and closing spaces.
  8126. element.className = newList.substring(1, newList.length - 1);
  8127. }
  8128. /**
  8129. * (Internal) Gets a space separated list of the class names on the element.
  8130. * The list is wrapped with a single space on each end to facilitate finding
  8131. * matches within the list.
  8132. */
  8133. function classList(element) {
  8134. return (' ' + (element.className || '') + ' ').replace(/\s+/gi, ' ');
  8135. }
  8136. /**
  8137. * (Internal) Removes an element from the DOM.
  8138. */
  8139. function removeElement(element) {
  8140. element && element.parentNode && element.parentNode.removeChild(element);
  8141. }
  8142. return NProgress;
  8143. })();
  8144. module.exports = UI.progress = Progress;
  8145. /***/ },
  8146. /* 20 */
  8147. /***/ function(module, exports, __webpack_require__) {
  8148. 'use strict';
  8149. var $ = __webpack_require__(1);
  8150. var UI = __webpack_require__(2);
  8151. var PinchZoom = __webpack_require__(17);
  8152. var Hammer = __webpack_require__(3);
  8153. var animation = UI.support.animation;
  8154. var transition = UI.support.transition;
  8155. /**
  8156. * PureView
  8157. * @desc Image browser for Mobile
  8158. * @param element
  8159. * @param options
  8160. * @constructor
  8161. */
  8162. var PureView = function(element, options) {
  8163. this.$element = $(element);
  8164. this.$body = $(document.body);
  8165. this.options = $.extend({}, PureView.DEFAULTS, options);
  8166. this.$pureview = $(this.options.tpl).attr('id',
  8167. UI.utils.generateGUID('am-pureview'));
  8168. this.$slides = null;
  8169. this.transitioning = null;
  8170. this.scrollbarWidth = 0;
  8171. this.init();
  8172. };
  8173. PureView.DEFAULTS = {
  8174. tpl: '<div class="am-pureview am-pureview-bar-active">' +
  8175. '<ul class="am-pureview-slider"></ul>' +
  8176. '<ul class="am-pureview-direction">' +
  8177. '<li class="am-pureview-prev"><a href=""></a></li>' +
  8178. '<li class="am-pureview-next"><a href=""></a></li></ul>' +
  8179. '<ol class="am-pureview-nav"></ol>' +
  8180. '<div class="am-pureview-bar am-active">' +
  8181. '<span class="am-pureview-title"></span>' +
  8182. '<div class="am-pureview-counter"><span class="am-pureview-current"></span> / ' +
  8183. '<span class="am-pureview-total"></span></div></div>' +
  8184. '<div class="am-pureview-actions am-active">' +
  8185. '<a href="javascript: void(0)" class="am-icon-chevron-left" ' +
  8186. 'data-am-close="pureview"></a></div>' +
  8187. '</div>',
  8188. className: {
  8189. prevSlide: 'am-pureview-slide-prev',
  8190. nextSlide: 'am-pureview-slide-next',
  8191. onlyOne: 'am-pureview-only',
  8192. active: 'am-active',
  8193. barActive: 'am-pureview-bar-active',
  8194. activeBody: 'am-pureview-active'
  8195. },
  8196. selector: {
  8197. slider: '.am-pureview-slider',
  8198. close: '[data-am-close="pureview"]',
  8199. total: '.am-pureview-total',
  8200. current: '.am-pureview-current',
  8201. title: '.am-pureview-title',
  8202. actions: '.am-pureview-actions',
  8203. bar: '.am-pureview-bar',
  8204. pinchZoom: '.am-pinch-zoom',
  8205. nav: '.am-pureview-nav'
  8206. },
  8207. shareBtn: false,
  8208. // press to toggle Toolbar
  8209. toggleToolbar: true,
  8210. // 从何处获取图片,img 可以使用 data-rel 指定大图
  8211. target: 'img',
  8212. // 微信 Webview 中调用微信的图片浏览器
  8213. // 实现图片保存、分享好友、收藏图片等功能
  8214. weChatImagePreview: true
  8215. };
  8216. PureView.prototype.init = function() {
  8217. var _this = this;
  8218. var options = this.options;
  8219. var $element = this.$element;
  8220. var $pureview = this.$pureview;
  8221. this.refreshSlides();
  8222. $('body').append($pureview);
  8223. this.$title = $pureview.find(options.selector.title);
  8224. this.$current = $pureview.find(options.selector.current);
  8225. this.$bar = $pureview.find(options.selector.bar);
  8226. this.$actions = $pureview.find(options.selector.actions);
  8227. if (options.shareBtn) {
  8228. this.$actions.append('<a href="javascript: void(0)" ' +
  8229. 'class="am-icon-share-square-o" data-am-toggle="share"></a>');
  8230. }
  8231. this.$element.on('click.pureview.amui', options.target, function(e) {
  8232. e.preventDefault();
  8233. var clicked = _this.$images.index(this);
  8234. // Invoke WeChat ImagePreview in WeChat
  8235. // TODO: detect WeChat before init
  8236. if (options.weChatImagePreview && window.WeixinJSBridge) {
  8237. window.WeixinJSBridge.invoke('imagePreview', {
  8238. current: _this.imgUrls[clicked],
  8239. urls: _this.imgUrls
  8240. });
  8241. } else {
  8242. _this.open(clicked);
  8243. }
  8244. });
  8245. $pureview.find('.am-pureview-direction').
  8246. on('click.direction.pureview.amui', 'li', function(e) {
  8247. e.preventDefault();
  8248. if ($(this).is('.am-pureview-prev')) {
  8249. _this.prevSlide();
  8250. } else {
  8251. _this.nextSlide();
  8252. }
  8253. });
  8254. // Nav Contorl
  8255. $pureview.find(options.selector.nav).on('click.nav.pureview.amui', 'li',
  8256. function() {
  8257. var index = _this.$navItems.index($(this));
  8258. _this.activate(_this.$slides.eq(index));
  8259. });
  8260. // Close Icon
  8261. $pureview.find(options.selector.close).
  8262. on('click.close.pureview.amui', function(e) {
  8263. e.preventDefault();
  8264. _this.close();
  8265. });
  8266. this.$slider.hammer().on('swipeleft.pureview.amui', function(e) {
  8267. e.preventDefault();
  8268. _this.nextSlide();
  8269. }).on('swiperight.pureview.amui', function(e) {
  8270. e.preventDefault();
  8271. _this.prevSlide();
  8272. }).on('press.pureview.amui', function(e) {
  8273. e.preventDefault();
  8274. options.toggleToolbar && _this.toggleToolBar();
  8275. });
  8276. this.$slider.data('hammer').get('swipe').set({
  8277. direction: Hammer.DIRECTION_HORIZONTAL,
  8278. velocity: 0.35
  8279. });
  8280. // Observe DOM
  8281. $element.DOMObserve({
  8282. childList: true,
  8283. subtree: true
  8284. }, function(mutations, observer) {
  8285. // _this.refreshSlides();
  8286. // console.log('mutations[0].type);
  8287. });
  8288. // NOTE:
  8289. // trigger this event manually if MutationObserver not supported
  8290. // when new images appended, or call refreshSlides()
  8291. // if (!UI.support.mutationobserver) $element.trigger('changed.dom.amui')
  8292. $element.on('changed.dom.amui', function(e) {
  8293. e.stopPropagation();
  8294. _this.refreshSlides();
  8295. });
  8296. $(document).on('keydown.pureview.amui', $.proxy(function(e) {
  8297. var keyCode = e.keyCode;
  8298. if (keyCode == 37) {
  8299. this.prevSlide();
  8300. } else if (keyCode == 39) {
  8301. this.nextSlide();
  8302. } else if (keyCode == 27) {
  8303. this.close();
  8304. }
  8305. }, this));
  8306. };
  8307. PureView.prototype.refreshSlides = function() {
  8308. // update images collections
  8309. this.$images = this.$element.find(this.options.target);
  8310. var _this = this;
  8311. var options = this.options;
  8312. var $pureview = this.$pureview;
  8313. var $slides = $([]);
  8314. var $navItems = $([]);
  8315. var $images = this.$images;
  8316. var total = $images.length;
  8317. this.$slider = $pureview.find(options.selector.slider);
  8318. this.$nav = $pureview.find(options.selector.nav);
  8319. var viewedFlag = 'data-am-pureviewed';
  8320. // for WeChat Image Preview
  8321. this.imgUrls = this.imgUrls || [];
  8322. if (!total) {
  8323. return;
  8324. }
  8325. if (total === 1) {
  8326. $pureview.addClass(options.className.onlyOne);
  8327. }
  8328. $images.not('[' + viewedFlag + ']').each(function(i, item) {
  8329. var src;
  8330. var title;
  8331. // get image URI from link's href attribute
  8332. if (item.nodeName === 'A') {
  8333. src = item.href; // to absolute path
  8334. title = item.title || '';
  8335. } else {
  8336. // NOTE: `data-rel` should be a full URL, otherwise,
  8337. // WeChat images preview will not work
  8338. src = $(item).data('rel') || item.src; // <img src='' data-rel='' />
  8339. src = UI.utils.getAbsoluteUrl(src);
  8340. title = $(item).attr('alt') || '';
  8341. }
  8342. // add pureviewed flag
  8343. item.setAttribute(viewedFlag, '1');
  8344. // hide bar: wechat_webview_type=1
  8345. // http://tmt.io/wechat/ not working?
  8346. _this.imgUrls.push(src);
  8347. $slides = $slides.add($('<li data-src="' + src + '" data-title="' + title +
  8348. '"></li>'));
  8349. $navItems = $navItems.add($('<li>' + (i + 1) + '</li>'));
  8350. });
  8351. $pureview.find(options.selector.total).text(total);
  8352. this.$slider.append($slides);
  8353. this.$nav.append($navItems);
  8354. this.$navItems = this.$nav.find('li');
  8355. this.$slides = this.$slider.find('li');
  8356. };
  8357. PureView.prototype.loadImage = function($slide, callback) {
  8358. var appendedFlag = 'image-appended';
  8359. if (!$slide.data(appendedFlag)) {
  8360. var $img = $('<img>', {
  8361. src: $slide.data('src'),
  8362. alt: $slide.data('title')
  8363. });
  8364. $slide.html($img).wrapInner('<div class="am-pinch-zoom"></div>').redraw();
  8365. var $pinchWrapper = $slide.find(this.options.selector.pinchZoom);
  8366. $pinchWrapper.data('amui.pinchzoom', new PinchZoom($pinchWrapper[0], {}));
  8367. $slide.data('image-appended', true);
  8368. }
  8369. callback && callback.call(this);
  8370. };
  8371. PureView.prototype.activate = function($slide) {
  8372. var options = this.options;
  8373. var $slides = this.$slides;
  8374. var activeIndex = $slides.index($slide);
  8375. var title = $slide.data('title') || '';
  8376. var active = options.className.active;
  8377. if ($slides.find('.' + active).is($slide)) {
  8378. return;
  8379. }
  8380. if (this.transitioning) {
  8381. return;
  8382. }
  8383. this.loadImage($slide, function() {
  8384. UI.utils.imageLoader($slide.find('img'), function(image) {
  8385. $slide.find('.am-pinch-zoom').addClass('am-pureview-loaded');
  8386. $(image).addClass('am-img-loaded');
  8387. });
  8388. });
  8389. this.transitioning = 1;
  8390. this.$title.text(title);
  8391. this.$current.text(activeIndex + 1);
  8392. $slides.removeClass();
  8393. $slide.addClass(active);
  8394. $slides.eq(activeIndex - 1).addClass(options.className.prevSlide);
  8395. $slides.eq(activeIndex + 1).addClass(options.className.nextSlide);
  8396. this.$navItems.removeClass().
  8397. eq(activeIndex).addClass(options.className.active);
  8398. if (transition) {
  8399. $slide.one(transition.end, $.proxy(function() {
  8400. this.transitioning = 0;
  8401. }, this)).emulateTransitionEnd(300);
  8402. } else {
  8403. this.transitioning = 0;
  8404. }
  8405. // TODO: pre-load next image
  8406. };
  8407. PureView.prototype.nextSlide = function() {
  8408. if (this.$slides.length === 1) {
  8409. return;
  8410. }
  8411. var $slides = this.$slides;
  8412. var $active = $slides.filter('.am-active');
  8413. var activeIndex = $slides.index($active);
  8414. var rightSpring = 'am-animation-right-spring';
  8415. if (activeIndex + 1 >= $slides.length) { // last one
  8416. animation && $active.addClass(rightSpring).on(animation.end, function() {
  8417. $active.removeClass(rightSpring);
  8418. });
  8419. } else {
  8420. this.activate($slides.eq(activeIndex + 1));
  8421. }
  8422. };
  8423. PureView.prototype.prevSlide = function() {
  8424. if (this.$slides.length === 1) {
  8425. return;
  8426. }
  8427. var $slides = this.$slides;
  8428. var $active = $slides.filter('.am-active');
  8429. var activeIndex = this.$slides.index(($active));
  8430. var leftSpring = 'am-animation-left-spring';
  8431. if (activeIndex === 0) { // first one
  8432. animation && $active.addClass(leftSpring).on(animation.end, function() {
  8433. $active.removeClass(leftSpring);
  8434. });
  8435. } else {
  8436. this.activate($slides.eq(activeIndex - 1));
  8437. }
  8438. };
  8439. PureView.prototype.toggleToolBar = function() {
  8440. this.$pureview.toggleClass(this.options.className.barActive);
  8441. };
  8442. PureView.prototype.open = function(index) {
  8443. var active = index || 0;
  8444. this.checkScrollbar();
  8445. this.setScrollbar();
  8446. this.activate(this.$slides.eq(active));
  8447. this.$pureview.show().redraw().addClass(this.options.className.active);
  8448. this.$body.addClass(this.options.className.activeBody);
  8449. };
  8450. PureView.prototype.close = function() {
  8451. var options = this.options;
  8452. this.$pureview.removeClass(options.className.active);
  8453. this.$slides.removeClass();
  8454. function resetBody() {
  8455. this.$pureview.hide();
  8456. this.$body.removeClass(options.className.activeBody);
  8457. this.resetScrollbar();
  8458. }
  8459. if (transition) {
  8460. this.$pureview.one(transition.end, $.proxy(resetBody, this)).
  8461. emulateTransitionEnd(300);
  8462. } else {
  8463. resetBody.call(this);
  8464. }
  8465. };
  8466. PureView.prototype.checkScrollbar = function() {
  8467. this.scrollbarWidth = UI.utils.measureScrollbar();
  8468. };
  8469. PureView.prototype.setScrollbar = function() {
  8470. var bodyPaddingRight = parseInt((this.$body.css('padding-right') || 0), 10);
  8471. if (this.scrollbarWidth) {
  8472. this.$body.css('padding-right', bodyPaddingRight + this.scrollbarWidth);
  8473. }
  8474. };
  8475. PureView.prototype.resetScrollbar = function() {
  8476. this.$body.css('padding-right', '');
  8477. };
  8478. UI.plugin('pureview', PureView);
  8479. // Init code
  8480. UI.ready(function(context) {
  8481. $('[data-am-pureview]', context).pureview();
  8482. });
  8483. module.exports = PureView;
  8484. // TODO: 1. 动画改进
  8485. // 2. 改变图片的时候恢复 Zoom
  8486. // 3. 选项
  8487. // 4. 图片高度问题:由于 PinchZoom 的原因,过高的图片如果设置看了滚动,则放大以后显示不全
  8488. /***/ },
  8489. /* 21 */
  8490. /***/ function(module, exports, __webpack_require__) {
  8491. 'use strict';
  8492. var $ = __webpack_require__(1);
  8493. var UI = __webpack_require__(2);
  8494. /**
  8495. * @via https://github.com/uikit/uikit/blob/master/src/js/scrollspy.js
  8496. * @license https://github.com/uikit/uikit/blob/master/LICENSE.md
  8497. */
  8498. var ScrollSpy = function(element, options) {
  8499. if (!UI.support.animation) {
  8500. return;
  8501. }
  8502. this.options = $.extend({}, ScrollSpy.DEFAULTS, options);
  8503. this.$element = $(element);
  8504. var checkViewRAF = function() {
  8505. UI.utils.rAF.call(window, $.proxy(this.checkView, this));
  8506. }.bind(this);
  8507. this.$window = $(window).on('scroll.scrollspy.amui', checkViewRAF)
  8508. .on('resize.scrollspy.amui orientationchange.scrollspy.amui',
  8509. UI.utils.debounce(checkViewRAF, 50));
  8510. this.timer = this.inViewState = this.initInView = null;
  8511. checkViewRAF();
  8512. };
  8513. ScrollSpy.DEFAULTS = {
  8514. animation: 'fade',
  8515. className: {
  8516. inView: 'am-scrollspy-inview',
  8517. init: 'am-scrollspy-init'
  8518. },
  8519. repeat: true,
  8520. delay: 0,
  8521. topOffset: 0,
  8522. leftOffset: 0
  8523. };
  8524. ScrollSpy.prototype.checkView = function() {
  8525. var $element = this.$element;
  8526. var options = this.options;
  8527. var inView = UI.utils.isInView($element, options);
  8528. var animation = options.animation ?
  8529. ' am-animation-' + options.animation : '';
  8530. if (inView && !this.inViewState) {
  8531. if (this.timer) {
  8532. clearTimeout(this.timer);
  8533. }
  8534. if (!this.initInView) {
  8535. $element.addClass(options.className.init);
  8536. this.offset = $element.offset();
  8537. this.initInView = true;
  8538. $element.trigger('init.scrollspy.amui');
  8539. }
  8540. this.timer = setTimeout(function() {
  8541. if (inView) {
  8542. $element.addClass(options.className.inView + animation).width();
  8543. }
  8544. }, options.delay);
  8545. this.inViewState = true;
  8546. $element.trigger('inview.scrollspy.amui');
  8547. }
  8548. if (!inView && this.inViewState && options.repeat) {
  8549. $element.removeClass(options.className.inView + animation);
  8550. this.inViewState = false;
  8551. $element.trigger('outview.scrollspy.amui');
  8552. }
  8553. };
  8554. ScrollSpy.prototype.check = function() {
  8555. UI.utils.rAF.call(window, $.proxy(this.checkView, this));
  8556. };
  8557. // Sticky Plugin
  8558. UI.plugin('scrollspy', ScrollSpy);
  8559. // Init code
  8560. UI.ready(function(context) {
  8561. $('[data-am-scrollspy]', context).scrollspy();
  8562. });
  8563. module.exports = ScrollSpy;
  8564. /***/ },
  8565. /* 22 */
  8566. /***/ function(module, exports, __webpack_require__) {
  8567. 'use strict';
  8568. var $ = __webpack_require__(1);
  8569. var UI = __webpack_require__(2);
  8570. __webpack_require__(23);
  8571. /**
  8572. * @via https://github.com/uikit/uikit/
  8573. * @license https://github.com/uikit/uikit/blob/master/LICENSE.md
  8574. */
  8575. // ScrollSpyNav Class
  8576. var ScrollSpyNav = function(element, options) {
  8577. this.options = $.extend({}, ScrollSpyNav.DEFAULTS, options);
  8578. this.$element = $(element);
  8579. this.anchors = [];
  8580. this.$links = this.$element.find('a[href^="#"]').each(function(i, link) {
  8581. this.anchors.push($(link).attr('href'));
  8582. }.bind(this));
  8583. this.$targets = $(this.anchors.join(', '));
  8584. var processRAF = function() {
  8585. UI.utils.rAF.call(window, $.proxy(this.process, this));
  8586. }.bind(this);
  8587. this.$window = $(window).on('scroll.scrollspynav.amui', processRAF)
  8588. .on('resize.scrollspynav.amui orientationchange.scrollspynav.amui',
  8589. UI.utils.debounce(processRAF, 50));
  8590. processRAF();
  8591. this.scrollProcess();
  8592. };
  8593. ScrollSpyNav.DEFAULTS = {
  8594. className: {
  8595. active: 'am-active'
  8596. },
  8597. closest: false,
  8598. smooth: true,
  8599. offsetTop: 0
  8600. };
  8601. ScrollSpyNav.prototype.process = function() {
  8602. var scrollTop = this.$window.scrollTop();
  8603. var options = this.options;
  8604. var inViews = [];
  8605. var $links = this.$links;
  8606. var $targets = this.$targets;
  8607. $targets.each(function(i, target) {
  8608. if (UI.utils.isInView(target, options)) {
  8609. inViews.push(target);
  8610. }
  8611. });
  8612. // console.log(inViews.length);
  8613. if (inViews.length) {
  8614. var $target;
  8615. $.each(inViews, function(i, item) {
  8616. if ($(item).offset().top >= scrollTop) {
  8617. $target = $(item);
  8618. return false; // break
  8619. }
  8620. });
  8621. if (!$target) {
  8622. return;
  8623. }
  8624. if (options.closest) {
  8625. $links.closest(options.closest).removeClass(options.className.active);
  8626. $links.filter('a[href="#' + $target.attr('id') + '"]').
  8627. closest(options.closest).addClass(options.className.active);
  8628. } else {
  8629. $links.removeClass(options.className.active).
  8630. filter('a[href="#' + $target.attr('id') + '"]').
  8631. addClass(options.className.active);
  8632. }
  8633. }
  8634. };
  8635. ScrollSpyNav.prototype.scrollProcess = function() {
  8636. var $links = this.$links;
  8637. var options = this.options;
  8638. // smoothScroll
  8639. if (options.smooth && $.fn.smoothScroll) {
  8640. $links.on('click', function(e) {
  8641. e.preventDefault();
  8642. var $this = $(this);
  8643. var $target = $($this.attr('href'));
  8644. if (!$target) {
  8645. return;
  8646. }
  8647. var offsetTop = options.offsetTop &&
  8648. !isNaN(parseInt(options.offsetTop)) && parseInt(options.offsetTop) || 0;
  8649. $(window).smoothScroll({position: $target.offset().top - offsetTop});
  8650. });
  8651. }
  8652. };
  8653. // ScrollSpyNav Plugin
  8654. UI.plugin('scrollspynav', ScrollSpyNav);
  8655. // Init code
  8656. UI.ready(function(context) {
  8657. $('[data-am-scrollspy-nav]', context).scrollspynav();
  8658. });
  8659. module.exports = ScrollSpyNav;
  8660. // TODO: 1. 算法改进
  8661. // 2. 多级菜单支持
  8662. // 3. smooth scroll pushState
  8663. /***/ },
  8664. /* 23 */
  8665. /***/ function(module, exports, __webpack_require__) {
  8666. 'use strict';
  8667. var $ = __webpack_require__(1);
  8668. var UI = __webpack_require__(2);
  8669. var rAF = UI.utils.rAF;
  8670. var cAF = UI.utils.cancelAF;
  8671. /**
  8672. * Smooth Scroll
  8673. * @param position
  8674. * @via http://mir.aculo.us/2014/01/19/scrolling-dom-elements-to-the-top-a-zepto-plugin/
  8675. */
  8676. // Usage: $(window).smoothScroll([options])
  8677. // only allow one scroll to top operation to be in progress at a time,
  8678. // which is probably what you want
  8679. var smoothScrollInProgress = false;
  8680. var SmoothScroll = function(element, options) {
  8681. options = options || {};
  8682. var $this = $(element);
  8683. var targetY = parseInt(options.position) || SmoothScroll.DEFAULTS.position;
  8684. var initialY = $this.scrollTop();
  8685. var lastY = initialY;
  8686. var delta = targetY - initialY;
  8687. // duration in ms, make it a bit shorter for short distances
  8688. // this is not scientific and you might want to adjust this for
  8689. // your preferences
  8690. var speed = options.speed ||
  8691. Math.min(750, Math.min(1500, Math.abs(initialY - targetY)));
  8692. // temp variables (t will be a position between 0 and 1, y is the calculated scrollTop)
  8693. var start;
  8694. var t;
  8695. var y;
  8696. var cancelScroll = function() {
  8697. abort();
  8698. };
  8699. // abort if already in progress or nothing to scroll
  8700. if (smoothScrollInProgress) {
  8701. return;
  8702. }
  8703. if (delta === 0) {
  8704. return;
  8705. }
  8706. // quint ease-in-out smoothing, from
  8707. // https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js#L127-L136
  8708. function smooth(pos) {
  8709. if ((pos /= 0.5) < 1) {
  8710. return 0.5 * Math.pow(pos, 5);
  8711. }
  8712. return 0.5 * (Math.pow((pos - 2), 5) + 2);
  8713. }
  8714. function abort() {
  8715. $this.off('touchstart.smoothscroll.amui', cancelScroll);
  8716. smoothScrollInProgress = false;
  8717. }
  8718. // when there's a touch detected while scrolling is in progress, abort
  8719. // the scrolling (emulates native scrolling behavior)
  8720. $this.on('touchstart.smoothscroll.amui', cancelScroll);
  8721. smoothScrollInProgress = true;
  8722. // start rendering away! note the function given to frame
  8723. // is named "render" so we can reference it again further down
  8724. function render(now) {
  8725. if (!smoothScrollInProgress) {
  8726. return;
  8727. }
  8728. if (!start) {
  8729. start = now;
  8730. }
  8731. // calculate t, position of animation in [0..1]
  8732. t = Math.min(1, Math.max((now - start) / speed, 0));
  8733. // calculate the new scrollTop position (don't forget to smooth)
  8734. y = Math.round(initialY + delta * smooth(t));
  8735. // bracket scrollTop so we're never over-scrolling
  8736. if (delta > 0 && y > targetY) {
  8737. y = targetY;
  8738. }
  8739. if (delta < 0 && y < targetY) {
  8740. y = targetY;
  8741. }
  8742. // only actually set scrollTop if there was a change fromt he last frame
  8743. if (lastY != y) {
  8744. $this.scrollTop(y);
  8745. }
  8746. lastY = y;
  8747. // if we're not done yet, queue up an other frame to render,
  8748. // or clean up
  8749. if (y !== targetY) {
  8750. cAF(scrollRAF);
  8751. scrollRAF = rAF(render);
  8752. } else {
  8753. cAF(scrollRAF);
  8754. abort();
  8755. }
  8756. }
  8757. var scrollRAF = rAF(render);
  8758. };
  8759. SmoothScroll.DEFAULTS = {
  8760. position: 0
  8761. };
  8762. $.fn.smoothScroll = function(option) {
  8763. return this.each(function() {
  8764. new SmoothScroll(this, option);
  8765. });
  8766. };
  8767. // Init code
  8768. $(document).on('click.smoothScroll.amui.data-api', '[data-am-smooth-scroll]',
  8769. function(e) {
  8770. e.preventDefault();
  8771. var options = UI.utils.parseOptions($(this).data('amSmoothScroll'));
  8772. $(window).smoothScroll(options);
  8773. });
  8774. module.exports = SmoothScroll;
  8775. /***/ },
  8776. /* 24 */
  8777. /***/ function(module, exports, __webpack_require__) {
  8778. 'use strict';
  8779. var $ = __webpack_require__(1);
  8780. var UI = __webpack_require__(2);
  8781. // require('./ui.dropdown');
  8782. // Make jQuery :contains Case-Insensitive
  8783. $.expr[':'].containsNC = function(elem, i, match, array) {
  8784. return (elem.textContent || elem.innerText || '').toLowerCase().
  8785. indexOf((match[3] || '').toLowerCase()) >= 0;
  8786. };
  8787. /**
  8788. * Selected
  8789. * @desc HTML select replacer
  8790. * @via https://github.com/silviomoreto/bootstrap-select
  8791. * @license https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE
  8792. * @param element
  8793. * @param options
  8794. * @constructor
  8795. */
  8796. var Selected = function(element, options) {
  8797. this.$element = $(element);
  8798. this.options = $.extend({}, Selected.DEFAULTS, {
  8799. placeholder: element.getAttribute('placeholder') ||
  8800. Selected.DEFAULTS.placeholder
  8801. }, options);
  8802. this.$originalOptions = this.$element.find('option');
  8803. this.multiple = element.multiple;
  8804. this.$selector = null;
  8805. this.initialized = false;
  8806. this.init();
  8807. };
  8808. Selected.DEFAULTS = {
  8809. btnWidth: null,
  8810. btnSize: null,
  8811. btnStyle: 'default',
  8812. dropUp: 0,
  8813. maxHeight: null,
  8814. maxChecked: null,
  8815. placeholder: '点击选择...',
  8816. selectedClass: 'am-checked',
  8817. disabledClass: 'am-disabled',
  8818. searchBox: false,
  8819. tpl: '<div class="am-selected am-dropdown ' +
  8820. '<%= dropUp ? \'am-dropdown-up\': \'\' %>" id="<%= id %>" data-am-dropdown>' +
  8821. ' <button type="button" class="am-selected-btn am-btn am-dropdown-toggle">' +
  8822. ' <span class="am-selected-status am-fl"></span>' +
  8823. ' <i class="am-selected-icon am-icon-caret-' +
  8824. '<%= dropUp ? \'up\' : \'down\' %>"></i>' +
  8825. ' </button>' +
  8826. ' <div class="am-selected-content am-dropdown-content">' +
  8827. ' <h2 class="am-selected-header">' +
  8828. '<span class="am-icon-chevron-left">返回</span></h2>' +
  8829. ' <% if (searchBox) { %>' +
  8830. ' <div class="am-selected-search">' +
  8831. ' <input autocomplete="off" class="am-form-field am-input-sm" />' +
  8832. ' </div>' +
  8833. ' <% } %>' +
  8834. ' <ul class="am-selected-list">' +
  8835. ' <% for (var i = 0; i < options.length; i++) { %>' +
  8836. ' <% var option = options[i] %>' +
  8837. ' <% if (option.header) { %>' +
  8838. ' <li data-group="<%= option.group %>" class="am-selected-list-header">' +
  8839. ' <%= option.text %></li>' +
  8840. ' <% } else { %>' +
  8841. ' <li class="<%= option.classNames%>" ' +
  8842. ' data-index="<%= option.index %>" ' +
  8843. ' data-group="<%= option.group || 0 %>" ' +
  8844. ' data-value="<%= option.value %>" >' +
  8845. ' <span class="am-selected-text"><%= option.text %></span>' +
  8846. ' <i class="am-icon-check"></i></li>' +
  8847. ' <% } %>' +
  8848. ' <% } %>' +
  8849. ' </ul>' +
  8850. ' <div class="am-selected-hint"></div>' +
  8851. ' </div>' +
  8852. '</div>',
  8853. listTpl: '<% for (var i = 0; i < options.length; i++) { %>' +
  8854. ' <% var option = options[i] %>' +
  8855. ' <% if (option.header) { %>' +
  8856. ' <li data-group="<%= option.group %>" class="am-selected-list-header">' +
  8857. ' <%= option.text %></li>' +
  8858. ' <% } else { %>' +
  8859. ' <li class="<%= option.classNames %>" ' +
  8860. ' data-index="<%= option.index %>" ' +
  8861. ' data-group="<%= option.group || 0 %>" ' +
  8862. ' data-value="<%= option.value %>" >' +
  8863. ' <span class="am-selected-text"><%= option.text %></span>' +
  8864. ' <i class="am-icon-check"></i></li>' +
  8865. ' <% } %>' +
  8866. ' <% } %>'
  8867. };
  8868. Selected.prototype.init = function() {
  8869. var _this = this;
  8870. var $element = this.$element;
  8871. var options = this.options;
  8872. $element.hide();
  8873. var data = {
  8874. id: UI.utils.generateGUID('am-selected'),
  8875. multiple: this.multiple,
  8876. options: [],
  8877. searchBox: options.searchBox,
  8878. dropUp: options.dropUp,
  8879. placeholder: options.placeholder
  8880. };
  8881. this.$selector = $(UI.template(this.options.tpl, data));
  8882. // set select button styles
  8883. this.$selector.css({width: this.options.btnWidth});
  8884. if (this.$element[0].disabled) {
  8885. this.$selector.addClass(options.disabledClass);
  8886. }
  8887. this.$list = this.$selector.find('.am-selected-list');
  8888. this.$searchField = this.$selector.find('.am-selected-search input');
  8889. this.$hint = this.$selector.find('.am-selected-hint');
  8890. var $selectorBtn = this.$selector.find('.am-selected-btn');
  8891. var btnClassNames = [];
  8892. options.btnSize && btnClassNames.push('am-btn-' + options.btnSize);
  8893. options.btnStyle && btnClassNames.push('am-btn-' + options.btnStyle);
  8894. $selectorBtn.addClass(btnClassNames.join(' '));
  8895. this.$selector.dropdown({
  8896. justify: $selectorBtn
  8897. });
  8898. // set list height
  8899. if (options.maxHeight) {
  8900. this.$selector.find('.am-selected-list').css({
  8901. 'max-height': options.maxHeight,
  8902. 'overflow-y': 'scroll'
  8903. });
  8904. }
  8905. // set hint text
  8906. var hint = [];
  8907. var min = $element.attr('minchecked');
  8908. var max = $element.attr('maxchecked') || options.maxChecked;
  8909. this.maxChecked = max || Infinity;
  8910. if ($element[0].required) {
  8911. hint.push('必选');
  8912. }
  8913. if (min || max) {
  8914. min && hint.push('至少选择 ' + min + ' 项');
  8915. max && hint.push('至多选择 ' + max + ' 项');
  8916. }
  8917. this.$hint.text(hint.join(','));
  8918. // render dropdown list
  8919. this.renderOptions();
  8920. // append $selector after <select>
  8921. this.$element.after(this.$selector);
  8922. this.dropdown = this.$selector.data('amui.dropdown');
  8923. this.$status = this.$selector.find('.am-selected-status');
  8924. // #try to fixes #476
  8925. setTimeout(function() {
  8926. _this.syncData();
  8927. _this.initialized = true;
  8928. }, 0);
  8929. this.bindEvents();
  8930. };
  8931. Selected.prototype.renderOptions = function() {
  8932. var $element = this.$element;
  8933. var options = this.options;
  8934. var optionItems = [];
  8935. var $optgroup = $element.find('optgroup');
  8936. this.$originalOptions = this.$element.find('option');
  8937. // 单选框使用 JS 禁用已经选择的 option 以后,
  8938. // 浏览器会重新选定第一个 option,但有一定延迟,致使 JS 获取 value 时返回 null
  8939. if (!this.multiple && ($element.val() === null)) {
  8940. this.$originalOptions.length &&
  8941. (this.$originalOptions.get(0).selected = true);
  8942. }
  8943. function pushOption(index, item, group) {
  8944. if (item.value === '') {
  8945. // skip to next iteration
  8946. // @see http://stackoverflow.com/questions/481601/how-to-skip-to-next-iteration-in-jquery-each-util
  8947. return true;
  8948. }
  8949. var classNames = '';
  8950. item.disabled && (classNames += options.disabledClass);
  8951. !item.disabled && item.selected && (classNames += options.selectedClass);
  8952. optionItems.push({
  8953. group: group,
  8954. index: index,
  8955. classNames: classNames,
  8956. text: item.text,
  8957. value: item.value
  8958. });
  8959. }
  8960. // select with option groups
  8961. if ($optgroup.length) {
  8962. $optgroup.each(function(i) {
  8963. // push group name
  8964. optionItems.push({
  8965. header: true,
  8966. group: i + 1,
  8967. text: this.label
  8968. });
  8969. $optgroup.eq(i).find('option').each(function(index, item) {
  8970. pushOption(index, item, i);
  8971. });
  8972. });
  8973. } else {
  8974. // without option groups
  8975. this.$originalOptions.each(function(index, item) {
  8976. pushOption(index, item, null);
  8977. });
  8978. }
  8979. this.$list.html(UI.template(options.listTpl, {options: optionItems}));
  8980. this.$shadowOptions = this.$list.find('> li').
  8981. not('.am-selected-list-header');
  8982. };
  8983. Selected.prototype.setChecked = function(item) {
  8984. var options = this.options;
  8985. var $item = $(item);
  8986. var isChecked = $item.hasClass(options.selectedClass);
  8987. if (this.multiple) {
  8988. // multiple
  8989. var checkedLength = this.$list.find('.' + options.selectedClass).length;
  8990. if (!isChecked && this.maxChecked <= checkedLength) {
  8991. this.$element.trigger('checkedOverflow.selected.amui', {
  8992. selected: this
  8993. });
  8994. return false;
  8995. }
  8996. } else {
  8997. if (isChecked) {
  8998. return false;
  8999. }
  9000. this.dropdown.close();
  9001. this.$shadowOptions.not($item).removeClass(options.selectedClass);
  9002. }
  9003. $item.toggleClass(options.selectedClass);
  9004. this.syncData(item);
  9005. };
  9006. /**
  9007. * syncData
  9008. * @desc if `item` set, only sync `item` related option
  9009. * @param {Object} item
  9010. */
  9011. Selected.prototype.syncData = function(item) {
  9012. var _this = this;
  9013. var options = this.options;
  9014. var status = [];
  9015. var $checked = $([]);
  9016. this.$shadowOptions.filter('.' + options.selectedClass).each(function() {
  9017. var $this = $(this);
  9018. status.push($this.find('.am-selected-text').text());
  9019. if (!item) {
  9020. $checked = $checked.add(_this.$originalOptions
  9021. .filter('[value="' + $this.data('value') + '"]')
  9022. .prop('selected', true));
  9023. }
  9024. });
  9025. if (item) {
  9026. var $item = $(item);
  9027. this.$originalOptions
  9028. .filter('[value="' + $item.data('value') + '"]')
  9029. .prop('selected', $item.hasClass(options.selectedClass));
  9030. } else {
  9031. this.$originalOptions.not($checked).prop('selected', false);
  9032. }
  9033. // nothing selected
  9034. if (!this.$element.val()) {
  9035. status = [options.placeholder];
  9036. }
  9037. this.$status.text(status.join(', '));
  9038. // Do not trigger change event on initializing
  9039. this.initialized && this.$element.trigger('change');
  9040. };
  9041. Selected.prototype.bindEvents = function() {
  9042. var _this = this;
  9043. var header = 'am-selected-list-header';
  9044. var handleKeyup = UI.utils.debounce(function(e) {
  9045. _this.$shadowOptions.not('.' + header).hide().
  9046. filter(':containsNC("' + e.target.value + '")').show();
  9047. }, 100);
  9048. this.$list.on('click', '> li', function(e) {
  9049. var $this = $(this);
  9050. !$this.hasClass(_this.options.disabledClass) &&
  9051. !$this.hasClass(header) && _this.setChecked(this);
  9052. });
  9053. // simple search with jQuery :contains
  9054. this.$searchField.on('keyup.selected.amui', handleKeyup);
  9055. // empty search keywords
  9056. this.$selector.on('closed.dropdown.amui', function() {
  9057. _this.$searchField.val('');
  9058. _this.$shadowOptions.css({display: ''});
  9059. });
  9060. // work with Validator
  9061. // @since 2.5
  9062. this.$element.on('validated.field.validator.amui', function(e) {
  9063. if (e.validity) {
  9064. var valid = e.validity.valid;
  9065. var errorClassName = 'am-invalid';
  9066. _this.$selector[(!valid ? 'add' : 'remove') + 'Class'](errorClassName);
  9067. }
  9068. });
  9069. // observe DOM
  9070. if (UI.support.mutationobserver) {
  9071. this.observer = new UI.support.mutationobserver(function() {
  9072. _this.$element.trigger('changed.selected.amui');
  9073. });
  9074. this.observer.observe(this.$element[0], {
  9075. childList: true,
  9076. attributes: true,
  9077. subtree: true,
  9078. characterData: true
  9079. });
  9080. }
  9081. // custom event
  9082. this.$element.on('changed.selected.amui', function() {
  9083. _this.renderOptions();
  9084. _this.syncData();
  9085. });
  9086. };
  9087. // @since: 2.5
  9088. Selected.prototype.select = function(item) {
  9089. var $item;
  9090. if (typeof item === 'number') {
  9091. $item = this.$list.find('> li').not('.am-selected-list-header').eq(item);
  9092. } else if (typeof item === 'string') {
  9093. $item = this.$list.find(item);
  9094. } else {
  9095. $item = $(item);
  9096. }
  9097. $item.trigger('click');
  9098. },
  9099. // @since: 2.5
  9100. Selected.prototype.enable = function() {
  9101. this.$element.prop('disable', false);
  9102. this.$selector.dropdown('enable');
  9103. },
  9104. // @since: 2.5
  9105. Selected.prototype.disable = function() {
  9106. this.$element.prop('disable', true);
  9107. this.$selector.dropdown('disable');
  9108. },
  9109. Selected.prototype.destroy = function() {
  9110. this.$element.removeData('amui.selected').show();
  9111. this.$selector.remove();
  9112. };
  9113. UI.plugin('selected', Selected);
  9114. // Conflict with jQuery form
  9115. // https://github.com/malsup/form/blob/6bf24a5f6d8be65f4e5491863180c09356d9dadd/jquery.form.js#L1240-L1258
  9116. // https://github.com/allmobilize/amazeui/issues/379
  9117. // @deprecated: $.fn.selected = $.fn.selectIt = Plugin;
  9118. // New way to resolve conflict:
  9119. // @see https://github.com/amazeui/amazeui/issues/781#issuecomment-158873541
  9120. UI.ready(function(context) {
  9121. $('[data-am-selected]', context).selected();
  9122. });
  9123. module.exports = Selected;
  9124. /***/ },
  9125. /* 25 */
  9126. /***/ function(module, exports, __webpack_require__) {
  9127. 'use strict';
  9128. __webpack_require__(15);
  9129. var $ = __webpack_require__(1);
  9130. var UI = __webpack_require__(2);
  9131. var QRCode = __webpack_require__(26);
  9132. var doc = document;
  9133. var $doc = $(doc);
  9134. var Share = function(options) {
  9135. this.options = $.extend({}, Share.DEFAULTS, options || {});
  9136. this.$element = null;
  9137. this.$wechatQr = null;
  9138. this.pics = null;
  9139. this.inited = false;
  9140. this.active = false;
  9141. // this.init();
  9142. };
  9143. Share.DEFAULTS = {
  9144. sns: ['weibo', 'qq', 'qzone', 'tqq', 'wechat', 'renren'],
  9145. title: '分享到',
  9146. cancel: '取消',
  9147. closeOnShare: true,
  9148. id: UI.utils.generateGUID('am-share'),
  9149. desc: 'Hi,孤夜观天象,发现一个不错的西西,分享一下下 ;-)',
  9150. via: 'Amaze UI',
  9151. tpl: '<div class="am-share am-modal-actions" id="<%= id %>">' +
  9152. '<h3 class="am-share-title"><%= title %></h3>' +
  9153. '<ul class="am-share-sns am-avg-sm-3">' +
  9154. '<% for(var i = 0; i < sns.length; i++) {%>' +
  9155. '<li>' +
  9156. '<a href="<%= sns[i].shareUrl %>" ' +
  9157. 'data-am-share-to="<%= sns[i].id %>" >' +
  9158. '<i class="am-icon-<%= sns[i].icon %>"></i>' +
  9159. '<span><%= sns[i].title %></span>' +
  9160. '</a></li>' +
  9161. '<% } %></ul>' +
  9162. '<div class="am-share-footer">' +
  9163. '<button class="am-btn am-btn-default am-btn-block" ' +
  9164. 'data-am-share-close><%= cancel %></button></div>' +
  9165. '</div>'
  9166. };
  9167. Share.SNS = {
  9168. weibo: {
  9169. title: '新浪微博',
  9170. url: 'http://service.weibo.com/share/share.php',
  9171. width: 620,
  9172. height: 450,
  9173. icon: 'weibo'
  9174. },
  9175. // url 链接地址
  9176. // title:”, 分享的文字内容(可选,默认为所在页面的title)
  9177. // appkey:”, 您申请的应用appkey,显示分享来源(可选)
  9178. // pic:”, 分享图片的路径(可选)
  9179. // ralateUid:”, 关联用户的UID,分享微博会@该用户(可选)
  9180. // NOTE: 会自动抓取图片,不用指定 pic
  9181. qq: {
  9182. title: 'QQ 好友',
  9183. url: 'http://connect.qq.com/widget/shareqq/index.html',
  9184. icon: 'qq'
  9185. },
  9186. // url:,
  9187. // title:'', 分享标题(可选)
  9188. // pics:'', 分享图片的路径(可选)
  9189. // summary:'', 分享摘要(可选)
  9190. // site:'', 分享来源 如:腾讯网(可选)
  9191. // desc: '' 发送给用户的消息
  9192. // NOTE: 经过测试,最终发给用户的只有 url 和 desc
  9193. qzone: {
  9194. title: 'QQ 空间',
  9195. url: 'http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey',
  9196. icon: 'star'
  9197. },
  9198. // http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=xxx&title=xxx&desc=&summary=&site=
  9199. // url:,
  9200. // title:'', 分享标题(可选)
  9201. // desc:'', 默认分享理由(可选)
  9202. // summary:'', 分享摘要(可选)
  9203. // site:'', 分享来源 如:腾讯网(可选)
  9204. // pics:'', 分享图片的路径(可选),不会自动抓取,多个图片用|分隔
  9205. tqq: {
  9206. title: '腾讯微博',
  9207. url: 'http://v.t.qq.com/share/share.php',
  9208. icon: 'tencent-weibo'
  9209. },
  9210. // url=xx&title=&appkey=801cf76d3cfc44ada52ec13114e84a96
  9211. // url
  9212. // title
  9213. // pic 多个图片用 | 分隔
  9214. // appkey
  9215. // NOTE: 不会自动抓取图片
  9216. wechat: {
  9217. title: '微信',
  9218. url: '[qrcode]',
  9219. icon: 'wechat'
  9220. },
  9221. // 生成一个二维码 供用户扫描
  9222. // 相关接口 https://github.com/zxlie/WeixinApi
  9223. renren: {
  9224. title: '人人网',
  9225. url: 'http://widget.renren.com/dialog/share',
  9226. icon: 'renren'
  9227. },
  9228. // http://widget.renren.com/dialog/share?resourceUrl=www&srcUrl=www&title=ww&description=xxx
  9229. // 550 * 400
  9230. // resourceUrl : '', // 分享的资源Url
  9231. // srcUrl : '', // 分享的资源来源Url,
  9232. // // 默认为header中的Referer,如果分享失败可以调整此值为resourceUrl试试
  9233. // pic : '', // 分享的主题图片,会自动抓取
  9234. // title : '', // 分享的标题
  9235. // description : '' // 分享的详细描述
  9236. // NOTE: 经过测试,直接使用 url 参数即可
  9237. douban: {
  9238. title: '豆瓣',
  9239. url: 'http://www.douban.com/recommend/',
  9240. icon: 'share-alt'
  9241. },
  9242. // http://www.douban.com/service/sharebutton
  9243. // 450 * 330
  9244. // http://www.douban.com/share/service?bm=1&image=&href=xxx&updated=&name=
  9245. // href 链接
  9246. // name 标题
  9247. /* void (function() {
  9248. var d = document, e = encodeURIComponent,
  9249. s1 = window.getSelection, s2 = d.getSelection,
  9250. s3 = d.selection, s = s1 ? s1()
  9251. : s2 ? s2() : s3 ? s3.createRange().text : '',
  9252. r = 'http://www.douban.com/recommend/?url=&title=&sel=&v=1&r=1'
  9253. })();
  9254. */
  9255. // tsohu: '',
  9256. // http://t.sohu.com/third/post.jsp?url=&title=&content=utf-8&pic=
  9257. // print: '',
  9258. mail: {
  9259. title: '邮件分享',
  9260. url: 'mailto:',
  9261. icon: 'envelope-o'
  9262. },
  9263. sms: {
  9264. title: '短信分享',
  9265. url: 'sms:',
  9266. icon: 'comment'
  9267. }
  9268. };
  9269. Share.prototype.render = function() {
  9270. var options = this.options;
  9271. var snsData = [];
  9272. var title = encodeURIComponent(doc.title);
  9273. var link = encodeURIComponent(doc.location);
  9274. var msgBody = '?body=' + title + link;
  9275. options.sns.forEach(function(item, i) {
  9276. if (Share.SNS[item]) {
  9277. var tmp = Share.SNS[item];
  9278. var shareUrl;
  9279. tmp.id = item;
  9280. if (item === 'mail') {
  9281. shareUrl = msgBody + '&subject=' + options.desc;
  9282. } else if (item === 'sms') {
  9283. shareUrl = msgBody;
  9284. } else {
  9285. shareUrl = '?url=' + link + '&title=' + title;
  9286. }
  9287. tmp.shareUrl = tmp.url + shareUrl;
  9288. snsData.push(tmp);
  9289. }
  9290. });
  9291. return UI.template(options.tpl, $.extend({}, options, {sns: snsData}));
  9292. };
  9293. Share.prototype.init = function() {
  9294. if (this.inited) {
  9295. return;
  9296. }
  9297. var me = this;
  9298. var shareItem = '[data-am-share-to]';
  9299. $doc.ready($.proxy(function() {
  9300. $('body').append(this.render()); // append share DOM to body
  9301. this.$element = $('#' + this.options.id);
  9302. this.$element.find('[data-am-share-close]').
  9303. on('click.share.amui', function() {
  9304. me.close();
  9305. });
  9306. }, this));
  9307. $doc.on('click.share.amui', shareItem, $.proxy(function(e) {
  9308. var $clicked = $(e.target);
  9309. var $target = $clicked.is(shareItem) && $clicked ||
  9310. $clicked.parent(shareItem);
  9311. var sns = $target.attr('data-am-share-to');
  9312. if (!(sns === 'mail' || sns === 'sms')) {
  9313. e.preventDefault();
  9314. this.shareTo(sns, this.setData(sns));
  9315. }
  9316. this.close();
  9317. }, this));
  9318. this.inited = true;
  9319. };
  9320. Share.prototype.open = function() {
  9321. !this.inited && this.init();
  9322. this.$element && this.$element.modal('open');
  9323. this.$element.trigger('open.share.amui');
  9324. this.active = true;
  9325. };
  9326. Share.prototype.close = function() {
  9327. this.$element && this.$element.modal('close');
  9328. this.$element.trigger('close.share.amui');
  9329. this.active = false;
  9330. };
  9331. Share.prototype.toggle = function() {
  9332. this.active ? this.close() : this.open();
  9333. };
  9334. Share.prototype.setData = function(sns) {
  9335. if (!sns) {
  9336. return;
  9337. }
  9338. var shareData = {
  9339. url: doc.location,
  9340. title: doc.title
  9341. };
  9342. var desc = this.options.desc;
  9343. var imgSrc = this.pics || [];
  9344. var qqReg = /^(qzone|qq|tqq)$/;
  9345. if (qqReg.test(sns) && !imgSrc.length) {
  9346. var allImages = doc.images;
  9347. for (var i = 0; i < allImages.length && i < 10; i++) {
  9348. !!allImages[i].src && imgSrc.push(encodeURIComponent(allImages[i].src));
  9349. }
  9350. this.pics = imgSrc; // 缓存图片
  9351. }
  9352. switch (sns) {
  9353. case 'qzone':
  9354. shareData.desc = desc;
  9355. shareData.site = this.options.via;
  9356. shareData.pics = imgSrc.join('|');
  9357. // TODO: 抓取图片多张
  9358. break;
  9359. case 'qq':
  9360. shareData.desc = desc;
  9361. shareData.site = this.options.via;
  9362. shareData.pics = imgSrc[0];
  9363. // 抓取一张图片
  9364. break;
  9365. case 'tqq':
  9366. // 抓取图片多张
  9367. shareData.pic = imgSrc.join('|');
  9368. break;
  9369. }
  9370. return shareData;
  9371. };
  9372. Share.prototype.shareTo = function(sns, data) {
  9373. var snsInfo = Share.SNS[sns];
  9374. if (!snsInfo) {
  9375. return;
  9376. }
  9377. if (sns === 'wechat' || sns === 'weixin') {
  9378. return this.wechatQr();
  9379. }
  9380. var query = [];
  9381. for (var key in data) {
  9382. if (data[key]) {
  9383. // 避免 encode 图片分隔符 |
  9384. query.push(key.toString() + '=' + ((key === 'pic' || key === 'pics') ?
  9385. data[key] : encodeURIComponent(data[key])));
  9386. }
  9387. }
  9388. window.open(snsInfo.url + '?' + query.join('&'));
  9389. };
  9390. Share.prototype.wechatQr = function() {
  9391. if (!this.$wechatQr) {
  9392. var qrId = UI.utils.generateGUID('am-share-wechat');
  9393. var $qr = $('<div class="am-modal am-modal-no-btn am-share-wechat-qr">' +
  9394. '<div class="am-modal-dialog"><div class="am-modal-hd">分享到微信 ' +
  9395. '<a href="" class="am-close am-close-spin" ' +
  9396. 'data-am-modal-close>&times;</a> </div>' +
  9397. '<div class="am-modal-bd">' +
  9398. '<div class="am-share-wx-qr"></div>' +
  9399. '<div class="am-share-wechat-tip">' +
  9400. '打开微信,点击底部的<em>发现</em>,<br/> ' +
  9401. '使用<em>扫一扫</em>将网页分享至朋友圈</div></div></div></div>');
  9402. $qr.attr('id', qrId);
  9403. var qrNode = new QRCode({
  9404. render: 'canvas',
  9405. correctLevel: 0,
  9406. text: doc.location.href,
  9407. width: 180,
  9408. height: 180,
  9409. background: '#fff',
  9410. foreground: '#000'
  9411. });
  9412. $qr.find('.am-share-wx-qr').html(qrNode);
  9413. $qr.appendTo($('body'));
  9414. this.$wechatQr = $('#' + qrId);
  9415. }
  9416. this.$wechatQr.modal('open');
  9417. };
  9418. var share = new Share();
  9419. $doc.on('click.share.amui.data-api', '[data-am-toggle="share"]', function(e) {
  9420. e.preventDefault();
  9421. share.toggle();
  9422. });
  9423. module.exports = UI.share = share;
  9424. /***/ },
  9425. /* 26 */
  9426. /***/ function(module, exports, __webpack_require__) {
  9427. var $ = __webpack_require__(1);
  9428. var UI = __webpack_require__(2);
  9429. /**
  9430. * @ver 1.1.0
  9431. * @via https://github.com/aralejs/qrcode/blob/master/src/qrcode.js
  9432. * @license http://aralejs.org/
  9433. */
  9434. var qrcodeAlgObjCache = [];
  9435. /**
  9436. * 二维码构造函数,主要用于绘制
  9437. * @param {Object} opt 传递参数
  9438. * @return {String} qrcode
  9439. * @constructor
  9440. */
  9441. var QRCode = function(opt) {
  9442. if (typeof opt === 'string') { // 只编码ASCII字符串
  9443. opt = {
  9444. text: opt
  9445. };
  9446. }
  9447. // 设置默认参数
  9448. this.options = $.extend({}, {
  9449. text: "",
  9450. render: "",
  9451. width: 256,
  9452. height: 256,
  9453. correctLevel: 3,
  9454. background: "#ffffff",
  9455. foreground: "#000000"
  9456. }, opt);
  9457. // 使用QRCodeAlg创建二维码结构
  9458. var qrCodeAlg = null;
  9459. for (var i = 0, l = qrcodeAlgObjCache.length; i < l; i++) {
  9460. if (qrcodeAlgObjCache[i].text == this.options.text && qrcodeAlgObjCache[i].text.correctLevel == this.options.correctLevel) {
  9461. qrCodeAlg = qrcodeAlgObjCache[i].obj;
  9462. break;
  9463. }
  9464. }
  9465. if (i == l) {
  9466. qrCodeAlg = new QRCodeAlg(this.options.text, this.options.correctLevel);
  9467. qrcodeAlgObjCache.push({
  9468. text: this.options.text,
  9469. correctLevel: this.options.correctLevel,
  9470. obj: qrCodeAlg
  9471. });
  9472. }
  9473. if (this.options.render) {
  9474. switch (this.options.render) {
  9475. case "canvas":
  9476. return this.createCanvas(qrCodeAlg);
  9477. case "table":
  9478. return this.createTable(qrCodeAlg);
  9479. case "svg":
  9480. return this.createSVG(qrCodeAlg);
  9481. default:
  9482. return this.createDefault(qrCodeAlg);
  9483. }
  9484. }
  9485. return this.createDefault(qrCodeAlg);
  9486. };
  9487. /**
  9488. * 使用Canvas来画二维码
  9489. * @return {}
  9490. */
  9491. QRCode.prototype.createDefault = function(qrCodeAlg) {
  9492. var canvas = document.createElement('canvas');
  9493. if (canvas.getContext)
  9494. return this.createCanvas(qrCodeAlg);
  9495. if (!!document.createElementNS && !!document.createElementNS(SVG_NS, 'svg').createSVGRect)
  9496. return this.createSVG(qrCodeAlg);
  9497. return this.createTable(qrCodeAlg);
  9498. };
  9499. QRCode.prototype.createCanvas = function(qrCodeAlg) {
  9500. //创建canvas节点
  9501. var canvas = document.createElement('canvas');
  9502. canvas.width = this.options.width;
  9503. canvas.height = this.options.height;
  9504. var ctx = canvas.getContext('2d');
  9505. //计算每个点的长宽
  9506. var tileW = (this.options.width / qrCodeAlg.getModuleCount()).toPrecision(4);
  9507. var tileH = this.options.height / qrCodeAlg.getModuleCount().toPrecision(4);
  9508. //绘制
  9509. for (var row = 0; row < qrCodeAlg.getModuleCount(); row++) {
  9510. for (var col = 0; col < qrCodeAlg.getModuleCount(); col++) {
  9511. ctx.fillStyle = qrCodeAlg.modules[row][col] ? this.options.foreground : this.options.background;
  9512. var w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW));
  9513. var h = (Math.ceil((row + 1) * tileW) - Math.floor(row * tileW));
  9514. ctx.fillRect(Math.round(col * tileW), Math.round(row * tileH), w, h);
  9515. }
  9516. }
  9517. //返回绘制的节点
  9518. return canvas;
  9519. };
  9520. /**
  9521. * 使用table来绘制二维码
  9522. * @return {}
  9523. */
  9524. QRCode.prototype.createTable = function(qrCodeAlg) {
  9525. //创建table节点
  9526. var s = [];
  9527. s.push('<table style="border:0px; margin:0px; padding:0px; border-collapse:collapse; background-color: ' +
  9528. this.options.background +
  9529. ';">');
  9530. // 计算每个节点的长宽;取整,防止点之间出现分离
  9531. var tileW = -1, tileH = -1, caculateW = -1, caculateH = -1;
  9532. tileW = caculateW = Math.floor(this.options.width / qrCodeAlg.getModuleCount());
  9533. tileH = caculateH = Math.floor(this.options.height / qrCodeAlg.getModuleCount());
  9534. if (caculateW <= 0) {
  9535. if (qrCodeAlg.getModuleCount() < 80) {
  9536. tileW = 2;
  9537. } else {
  9538. tileW = 1;
  9539. }
  9540. }
  9541. if (caculateH <= 0) {
  9542. if (qrCodeAlg.getModuleCount() < 80) {
  9543. tileH = 2;
  9544. } else {
  9545. tileH = 1;
  9546. }
  9547. }
  9548. // 绘制二维码
  9549. foreTd = '<td style="border:0px; margin:0px; padding:0px; width:' + tileW + 'px; background-color: ' + this.options.foreground + '"></td>',
  9550. backTd = '<td style="border:0px; margin:0px; padding:0px; width:' + tileW + 'px; background-color: ' + this.options.background + '"></td>',
  9551. l = qrCodeAlg.getModuleCount();
  9552. for (var row = 0; row < l; row++) {
  9553. s.push('<tr style="border:0px; margin:0px; padding:0px; height: ' + tileH + 'px">');
  9554. for (var col = 0; col < l; col++) {
  9555. s.push(qrCodeAlg.modules[row][col] ? foreTd : backTd);
  9556. }
  9557. s.push('</tr>');
  9558. }
  9559. s.push('</table>');
  9560. var span = document.createElement("span");
  9561. span.innerHTML = s.join('');
  9562. return span.firstChild;
  9563. };
  9564. /**
  9565. * 使用SVG开绘制二维码
  9566. * @return {}
  9567. */
  9568. QRCode.prototype.createSVG = function(qrCodeAlg) {
  9569. var x, dx, y, dy,
  9570. moduleCount = qrCodeAlg.getModuleCount(),
  9571. scale = this.options.height / this.options.width,
  9572. svg = '<svg xmlns="http://www.w3.org/2000/svg" '
  9573. + 'width="' + this.options.width + 'px" height="' + this.options.height + 'px" '
  9574. + 'viewbox="0 0 ' + moduleCount * 10 + ' ' + moduleCount * 10 * scale + '">',
  9575. rectHead = '<path ',
  9576. foreRect = ' style="stroke-width:0.5;stroke:' + this.options.foreground
  9577. + ';fill:' + this.options.foreground + ';"></path>',
  9578. backRect = ' style="stroke-width:0.5;stroke:' + this.options.background
  9579. + ';fill:' + this.options.background + ';"></path>';
  9580. // draw in the svg
  9581. for (var row = 0; row < moduleCount; row++) {
  9582. for (var col = 0; col < moduleCount; col++) {
  9583. x = col * 10;
  9584. y = row * 10 * scale;
  9585. dx = (col + 1) * 10;
  9586. dy = (row + 1) * 10 * scale;
  9587. svg += rectHead + 'd="M ' + x + ',' + y
  9588. + ' L ' + dx + ',' + y
  9589. + ' L ' + dx + ',' + dy
  9590. + ' L ' + x + ',' + dy
  9591. + ' Z"';
  9592. svg += qrCodeAlg.modules[row][col] ? foreRect : backRect;
  9593. }
  9594. }
  9595. svg += '</svg>';
  9596. // return just built svg
  9597. return $(svg)[0];
  9598. };
  9599. /**
  9600. * 获取单个字符的utf8编码
  9601. * unicode BMP平面约65535个字符
  9602. * @param {num} code
  9603. * return {array}
  9604. */
  9605. function unicodeFormat8(code) {
  9606. // 1 byte
  9607. if (code < 128) {
  9608. return [code];
  9609. // 2 bytes
  9610. } else if (code < 2048) {
  9611. c0 = 192 + (code >> 6);
  9612. c1 = 128 + (code & 63);
  9613. return [c0, c1];
  9614. // 3 bytes
  9615. } else {
  9616. c0 = 224 + (code >> 12);
  9617. c1 = 128 + (code >> 6 & 63);
  9618. c2 = 128 + (code & 63);
  9619. return [c0, c1, c2];
  9620. }
  9621. }
  9622. /**
  9623. * 获取字符串的utf8编码字节串
  9624. * @param {string} string
  9625. * @return {array}
  9626. */
  9627. function getUTF8Bytes(string) {
  9628. var utf8codes = [];
  9629. for (var i = 0; i < string.length; i++) {
  9630. var code = string.charCodeAt(i);
  9631. var utf8 = unicodeFormat8(code);
  9632. for (var j = 0; j < utf8.length; j++) {
  9633. utf8codes.push(utf8[j]);
  9634. }
  9635. }
  9636. return utf8codes;
  9637. }
  9638. /**
  9639. * 二维码算法实现
  9640. * @param {string} data 要编码的信息字符串
  9641. * @param {num} errorCorrectLevel 纠错等级
  9642. */
  9643. function QRCodeAlg(data, errorCorrectLevel) {
  9644. this.typeNumber = -1; // 版本
  9645. this.errorCorrectLevel = errorCorrectLevel;
  9646. this.modules = null; // 二维矩阵,存放最终结果
  9647. this.moduleCount = 0; // 矩阵大小
  9648. this.dataCache = null; // 数据缓存
  9649. this.rsBlocks = null; // 版本数据信息
  9650. this.totalDataCount = -1; // 可使用的数据量
  9651. this.data = data;
  9652. this.utf8bytes = getUTF8Bytes(data);
  9653. this.make();
  9654. }
  9655. QRCodeAlg.prototype = {
  9656. constructor: QRCodeAlg,
  9657. /**
  9658. * 获取二维码矩阵大小
  9659. * @return {num} 矩阵大小
  9660. */
  9661. getModuleCount: function() {
  9662. return this.moduleCount;
  9663. },
  9664. /**
  9665. * 编码
  9666. */
  9667. make: function() {
  9668. this.getRightType();
  9669. this.dataCache = this.createData();
  9670. this.createQrcode();
  9671. },
  9672. /**
  9673. * 设置二位矩阵功能图形
  9674. * @param {bool} test 表示是否在寻找最好掩膜阶段
  9675. * @param {num} maskPattern 掩膜的版本
  9676. */
  9677. makeImpl: function(maskPattern) {
  9678. this.moduleCount = this.typeNumber * 4 + 17;
  9679. this.modules = new Array(this.moduleCount);
  9680. for (var row = 0; row < this.moduleCount; row++) {
  9681. this.modules[row] = new Array(this.moduleCount);
  9682. }
  9683. this.setupPositionProbePattern(0, 0);
  9684. this.setupPositionProbePattern(this.moduleCount - 7, 0);
  9685. this.setupPositionProbePattern(0, this.moduleCount - 7);
  9686. this.setupPositionAdjustPattern();
  9687. this.setupTimingPattern();
  9688. this.setupTypeInfo(true, maskPattern);
  9689. if (this.typeNumber >= 7) {
  9690. this.setupTypeNumber(true);
  9691. }
  9692. this.mapData(this.dataCache, maskPattern);
  9693. },
  9694. /**
  9695. * 设置二维码的位置探测图形
  9696. * @param {num} row 探测图形的中心横坐标
  9697. * @param {num} col 探测图形的中心纵坐标
  9698. */
  9699. setupPositionProbePattern: function(row, col) {
  9700. for (var r = -1; r <= 7; r++) {
  9701. if (row + r <= -1 || this.moduleCount <= row + r) continue;
  9702. for (var c = -1; c <= 7; c++) {
  9703. if (col + c <= -1 || this.moduleCount <= col + c) continue;
  9704. 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)) {
  9705. this.modules[row + r][col + c] = true;
  9706. } else {
  9707. this.modules[row + r][col + c] = false;
  9708. }
  9709. }
  9710. }
  9711. },
  9712. /**
  9713. * 创建二维码
  9714. * @return {[type]} [description]
  9715. */
  9716. createQrcode: function() {
  9717. var minLostPoint = 0;
  9718. var pattern = 0;
  9719. var bestModules = null;
  9720. for (var i = 0; i < 8; i++) {
  9721. this.makeImpl(i);
  9722. var lostPoint = QRUtil.getLostPoint(this);
  9723. if (i == 0 || minLostPoint > lostPoint) {
  9724. minLostPoint = lostPoint;
  9725. pattern = i;
  9726. bestModules = this.modules;
  9727. }
  9728. }
  9729. this.modules = bestModules;
  9730. this.setupTypeInfo(false, pattern);
  9731. if (this.typeNumber >= 7) {
  9732. this.setupTypeNumber(false);
  9733. }
  9734. },
  9735. /**
  9736. * 设置定位图形
  9737. * @return {[type]} [description]
  9738. */
  9739. setupTimingPattern: function() {
  9740. for (var r = 8; r < this.moduleCount - 8; r++) {
  9741. if (this.modules[r][6] != null) {
  9742. continue;
  9743. }
  9744. this.modules[r][6] = (r % 2 == 0);
  9745. if (this.modules[6][r] != null) {
  9746. continue;
  9747. }
  9748. this.modules[6][r] = (r % 2 == 0);
  9749. }
  9750. },
  9751. /**
  9752. * 设置矫正图形
  9753. * @return {[type]} [description]
  9754. */
  9755. setupPositionAdjustPattern: function() {
  9756. var pos = QRUtil.getPatternPosition(this.typeNumber);
  9757. for (var i = 0; i < pos.length; i++) {
  9758. for (var j = 0; j < pos.length; j++) {
  9759. var row = pos[i];
  9760. var col = pos[j];
  9761. if (this.modules[row][col] != null) {
  9762. continue;
  9763. }
  9764. for (var r = -2; r <= 2; r++) {
  9765. for (var c = -2; c <= 2; c++) {
  9766. if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) {
  9767. this.modules[row + r][col + c] = true;
  9768. } else {
  9769. this.modules[row + r][col + c] = false;
  9770. }
  9771. }
  9772. }
  9773. }
  9774. }
  9775. },
  9776. /**
  9777. * 设置版本信息(7以上版本才有)
  9778. * @param {bool} test 是否处于判断最佳掩膜阶段
  9779. * @return {[type]} [description]
  9780. */
  9781. setupTypeNumber: function(test) {
  9782. var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
  9783. for (var i = 0; i < 18; i++) {
  9784. var mod = (!test && ((bits >> i) & 1) == 1);
  9785. this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
  9786. this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
  9787. }
  9788. },
  9789. /**
  9790. * 设置格式信息(纠错等级和掩膜版本)
  9791. * @param {bool} test
  9792. * @param {num} maskPattern 掩膜版本
  9793. * @return {}
  9794. */
  9795. setupTypeInfo: function(test, maskPattern) {
  9796. var data = (QRErrorCorrectLevel[this.errorCorrectLevel] << 3) | maskPattern;
  9797. var bits = QRUtil.getBCHTypeInfo(data);
  9798. // vertical
  9799. for (var i = 0; i < 15; i++) {
  9800. var mod = (!test && ((bits >> i) & 1) == 1);
  9801. if (i < 6) {
  9802. this.modules[i][8] = mod;
  9803. } else if (i < 8) {
  9804. this.modules[i + 1][8] = mod;
  9805. } else {
  9806. this.modules[this.moduleCount - 15 + i][8] = mod;
  9807. }
  9808. // horizontal
  9809. var mod = (!test && ((bits >> i) & 1) == 1);
  9810. if (i < 8) {
  9811. this.modules[8][this.moduleCount - i - 1] = mod;
  9812. } else if (i < 9) {
  9813. this.modules[8][15 - i - 1 + 1] = mod;
  9814. } else {
  9815. this.modules[8][15 - i - 1] = mod;
  9816. }
  9817. }
  9818. // fixed module
  9819. this.modules[this.moduleCount - 8][8] = (!test);
  9820. },
  9821. /**
  9822. * 数据编码
  9823. * @return {[type]} [description]
  9824. */
  9825. createData: function() {
  9826. var buffer = new QRBitBuffer();
  9827. var lengthBits = this.typeNumber > 9 ? 16 : 8;
  9828. buffer.put(4, 4); //添加模式
  9829. buffer.put(this.utf8bytes.length, lengthBits);
  9830. for (var i = 0, l = this.utf8bytes.length; i < l; i++) {
  9831. buffer.put(this.utf8bytes[i], 8);
  9832. }
  9833. if (buffer.length + 4 <= this.totalDataCount * 8) {
  9834. buffer.put(0, 4);
  9835. }
  9836. // padding
  9837. while (buffer.length % 8 != 0) {
  9838. buffer.putBit(false);
  9839. }
  9840. // padding
  9841. while (true) {
  9842. if (buffer.length >= this.totalDataCount * 8) {
  9843. break;
  9844. }
  9845. buffer.put(QRCodeAlg.PAD0, 8);
  9846. if (buffer.length >= this.totalDataCount * 8) {
  9847. break;
  9848. }
  9849. buffer.put(QRCodeAlg.PAD1, 8);
  9850. }
  9851. return this.createBytes(buffer);
  9852. },
  9853. /**
  9854. * 纠错码编码
  9855. * @param {buffer} buffer 数据编码
  9856. * @return {[type]}
  9857. */
  9858. createBytes: function(buffer) {
  9859. var offset = 0;
  9860. var maxDcCount = 0;
  9861. var maxEcCount = 0;
  9862. var length = this.rsBlock.length / 3;
  9863. var rsBlocks = new Array();
  9864. for (var i = 0; i < length; i++) {
  9865. var count = this.rsBlock[i * 3 + 0];
  9866. var totalCount = this.rsBlock[i * 3 + 1];
  9867. var dataCount = this.rsBlock[i * 3 + 2];
  9868. for (var j = 0; j < count; j++) {
  9869. rsBlocks.push([dataCount, totalCount]);
  9870. }
  9871. }
  9872. var dcdata = new Array(rsBlocks.length);
  9873. var ecdata = new Array(rsBlocks.length);
  9874. for (var r = 0; r < rsBlocks.length; r++) {
  9875. var dcCount = rsBlocks[r][0];
  9876. var ecCount = rsBlocks[r][1] - dcCount;
  9877. maxDcCount = Math.max(maxDcCount, dcCount);
  9878. maxEcCount = Math.max(maxEcCount, ecCount);
  9879. dcdata[r] = new Array(dcCount);
  9880. for (var i = 0; i < dcdata[r].length; i++) {
  9881. dcdata[r][i] = 0xff & buffer.buffer[i + offset];
  9882. }
  9883. offset += dcCount;
  9884. var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
  9885. var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
  9886. var modPoly = rawPoly.mod(rsPoly);
  9887. ecdata[r] = new Array(rsPoly.getLength() - 1);
  9888. for (var i = 0; i < ecdata[r].length; i++) {
  9889. var modIndex = i + modPoly.getLength() - ecdata[r].length;
  9890. ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;
  9891. }
  9892. }
  9893. var data = new Array(this.totalDataCount);
  9894. var index = 0;
  9895. for (var i = 0; i < maxDcCount; i++) {
  9896. for (var r = 0; r < rsBlocks.length; r++) {
  9897. if (i < dcdata[r].length) {
  9898. data[index++] = dcdata[r][i];
  9899. }
  9900. }
  9901. }
  9902. for (var i = 0; i < maxEcCount; i++) {
  9903. for (var r = 0; r < rsBlocks.length; r++) {
  9904. if (i < ecdata[r].length) {
  9905. data[index++] = ecdata[r][i];
  9906. }
  9907. }
  9908. }
  9909. return data;
  9910. },
  9911. /**
  9912. * 布置模块,构建最终信息
  9913. * @param {} data
  9914. * @param {} maskPattern
  9915. * @return {}
  9916. */
  9917. mapData: function(data, maskPattern) {
  9918. var inc = -1;
  9919. var row = this.moduleCount - 1;
  9920. var bitIndex = 7;
  9921. var byteIndex = 0;
  9922. for (var col = this.moduleCount - 1; col > 0; col -= 2) {
  9923. if (col == 6) col--;
  9924. while (true) {
  9925. for (var c = 0; c < 2; c++) {
  9926. if (this.modules[row][col - c] == null) {
  9927. var dark = false;
  9928. if (byteIndex < data.length) {
  9929. dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);
  9930. }
  9931. var mask = QRUtil.getMask(maskPattern, row, col - c);
  9932. if (mask) {
  9933. dark = !dark;
  9934. }
  9935. this.modules[row][col - c] = dark;
  9936. bitIndex--;
  9937. if (bitIndex == -1) {
  9938. byteIndex++;
  9939. bitIndex = 7;
  9940. }
  9941. }
  9942. }
  9943. row += inc;
  9944. if (row < 0 || this.moduleCount <= row) {
  9945. row -= inc;
  9946. inc = -inc;
  9947. break;
  9948. }
  9949. }
  9950. }
  9951. }
  9952. };
  9953. /**
  9954. * 填充字段
  9955. */
  9956. QRCodeAlg.PAD0 = 0xEC;
  9957. QRCodeAlg.PAD1 = 0x11;
  9958. //---------------------------------------------------------------------
  9959. // 纠错等级对应的编码
  9960. //---------------------------------------------------------------------
  9961. var QRErrorCorrectLevel = [1, 0, 3, 2];
  9962. //---------------------------------------------------------------------
  9963. // 掩膜版本
  9964. //---------------------------------------------------------------------
  9965. var QRMaskPattern = {
  9966. PATTERN000: 0,
  9967. PATTERN001: 1,
  9968. PATTERN010: 2,
  9969. PATTERN011: 3,
  9970. PATTERN100: 4,
  9971. PATTERN101: 5,
  9972. PATTERN110: 6,
  9973. PATTERN111: 7
  9974. };
  9975. //---------------------------------------------------------------------
  9976. // 工具类
  9977. //---------------------------------------------------------------------
  9978. var QRUtil = {
  9979. /*
  9980. 每个版本矫正图形的位置
  9981. */
  9982. PATTERN_POSITION_TABLE: [
  9983. [],
  9984. [6, 18],
  9985. [6, 22],
  9986. [6, 26],
  9987. [6, 30],
  9988. [6, 34],
  9989. [6, 22, 38],
  9990. [6, 24, 42],
  9991. [6, 26, 46],
  9992. [6, 28, 50],
  9993. [6, 30, 54],
  9994. [6, 32, 58],
  9995. [6, 34, 62],
  9996. [6, 26, 46, 66],
  9997. [6, 26, 48, 70],
  9998. [6, 26, 50, 74],
  9999. [6, 30, 54, 78],
  10000. [6, 30, 56, 82],
  10001. [6, 30, 58, 86],
  10002. [6, 34, 62, 90],
  10003. [6, 28, 50, 72, 94],
  10004. [6, 26, 50, 74, 98],
  10005. [6, 30, 54, 78, 102],
  10006. [6, 28, 54, 80, 106],
  10007. [6, 32, 58, 84, 110],
  10008. [6, 30, 58, 86, 114],
  10009. [6, 34, 62, 90, 118],
  10010. [6, 26, 50, 74, 98, 122],
  10011. [6, 30, 54, 78, 102, 126],
  10012. [6, 26, 52, 78, 104, 130],
  10013. [6, 30, 56, 82, 108, 134],
  10014. [6, 34, 60, 86, 112, 138],
  10015. [6, 30, 58, 86, 114, 142],
  10016. [6, 34, 62, 90, 118, 146],
  10017. [6, 30, 54, 78, 102, 126, 150],
  10018. [6, 24, 50, 76, 102, 128, 154],
  10019. [6, 28, 54, 80, 106, 132, 158],
  10020. [6, 32, 58, 84, 110, 136, 162],
  10021. [6, 26, 54, 82, 110, 138, 166],
  10022. [6, 30, 58, 86, 114, 142, 170]
  10023. ],
  10024. G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
  10025. G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
  10026. G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
  10027. /*
  10028. BCH编码格式信息
  10029. */
  10030. getBCHTypeInfo: function(data) {
  10031. var d = data << 10;
  10032. while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
  10033. d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)));
  10034. }
  10035. return ((data << 10) | d) ^ QRUtil.G15_MASK;
  10036. },
  10037. /*
  10038. BCH编码版本信息
  10039. */
  10040. getBCHTypeNumber: function(data) {
  10041. var d = data << 12;
  10042. while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
  10043. d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)));
  10044. }
  10045. return (data << 12) | d;
  10046. },
  10047. /*
  10048. 获取BCH位信息
  10049. */
  10050. getBCHDigit: function(data) {
  10051. var digit = 0;
  10052. while (data != 0) {
  10053. digit++;
  10054. data >>>= 1;
  10055. }
  10056. return digit;
  10057. },
  10058. /*
  10059. 获取版本对应的矫正图形位置
  10060. */
  10061. getPatternPosition: function(typeNumber) {
  10062. return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
  10063. },
  10064. /*
  10065. 掩膜算法
  10066. */
  10067. getMask: function(maskPattern, i, j) {
  10068. switch (maskPattern) {
  10069. case QRMaskPattern.PATTERN000:
  10070. return (i + j) % 2 == 0;
  10071. case QRMaskPattern.PATTERN001:
  10072. return i % 2 == 0;
  10073. case QRMaskPattern.PATTERN010:
  10074. return j % 3 == 0;
  10075. case QRMaskPattern.PATTERN011:
  10076. return (i + j) % 3 == 0;
  10077. case QRMaskPattern.PATTERN100:
  10078. return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
  10079. case QRMaskPattern.PATTERN101:
  10080. return (i * j) % 2 + (i * j) % 3 == 0;
  10081. case QRMaskPattern.PATTERN110:
  10082. return ((i * j) % 2 + (i * j) % 3) % 2 == 0;
  10083. case QRMaskPattern.PATTERN111:
  10084. return ((i * j) % 3 + (i + j) % 2) % 2 == 0;
  10085. default:
  10086. throw new Error("bad maskPattern:" + maskPattern);
  10087. }
  10088. },
  10089. /*
  10090. 获取RS的纠错多项式
  10091. */
  10092. getErrorCorrectPolynomial: function(errorCorrectLength) {
  10093. var a = new QRPolynomial([1], 0);
  10094. for (var i = 0; i < errorCorrectLength; i++) {
  10095. a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));
  10096. }
  10097. return a;
  10098. },
  10099. /*
  10100. 获取评价
  10101. */
  10102. getLostPoint: function(qrCode) {
  10103. var moduleCount = qrCode.getModuleCount(),
  10104. lostPoint = 0,
  10105. darkCount = 0;
  10106. for (var row = 0; row < moduleCount; row++) {
  10107. var sameCount = 0;
  10108. var head = qrCode.modules[row][0];
  10109. for (var col = 0; col < moduleCount; col++) {
  10110. var current = qrCode.modules[row][col];
  10111. //level 3 评价
  10112. if (col < moduleCount - 6) {
  10113. 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]) {
  10114. if (col < moduleCount - 10) {
  10115. if (qrCode.modules[row][col + 7] && qrCode.modules[row][col + 8] && qrCode.modules[row][col + 9] && qrCode.modules[row][col + 10]) {
  10116. lostPoint += 40;
  10117. }
  10118. } else if (col > 3) {
  10119. if (qrCode.modules[row][col - 1] && qrCode.modules[row][col - 2] && qrCode.modules[row][col - 3] && qrCode.modules[row][col - 4]) {
  10120. lostPoint += 40;
  10121. }
  10122. }
  10123. }
  10124. }
  10125. //level 2 评价
  10126. if ((row < moduleCount - 1) && (col < moduleCount - 1)) {
  10127. var count = 0;
  10128. if (current) count++;
  10129. if (qrCode.modules[row + 1][col]) count++;
  10130. if (qrCode.modules[row][col + 1]) count++;
  10131. if (qrCode.modules[row + 1][col + 1]) count++;
  10132. if (count == 0 || count == 4) {
  10133. lostPoint += 3;
  10134. }
  10135. }
  10136. //level 1 评价
  10137. if (head ^ current) {
  10138. sameCount++;
  10139. } else {
  10140. head = current;
  10141. if (sameCount >= 5) {
  10142. lostPoint += (3 + sameCount - 5);
  10143. }
  10144. sameCount = 1;
  10145. }
  10146. //level 4 评价
  10147. if (current) {
  10148. darkCount++;
  10149. }
  10150. }
  10151. }
  10152. for (var col = 0; col < moduleCount; col++) {
  10153. var sameCount = 0;
  10154. var head = qrCode.modules[0][col];
  10155. for (var row = 0; row < moduleCount; row++) {
  10156. var current = qrCode.modules[row][col];
  10157. //level 3 评价
  10158. if (row < moduleCount - 6) {
  10159. 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]) {
  10160. if (row < moduleCount - 10) {
  10161. if (qrCode.modules[row + 7][col] && qrCode.modules[row + 8][col] && qrCode.modules[row + 9][col] && qrCode.modules[row + 10][col]) {
  10162. lostPoint += 40;
  10163. }
  10164. } else if (row > 3) {
  10165. if (qrCode.modules[row - 1][col] && qrCode.modules[row - 2][col] && qrCode.modules[row - 3][col] && qrCode.modules[row - 4][col]) {
  10166. lostPoint += 40;
  10167. }
  10168. }
  10169. }
  10170. }
  10171. //level 1 评价
  10172. if (head ^ current) {
  10173. sameCount++;
  10174. } else {
  10175. head = current;
  10176. if (sameCount >= 5) {
  10177. lostPoint += (3 + sameCount - 5);
  10178. }
  10179. sameCount = 1;
  10180. }
  10181. }
  10182. }
  10183. // LEVEL4
  10184. var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
  10185. lostPoint += ratio * 10;
  10186. return lostPoint;
  10187. }
  10188. };
  10189. //---------------------------------------------------------------------
  10190. // QRMath使用的数学工具
  10191. //---------------------------------------------------------------------
  10192. var QRMath = {
  10193. /*
  10194. 将n转化为a^m
  10195. */
  10196. glog: function(n) {
  10197. if (n < 1) {
  10198. throw new Error("glog(" + n + ")");
  10199. }
  10200. return QRMath.LOG_TABLE[n];
  10201. },
  10202. /*
  10203. 将a^m转化为n
  10204. */
  10205. gexp: function(n) {
  10206. while (n < 0) {
  10207. n += 255;
  10208. }
  10209. while (n >= 256) {
  10210. n -= 255;
  10211. }
  10212. return QRMath.EXP_TABLE[n];
  10213. },
  10214. EXP_TABLE: new Array(256),
  10215. LOG_TABLE: new Array(256)
  10216. };
  10217. for (var i = 0; i < 8; i++) {
  10218. QRMath.EXP_TABLE[i] = 1 << i;
  10219. }
  10220. for (var i = 8; i < 256; i++) {
  10221. QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8];
  10222. }
  10223. for (var i = 0; i < 255; i++) {
  10224. QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;
  10225. }
  10226. //---------------------------------------------------------------------
  10227. // QRPolynomial 多项式
  10228. //---------------------------------------------------------------------
  10229. /**
  10230. * 多项式类
  10231. * @param {Array} num 系数
  10232. * @param {num} shift a^shift
  10233. */
  10234. function QRPolynomial(num, shift) {
  10235. if (num.length == undefined) {
  10236. throw new Error(num.length + "/" + shift);
  10237. }
  10238. var offset = 0;
  10239. while (offset < num.length && num[offset] == 0) {
  10240. offset++;
  10241. }
  10242. this.num = new Array(num.length - offset + shift);
  10243. for (var i = 0; i < num.length - offset; i++) {
  10244. this.num[i] = num[i + offset];
  10245. }
  10246. }
  10247. QRPolynomial.prototype = {
  10248. get: function(index) {
  10249. return this.num[index];
  10250. },
  10251. getLength: function() {
  10252. return this.num.length;
  10253. },
  10254. /**
  10255. * 多项式乘法
  10256. * @param {QRPolynomial} e 被乘多项式
  10257. * @return {[type]} [description]
  10258. */
  10259. multiply: function(e) {
  10260. var num = new Array(this.getLength() + e.getLength() - 1);
  10261. for (var i = 0; i < this.getLength(); i++) {
  10262. for (var j = 0; j < e.getLength(); j++) {
  10263. num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
  10264. }
  10265. }
  10266. return new QRPolynomial(num, 0);
  10267. },
  10268. /**
  10269. * 多项式模运算
  10270. * @param {QRPolynomial} e 模多项式
  10271. * @return {}
  10272. */
  10273. mod: function(e) {
  10274. var tl = this.getLength(),
  10275. el = e.getLength();
  10276. if (tl - el < 0) {
  10277. return this;
  10278. }
  10279. var num = new Array(tl);
  10280. for (var i = 0; i < tl; i++) {
  10281. num[i] = this.get(i);
  10282. }
  10283. while (num.length >= el) {
  10284. var ratio = QRMath.glog(num[0]) - QRMath.glog(e.get(0));
  10285. for (var i = 0; i < e.getLength(); i++) {
  10286. num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
  10287. }
  10288. while (num[0] == 0) {
  10289. num.shift();
  10290. }
  10291. }
  10292. return new QRPolynomial(num, 0);
  10293. }
  10294. };
  10295. //---------------------------------------------------------------------
  10296. // RS_BLOCK_TABLE
  10297. //---------------------------------------------------------------------
  10298. /*
  10299. 二维码各个版本信息[块数, 每块中的数据块数, 每块中的信息块数]
  10300. */
  10301. var RS_BLOCK_TABLE = [
  10302. // L
  10303. // M
  10304. // Q
  10305. // H
  10306. // 1
  10307. [1, 26, 19],
  10308. [1, 26, 16],
  10309. [1, 26, 13],
  10310. [1, 26, 9],
  10311. // 2
  10312. [1, 44, 34],
  10313. [1, 44, 28],
  10314. [1, 44, 22],
  10315. [1, 44, 16],
  10316. // 3
  10317. [1, 70, 55],
  10318. [1, 70, 44],
  10319. [2, 35, 17],
  10320. [2, 35, 13],
  10321. // 4
  10322. [1, 100, 80],
  10323. [2, 50, 32],
  10324. [2, 50, 24],
  10325. [4, 25, 9],
  10326. // 5
  10327. [1, 134, 108],
  10328. [2, 67, 43],
  10329. [2, 33, 15, 2, 34, 16],
  10330. [2, 33, 11, 2, 34, 12],
  10331. // 6
  10332. [2, 86, 68],
  10333. [4, 43, 27],
  10334. [4, 43, 19],
  10335. [4, 43, 15],
  10336. // 7
  10337. [2, 98, 78],
  10338. [4, 49, 31],
  10339. [2, 32, 14, 4, 33, 15],
  10340. [4, 39, 13, 1, 40, 14],
  10341. // 8
  10342. [2, 121, 97],
  10343. [2, 60, 38, 2, 61, 39],
  10344. [4, 40, 18, 2, 41, 19],
  10345. [4, 40, 14, 2, 41, 15],
  10346. // 9
  10347. [2, 146, 116],
  10348. [3, 58, 36, 2, 59, 37],
  10349. [4, 36, 16, 4, 37, 17],
  10350. [4, 36, 12, 4, 37, 13],
  10351. // 10
  10352. [2, 86, 68, 2, 87, 69],
  10353. [4, 69, 43, 1, 70, 44],
  10354. [6, 43, 19, 2, 44, 20],
  10355. [6, 43, 15, 2, 44, 16],
  10356. // 11
  10357. [4, 101, 81],
  10358. [1, 80, 50, 4, 81, 51],
  10359. [4, 50, 22, 4, 51, 23],
  10360. [3, 36, 12, 8, 37, 13],
  10361. // 12
  10362. [2, 116, 92, 2, 117, 93],
  10363. [6, 58, 36, 2, 59, 37],
  10364. [4, 46, 20, 6, 47, 21],
  10365. [7, 42, 14, 4, 43, 15],
  10366. // 13
  10367. [4, 133, 107],
  10368. [8, 59, 37, 1, 60, 38],
  10369. [8, 44, 20, 4, 45, 21],
  10370. [12, 33, 11, 4, 34, 12],
  10371. // 14
  10372. [3, 145, 115, 1, 146, 116],
  10373. [4, 64, 40, 5, 65, 41],
  10374. [11, 36, 16, 5, 37, 17],
  10375. [11, 36, 12, 5, 37, 13],
  10376. // 15
  10377. [5, 109, 87, 1, 110, 88],
  10378. [5, 65, 41, 5, 66, 42],
  10379. [5, 54, 24, 7, 55, 25],
  10380. [11, 36, 12],
  10381. // 16
  10382. [5, 122, 98, 1, 123, 99],
  10383. [7, 73, 45, 3, 74, 46],
  10384. [15, 43, 19, 2, 44, 20],
  10385. [3, 45, 15, 13, 46, 16],
  10386. // 17
  10387. [1, 135, 107, 5, 136, 108],
  10388. [10, 74, 46, 1, 75, 47],
  10389. [1, 50, 22, 15, 51, 23],
  10390. [2, 42, 14, 17, 43, 15],
  10391. // 18
  10392. [5, 150, 120, 1, 151, 121],
  10393. [9, 69, 43, 4, 70, 44],
  10394. [17, 50, 22, 1, 51, 23],
  10395. [2, 42, 14, 19, 43, 15],
  10396. // 19
  10397. [3, 141, 113, 4, 142, 114],
  10398. [3, 70, 44, 11, 71, 45],
  10399. [17, 47, 21, 4, 48, 22],
  10400. [9, 39, 13, 16, 40, 14],
  10401. // 20
  10402. [3, 135, 107, 5, 136, 108],
  10403. [3, 67, 41, 13, 68, 42],
  10404. [15, 54, 24, 5, 55, 25],
  10405. [15, 43, 15, 10, 44, 16],
  10406. // 21
  10407. [4, 144, 116, 4, 145, 117],
  10408. [17, 68, 42],
  10409. [17, 50, 22, 6, 51, 23],
  10410. [19, 46, 16, 6, 47, 17],
  10411. // 22
  10412. [2, 139, 111, 7, 140, 112],
  10413. [17, 74, 46],
  10414. [7, 54, 24, 16, 55, 25],
  10415. [34, 37, 13],
  10416. // 23
  10417. [4, 151, 121, 5, 152, 122],
  10418. [4, 75, 47, 14, 76, 48],
  10419. [11, 54, 24, 14, 55, 25],
  10420. [16, 45, 15, 14, 46, 16],
  10421. // 24
  10422. [6, 147, 117, 4, 148, 118],
  10423. [6, 73, 45, 14, 74, 46],
  10424. [11, 54, 24, 16, 55, 25],
  10425. [30, 46, 16, 2, 47, 17],
  10426. // 25
  10427. [8, 132, 106, 4, 133, 107],
  10428. [8, 75, 47, 13, 76, 48],
  10429. [7, 54, 24, 22, 55, 25],
  10430. [22, 45, 15, 13, 46, 16],
  10431. // 26
  10432. [10, 142, 114, 2, 143, 115],
  10433. [19, 74, 46, 4, 75, 47],
  10434. [28, 50, 22, 6, 51, 23],
  10435. [33, 46, 16, 4, 47, 17],
  10436. // 27
  10437. [8, 152, 122, 4, 153, 123],
  10438. [22, 73, 45, 3, 74, 46],
  10439. [8, 53, 23, 26, 54, 24],
  10440. [12, 45, 15, 28, 46, 16],
  10441. // 28
  10442. [3, 147, 117, 10, 148, 118],
  10443. [3, 73, 45, 23, 74, 46],
  10444. [4, 54, 24, 31, 55, 25],
  10445. [11, 45, 15, 31, 46, 16],
  10446. // 29
  10447. [7, 146, 116, 7, 147, 117],
  10448. [21, 73, 45, 7, 74, 46],
  10449. [1, 53, 23, 37, 54, 24],
  10450. [19, 45, 15, 26, 46, 16],
  10451. // 30
  10452. [5, 145, 115, 10, 146, 116],
  10453. [19, 75, 47, 10, 76, 48],
  10454. [15, 54, 24, 25, 55, 25],
  10455. [23, 45, 15, 25, 46, 16],
  10456. // 31
  10457. [13, 145, 115, 3, 146, 116],
  10458. [2, 74, 46, 29, 75, 47],
  10459. [42, 54, 24, 1, 55, 25],
  10460. [23, 45, 15, 28, 46, 16],
  10461. // 32
  10462. [17, 145, 115],
  10463. [10, 74, 46, 23, 75, 47],
  10464. [10, 54, 24, 35, 55, 25],
  10465. [19, 45, 15, 35, 46, 16],
  10466. // 33
  10467. [17, 145, 115, 1, 146, 116],
  10468. [14, 74, 46, 21, 75, 47],
  10469. [29, 54, 24, 19, 55, 25],
  10470. [11, 45, 15, 46, 46, 16],
  10471. // 34
  10472. [13, 145, 115, 6, 146, 116],
  10473. [14, 74, 46, 23, 75, 47],
  10474. [44, 54, 24, 7, 55, 25],
  10475. [59, 46, 16, 1, 47, 17],
  10476. // 35
  10477. [12, 151, 121, 7, 152, 122],
  10478. [12, 75, 47, 26, 76, 48],
  10479. [39, 54, 24, 14, 55, 25],
  10480. [22, 45, 15, 41, 46, 16],
  10481. // 36
  10482. [6, 151, 121, 14, 152, 122],
  10483. [6, 75, 47, 34, 76, 48],
  10484. [46, 54, 24, 10, 55, 25],
  10485. [2, 45, 15, 64, 46, 16],
  10486. // 37
  10487. [17, 152, 122, 4, 153, 123],
  10488. [29, 74, 46, 14, 75, 47],
  10489. [49, 54, 24, 10, 55, 25],
  10490. [24, 45, 15, 46, 46, 16],
  10491. // 38
  10492. [4, 152, 122, 18, 153, 123],
  10493. [13, 74, 46, 32, 75, 47],
  10494. [48, 54, 24, 14, 55, 25],
  10495. [42, 45, 15, 32, 46, 16],
  10496. // 39
  10497. [20, 147, 117, 4, 148, 118],
  10498. [40, 75, 47, 7, 76, 48],
  10499. [43, 54, 24, 22, 55, 25],
  10500. [10, 45, 15, 67, 46, 16],
  10501. // 40
  10502. [19, 148, 118, 6, 149, 119],
  10503. [18, 75, 47, 31, 76, 48],
  10504. [34, 54, 24, 34, 55, 25],
  10505. [20, 45, 15, 61, 46, 16]
  10506. ];
  10507. /**
  10508. * 根据数据获取对应版本
  10509. * @return {[type]} [description]
  10510. */
  10511. QRCodeAlg.prototype.getRightType = function() {
  10512. for (var typeNumber = 1; typeNumber < 41; typeNumber++) {
  10513. var rsBlock = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + this.errorCorrectLevel];
  10514. if (rsBlock == undefined) {
  10515. throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + this.errorCorrectLevel);
  10516. }
  10517. var length = rsBlock.length / 3;
  10518. var totalDataCount = 0;
  10519. for (var i = 0; i < length; i++) {
  10520. var count = rsBlock[i * 3 + 0];
  10521. var dataCount = rsBlock[i * 3 + 2];
  10522. totalDataCount += dataCount * count;
  10523. }
  10524. var lengthBytes = typeNumber > 9 ? 2 : 1;
  10525. if (this.utf8bytes.length + lengthBytes < totalDataCount || typeNumber == 40) {
  10526. this.typeNumber = typeNumber;
  10527. this.rsBlock = rsBlock;
  10528. this.totalDataCount = totalDataCount;
  10529. break;
  10530. }
  10531. }
  10532. };
  10533. //---------------------------------------------------------------------
  10534. // QRBitBuffer
  10535. //---------------------------------------------------------------------
  10536. function QRBitBuffer() {
  10537. this.buffer = new Array();
  10538. this.length = 0;
  10539. }
  10540. QRBitBuffer.prototype = {
  10541. get: function(index) {
  10542. var bufIndex = Math.floor(index / 8);
  10543. return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1);
  10544. },
  10545. put: function(num, length) {
  10546. for (var i = 0; i < length; i++) {
  10547. this.putBit(((num >>> (length - i - 1)) & 1));
  10548. }
  10549. },
  10550. putBit: function(bit) {
  10551. var bufIndex = Math.floor(this.length / 8);
  10552. if (this.buffer.length <= bufIndex) {
  10553. this.buffer.push(0);
  10554. }
  10555. if (bit) {
  10556. this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));
  10557. }
  10558. this.length++;
  10559. }
  10560. };
  10561. /**
  10562. * 获取单个字符的utf8编码
  10563. * unicode BMP平面约65535个字符
  10564. * @param {num} code
  10565. * return {array}
  10566. */
  10567. function unicodeFormat8(code) {
  10568. // 1 byte
  10569. if (code < 128) {
  10570. return [code];
  10571. // 2 bytes
  10572. } else if (code < 2048) {
  10573. c0 = 192 + (code >> 6);
  10574. c1 = 128 + (code & 63);
  10575. return [c0, c1];
  10576. // 3 bytes
  10577. } else {
  10578. c0 = 224 + (code >> 12);
  10579. c1 = 128 + (code >> 6 & 63);
  10580. c2 = 128 + (code & 63);
  10581. return [c0, c1, c2];
  10582. }
  10583. }
  10584. /**
  10585. * 获取字符串的utf8编码字节串
  10586. * @param {string} string
  10587. * @return {array}
  10588. */
  10589. function getUTF8Bytes(string) {
  10590. var utf8codes = [];
  10591. for (var i = 0; i < string.length; i++) {
  10592. var code = string.charCodeAt(i);
  10593. var utf8 = unicodeFormat8(code);
  10594. for (var j = 0; j < utf8.length; j++) {
  10595. utf8codes.push(utf8[j]);
  10596. }
  10597. }
  10598. return utf8codes;
  10599. }
  10600. /**
  10601. * 二维码算法实现
  10602. * @param {string} data 要编码的信息字符串
  10603. * @param {num} errorCorrectLevel 纠错等级
  10604. */
  10605. function QRCodeAlg(data, errorCorrectLevel) {
  10606. this.typeNumber = -1; //版本
  10607. this.errorCorrectLevel = errorCorrectLevel;
  10608. this.modules = null; //二维矩阵,存放最终结果
  10609. this.moduleCount = 0; //矩阵大小
  10610. this.dataCache = null; //数据缓存
  10611. this.rsBlocks = null; //版本数据信息
  10612. this.totalDataCount = -1; //可使用的数据量
  10613. this.data = data;
  10614. this.utf8bytes = getUTF8Bytes(data);
  10615. this.make();
  10616. }
  10617. QRCodeAlg.prototype = {
  10618. constructor: QRCodeAlg,
  10619. /**
  10620. * 获取二维码矩阵大小
  10621. * @return {num} 矩阵大小
  10622. */
  10623. getModuleCount: function() {
  10624. return this.moduleCount;
  10625. },
  10626. /**
  10627. * 编码
  10628. */
  10629. make: function() {
  10630. this.getRightType();
  10631. this.dataCache = this.createData();
  10632. this.createQrcode();
  10633. },
  10634. /**
  10635. * 设置二位矩阵功能图形
  10636. * @param {bool} test 表示是否在寻找最好掩膜阶段
  10637. * @param {num} maskPattern 掩膜的版本
  10638. */
  10639. makeImpl: function(maskPattern) {
  10640. this.moduleCount = this.typeNumber * 4 + 17;
  10641. this.modules = new Array(this.moduleCount);
  10642. for (var row = 0; row < this.moduleCount; row++) {
  10643. this.modules[row] = new Array(this.moduleCount);
  10644. }
  10645. this.setupPositionProbePattern(0, 0);
  10646. this.setupPositionProbePattern(this.moduleCount - 7, 0);
  10647. this.setupPositionProbePattern(0, this.moduleCount - 7);
  10648. this.setupPositionAdjustPattern();
  10649. this.setupTimingPattern();
  10650. this.setupTypeInfo(true, maskPattern);
  10651. if (this.typeNumber >= 7) {
  10652. this.setupTypeNumber(true);
  10653. }
  10654. this.mapData(this.dataCache, maskPattern);
  10655. },
  10656. /**
  10657. * 设置二维码的位置探测图形
  10658. * @param {num} row 探测图形的中心横坐标
  10659. * @param {num} col 探测图形的中心纵坐标
  10660. */
  10661. setupPositionProbePattern: function(row, col) {
  10662. for (var r = -1; r <= 7; r++) {
  10663. if (row + r <= -1 || this.moduleCount <= row + r) continue;
  10664. for (var c = -1; c <= 7; c++) {
  10665. if (col + c <= -1 || this.moduleCount <= col + c) continue;
  10666. 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)) {
  10667. this.modules[row + r][col + c] = true;
  10668. } else {
  10669. this.modules[row + r][col + c] = false;
  10670. }
  10671. }
  10672. }
  10673. },
  10674. /**
  10675. * 创建二维码
  10676. * @return {[type]} [description]
  10677. */
  10678. createQrcode: function() {
  10679. var minLostPoint = 0;
  10680. var pattern = 0;
  10681. var bestModules = null;
  10682. for (var i = 0; i < 8; i++) {
  10683. this.makeImpl(i);
  10684. var lostPoint = QRUtil.getLostPoint(this);
  10685. if (i == 0 || minLostPoint > lostPoint) {
  10686. minLostPoint = lostPoint;
  10687. pattern = i;
  10688. bestModules = this.modules;
  10689. }
  10690. }
  10691. this.modules = bestModules;
  10692. this.setupTypeInfo(false, pattern);
  10693. if (this.typeNumber >= 7) {
  10694. this.setupTypeNumber(false);
  10695. }
  10696. },
  10697. /**
  10698. * 设置定位图形
  10699. * @return {[type]} [description]
  10700. */
  10701. setupTimingPattern: function() {
  10702. for (var r = 8; r < this.moduleCount - 8; r++) {
  10703. if (this.modules[r][6] != null) {
  10704. continue;
  10705. }
  10706. this.modules[r][6] = (r % 2 == 0);
  10707. if (this.modules[6][r] != null) {
  10708. continue;
  10709. }
  10710. this.modules[6][r] = (r % 2 == 0);
  10711. }
  10712. },
  10713. /**
  10714. * 设置矫正图形
  10715. * @return {[type]} [description]
  10716. */
  10717. setupPositionAdjustPattern: function() {
  10718. var pos = QRUtil.getPatternPosition(this.typeNumber);
  10719. for (var i = 0; i < pos.length; i++) {
  10720. for (var j = 0; j < pos.length; j++) {
  10721. var row = pos[i];
  10722. var col = pos[j];
  10723. if (this.modules[row][col] != null) {
  10724. continue;
  10725. }
  10726. for (var r = -2; r <= 2; r++) {
  10727. for (var c = -2; c <= 2; c++) {
  10728. if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) {
  10729. this.modules[row + r][col + c] = true;
  10730. } else {
  10731. this.modules[row + r][col + c] = false;
  10732. }
  10733. }
  10734. }
  10735. }
  10736. }
  10737. },
  10738. /**
  10739. * 设置版本信息(7以上版本才有)
  10740. * @param {bool} test 是否处于判断最佳掩膜阶段
  10741. * @return {[type]} [description]
  10742. */
  10743. setupTypeNumber: function(test) {
  10744. var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
  10745. for (var i = 0; i < 18; i++) {
  10746. var mod = (!test && ((bits >> i) & 1) == 1);
  10747. this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
  10748. this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
  10749. }
  10750. },
  10751. /**
  10752. * 设置格式信息(纠错等级和掩膜版本)
  10753. * @param {bool} test
  10754. * @param {num} maskPattern 掩膜版本
  10755. * @return {}
  10756. */
  10757. setupTypeInfo: function(test, maskPattern) {
  10758. var data = (QRErrorCorrectLevel[this.errorCorrectLevel] << 3) | maskPattern;
  10759. var bits = QRUtil.getBCHTypeInfo(data);
  10760. // vertical
  10761. for (var i = 0; i < 15; i++) {
  10762. var mod = (!test && ((bits >> i) & 1) == 1);
  10763. if (i < 6) {
  10764. this.modules[i][8] = mod;
  10765. } else if (i < 8) {
  10766. this.modules[i + 1][8] = mod;
  10767. } else {
  10768. this.modules[this.moduleCount - 15 + i][8] = mod;
  10769. }
  10770. // horizontal
  10771. var mod = (!test && ((bits >> i) & 1) == 1);
  10772. if (i < 8) {
  10773. this.modules[8][this.moduleCount - i - 1] = mod;
  10774. } else if (i < 9) {
  10775. this.modules[8][15 - i - 1 + 1] = mod;
  10776. } else {
  10777. this.modules[8][15 - i - 1] = mod;
  10778. }
  10779. }
  10780. // fixed module
  10781. this.modules[this.moduleCount - 8][8] = (!test);
  10782. },
  10783. /**
  10784. * 数据编码
  10785. * @return {[type]} [description]
  10786. */
  10787. createData: function() {
  10788. var buffer = new QRBitBuffer();
  10789. var lengthBits = this.typeNumber > 9 ? 16 : 8;
  10790. buffer.put(4, 4); //添加模式
  10791. buffer.put(this.utf8bytes.length, lengthBits);
  10792. for (var i = 0, l = this.utf8bytes.length; i < l; i++) {
  10793. buffer.put(this.utf8bytes[i], 8);
  10794. }
  10795. if (buffer.length + 4 <= this.totalDataCount * 8) {
  10796. buffer.put(0, 4);
  10797. }
  10798. // padding
  10799. while (buffer.length % 8 != 0) {
  10800. buffer.putBit(false);
  10801. }
  10802. // padding
  10803. while (true) {
  10804. if (buffer.length >= this.totalDataCount * 8) {
  10805. break;
  10806. }
  10807. buffer.put(QRCodeAlg.PAD0, 8);
  10808. if (buffer.length >= this.totalDataCount * 8) {
  10809. break;
  10810. }
  10811. buffer.put(QRCodeAlg.PAD1, 8);
  10812. }
  10813. return this.createBytes(buffer);
  10814. },
  10815. /**
  10816. * 纠错码编码
  10817. * @param {buffer} buffer 数据编码
  10818. * @return {[type]}
  10819. */
  10820. createBytes: function(buffer) {
  10821. var offset = 0;
  10822. var maxDcCount = 0;
  10823. var maxEcCount = 0;
  10824. var length = this.rsBlock.length / 3;
  10825. var rsBlocks = new Array();
  10826. for (var i = 0; i < length; i++) {
  10827. var count = this.rsBlock[i * 3 + 0];
  10828. var totalCount = this.rsBlock[i * 3 + 1];
  10829. var dataCount = this.rsBlock[i * 3 + 2];
  10830. for (var j = 0; j < count; j++) {
  10831. rsBlocks.push([dataCount, totalCount]);
  10832. }
  10833. }
  10834. var dcdata = new Array(rsBlocks.length);
  10835. var ecdata = new Array(rsBlocks.length);
  10836. for (var r = 0; r < rsBlocks.length; r++) {
  10837. var dcCount = rsBlocks[r][0];
  10838. var ecCount = rsBlocks[r][1] - dcCount;
  10839. maxDcCount = Math.max(maxDcCount, dcCount);
  10840. maxEcCount = Math.max(maxEcCount, ecCount);
  10841. dcdata[r] = new Array(dcCount);
  10842. for (var i = 0; i < dcdata[r].length; i++) {
  10843. dcdata[r][i] = 0xff & buffer.buffer[i + offset];
  10844. }
  10845. offset += dcCount;
  10846. var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
  10847. var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
  10848. var modPoly = rawPoly.mod(rsPoly);
  10849. ecdata[r] = new Array(rsPoly.getLength() - 1);
  10850. for (var i = 0; i < ecdata[r].length; i++) {
  10851. var modIndex = i + modPoly.getLength() - ecdata[r].length;
  10852. ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;
  10853. }
  10854. }
  10855. var data = new Array(this.totalDataCount);
  10856. var index = 0;
  10857. for (var i = 0; i < maxDcCount; i++) {
  10858. for (var r = 0; r < rsBlocks.length; r++) {
  10859. if (i < dcdata[r].length) {
  10860. data[index++] = dcdata[r][i];
  10861. }
  10862. }
  10863. }
  10864. for (var i = 0; i < maxEcCount; i++) {
  10865. for (var r = 0; r < rsBlocks.length; r++) {
  10866. if (i < ecdata[r].length) {
  10867. data[index++] = ecdata[r][i];
  10868. }
  10869. }
  10870. }
  10871. return data;
  10872. },
  10873. /**
  10874. * 布置模块,构建最终信息
  10875. * @param {} data
  10876. * @param {} maskPattern
  10877. * @return {}
  10878. */
  10879. mapData: function(data, maskPattern) {
  10880. var inc = -1;
  10881. var row = this.moduleCount - 1;
  10882. var bitIndex = 7;
  10883. var byteIndex = 0;
  10884. for (var col = this.moduleCount - 1; col > 0; col -= 2) {
  10885. if (col == 6) col--;
  10886. while (true) {
  10887. for (var c = 0; c < 2; c++) {
  10888. if (this.modules[row][col - c] == null) {
  10889. var dark = false;
  10890. if (byteIndex < data.length) {
  10891. dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);
  10892. }
  10893. var mask = QRUtil.getMask(maskPattern, row, col - c);
  10894. if (mask) {
  10895. dark = !dark;
  10896. }
  10897. this.modules[row][col - c] = dark;
  10898. bitIndex--;
  10899. if (bitIndex == -1) {
  10900. byteIndex++;
  10901. bitIndex = 7;
  10902. }
  10903. }
  10904. }
  10905. row += inc;
  10906. if (row < 0 || this.moduleCount <= row) {
  10907. row -= inc;
  10908. inc = -inc;
  10909. break;
  10910. }
  10911. }
  10912. }
  10913. }
  10914. };
  10915. /**
  10916. * 填充字段
  10917. */
  10918. QRCodeAlg.PAD0 = 0xEC;
  10919. QRCodeAlg.PAD1 = 0x11;
  10920. //---------------------------------------------------------------------
  10921. // 纠错等级对应的编码
  10922. //---------------------------------------------------------------------
  10923. var QRErrorCorrectLevel = [1, 0, 3, 2];
  10924. //---------------------------------------------------------------------
  10925. // 掩膜版本
  10926. //---------------------------------------------------------------------
  10927. var QRMaskPattern = {
  10928. PATTERN000: 0,
  10929. PATTERN001: 1,
  10930. PATTERN010: 2,
  10931. PATTERN011: 3,
  10932. PATTERN100: 4,
  10933. PATTERN101: 5,
  10934. PATTERN110: 6,
  10935. PATTERN111: 7
  10936. };
  10937. //---------------------------------------------------------------------
  10938. // 工具类
  10939. //---------------------------------------------------------------------
  10940. var QRUtil = {
  10941. /*
  10942. 每个版本矫正图形的位置
  10943. */
  10944. PATTERN_POSITION_TABLE: [
  10945. [],
  10946. [6, 18],
  10947. [6, 22],
  10948. [6, 26],
  10949. [6, 30],
  10950. [6, 34],
  10951. [6, 22, 38],
  10952. [6, 24, 42],
  10953. [6, 26, 46],
  10954. [6, 28, 50],
  10955. [6, 30, 54],
  10956. [6, 32, 58],
  10957. [6, 34, 62],
  10958. [6, 26, 46, 66],
  10959. [6, 26, 48, 70],
  10960. [6, 26, 50, 74],
  10961. [6, 30, 54, 78],
  10962. [6, 30, 56, 82],
  10963. [6, 30, 58, 86],
  10964. [6, 34, 62, 90],
  10965. [6, 28, 50, 72, 94],
  10966. [6, 26, 50, 74, 98],
  10967. [6, 30, 54, 78, 102],
  10968. [6, 28, 54, 80, 106],
  10969. [6, 32, 58, 84, 110],
  10970. [6, 30, 58, 86, 114],
  10971. [6, 34, 62, 90, 118],
  10972. [6, 26, 50, 74, 98, 122],
  10973. [6, 30, 54, 78, 102, 126],
  10974. [6, 26, 52, 78, 104, 130],
  10975. [6, 30, 56, 82, 108, 134],
  10976. [6, 34, 60, 86, 112, 138],
  10977. [6, 30, 58, 86, 114, 142],
  10978. [6, 34, 62, 90, 118, 146],
  10979. [6, 30, 54, 78, 102, 126, 150],
  10980. [6, 24, 50, 76, 102, 128, 154],
  10981. [6, 28, 54, 80, 106, 132, 158],
  10982. [6, 32, 58, 84, 110, 136, 162],
  10983. [6, 26, 54, 82, 110, 138, 166],
  10984. [6, 30, 58, 86, 114, 142, 170]
  10985. ],
  10986. G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
  10987. G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
  10988. G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
  10989. /*
  10990. BCH编码格式信息
  10991. */
  10992. getBCHTypeInfo: function(data) {
  10993. var d = data << 10;
  10994. while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
  10995. d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)));
  10996. }
  10997. return ((data << 10) | d) ^ QRUtil.G15_MASK;
  10998. },
  10999. /*
  11000. BCH编码版本信息
  11001. */
  11002. getBCHTypeNumber: function(data) {
  11003. var d = data << 12;
  11004. while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
  11005. d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)));
  11006. }
  11007. return (data << 12) | d;
  11008. },
  11009. /*
  11010. 获取BCH位信息
  11011. */
  11012. getBCHDigit: function(data) {
  11013. var digit = 0;
  11014. while (data != 0) {
  11015. digit++;
  11016. data >>>= 1;
  11017. }
  11018. return digit;
  11019. },
  11020. /*
  11021. 获取版本对应的矫正图形位置
  11022. */
  11023. getPatternPosition: function(typeNumber) {
  11024. return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
  11025. },
  11026. /*
  11027. 掩膜算法
  11028. */
  11029. getMask: function(maskPattern, i, j) {
  11030. switch (maskPattern) {
  11031. case QRMaskPattern.PATTERN000:
  11032. return (i + j) % 2 == 0;
  11033. case QRMaskPattern.PATTERN001:
  11034. return i % 2 == 0;
  11035. case QRMaskPattern.PATTERN010:
  11036. return j % 3 == 0;
  11037. case QRMaskPattern.PATTERN011:
  11038. return (i + j) % 3 == 0;
  11039. case QRMaskPattern.PATTERN100:
  11040. return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
  11041. case QRMaskPattern.PATTERN101:
  11042. return (i * j) % 2 + (i * j) % 3 == 0;
  11043. case QRMaskPattern.PATTERN110:
  11044. return ((i * j) % 2 + (i * j) % 3) % 2 == 0;
  11045. case QRMaskPattern.PATTERN111:
  11046. return ((i * j) % 3 + (i + j) % 2) % 2 == 0;
  11047. default:
  11048. throw new Error("bad maskPattern:" + maskPattern);
  11049. }
  11050. },
  11051. /*
  11052. 获取RS的纠错多项式
  11053. */
  11054. getErrorCorrectPolynomial: function(errorCorrectLength) {
  11055. var a = new QRPolynomial([1], 0);
  11056. for (var i = 0; i < errorCorrectLength; i++) {
  11057. a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));
  11058. }
  11059. return a;
  11060. },
  11061. /*
  11062. 获取评价
  11063. */
  11064. getLostPoint: function(qrCode) {
  11065. var moduleCount = qrCode.getModuleCount(),
  11066. lostPoint = 0,
  11067. darkCount = 0;
  11068. for (var row = 0; row < moduleCount; row++) {
  11069. var sameCount = 0;
  11070. var head = qrCode.modules[row][0];
  11071. for (var col = 0; col < moduleCount; col++) {
  11072. var current = qrCode.modules[row][col];
  11073. //level 3 评价
  11074. if (col < moduleCount - 6) {
  11075. 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]) {
  11076. if (col < moduleCount - 10) {
  11077. if (qrCode.modules[row][col + 7] && qrCode.modules[row][col + 8] && qrCode.modules[row][col + 9] && qrCode.modules[row][col + 10]) {
  11078. lostPoint += 40;
  11079. }
  11080. } else if (col > 3) {
  11081. if (qrCode.modules[row][col - 1] && qrCode.modules[row][col - 2] && qrCode.modules[row][col - 3] && qrCode.modules[row][col - 4]) {
  11082. lostPoint += 40;
  11083. }
  11084. }
  11085. }
  11086. }
  11087. //level 2 评价
  11088. if ((row < moduleCount - 1) && (col < moduleCount - 1)) {
  11089. var count = 0;
  11090. if (current) count++;
  11091. if (qrCode.modules[row + 1][col]) count++;
  11092. if (qrCode.modules[row][col + 1]) count++;
  11093. if (qrCode.modules[row + 1][col + 1]) count++;
  11094. if (count == 0 || count == 4) {
  11095. lostPoint += 3;
  11096. }
  11097. }
  11098. //level 1 评价
  11099. if (head ^ current) {
  11100. sameCount++;
  11101. } else {
  11102. head = current;
  11103. if (sameCount >= 5) {
  11104. lostPoint += (3 + sameCount - 5);
  11105. }
  11106. sameCount = 1;
  11107. }
  11108. //level 4 评价
  11109. if (current) {
  11110. darkCount++;
  11111. }
  11112. }
  11113. }
  11114. for (var col = 0; col < moduleCount; col++) {
  11115. var sameCount = 0;
  11116. var head = qrCode.modules[0][col];
  11117. for (var row = 0; row < moduleCount; row++) {
  11118. var current = qrCode.modules[row][col];
  11119. //level 3 评价
  11120. if (row < moduleCount - 6) {
  11121. 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]) {
  11122. if (row < moduleCount - 10) {
  11123. if (qrCode.modules[row + 7][col] && qrCode.modules[row + 8][col] && qrCode.modules[row + 9][col] && qrCode.modules[row + 10][col]) {
  11124. lostPoint += 40;
  11125. }
  11126. } else if (row > 3) {
  11127. if (qrCode.modules[row - 1][col] && qrCode.modules[row - 2][col] && qrCode.modules[row - 3][col] && qrCode.modules[row - 4][col]) {
  11128. lostPoint += 40;
  11129. }
  11130. }
  11131. }
  11132. }
  11133. //level 1 评价
  11134. if (head ^ current) {
  11135. sameCount++;
  11136. } else {
  11137. head = current;
  11138. if (sameCount >= 5) {
  11139. lostPoint += (3 + sameCount - 5);
  11140. }
  11141. sameCount = 1;
  11142. }
  11143. }
  11144. }
  11145. // LEVEL4
  11146. var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
  11147. lostPoint += ratio * 10;
  11148. return lostPoint;
  11149. }
  11150. };
  11151. //---------------------------------------------------------------------
  11152. // QRMath使用的数学工具
  11153. //---------------------------------------------------------------------
  11154. var QRMath = {
  11155. /*
  11156. 将n转化为a^m
  11157. */
  11158. glog: function(n) {
  11159. if (n < 1) {
  11160. throw new Error("glog(" + n + ")");
  11161. }
  11162. return QRMath.LOG_TABLE[n];
  11163. },
  11164. /*
  11165. 将a^m转化为n
  11166. */
  11167. gexp: function(n) {
  11168. while (n < 0) {
  11169. n += 255;
  11170. }
  11171. while (n >= 256) {
  11172. n -= 255;
  11173. }
  11174. return QRMath.EXP_TABLE[n];
  11175. },
  11176. EXP_TABLE: new Array(256),
  11177. LOG_TABLE: new Array(256)
  11178. };
  11179. for (var i = 0; i < 8; i++) {
  11180. QRMath.EXP_TABLE[i] = 1 << i;
  11181. }
  11182. for (var i = 8; i < 256; i++) {
  11183. QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8];
  11184. }
  11185. for (var i = 0; i < 255; i++) {
  11186. QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;
  11187. }
  11188. //---------------------------------------------------------------------
  11189. // QRPolynomial 多项式
  11190. //---------------------------------------------------------------------
  11191. /**
  11192. * 多项式类
  11193. * @param {Array} num 系数
  11194. * @param {num} shift a^shift
  11195. */
  11196. function QRPolynomial(num, shift) {
  11197. if (num.length == undefined) {
  11198. throw new Error(num.length + "/" + shift);
  11199. }
  11200. var offset = 0;
  11201. while (offset < num.length && num[offset] == 0) {
  11202. offset++;
  11203. }
  11204. this.num = new Array(num.length - offset + shift);
  11205. for (var i = 0; i < num.length - offset; i++) {
  11206. this.num[i] = num[i + offset];
  11207. }
  11208. }
  11209. QRPolynomial.prototype = {
  11210. get: function(index) {
  11211. return this.num[index];
  11212. },
  11213. getLength: function() {
  11214. return this.num.length;
  11215. },
  11216. /**
  11217. * 多项式乘法
  11218. * @param {QRPolynomial} e 被乘多项式
  11219. * @return {[type]} [description]
  11220. */
  11221. multiply: function(e) {
  11222. var num = new Array(this.getLength() + e.getLength() - 1);
  11223. for (var i = 0; i < this.getLength(); i++) {
  11224. for (var j = 0; j < e.getLength(); j++) {
  11225. num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
  11226. }
  11227. }
  11228. return new QRPolynomial(num, 0);
  11229. },
  11230. /**
  11231. * 多项式模运算
  11232. * @param {QRPolynomial} e 模多项式
  11233. * @return {}
  11234. */
  11235. mod: function(e) {
  11236. var tl = this.getLength(),
  11237. el = e.getLength();
  11238. if (tl - el < 0) {
  11239. return this;
  11240. }
  11241. var num = new Array(tl);
  11242. for (var i = 0; i < tl; i++) {
  11243. num[i] = this.get(i);
  11244. }
  11245. while (num.length >= el) {
  11246. var ratio = QRMath.glog(num[0]) - QRMath.glog(e.get(0));
  11247. for (var i = 0; i < e.getLength(); i++) {
  11248. num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
  11249. }
  11250. while (num[0] == 0) {
  11251. num.shift();
  11252. }
  11253. }
  11254. return new QRPolynomial(num, 0);
  11255. }
  11256. };
  11257. //---------------------------------------------------------------------
  11258. // RS_BLOCK_TABLE
  11259. //---------------------------------------------------------------------
  11260. /*
  11261. 二维码各个版本信息[块数, 每块中的数据块数, 每块中的信息块数]
  11262. */
  11263. RS_BLOCK_TABLE = [
  11264. // L
  11265. // M
  11266. // Q
  11267. // H
  11268. // 1
  11269. [1, 26, 19],
  11270. [1, 26, 16],
  11271. [1, 26, 13],
  11272. [1, 26, 9],
  11273. // 2
  11274. [1, 44, 34],
  11275. [1, 44, 28],
  11276. [1, 44, 22],
  11277. [1, 44, 16],
  11278. // 3
  11279. [1, 70, 55],
  11280. [1, 70, 44],
  11281. [2, 35, 17],
  11282. [2, 35, 13],
  11283. // 4
  11284. [1, 100, 80],
  11285. [2, 50, 32],
  11286. [2, 50, 24],
  11287. [4, 25, 9],
  11288. // 5
  11289. [1, 134, 108],
  11290. [2, 67, 43],
  11291. [2, 33, 15, 2, 34, 16],
  11292. [2, 33, 11, 2, 34, 12],
  11293. // 6
  11294. [2, 86, 68],
  11295. [4, 43, 27],
  11296. [4, 43, 19],
  11297. [4, 43, 15],
  11298. // 7
  11299. [2, 98, 78],
  11300. [4, 49, 31],
  11301. [2, 32, 14, 4, 33, 15],
  11302. [4, 39, 13, 1, 40, 14],
  11303. // 8
  11304. [2, 121, 97],
  11305. [2, 60, 38, 2, 61, 39],
  11306. [4, 40, 18, 2, 41, 19],
  11307. [4, 40, 14, 2, 41, 15],
  11308. // 9
  11309. [2, 146, 116],
  11310. [3, 58, 36, 2, 59, 37],
  11311. [4, 36, 16, 4, 37, 17],
  11312. [4, 36, 12, 4, 37, 13],
  11313. // 10
  11314. [2, 86, 68, 2, 87, 69],
  11315. [4, 69, 43, 1, 70, 44],
  11316. [6, 43, 19, 2, 44, 20],
  11317. [6, 43, 15, 2, 44, 16],
  11318. // 11
  11319. [4, 101, 81],
  11320. [1, 80, 50, 4, 81, 51],
  11321. [4, 50, 22, 4, 51, 23],
  11322. [3, 36, 12, 8, 37, 13],
  11323. // 12
  11324. [2, 116, 92, 2, 117, 93],
  11325. [6, 58, 36, 2, 59, 37],
  11326. [4, 46, 20, 6, 47, 21],
  11327. [7, 42, 14, 4, 43, 15],
  11328. // 13
  11329. [4, 133, 107],
  11330. [8, 59, 37, 1, 60, 38],
  11331. [8, 44, 20, 4, 45, 21],
  11332. [12, 33, 11, 4, 34, 12],
  11333. // 14
  11334. [3, 145, 115, 1, 146, 116],
  11335. [4, 64, 40, 5, 65, 41],
  11336. [11, 36, 16, 5, 37, 17],
  11337. [11, 36, 12, 5, 37, 13],
  11338. // 15
  11339. [5, 109, 87, 1, 110, 88],
  11340. [5, 65, 41, 5, 66, 42],
  11341. [5, 54, 24, 7, 55, 25],
  11342. [11, 36, 12],
  11343. // 16
  11344. [5, 122, 98, 1, 123, 99],
  11345. [7, 73, 45, 3, 74, 46],
  11346. [15, 43, 19, 2, 44, 20],
  11347. [3, 45, 15, 13, 46, 16],
  11348. // 17
  11349. [1, 135, 107, 5, 136, 108],
  11350. [10, 74, 46, 1, 75, 47],
  11351. [1, 50, 22, 15, 51, 23],
  11352. [2, 42, 14, 17, 43, 15],
  11353. // 18
  11354. [5, 150, 120, 1, 151, 121],
  11355. [9, 69, 43, 4, 70, 44],
  11356. [17, 50, 22, 1, 51, 23],
  11357. [2, 42, 14, 19, 43, 15],
  11358. // 19
  11359. [3, 141, 113, 4, 142, 114],
  11360. [3, 70, 44, 11, 71, 45],
  11361. [17, 47, 21, 4, 48, 22],
  11362. [9, 39, 13, 16, 40, 14],
  11363. // 20
  11364. [3, 135, 107, 5, 136, 108],
  11365. [3, 67, 41, 13, 68, 42],
  11366. [15, 54, 24, 5, 55, 25],
  11367. [15, 43, 15, 10, 44, 16],
  11368. // 21
  11369. [4, 144, 116, 4, 145, 117],
  11370. [17, 68, 42],
  11371. [17, 50, 22, 6, 51, 23],
  11372. [19, 46, 16, 6, 47, 17],
  11373. // 22
  11374. [2, 139, 111, 7, 140, 112],
  11375. [17, 74, 46],
  11376. [7, 54, 24, 16, 55, 25],
  11377. [34, 37, 13],
  11378. // 23
  11379. [4, 151, 121, 5, 152, 122],
  11380. [4, 75, 47, 14, 76, 48],
  11381. [11, 54, 24, 14, 55, 25],
  11382. [16, 45, 15, 14, 46, 16],
  11383. // 24
  11384. [6, 147, 117, 4, 148, 118],
  11385. [6, 73, 45, 14, 74, 46],
  11386. [11, 54, 24, 16, 55, 25],
  11387. [30, 46, 16, 2, 47, 17],
  11388. // 25
  11389. [8, 132, 106, 4, 133, 107],
  11390. [8, 75, 47, 13, 76, 48],
  11391. [7, 54, 24, 22, 55, 25],
  11392. [22, 45, 15, 13, 46, 16],
  11393. // 26
  11394. [10, 142, 114, 2, 143, 115],
  11395. [19, 74, 46, 4, 75, 47],
  11396. [28, 50, 22, 6, 51, 23],
  11397. [33, 46, 16, 4, 47, 17],
  11398. // 27
  11399. [8, 152, 122, 4, 153, 123],
  11400. [22, 73, 45, 3, 74, 46],
  11401. [8, 53, 23, 26, 54, 24],
  11402. [12, 45, 15, 28, 46, 16],
  11403. // 28
  11404. [3, 147, 117, 10, 148, 118],
  11405. [3, 73, 45, 23, 74, 46],
  11406. [4, 54, 24, 31, 55, 25],
  11407. [11, 45, 15, 31, 46, 16],
  11408. // 29
  11409. [7, 146, 116, 7, 147, 117],
  11410. [21, 73, 45, 7, 74, 46],
  11411. [1, 53, 23, 37, 54, 24],
  11412. [19, 45, 15, 26, 46, 16],
  11413. // 30
  11414. [5, 145, 115, 10, 146, 116],
  11415. [19, 75, 47, 10, 76, 48],
  11416. [15, 54, 24, 25, 55, 25],
  11417. [23, 45, 15, 25, 46, 16],
  11418. // 31
  11419. [13, 145, 115, 3, 146, 116],
  11420. [2, 74, 46, 29, 75, 47],
  11421. [42, 54, 24, 1, 55, 25],
  11422. [23, 45, 15, 28, 46, 16],
  11423. // 32
  11424. [17, 145, 115],
  11425. [10, 74, 46, 23, 75, 47],
  11426. [10, 54, 24, 35, 55, 25],
  11427. [19, 45, 15, 35, 46, 16],
  11428. // 33
  11429. [17, 145, 115, 1, 146, 116],
  11430. [14, 74, 46, 21, 75, 47],
  11431. [29, 54, 24, 19, 55, 25],
  11432. [11, 45, 15, 46, 46, 16],
  11433. // 34
  11434. [13, 145, 115, 6, 146, 116],
  11435. [14, 74, 46, 23, 75, 47],
  11436. [44, 54, 24, 7, 55, 25],
  11437. [59, 46, 16, 1, 47, 17],
  11438. // 35
  11439. [12, 151, 121, 7, 152, 122],
  11440. [12, 75, 47, 26, 76, 48],
  11441. [39, 54, 24, 14, 55, 25],
  11442. [22, 45, 15, 41, 46, 16],
  11443. // 36
  11444. [6, 151, 121, 14, 152, 122],
  11445. [6, 75, 47, 34, 76, 48],
  11446. [46, 54, 24, 10, 55, 25],
  11447. [2, 45, 15, 64, 46, 16],
  11448. // 37
  11449. [17, 152, 122, 4, 153, 123],
  11450. [29, 74, 46, 14, 75, 47],
  11451. [49, 54, 24, 10, 55, 25],
  11452. [24, 45, 15, 46, 46, 16],
  11453. // 38
  11454. [4, 152, 122, 18, 153, 123],
  11455. [13, 74, 46, 32, 75, 47],
  11456. [48, 54, 24, 14, 55, 25],
  11457. [42, 45, 15, 32, 46, 16],
  11458. // 39
  11459. [20, 147, 117, 4, 148, 118],
  11460. [40, 75, 47, 7, 76, 48],
  11461. [43, 54, 24, 22, 55, 25],
  11462. [10, 45, 15, 67, 46, 16],
  11463. // 40
  11464. [19, 148, 118, 6, 149, 119],
  11465. [18, 75, 47, 31, 76, 48],
  11466. [34, 54, 24, 34, 55, 25],
  11467. [20, 45, 15, 61, 46, 16]
  11468. ];
  11469. /**
  11470. * 根据数据获取对应版本
  11471. * @return {[type]} [description]
  11472. */
  11473. QRCodeAlg.prototype.getRightType = function() {
  11474. for (var typeNumber = 1; typeNumber < 41; typeNumber++) {
  11475. var rsBlock = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + this.errorCorrectLevel];
  11476. if (rsBlock == undefined) {
  11477. throw new Error('bad rs block @ typeNumber:' + typeNumber + '/errorCorrectLevel:' + this.errorCorrectLevel);
  11478. }
  11479. var length = rsBlock.length / 3;
  11480. var totalDataCount = 0;
  11481. for (var i = 0; i < length; i++) {
  11482. var count = rsBlock[i * 3 + 0];
  11483. var dataCount = rsBlock[i * 3 + 2];
  11484. totalDataCount += dataCount * count;
  11485. }
  11486. var lengthBytes = typeNumber > 9 ? 2 : 1;
  11487. if (this.utf8bytes.length + lengthBytes < totalDataCount || typeNumber == 40) {
  11488. this.typeNumber = typeNumber;
  11489. this.rsBlock = rsBlock;
  11490. this.totalDataCount = totalDataCount;
  11491. break;
  11492. }
  11493. }
  11494. };
  11495. // ---------------------------------------------------------------------
  11496. // QRBitBuffer
  11497. // ---------------------------------------------------------------------
  11498. function QRBitBuffer() {
  11499. this.buffer = new Array();
  11500. this.length = 0;
  11501. }
  11502. QRBitBuffer.prototype = {
  11503. get: function(index) {
  11504. var bufIndex = Math.floor(index / 8);
  11505. return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1);
  11506. },
  11507. put: function(num, length) {
  11508. for (var i = 0; i < length; i++) {
  11509. this.putBit(((num >>> (length - i - 1)) & 1));
  11510. }
  11511. },
  11512. putBit: function(bit) {
  11513. var bufIndex = Math.floor(this.length / 8);
  11514. if (this.buffer.length <= bufIndex) {
  11515. this.buffer.push(0);
  11516. }
  11517. if (bit) {
  11518. this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));
  11519. }
  11520. this.length++;
  11521. }
  11522. };
  11523. $.fn.qrcode = function QRCodePlugin(option) {
  11524. return this.each(function() {
  11525. $(this).append(new QRCode(option));
  11526. });
  11527. };
  11528. module.exports = UI.qrcode = QRCode;
  11529. /***/ },
  11530. /* 27 */
  11531. /***/ function(module, exports, __webpack_require__) {
  11532. 'use strict';
  11533. var $ = __webpack_require__(1);
  11534. var UI = __webpack_require__(2);
  11535. /**
  11536. * @via https://github.com/uikit/uikit/blob/master/src/js/addons/sticky.js
  11537. * @license https://github.com/uikit/uikit/blob/master/LICENSE.md
  11538. */
  11539. // Sticky Class
  11540. var Sticky = function(element, options) {
  11541. var _this = this;
  11542. this.options = $.extend({}, Sticky.DEFAULTS, options);
  11543. this.$element = $(element);
  11544. this.sticked = null;
  11545. this.inited = null;
  11546. this.$holder = undefined;
  11547. this.$window = $(window).
  11548. on('scroll.sticky.amui',
  11549. UI.utils.debounce($.proxy(this.checkPosition, this), 10)).
  11550. on('resize.sticky.amui orientationchange.sticky.amui',
  11551. UI.utils.debounce(function() {
  11552. _this.reset(true, function() {
  11553. _this.checkPosition();
  11554. });
  11555. }, 50)).
  11556. on('load.sticky.amui', $.proxy(this.checkPosition, this));
  11557. // the `.offset()` is diff between jQuery & Zepto.js
  11558. // jQuery: return `top` and `left`
  11559. // Zepto.js: return `top`, `left`, `width`, `height`
  11560. this.offset = this.$element.offset();
  11561. this.init();
  11562. };
  11563. Sticky.DEFAULTS = {
  11564. top: 0,
  11565. bottom: 0,
  11566. animation: '',
  11567. className: {
  11568. sticky: 'am-sticky',
  11569. resetting: 'am-sticky-resetting',
  11570. stickyBtm: 'am-sticky-bottom',
  11571. animationRev: 'am-animation-reverse'
  11572. }
  11573. };
  11574. Sticky.prototype.init = function() {
  11575. var result = this.check();
  11576. if (!result) {
  11577. return false;
  11578. }
  11579. var $element = this.$element;
  11580. var $elementMargin = '';
  11581. $.each($element.css(
  11582. ['marginTop', 'marginRight', 'marginBottom', 'marginLeft']),
  11583. function(name, value) {
  11584. return $elementMargin += ' ' + value;
  11585. });
  11586. var $holder = $('<div class="am-sticky-placeholder"></div>').css({
  11587. height: $element.css('position') !== 'absolute' ?
  11588. $element.outerHeight() : '',
  11589. float: $element.css('float') != 'none' ? $element.css('float') : '',
  11590. margin: $elementMargin
  11591. });
  11592. this.$holder = $element.css('margin', 0).wrap($holder).parent();
  11593. this.inited = 1;
  11594. return true;
  11595. };
  11596. Sticky.prototype.reset = function(force, cb) {
  11597. var options = this.options;
  11598. var $element = this.$element;
  11599. var animation = (options.animation) ?
  11600. ' am-animation-' + options.animation : '';
  11601. var complete = function() {
  11602. $element.css({position: '', top: '', width: '', left: '', margin: 0});
  11603. $element.removeClass([
  11604. animation,
  11605. options.className.animationRev,
  11606. options.className.sticky,
  11607. options.className.resetting
  11608. ].join(' '));
  11609. this.animating = false;
  11610. this.sticked = false;
  11611. this.offset = $element.offset();
  11612. cb && cb();
  11613. }.bind(this);
  11614. $element.addClass(options.className.resetting);
  11615. if (!force && options.animation && UI.support.animation) {
  11616. this.animating = true;
  11617. $element.removeClass(animation).one(UI.support.animation.end, function() {
  11618. complete();
  11619. }).width(); // force redraw
  11620. $element.addClass(animation + ' ' + options.className.animationRev);
  11621. } else {
  11622. complete();
  11623. }
  11624. };
  11625. Sticky.prototype.check = function() {
  11626. if (!this.$element.is(':visible')) {
  11627. return false;
  11628. }
  11629. var media = this.options.media;
  11630. if (media) {
  11631. switch (typeof(media)) {
  11632. case 'number':
  11633. if (window.innerWidth < media) {
  11634. return false;
  11635. }
  11636. break;
  11637. case 'string':
  11638. if (window.matchMedia && !window.matchMedia(media).matches) {
  11639. return false;
  11640. }
  11641. break;
  11642. }
  11643. }
  11644. return true;
  11645. };
  11646. Sticky.prototype.checkPosition = function() {
  11647. if (!this.inited) {
  11648. var initialized = this.init();
  11649. if (!initialized) {
  11650. return;
  11651. }
  11652. }
  11653. var options = this.options;
  11654. var scrollTop = this.$window.scrollTop();
  11655. var offsetTop = options.top;
  11656. var offsetBottom = options.bottom;
  11657. var $element = this.$element;
  11658. var animation = (options.animation) ?
  11659. ' am-animation-' + options.animation : '';
  11660. var className = [options.className.sticky, animation].join(' ');
  11661. if (typeof offsetBottom == 'function') {
  11662. offsetBottom = offsetBottom(this.$element);
  11663. }
  11664. var checkResult = (scrollTop > this.$holder.offset().top);
  11665. if (!this.sticked && checkResult) {
  11666. $element.addClass(className);
  11667. } else if (this.sticked && !checkResult) {
  11668. this.reset();
  11669. }
  11670. this.$holder.css({
  11671. height: $element.is(':visible') && $element.css('position') !== 'absolute' ?
  11672. $element.outerHeight() : ''
  11673. });
  11674. if (checkResult) {
  11675. $element.css({
  11676. top: offsetTop,
  11677. left: this.$holder.offset().left,
  11678. width: this.$holder.width()
  11679. });
  11680. /*
  11681. if (offsetBottom) {
  11682. // (底部边距 + 元素高度 > 窗口高度) 时定位到底部
  11683. if ((offsetBottom + this.offset.height > $(window).height()) &&
  11684. (scrollTop + $(window).height() >= scrollHeight - offsetBottom)) {
  11685. $element.addClass(options.className.stickyBtm).
  11686. css({top: $(window).height() - offsetBottom - this.offset.height});
  11687. } else {
  11688. $element.removeClass(options.className.stickyBtm).css({top: offsetTop});
  11689. }
  11690. }
  11691. */
  11692. }
  11693. this.sticked = checkResult;
  11694. };
  11695. // Sticky Plugin
  11696. UI.plugin('sticky', Sticky);
  11697. // Init code
  11698. $(window).on('load', function() {
  11699. $('[data-am-sticky]').sticky();
  11700. });
  11701. module.exports = Sticky;
  11702. /***/ },
  11703. /* 28 */
  11704. /***/ function(module, exports, __webpack_require__) {
  11705. 'use strict';
  11706. var $ = __webpack_require__(1);
  11707. var UI = __webpack_require__(2);
  11708. var Hammer = __webpack_require__(3);
  11709. var supportTransition = UI.support.transition;
  11710. var animation = UI.support.animation;
  11711. /**
  11712. * @via https://github.com/twbs/bootstrap/blob/master/js/tab.js
  11713. * @copyright 2011-2014 Twitter, Inc.
  11714. * @license MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  11715. */
  11716. /**
  11717. * Tabs
  11718. * @param {HTMLElement} element
  11719. * @param {Object} options
  11720. * @constructor
  11721. */
  11722. var Tabs = function(element, options) {
  11723. this.$element = $(element);
  11724. this.options = $.extend({}, Tabs.DEFAULTS, options || {});
  11725. this.transitioning = this.activeIndex = null;
  11726. this.refresh();
  11727. this.init();
  11728. };
  11729. Tabs.DEFAULTS = {
  11730. selector: {
  11731. nav: '> .am-tabs-nav',
  11732. content: '> .am-tabs-bd',
  11733. panel: '> .am-tab-panel'
  11734. },
  11735. activeClass: 'am-active'
  11736. };
  11737. Tabs.prototype.refresh = function() {
  11738. var selector = this.options.selector;
  11739. this.$tabNav = this.$element.find(selector.nav);
  11740. this.$navs = this.$tabNav.find('a');
  11741. this.$content = this.$element.find(selector.content);
  11742. this.$tabPanels = this.$content.find(selector.panel);
  11743. var $active = this.$tabNav.find('> .' + this.options.activeClass);
  11744. // Activate the first Tab when no active Tab or multiple active Tabs
  11745. if ($active.length !== 1) {
  11746. this.open(0);
  11747. } else {
  11748. this.activeIndex = this.$navs.index($active.children('a'));
  11749. }
  11750. };
  11751. Tabs.prototype.init = function() {
  11752. var _this = this;
  11753. var options = this.options;
  11754. this.$element.on('click.tabs.amui', options.selector.nav + ' a', function(e) {
  11755. e.preventDefault();
  11756. _this.open($(this));
  11757. });
  11758. // TODO: nested Tabs touch events
  11759. if (!options.noSwipe) {
  11760. if (!this.$content.length) {
  11761. return this;
  11762. }
  11763. var hammer = new Hammer.Manager(this.$content[0]);
  11764. var swipe = new Hammer.Swipe({
  11765. direction: Hammer.DIRECTION_HORIZONTAL
  11766. // threshold: 40
  11767. });
  11768. hammer.add(swipe);
  11769. hammer.on('swipeleft', UI.utils.debounce(function(e) {
  11770. e.preventDefault();
  11771. _this.goTo('next');
  11772. }, 100));
  11773. hammer.on('swiperight', UI.utils.debounce(function(e) {
  11774. e.preventDefault();
  11775. _this.goTo('prev');
  11776. }, 100));
  11777. this._hammer = hammer;
  11778. }
  11779. };
  11780. /**
  11781. * Open $nav tab
  11782. * @param {jQuery|HTMLElement|Number} $nav
  11783. * @returns {Tabs}
  11784. */
  11785. Tabs.prototype.open = function($nav) {
  11786. var activeClass = this.options.activeClass;
  11787. var activeIndex = typeof $nav === 'number' ? $nav : this.$navs.index($($nav));
  11788. $nav = typeof $nav === 'number' ? this.$navs.eq(activeIndex) : $($nav);
  11789. if (!$nav ||
  11790. !$nav.length ||
  11791. this.transitioning ||
  11792. $nav.parent('li').hasClass(activeClass)) {
  11793. return;
  11794. }
  11795. var $tabNav = this.$tabNav;
  11796. var href = $nav.attr('href');
  11797. var regexHash = /^#.+$/;
  11798. var $target = regexHash.test(href) && this.$content.find(href) ||
  11799. this.$tabPanels.eq(activeIndex);
  11800. var previous = $tabNav.find('.' + activeClass + ' a')[0];
  11801. var e = $.Event('open.tabs.amui', {
  11802. relatedTarget: previous
  11803. });
  11804. $nav.trigger(e);
  11805. if (e.isDefaultPrevented()) {
  11806. return;
  11807. }
  11808. // activate Tab nav
  11809. this.activate($nav.closest('li'), $tabNav);
  11810. // activate Tab content
  11811. this.activate($target, this.$content, function() {
  11812. $nav.trigger({
  11813. type: 'opened.tabs.amui',
  11814. relatedTarget: previous
  11815. });
  11816. });
  11817. this.activeIndex = activeIndex;
  11818. };
  11819. Tabs.prototype.activate = function($element, $container, callback) {
  11820. this.transitioning = true;
  11821. var activeClass = this.options.activeClass;
  11822. var $active = $container.find('> .' + activeClass);
  11823. var transition = callback && supportTransition && !!$active.length;
  11824. $active.removeClass(activeClass + ' am-in');
  11825. $element.addClass(activeClass);
  11826. if (transition) {
  11827. $element.redraw(); // reflow for transition
  11828. $element.addClass('am-in');
  11829. } else {
  11830. $element.removeClass('am-fade');
  11831. }
  11832. var complete = $.proxy(function complete() {
  11833. callback && callback();
  11834. this.transitioning = false;
  11835. }, this);
  11836. transition ? $active.one(supportTransition.end, complete) : complete();
  11837. };
  11838. /**
  11839. * Go to `next` or `prev` tab
  11840. * @param {String} direction - `next` or `prev`
  11841. */
  11842. Tabs.prototype.goTo = function(direction) {
  11843. var navIndex = this.activeIndex;
  11844. var isNext = direction === 'next';
  11845. var spring = isNext ? 'am-animation-right-spring' :
  11846. 'am-animation-left-spring';
  11847. if ((isNext && navIndex + 1 >= this.$navs.length) || // last one
  11848. (!isNext && navIndex === 0)) { // first one
  11849. var $panel = this.$tabPanels.eq(navIndex);
  11850. animation && $panel.addClass(spring).on(animation.end, function() {
  11851. $panel.removeClass(spring);
  11852. });
  11853. } else {
  11854. this.open(isNext ? navIndex + 1 : navIndex - 1);
  11855. }
  11856. };
  11857. Tabs.prototype.destroy = function() {
  11858. this.$element.off('.tabs.amui');
  11859. Hammer.off(this.$content[0], 'swipeleft swiperight');
  11860. this._hammer && this._hammer.destroy();
  11861. $.removeData(this.$element, 'amui.tabs');
  11862. };
  11863. // Plugin
  11864. function Plugin(option) {
  11865. var args = Array.prototype.slice.call(arguments, 1);
  11866. var methodReturn;
  11867. this.each(function() {
  11868. var $this = $(this);
  11869. var $tabs = $this.is('.am-tabs') && $this || $this.closest('.am-tabs');
  11870. var data = $tabs.data('amui.tabs');
  11871. var options = $.extend({}, UI.utils.parseOptions($this.data('amTabs')),
  11872. $.isPlainObject(option) && option);
  11873. if (!data) {
  11874. $tabs.data('amui.tabs', (data = new Tabs($tabs[0], options)));
  11875. }
  11876. if (typeof option === 'string') {
  11877. if (option === 'open' && $this.is('.am-tabs-nav a')) {
  11878. data.open($this);
  11879. } else {
  11880. methodReturn = typeof data[option] === 'function' ?
  11881. data[option].apply(data, args) : data[option];
  11882. }
  11883. }
  11884. });
  11885. return methodReturn === undefined ? this : methodReturn;
  11886. }
  11887. $.fn.tabs = Plugin;
  11888. // Init code
  11889. UI.ready(function(context) {
  11890. $('[data-am-tabs]', context).tabs();
  11891. });
  11892. $(document).on('click.tabs.amui.data-api', '[data-am-tabs] .am-tabs-nav a',
  11893. function(e) {
  11894. e.preventDefault();
  11895. Plugin.call($(this), 'open');
  11896. });
  11897. module.exports = UI.tabs = Tabs;
  11898. // TODO: 1. Ajax 支持
  11899. // 2. touch 事件处理逻辑优化
  11900. /***/ },
  11901. /* 29 */
  11902. /***/ function(module, exports, __webpack_require__) {
  11903. 'use strict';
  11904. var $ = __webpack_require__(1);
  11905. var UI = __webpack_require__(2);
  11906. /**
  11907. * UCheck
  11908. * @via https://github.com/designmodo/Flat-UI/blob/8ef98df23ba7f5033e596a9bd05b53b535a9fe99/js/radiocheck.js
  11909. * @license CC BY 3.0 & MIT
  11910. * @param {HTMLElement} element
  11911. * @param {object} options
  11912. * @constructor
  11913. */
  11914. var UCheck = function(element, options) {
  11915. this.options = $.extend({}, UCheck.DEFAULTS, options);
  11916. // this.options = $.extend({}, UCheck.DEFAULTS, this.$element.data(), options);
  11917. this.$element = $(element);
  11918. this.init();
  11919. };
  11920. UCheck.DEFAULTS = {
  11921. checkboxClass: 'am-ucheck-checkbox',
  11922. radioClass: 'am-ucheck-radio',
  11923. checkboxTpl: '<span class="am-ucheck-icons">' +
  11924. '<i class="am-icon-unchecked"></i><i class="am-icon-checked"></i></span>',
  11925. radioTpl: '<span class="am-ucheck-icons">' +
  11926. '<i class="am-icon-unchecked"></i><i class="am-icon-checked"></i></span>'
  11927. };
  11928. UCheck.prototype.init = function() {
  11929. var $element = this.$element;
  11930. var element = $element[0];
  11931. var options = this.options;
  11932. if (element.type === 'checkbox') {
  11933. $element.addClass(options.checkboxClass)
  11934. .after(options.checkboxTpl);
  11935. } else if (element.type === 'radio') {
  11936. $element.addClass(options.radioClass)
  11937. .after(options.radioTpl);
  11938. }
  11939. };
  11940. UCheck.prototype.check = function() {
  11941. this.$element
  11942. .prop('checked', true)
  11943. .trigger('change.ucheck.amui')
  11944. .trigger('checked.ucheck.amui');
  11945. },
  11946. UCheck.prototype.uncheck = function() {
  11947. this.$element
  11948. .prop('checked', false)
  11949. .trigger('change.ucheck.amui')
  11950. .trigger('unchecked.ucheck.amui');
  11951. },
  11952. UCheck.prototype.toggle = function() {
  11953. this.$element.
  11954. prop('checked', function(i, value) {
  11955. return !value;
  11956. })
  11957. .trigger('change.ucheck.amui')
  11958. .trigger('toggled.ucheck.amui');
  11959. },
  11960. UCheck.prototype.disable = function() {
  11961. this.$element
  11962. .prop('disabled', true)
  11963. .trigger('change.ucheck.amui')
  11964. .trigger('disabled.ucheck.amui');
  11965. },
  11966. UCheck.prototype.enable = function() {
  11967. this.$element.prop('disabled', false);
  11968. this.$element.trigger('change.ucheck.amui').trigger('enabled.ucheck.amui');
  11969. },
  11970. UCheck.prototype.destroy = function() {
  11971. this.$element
  11972. .removeData('amui.ucheck')
  11973. .removeClass(this.options.checkboxClass + ' ' + this.options.radioClass)
  11974. .next('.am-ucheck-icons')
  11975. .remove()
  11976. .end()
  11977. .trigger('destroyed.ucheck.amui');
  11978. };
  11979. UI.plugin('uCheck', UCheck, {
  11980. after: function() {
  11981. // Adding 'am-nohover' class for touch devices
  11982. if (UI.support.touch) {
  11983. this.parent().hover(function() {
  11984. $(this).addClass('am-nohover');
  11985. }, function() {
  11986. $(this).removeClass('am-nohover');
  11987. });
  11988. }
  11989. }
  11990. });
  11991. UI.ready(function(context) {
  11992. $('[data-am-ucheck]', context).uCheck();
  11993. });
  11994. module.exports = UCheck;
  11995. // TODO: 与表单验证结合使用的情况
  11996. /***/ },
  11997. /* 30 */
  11998. /***/ function(module, exports, __webpack_require__) {
  11999. 'use strict';
  12000. var $ = __webpack_require__(1);
  12001. var UI = __webpack_require__(2);
  12002. var Validator = function(element, options) {
  12003. this.options = $.extend({}, Validator.DEFAULTS, options);
  12004. this.options.patterns = $.extend({}, Validator.patterns,
  12005. this.options.patterns);
  12006. var locales = this.options.locales;
  12007. !Validator.validationMessages[locales] && (this.options.locales = 'zh_CN');
  12008. this.$element = $(element);
  12009. this.init();
  12010. };
  12011. Validator.DEFAULTS = {
  12012. debug: false,
  12013. locales: 'zh_CN',
  12014. H5validation: false,
  12015. H5inputType: ['email', 'url', 'number'],
  12016. patterns: {},
  12017. patternClassPrefix: 'js-pattern-',
  12018. activeClass: 'am-active',
  12019. inValidClass: 'am-field-error',
  12020. validClass: 'am-field-valid',
  12021. validateOnSubmit: true,
  12022. alwaysRevalidate: false,
  12023. // Elements to validate with allValid (only validating visible elements)
  12024. // :input: selects all input, textarea, select and button elements.
  12025. // @since 2.5: move `:visible` to `ignore` option (became to `:hidden`)
  12026. allFields: ':input:not(:submit, :button, :disabled, .am-novalidate)',
  12027. // ignored elements
  12028. // @since 2.5
  12029. ignore: ':hidden:not([data-am-selected], .am-validate)',
  12030. // Custom events
  12031. customEvents: 'validate',
  12032. // Keyboard events
  12033. keyboardFields: ':input:not(:submit, :button, :disabled, .am-novalidate)',
  12034. keyboardEvents: 'focusout, change', // keyup, focusin
  12035. // bind `keyup` event to active field
  12036. activeKeyup: false,
  12037. textareaMaxlenthKeyup: true,
  12038. // Mouse events
  12039. pointerFields: 'input[type="range"]:not(:disabled, .am-novalidate), ' +
  12040. 'input[type="radio"]:not(:disabled, .am-novalidate), ' +
  12041. 'input[type="checkbox"]:not(:disabled, .am-novalidate), ' +
  12042. 'select:not(:disabled, .am-novalidate), ' +
  12043. 'option:not(:disabled, .am-novalidate)',
  12044. pointerEvents: 'click',
  12045. onValid: function(validity) {
  12046. },
  12047. onInValid: function(validity) {
  12048. },
  12049. markValid: function(validity) {
  12050. // this is Validator instance
  12051. var options = this.options;
  12052. var $field = $(validity.field);
  12053. var $parent = $field.closest('.am-form-group');
  12054. $field.addClass(options.validClass).removeClass(options.inValidClass);
  12055. $parent.addClass('am-form-success').removeClass('am-form-error');
  12056. options.onValid.call(this, validity);
  12057. },
  12058. markInValid: function(validity) {
  12059. var options = this.options;
  12060. var $field = $(validity.field);
  12061. var $parent = $field.closest('.am-form-group');
  12062. $field.addClass(options.inValidClass + ' ' + options.activeClass).
  12063. removeClass(options.validClass);
  12064. $parent.addClass('am-form-error').removeClass('am-form-success');
  12065. options.onInValid.call(this, validity);
  12066. },
  12067. validate: function(validity) {
  12068. // return validity;
  12069. },
  12070. submit: null
  12071. };
  12072. Validator.VERSION = '2.5.2';
  12073. /* jshint -W101 */
  12074. Validator.patterns = {
  12075. 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])))\.?$/,
  12076. 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})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/,
  12077. // Number, including positive, negative, and floating decimal
  12078. number: /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/,
  12079. dateISO: /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/,
  12080. integer: /^-?\d+$/
  12081. };
  12082. /* jshint +W101 */
  12083. Validator.validationMessages = {
  12084. zh_CN: {
  12085. valueMissing: '请填写(选择)此字段',
  12086. customError: {
  12087. tooShort: '至少填写 %s 个字符',
  12088. checkedOverflow: '至多选择 %s 项',
  12089. checkedUnderflow: '至少选择 %s 项'
  12090. },
  12091. patternMismatch: '请按照要求的格式填写',
  12092. rangeOverflow: '请填写小于等于 %s 的值',
  12093. rangeUnderflow: '请填写大于等于 %s 的值',
  12094. stepMismatch: '',
  12095. tooLong: '至多填写 %s 个字符',
  12096. typeMismatch: '请按照要求的类型填写'
  12097. }
  12098. };
  12099. Validator.ERROR_MAP = {
  12100. tooShort: 'minlength',
  12101. checkedOverflow: 'maxchecked',
  12102. checkedUnderflow: 'minchecked',
  12103. rangeOverflow: 'max',
  12104. rangeUnderflow: 'min',
  12105. tooLong: 'maxlength'
  12106. };
  12107. // TODO: 考虑表单元素不是 form 子元素的情形
  12108. // TODO: change/click/focusout 同时触发时处理重复
  12109. // TODO: 显示提示信息
  12110. Validator.prototype.init = function() {
  12111. var _this = this;
  12112. var $element = this.$element;
  12113. var options = this.options;
  12114. // using H5 form validation if option set and supported
  12115. if (options.H5validation && UI.support.formValidation) {
  12116. return false;
  12117. }
  12118. // disable HTML5 form validation
  12119. $element.attr('novalidate', 'novalidate');
  12120. function regexToPattern(regex) {
  12121. var pattern = regex.toString();
  12122. return pattern.substring(1, pattern.length - 1);
  12123. }
  12124. // add pattern to H5 input type
  12125. $.each(options.H5inputType, function(i, type) {
  12126. var $field = $element.find('input[type=' + type + ']');
  12127. if (!$field.attr('pattern') &&
  12128. !$field.is('[class*=' + options.patternClassPrefix + ']')) {
  12129. $field.attr('pattern', regexToPattern(options.patterns[type]));
  12130. }
  12131. });
  12132. // add pattern to .js-pattern-xx
  12133. $.each(options.patterns, function(key, value) {
  12134. var $field = $element.find('.' + options.patternClassPrefix + key);
  12135. !$field.attr('pattern') && $field.attr('pattern', regexToPattern(value));
  12136. });
  12137. $element.on('submit.validator.amui', function(e) {
  12138. // user custom submit handler
  12139. if (typeof options.submit === 'function') {
  12140. return options.submit.call(_this, e);
  12141. }
  12142. if (options.validateOnSubmit) {
  12143. var formValidity = _this.isFormValid();
  12144. // sync validate, return result
  12145. if ($.type(formValidity) === 'boolean') {
  12146. return formValidity;
  12147. }
  12148. if ($element.data('amui.checked')) {
  12149. return true;
  12150. } else {
  12151. $.when(formValidity).then(function() {
  12152. // done, submit form
  12153. $element.data('amui.checked', true).submit();
  12154. }, function() {
  12155. // fail
  12156. $element.data('amui.checked', false).
  12157. find('.' + options.inValidClass).eq(0).focus();
  12158. });
  12159. return false;
  12160. }
  12161. }
  12162. });
  12163. function bindEvents(fields, eventFlags, debounce) {
  12164. var events = eventFlags.split(',');
  12165. var validate = function(e) {
  12166. // console.log(e.type);
  12167. _this.validate(this);
  12168. };
  12169. if (debounce) {
  12170. validate = UI.utils.debounce(validate, debounce);
  12171. }
  12172. $.each(events, function(i, event) {
  12173. $element.on(event + '.validator.amui', fields, validate);
  12174. });
  12175. }
  12176. bindEvents(':input', options.customEvents);
  12177. bindEvents(options.keyboardFields, options.keyboardEvents);
  12178. bindEvents(options.pointerFields, options.pointerEvents);
  12179. if (options.textareaMaxlenthKeyup) {
  12180. bindEvents('textarea[maxlength]', 'keyup', 50);
  12181. }
  12182. if (options.activeKeyup) {
  12183. bindEvents('.am-active', 'keyup', 50);
  12184. }
  12185. /*if (options.errorMessage === 'tooltip') {
  12186. this.$tooltip = $('<div></div>', {
  12187. 'class': 'am-validator-message',
  12188. id: UI.utils.generateGUID('am-validator-message')
  12189. });
  12190. $(document.body).append(this.$tooltip);
  12191. }*/
  12192. };
  12193. Validator.prototype.isValid = function(field) {
  12194. var $field = $(field);
  12195. var options = this.options;
  12196. // valid field not has been validated
  12197. if ($field.data('validity') === undefined || options.alwaysRevalidate) {
  12198. this.validate(field);
  12199. }
  12200. return $field.data('validity') && $field.data('validity').valid;
  12201. };
  12202. Validator.prototype.validate = function(field) {
  12203. var _this = this;
  12204. var $element = this.$element;
  12205. var options = this.options;
  12206. var $field = $(field);
  12207. // Validate equal, e.g. confirm password
  12208. var equalTo = $field.data('equalTo');
  12209. if (equalTo) {
  12210. $field.attr('pattern', '^' + $element.find(equalTo).val() + '$');
  12211. }
  12212. var pattern = $field.attr('pattern') || false;
  12213. var re = new RegExp(pattern);
  12214. var $radioGroup = null;
  12215. var $checkboxGroup = null;
  12216. // if checkbox, return `:chcked` length
  12217. // NOTE: checkbox and radio should have name attribute
  12218. var value = ($field.is('[type=checkbox]')) ?
  12219. ($checkboxGroup = $element.find('input[name="' + field.name + '"]')).
  12220. filter(':checked').length : ($field.is('[type=radio]') ?
  12221. ($radioGroup = this.$element.find('input[name="' + field.name + '"]')).
  12222. filter(':checked').length > 0 : $field.val());
  12223. // if checkbox, valid the first input of checkbox group
  12224. $field = ($checkboxGroup && $checkboxGroup.length) ?
  12225. $checkboxGroup.first() : $field;
  12226. var required = ($field.attr('required') !== undefined) &&
  12227. ($field.attr('required') !== 'false');
  12228. var maxLength = parseInt($field.attr('maxlength'), 10);
  12229. var minLength = parseInt($field.attr('minlength'), 10);
  12230. var min = Number($field.attr('min'));
  12231. var max = Number($field.attr('max'));
  12232. var validity = this.createValidity({field: $field[0], valid: true});
  12233. // Debug
  12234. if (options.debug && window.console) {
  12235. console.log('Validate: value -> [' + value + ', regex -> [' + re +
  12236. '], required -> ' + required);
  12237. console.log('Regex test: ' + re.test(value) + ', Pattern: ' + pattern);
  12238. }
  12239. // check value length
  12240. if (!isNaN(maxLength) && value.length > maxLength) {
  12241. validity.valid = false;
  12242. validity.tooLong = true;
  12243. }
  12244. if (!isNaN(minLength) && value.length < minLength) {
  12245. validity.valid = false;
  12246. validity.customError = 'tooShort';
  12247. }
  12248. // check minimum and maximum
  12249. // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input
  12250. // TODO: 日期验证最小值和最大值 min/max
  12251. if (!isNaN(min) && Number(value) < min) {
  12252. validity.valid = false;
  12253. validity.rangeUnderflow = true;
  12254. }
  12255. if (!isNaN(max) && Number(value) > max) {
  12256. validity.valid = false;
  12257. validity.rangeOverflow = true;
  12258. }
  12259. // check required
  12260. if (required && !value) {
  12261. validity.valid = false;
  12262. validity.valueMissing = true;
  12263. } else if (($checkboxGroup || $field.is('select[multiple="multiple"]')) &&
  12264. value) {
  12265. // check checkboxes / multiple select with `minchecked`/`maxchecked` attr
  12266. // var $multipleField = $checkboxGroup ? $checkboxGroup.first() : $field;
  12267. // if is select[multiple="multiple"], return selected length
  12268. value = $checkboxGroup ? value : value.length;
  12269. // at least checked
  12270. var minChecked = parseInt($field.attr('minchecked'), 10);
  12271. // at most checked
  12272. var maxChecked = parseInt($field.attr('maxchecked'), 10);
  12273. if (!isNaN(minChecked) && value < minChecked) {
  12274. // console.log('At least [%d] items checked!', maxChecked);
  12275. validity.valid = false;
  12276. validity.customError = 'checkedUnderflow';
  12277. }
  12278. if (!isNaN(maxChecked) && value > maxChecked) {
  12279. // console.log('At most [%d] items checked!', maxChecked);
  12280. validity.valid = false;
  12281. validity.customError = 'checkedOverflow';
  12282. }
  12283. } else if (pattern && !re.test(value) && value) { // check pattern
  12284. validity.valid = false;
  12285. validity.patternMismatch = true;
  12286. }
  12287. var validateComplete = function(validity) {
  12288. this.markField(validity);
  12289. var event = $.Event('validated.field.validator.amui');
  12290. event.validity = validity;
  12291. $field.trigger(event).data('validity', validity);
  12292. // validate the radios/checkboxes with the same name
  12293. var $fields = $radioGroup || $checkboxGroup;
  12294. if ($fields) {
  12295. $fields.not($field).data('validity', validity).each(function() {
  12296. validity.field = this;
  12297. _this.markField(validity);
  12298. });
  12299. }
  12300. return validity;
  12301. };
  12302. // Run custom validate
  12303. // NOTE: async custom validate should return Deferred project
  12304. var customValidate;
  12305. (typeof options.validate === 'function') &&
  12306. (customValidate = options.validate.call(this, validity));
  12307. // Deferred
  12308. if (customValidate) {
  12309. var dfd = new $.Deferred();
  12310. $field.data('amui.dfdValidity', dfd.promise());
  12311. return $.when(customValidate).always(function(validity) {
  12312. dfd[validity.valid ? 'resolve' : 'reject'](validity);
  12313. validateComplete.call(_this, validity);
  12314. });
  12315. }
  12316. validateComplete.call(this, validity);
  12317. };
  12318. Validator.prototype.markField = function(validity) {
  12319. var options = this.options;
  12320. var flag = 'mark' + (validity.valid ? '' : 'In') + 'Valid';
  12321. options[flag] && options[flag].call(this, validity);
  12322. };
  12323. // check all fields in the form are valid
  12324. Validator.prototype.validateForm = function() {
  12325. var _this = this;
  12326. var $element = this.$element;
  12327. var options = this.options;
  12328. var $allFields = $element.find(options.allFields).not(options.ignore);
  12329. var radioNames = [];
  12330. var valid = true;
  12331. var formValidity = [];
  12332. var $inValidFields = $([]);
  12333. var promises = [];
  12334. // for async validate
  12335. var async = false;
  12336. $element.trigger('validate.form.validator.amui');
  12337. // Filter radio with the same name and keep only one,
  12338. // since they will be checked as a group by validate()
  12339. var $filteredFields = $allFields.filter(function(index) {
  12340. var name;
  12341. if (this.tagName === 'INPUT' && this.type === 'radio') {
  12342. name = this.name;
  12343. if (radioNames[name] === true) {
  12344. return false;
  12345. }
  12346. radioNames[name] = true;
  12347. }
  12348. return true;
  12349. });
  12350. $filteredFields.each(function() {
  12351. var $this = $(this);
  12352. var fieldValid = _this.isValid(this);
  12353. var fieldValidity = $this.data('validity');
  12354. valid = !!fieldValid && valid;
  12355. formValidity.push(fieldValidity);
  12356. if (!fieldValid) {
  12357. $inValidFields = $inValidFields.add($(this), $element);
  12358. }
  12359. // async validity
  12360. var promise = $this.data('amui.dfdValidity');
  12361. if (promise) {
  12362. promises.push(promise);
  12363. async = true;
  12364. } else {
  12365. // convert sync validity to Promise
  12366. var dfd = new $.Deferred();
  12367. promises.push(dfd.promise());
  12368. dfd[fieldValid ? 'resolve' : 'reject'](fieldValidity);
  12369. }
  12370. });
  12371. // NOTE: If there are async validity, the valid may be not exact result.
  12372. var validity = {
  12373. valid: valid,
  12374. $invalidFields: $inValidFields,
  12375. validity: formValidity,
  12376. promises: promises,
  12377. async: async
  12378. };
  12379. $element.trigger('validated.form.validator.amui', validity);
  12380. return validity;
  12381. };
  12382. Validator.prototype.isFormValid = function() {
  12383. var _this = this;
  12384. var formValidity = this.validateForm();
  12385. var triggerValid = function(type) {
  12386. _this.$element.trigger(type + '.validator.amui');
  12387. };
  12388. if (formValidity.async) {
  12389. var masterDfd = new $.Deferred();
  12390. $.when.apply(null, formValidity.promises).then(function() {
  12391. masterDfd.resolve();
  12392. triggerValid('valid');
  12393. }, function() {
  12394. masterDfd.reject();
  12395. triggerValid('invalid');
  12396. });
  12397. return masterDfd.promise();
  12398. } else {
  12399. if (!formValidity.valid) {
  12400. var $first = formValidity.$invalidFields.first();
  12401. // Selected plugin support
  12402. // @since 2.5
  12403. if ($first.is('[data-am-selected]')) {
  12404. $first = $first.next('.am-selected').find('.am-selected-btn');
  12405. }
  12406. $first.focus();
  12407. triggerValid('invalid');
  12408. return false;
  12409. }
  12410. triggerValid('valid');
  12411. return true;
  12412. }
  12413. };
  12414. // customErrors:
  12415. // 1. tooShort
  12416. // 2. checkedOverflow
  12417. // 3. checkedUnderflow
  12418. Validator.prototype.createValidity = function(validity) {
  12419. return $.extend({
  12420. customError: validity.customError || false,
  12421. patternMismatch: validity.patternMismatch || false,
  12422. rangeOverflow: validity.rangeOverflow || false, // higher than maximum
  12423. rangeUnderflow: validity.rangeUnderflow || false, // lower than minimum
  12424. stepMismatch: validity.stepMismatch || false,
  12425. tooLong: validity.tooLong || false,
  12426. // value is not in the correct syntax
  12427. typeMismatch: validity.typeMismatch || false,
  12428. valid: validity.valid || true,
  12429. // Returns true if the element has no value but is a required field
  12430. valueMissing: validity.valueMissing || false
  12431. }, validity);
  12432. };
  12433. Validator.prototype.getValidationMessage = function(validity) {
  12434. var messages = Validator.validationMessages[this.options.locales];
  12435. var error;
  12436. var message;
  12437. var placeholder = '%s';
  12438. var $field = $(validity.field);
  12439. if ($field.is('[type="checkbox"]') || $field.is('[type="radio"]')) {
  12440. $field = this.$element.find('[name=' + $field.attr('name') + ']').first();
  12441. }
  12442. // get error name
  12443. $.each(validity, function(key, val) {
  12444. // skip `field` and `valid`
  12445. if (key === 'field' || key === 'valid') {
  12446. return key;
  12447. }
  12448. // Amaze UI custom error type
  12449. if (key === 'customError' && val) {
  12450. error = val;
  12451. messages = messages.customError;
  12452. return false;
  12453. }
  12454. // W3C specs error type
  12455. if (val === true) {
  12456. error = key;
  12457. return false;
  12458. }
  12459. });
  12460. message = messages[error] || undefined;
  12461. if (message && Validator.ERROR_MAP[error]) {
  12462. message = message.replace(placeholder,
  12463. $field.attr(Validator.ERROR_MAP[error]) || '规定的');
  12464. }
  12465. return message;
  12466. };
  12467. // remove valid mark
  12468. Validator.prototype.removeMark = function() {
  12469. this.$element
  12470. .find('.am-form-success, .am-form-error, .' + this.options.inValidClass +
  12471. ', .' + this.options.validClass)
  12472. .removeClass([
  12473. 'am-form-success',
  12474. 'am-form-error',
  12475. this.options.inValidClass,
  12476. this.options.validClass
  12477. ].join(' '));
  12478. };
  12479. // @since 2.5
  12480. Validator.prototype.destroy = function() {
  12481. this.removeMark();
  12482. // Remove data
  12483. // - Validator.prototype.init -> $element.data('amui.checked')
  12484. // - Validator.prototype.validateForm
  12485. // - Validator.prototype.isValid
  12486. this.$element.removeData('amui.validator amui.checked')
  12487. .off('.validator.amui')
  12488. .find(this.options.allFields).removeData('validity amui.dfdValidity');
  12489. };
  12490. UI.plugin('validator', Validator);
  12491. // init code
  12492. UI.ready(function(context) {
  12493. $('[data-am-validator]', context).validator();
  12494. });
  12495. module.exports = Validator;
  12496. /***/ },
  12497. /* 31 */
  12498. /***/ function(module, exports, __webpack_require__) {
  12499. 'use strict';
  12500. var UI = __webpack_require__(2);
  12501. var cookie = {
  12502. get: function(name) {
  12503. var cookieName = encodeURIComponent(name) + '=';
  12504. var cookieStart = document.cookie.indexOf(cookieName);
  12505. var cookieValue = null;
  12506. var cookieEnd;
  12507. if (cookieStart > -1) {
  12508. cookieEnd = document.cookie.indexOf(';', cookieStart);
  12509. if (cookieEnd == -1) {
  12510. cookieEnd = document.cookie.length;
  12511. }
  12512. cookieValue = decodeURIComponent(document.cookie.substring(cookieStart +
  12513. cookieName.length, cookieEnd));
  12514. }
  12515. return cookieValue;
  12516. },
  12517. set: function(name, value, expires, path, domain, secure) {
  12518. var cookieText = encodeURIComponent(name) + '=' +
  12519. encodeURIComponent(value);
  12520. if (expires instanceof Date) {
  12521. cookieText += '; expires=' + expires.toUTCString();
  12522. }
  12523. if (path) {
  12524. cookieText += '; path=' + path;
  12525. }
  12526. if (domain) {
  12527. cookieText += '; domain=' + domain;
  12528. }
  12529. if (secure) {
  12530. cookieText += '; secure';
  12531. }
  12532. document.cookie = cookieText;
  12533. },
  12534. unset: function(name, path, domain, secure) {
  12535. this.set(name, '', new Date(0), path, domain, secure);
  12536. }
  12537. };
  12538. UI.utils = UI.utils || {};
  12539. module.exports = UI.utils.cookie = cookie;
  12540. /***/ },
  12541. /* 32 */
  12542. /***/ function(module, exports, __webpack_require__) {
  12543. 'use strict';
  12544. var UI = __webpack_require__(2);
  12545. var screenfull = (function() {
  12546. var keyboardAllowed = typeof Element !== 'undefined' &&
  12547. 'ALLOW_KEYBOARD_INPUT' in Element;
  12548. var fn = (function() {
  12549. var val;
  12550. var valLength;
  12551. var fnMap = [
  12552. [
  12553. 'requestFullscreen',
  12554. 'exitFullscreen',
  12555. 'fullscreenElement',
  12556. 'fullscreenEnabled',
  12557. 'fullscreenchange',
  12558. 'fullscreenerror'
  12559. ],
  12560. // new WebKit
  12561. [
  12562. 'webkitRequestFullscreen',
  12563. 'webkitExitFullscreen',
  12564. 'webkitFullscreenElement',
  12565. 'webkitFullscreenEnabled',
  12566. 'webkitfullscreenchange',
  12567. 'webkitfullscreenerror'
  12568. ],
  12569. // old WebKit (Safari 5.1)
  12570. [
  12571. 'webkitRequestFullScreen',
  12572. 'webkitCancelFullScreen',
  12573. 'webkitCurrentFullScreenElement',
  12574. 'webkitCancelFullScreen',
  12575. 'webkitfullscreenchange',
  12576. 'webkitfullscreenerror'
  12577. ],
  12578. [
  12579. 'mozRequestFullScreen',
  12580. 'mozCancelFullScreen',
  12581. 'mozFullScreenElement',
  12582. 'mozFullScreenEnabled',
  12583. 'mozfullscreenchange',
  12584. 'mozfullscreenerror'
  12585. ],
  12586. [
  12587. 'msRequestFullscreen',
  12588. 'msExitFullscreen',
  12589. 'msFullscreenElement',
  12590. 'msFullscreenEnabled',
  12591. 'MSFullscreenChange',
  12592. 'MSFullscreenError'
  12593. ]
  12594. ];
  12595. var i = 0;
  12596. var l = fnMap.length;
  12597. var ret = {};
  12598. for (; i < l; i++) {
  12599. val = fnMap[i];
  12600. if (val && val[1] in document) {
  12601. for (i = 0, valLength = val.length; i < valLength; i++) {
  12602. ret[fnMap[0][i]] = val[i];
  12603. }
  12604. return ret;
  12605. }
  12606. }
  12607. return false;
  12608. })();
  12609. var screenfull = {
  12610. request: function(elem) {
  12611. var request = fn.requestFullscreen;
  12612. elem = elem || document.documentElement;
  12613. // Work around Safari 5.1 bug: reports support for
  12614. // keyboard in fullscreen even though it doesn't.
  12615. // Browser sniffing, since the alternative with
  12616. // setTimeout is even worse.
  12617. if (/5\.1[\.\d]* Safari/.test(navigator.userAgent)) {
  12618. elem[request]();
  12619. } else {
  12620. elem[request](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT);
  12621. }
  12622. },
  12623. exit: function() {
  12624. document[fn.exitFullscreen]();
  12625. },
  12626. toggle: function(elem) {
  12627. if (this.isFullscreen) {
  12628. this.exit();
  12629. } else {
  12630. this.request(elem);
  12631. }
  12632. },
  12633. raw: fn
  12634. };
  12635. if (!fn) {
  12636. return false;
  12637. }
  12638. Object.defineProperties(screenfull, {
  12639. isFullscreen: {
  12640. get: function() {
  12641. return !!document[fn.fullscreenElement];
  12642. }
  12643. },
  12644. element: {
  12645. enumerable: true,
  12646. get: function() {
  12647. return document[fn.fullscreenElement];
  12648. }
  12649. },
  12650. enabled: {
  12651. enumerable: true,
  12652. get: function() {
  12653. // Coerce to boolean in case of old WebKit
  12654. return !!document[fn.fullscreenEnabled];
  12655. }
  12656. }
  12657. });
  12658. screenfull.VERSION = '2.0.0';
  12659. return screenfull;
  12660. })();
  12661. module.exports = UI.fullscreen = screenfull;
  12662. /***/ },
  12663. /* 33 */
  12664. /***/ function(module, exports, __webpack_require__) {
  12665. 'use strict';
  12666. var $ = __webpack_require__(1);
  12667. var UI = __webpack_require__(2);
  12668. UI.support.geolocation = window.navigator && window.navigator.geolocation;
  12669. var geo = UI.support.geolocation;
  12670. var Geolocation = function(options) {
  12671. this.options = options || {};
  12672. };
  12673. Geolocation.MESSAGES = {
  12674. unsupportedBrowser: 'Browser does not support location services',
  12675. permissionDenied: 'You have rejected access to your location',
  12676. positionUnavailable: 'Unable to determine your location',
  12677. timeout: 'Service timeout has been reached'
  12678. };
  12679. Geolocation.ERROR_CODE = {
  12680. 0: 'unsupportedBrowser',
  12681. 1: 'permissionDenied',
  12682. 2: 'positionUnavailable',
  12683. 3: 'timeout'
  12684. };
  12685. Geolocation.prototype.get = function(options) {
  12686. var _this = this;
  12687. options = $.extend({}, this.options, options);
  12688. var deferred = new $.Deferred();
  12689. if (geo) {
  12690. this.watchID = geo.getCurrentPosition(function(position) {
  12691. deferred.resolve.call(_this, position);
  12692. }, function(error) {
  12693. deferred.reject(Geolocation.MESSAGES[Geolocation.ERROR_CODE[error.code]]);
  12694. }, options);
  12695. } else {
  12696. deferred.reject(Geolocation.MESSAGES.unsupportedBrowser);
  12697. }
  12698. return deferred.promise();
  12699. };
  12700. Geolocation.prototype.watch = function(options) {
  12701. if (!geo) {
  12702. return;
  12703. }
  12704. options = $.extend({}, this.options, options);
  12705. if (!$.isFunction(options.done)) {
  12706. return;
  12707. }
  12708. this.clearWatch();
  12709. var fail = $.isFunction(options.fail) ? options.fail : null;
  12710. this.watchID = geo.watchPosition(options.done, fail, options);
  12711. return this.watchID;
  12712. };
  12713. Geolocation.prototype.clearWatch = function() {
  12714. if (!geo || !this.watchID) {
  12715. return;
  12716. }
  12717. geo.clearWatch(this.watchID);
  12718. this.watchID = null;
  12719. };
  12720. module.exports = UI.Geolocation = Geolocation;
  12721. /***/ },
  12722. /* 34 */
  12723. /***/ function(module, exports, __webpack_require__) {
  12724. 'use strict';
  12725. var UI = __webpack_require__(2);
  12726. /**
  12727. * store.js
  12728. * @via https://github.com/marcuswestin/store.js
  12729. * @license https://github.com/marcuswestin/store.js/blob/master/LICENSE
  12730. */
  12731. var store = {};
  12732. var win = window;
  12733. var localStorageName = 'localStorage';
  12734. var storage;
  12735. store.disabled = false;
  12736. store.version = '1.3.17';
  12737. store.set = function(key, value) {
  12738. };
  12739. store.get = function(key, defaultVal) {
  12740. };
  12741. store.has = function(key) {
  12742. return store.get(key) !== undefined;
  12743. };
  12744. store.remove = function(key) {
  12745. };
  12746. store.clear = function() {
  12747. };
  12748. store.transact = function(key, defaultVal, transactionFn) {
  12749. if (transactionFn == null) {
  12750. transactionFn = defaultVal;
  12751. defaultVal = null;
  12752. }
  12753. if (defaultVal == null) {
  12754. defaultVal = {};
  12755. }
  12756. var val = store.get(key, defaultVal);
  12757. transactionFn(val);
  12758. store.set(key, val);
  12759. };
  12760. store.getAll = function() {
  12761. };
  12762. store.forEach = function() {
  12763. };
  12764. store.serialize = function(value) {
  12765. return JSON.stringify(value);
  12766. };
  12767. store.deserialize = function(value) {
  12768. if (typeof value != 'string') {
  12769. return undefined;
  12770. }
  12771. try {
  12772. return JSON.parse(value);
  12773. } catch (e) {
  12774. return value || undefined;
  12775. }
  12776. };
  12777. // Functions to encapsulate questionable FireFox 3.6.13 behavior
  12778. // when about.config::dom.storage.enabled === false
  12779. // See https://github.com/marcuswestin/store.js/issues#issue/13
  12780. function isLocalStorageNameSupported() {
  12781. try {
  12782. return (localStorageName in win && win[localStorageName]);
  12783. }
  12784. catch (err) {
  12785. return false;
  12786. }
  12787. }
  12788. if (isLocalStorageNameSupported()) {
  12789. storage = win[localStorageName];
  12790. store.set = function(key, val) {
  12791. if (val === undefined) {
  12792. return store.remove(key);
  12793. }
  12794. storage.setItem(key, store.serialize(val));
  12795. return val;
  12796. };
  12797. store.get = function(key, defaultVal) {
  12798. var val = store.deserialize(storage.getItem(key));
  12799. return (val === undefined ? defaultVal : val);
  12800. };
  12801. store.remove = function(key) {
  12802. storage.removeItem(key);
  12803. };
  12804. store.clear = function() {
  12805. storage.clear();
  12806. };
  12807. store.getAll = function() {
  12808. var ret = {};
  12809. store.forEach(function(key, val) {
  12810. ret[key] = val;
  12811. });
  12812. return ret;
  12813. };
  12814. store.forEach = function(callback) {
  12815. for (var i = 0; i < storage.length; i++) {
  12816. var key = storage.key(i);
  12817. callback(key, store.get(key));
  12818. }
  12819. };
  12820. }
  12821. try {
  12822. var testKey = '__storeJs__';
  12823. store.set(testKey, testKey);
  12824. if (store.get(testKey) != testKey) {
  12825. store.disabled = true;
  12826. }
  12827. store.remove(testKey);
  12828. } catch (e) {
  12829. store.disabled = true;
  12830. }
  12831. store.enabled = !store.disabled;
  12832. module.exports = UI.store = store;
  12833. /***/ },
  12834. /* 35 */
  12835. /***/ function(module, exports, __webpack_require__) {
  12836. 'use strict';
  12837. var $ = __webpack_require__(1);
  12838. var UI = __webpack_require__(2);
  12839. __webpack_require__(7);
  12840. function accordionInit() {
  12841. var $accordion = $('[data-am-widget="accordion"]');
  12842. var selector = {
  12843. item: '.am-accordion-item',
  12844. title: '.am-accordion-title',
  12845. body: '.am-accordion-bd',
  12846. disabled: '.am-disabled'
  12847. };
  12848. $accordion.each(function(i, item) {
  12849. var options = UI.utils.parseOptions($(item).attr('data-am-accordion'));
  12850. var $title = $(item).find(selector.title);
  12851. $title.on('click.accordion.amui', function() {
  12852. var $collapse = $(this).next(selector.body);
  12853. var $parent = $(this).parent(selector.item);
  12854. var data = $collapse.data('amui.collapse');
  12855. if ($parent.is(selector.disabled)) {
  12856. return;
  12857. }
  12858. $parent.toggleClass('am-active');
  12859. if (!data) {
  12860. $collapse.collapse();
  12861. } else {
  12862. $collapse.collapse('toggle');
  12863. }
  12864. !options.multiple &&
  12865. $(item).children('.am-active').
  12866. not($parent).not(selector.disabled).removeClass('am-active').
  12867. find(selector.body + '.am-in').collapse('close');
  12868. });
  12869. });
  12870. }
  12871. // Init on DOM ready
  12872. $(accordionInit);
  12873. module.exports = UI.accordion = {
  12874. VERSION: '2.1.0',
  12875. init: accordionInit
  12876. };
  12877. /***/ },
  12878. /* 36 */
  12879. /***/ function(module, exports) {
  12880. 'use strict';
  12881. module.exports = {
  12882. VERSION: '2.0.1'
  12883. };
  12884. /***/ },
  12885. /* 37 */
  12886. /***/ function(module, exports, __webpack_require__) {
  12887. 'use strict';
  12888. var $ = __webpack_require__(1);
  12889. var UI = __webpack_require__(2);
  12890. function duoshuoInit() {
  12891. var $dsThread = $('.ds-thread');
  12892. var dsShortName = $dsThread.parent('[data-am-widget="duoshuo"]').
  12893. attr('data-ds-short-name');
  12894. var dsSrc = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
  12895. '//static.duoshuo.com/embed.js';
  12896. if (!$dsThread.length || !dsShortName) {
  12897. return;
  12898. }
  12899. window.duoshuoQuery = {
  12900. short_name: dsShortName
  12901. };
  12902. // 已经有多说脚本
  12903. if ($('script[src="' + dsSrc + '"]').length) {
  12904. return;
  12905. }
  12906. var $dsJS = $('<script>', {
  12907. async: true,
  12908. type: 'text/javascript',
  12909. src: dsSrc,
  12910. charset: 'utf-8'
  12911. });
  12912. $('body').append($dsJS);
  12913. }
  12914. $(window).on('load', duoshuoInit);
  12915. module.exports = UI.duoshuo = {
  12916. VERSION: '2.0.1',
  12917. init: duoshuoInit
  12918. };
  12919. /***/ },
  12920. /* 38 */
  12921. /***/ function(module, exports, __webpack_require__) {
  12922. 'use strict';
  12923. var $ = __webpack_require__(1);
  12924. var UI = __webpack_require__(2);
  12925. __webpack_require__(20);
  12926. /**
  12927. * Is Images zoomable
  12928. * @return {Boolean}
  12929. */
  12930. $.isImgZoomAble = function(element) {
  12931. var t = new Image();
  12932. t.src = element.src;
  12933. var zoomAble = ($(element).width() < t.width);
  12934. if (zoomAble) {
  12935. $(element).closest('.am-figure').addClass('am-figure-zoomable');
  12936. }
  12937. return zoomAble;
  12938. };
  12939. function figureInit() {
  12940. $('.am-figure').each(function(i, item) {
  12941. var options = UI.utils.parseOptions($(item).attr('data-am-figure'));
  12942. var $item = $(item);
  12943. var data;
  12944. if (options.pureview) {
  12945. if (options.pureview === 'auto') {
  12946. var zoomAble = $.isImgZoomAble($item.find('img')[0]);
  12947. zoomAble && $item.pureview();
  12948. } else {
  12949. $item.addClass('am-figure-zoomable').pureview();
  12950. }
  12951. }
  12952. data = $item.data('amui.pureview');
  12953. if (data) {
  12954. $item.on('click', ':not(img)', function() {
  12955. data.open(0);
  12956. });
  12957. }
  12958. });
  12959. }
  12960. $(window).on('load', figureInit);
  12961. module.exports = UI.figure = {
  12962. VERSION: '2.0.3',
  12963. init: figureInit
  12964. };
  12965. /***/ },
  12966. /* 39 */
  12967. /***/ function(module, exports, __webpack_require__) {
  12968. 'use strict';
  12969. var $ = __webpack_require__(1);
  12970. var UI = __webpack_require__(2);
  12971. __webpack_require__(15);
  12972. var addToHS = __webpack_require__(4);
  12973. var cookie = __webpack_require__(31);
  12974. function footerInit() {
  12975. // modal mode
  12976. $('.am-footer-ysp').on('click', function() {
  12977. $('#am-footer-modal').modal();
  12978. });
  12979. var options = UI.utils.parseOptions($('.am-footer').data('amFooter'));
  12980. options.addToHS && addToHS();
  12981. // switch mode
  12982. // switch to desktop
  12983. $('[data-rel="desktop"]').on('click', function(e) {
  12984. e.preventDefault();
  12985. if (window.AMPlatform) { // front end
  12986. window.AMPlatform.util.goDesktop();
  12987. } else { // back end
  12988. cookie.set('allmobilize', 'desktop', '', '/');
  12989. window.location = window.location;
  12990. }
  12991. });
  12992. }
  12993. $(footerInit);
  12994. module.exports = UI.footer = {
  12995. VERSION: '3.1.2',
  12996. init: footerInit
  12997. };
  12998. /***/ },
  12999. /* 40 */
  13000. /***/ function(module, exports, __webpack_require__) {
  13001. 'use strict';
  13002. var $ = __webpack_require__(1);
  13003. var UI = __webpack_require__(2);
  13004. __webpack_require__(20);
  13005. function galleryInit() {
  13006. var $gallery = $('[data-am-widget="gallery"]');
  13007. $gallery.each(function() {
  13008. var options = UI.utils.parseOptions($(this).attr('data-am-gallery'));
  13009. if (options.pureview) {
  13010. (typeof options.pureview === 'object') ?
  13011. $(this).pureview(options.pureview) : $(this).pureview();
  13012. }
  13013. });
  13014. }
  13015. $(galleryInit);
  13016. module.exports = UI.gallery = {
  13017. VERSION: '3.0.0',
  13018. init: galleryInit
  13019. };
  13020. /***/ },
  13021. /* 41 */
  13022. /***/ function(module, exports, __webpack_require__) {
  13023. 'use strict';
  13024. var $ = __webpack_require__(1);
  13025. var UI = __webpack_require__(2);
  13026. __webpack_require__(23);
  13027. function goTopInit() {
  13028. var $goTop = $('[data-am-widget="gotop"]');
  13029. var $fixed = $goTop.filter('.am-gotop-fixed');
  13030. var $win = $(window);
  13031. if ($goTop.data('init')) {
  13032. return;
  13033. }
  13034. $goTop.find('a').on('click', function(e) {
  13035. e.preventDefault();
  13036. $win.smoothScroll();
  13037. });
  13038. function checkPosition() {
  13039. $fixed[($win.scrollTop() > 50 ? 'add' : 'remove') + 'Class']('am-active');
  13040. }
  13041. checkPosition();
  13042. $win.on('scroll.gotop.amui', UI.utils.debounce(checkPosition, 100));
  13043. $goTop.data('init', true);
  13044. }
  13045. $(goTopInit);
  13046. module.exports = UI.gotop = {
  13047. VERSION: '4.0.2',
  13048. init: goTopInit
  13049. };
  13050. /***/ },
  13051. /* 42 */
  13052. /***/ function(module, exports, __webpack_require__) {
  13053. 'use strict';
  13054. var $ = __webpack_require__(1);
  13055. var UI = __webpack_require__(2);
  13056. function headerInit() {
  13057. $('[data-am-widget="header"]').each(function() {
  13058. if ($(this).hasClass('am-header-fixed')) {
  13059. $('body').addClass('am-with-fixed-header');
  13060. return false;
  13061. }
  13062. });
  13063. }
  13064. $(headerInit);
  13065. module.exports = UI.header = {
  13066. VERSION: '2.0.0',
  13067. init: headerInit
  13068. };
  13069. /***/ },
  13070. /* 43 */
  13071. /***/ function(module, exports, __webpack_require__) {
  13072. 'use strict';
  13073. var UI = __webpack_require__(2);
  13074. module.exports = UI.intro = {
  13075. VERSION: '4.0.2',
  13076. init: function() {}
  13077. };
  13078. /***/ },
  13079. /* 44 */
  13080. /***/ function(module, exports, __webpack_require__) {
  13081. 'use strict';
  13082. var UI = __webpack_require__(2);
  13083. module.exports = UI.listNews = {
  13084. VERSION: '4.0.0',
  13085. init: function() {}
  13086. };
  13087. /***/ },
  13088. /* 45 */
  13089. /***/ function(module, exports, __webpack_require__) {
  13090. /* jshint strict: false, maxlen: 200 */
  13091. /* global BMap */
  13092. var $ = __webpack_require__(1);
  13093. var UI = __webpack_require__(2);
  13094. function addMapApi(callback) {
  13095. var $mapApi0 = $('<script />', {
  13096. id: 'am-map-api-0'
  13097. });
  13098. $('body').append($mapApi0);
  13099. $mapApi0.on('load', function() {
  13100. console.log('load');
  13101. var $mapApi1 = $('<script/>', {
  13102. id: 'am-map-api-1'
  13103. });
  13104. $('body').append($mapApi1);
  13105. $mapApi1.on('load', function() {
  13106. var script = document.createElement('script');
  13107. script.textContent = '(' + callback.toString() + ')();';
  13108. $('body')[0].appendChild(script);
  13109. }).attr('src', 'http://api.map.baidu.com/getscript' +
  13110. '?type=quick&file=feature' +
  13111. '&ak=WVAXZ05oyNRXS5egLImmentg&t=20140109092002');
  13112. }).attr('src', 'http://api.map.baidu.com/getscript' +
  13113. '?type=quick&file=api&ak=WVAXZ05oyNRXS5egLImmentg&t=20140109092002');
  13114. // jQuery 中 `load` 事件触发有问题,动态设置 src 属性才会触发 `load` 事件
  13115. // $mapApi0 = $('<script />', {src: 'xxx'}); 这样的写法在 Zepto.js 中则没有问题
  13116. }
  13117. function addBdMap() {
  13118. // 如果使用 $ 选择符,minify 以后会报错: $ is undefined
  13119. // 即使传入 $ 也无效,改为使用原生方法
  13120. // 这个函数作为 callback 会插入到 body 以后才执行,应该是 $ 引用错误导致
  13121. var content = document.querySelector('.am-map');
  13122. var defaultLng = 116.331398; // 经度默认值
  13123. var defaultLat = 39.897445; // 纬度默认值
  13124. var name = content.getAttribute('data-name');
  13125. var address = content.getAttribute('data-address');
  13126. var lng = content.getAttribute('data-longitude') || defaultLng;
  13127. var lat = content.getAttribute('data-latitude') || defaultLat;
  13128. var setZoom = content.getAttribute('data-setZoom') || 17;
  13129. var icon = content.getAttribute('data-icon');
  13130. var map = new BMap.Map('bd-map');
  13131. // 实例化一个地理坐标点
  13132. var point = new BMap.Point(lng, lat);
  13133. // 设初始化地图, options: 3-18
  13134. map.centerAndZoom(point, setZoom);
  13135. // 添加地图缩放控件
  13136. if (content.getAttribute('data-zoomControl')) {
  13137. map.addControl(new BMap.ZoomControl());
  13138. }
  13139. // 添加比例尺控件
  13140. if (content.getAttribute('data-scaleControl')) {
  13141. map.addControl(new BMap.ScaleControl());
  13142. }
  13143. // 创建标准与自定义 icon
  13144. var marker = new BMap.Marker(point);
  13145. if (icon) {
  13146. marker.setIcon(new BMap.Icon(icon, new BMap.Size(40, 40)));
  13147. }
  13148. var opts = {
  13149. width: 200, // 信息窗口宽度
  13150. // height: 'auto', // 信息窗口高度
  13151. title: name // 信息窗口标题
  13152. };
  13153. // 创建信息窗口对象
  13154. var infoWindow = new BMap.InfoWindow('地址:' + address, opts);
  13155. // 创建地址解析器实例
  13156. var myGeo = new BMap.Geocoder();
  13157. // 判断有没有使用经纬度
  13158. if (lng == defaultLng && lat == defaultLat) {
  13159. // 使用地址反解析来设置地图
  13160. // 将地址解析结果显示在地图上,并调整地图视野
  13161. myGeo.getPoint(address, function(point) {
  13162. if (point) {
  13163. map.centerAndZoom(point, setZoom);
  13164. marker.setPosition(point);
  13165. map.addOverlay(marker);
  13166. map.openInfoWindow(infoWindow, point); // 开启信息窗口
  13167. }
  13168. }, '');
  13169. } else {
  13170. // 使用经纬度来设置地图
  13171. myGeo.getLocation(point, function(result) {
  13172. map.centerAndZoom(point, setZoom);
  13173. marker.setPosition(point);
  13174. map.addOverlay(marker);
  13175. if (address) {
  13176. map.openInfoWindow(infoWindow, point); // 开启信息窗口
  13177. } else {
  13178. map.openInfoWindow(new BMap.InfoWindow(address, opts), point); // 开启信息窗口
  13179. }
  13180. });
  13181. }
  13182. }
  13183. var mapInit = function() {
  13184. $('.am-map').length && addMapApi(addBdMap);
  13185. };
  13186. $(mapInit);
  13187. module.exports = UI.map = {
  13188. VERSION: '2.0.2',
  13189. init: mapInit
  13190. };
  13191. /***/ },
  13192. /* 46 */
  13193. /***/ function(module, exports, __webpack_require__) {
  13194. 'use strict';
  13195. var $ = __webpack_require__(1);
  13196. var UI = __webpack_require__(2);
  13197. function mechatInit() {
  13198. if (!$('#mechat').length) {
  13199. return;
  13200. }
  13201. var $mechat = $('[data-am-widget="mechat"]');
  13202. var unitid = $mechat.data('am-mechat-unitid');
  13203. var $mechatData = $('<script>', {
  13204. charset: 'utf-8',
  13205. src: 'http://mechatim.com/js/unit/button.js?id=' + unitid
  13206. });
  13207. $('body').append($mechatData);
  13208. }
  13209. // Lazy load
  13210. $(window).on('load', mechatInit);
  13211. module.exports = UI.mechat = {
  13212. VERSION: '2.0.1',
  13213. init: mechatInit
  13214. };
  13215. /***/ },
  13216. /* 47 */
  13217. /***/ function(module, exports, __webpack_require__) {
  13218. 'use strict';
  13219. var $ = __webpack_require__(1);
  13220. var UI = __webpack_require__(2);
  13221. var IScroll = __webpack_require__(14);
  13222. __webpack_require__(16);
  13223. __webpack_require__(7);
  13224. var menuInit = function() {
  13225. var $menus = $('[data-am-widget="menu"]');
  13226. $menus.find('.am-menu-nav .am-parent > a').on('click', function(e) {
  13227. e.preventDefault();
  13228. var $clicked = $(this);
  13229. var $parent = $clicked.parent();
  13230. var $subMenu = $clicked.next('.am-menu-sub');
  13231. $parent.toggleClass('am-open');
  13232. $subMenu.collapse('toggle');
  13233. $parent.siblings('.am-parent').removeClass('am-open')
  13234. .children('.am-menu-sub.am-in').collapse('close');
  13235. });
  13236. // Dropdown/slideDown menu
  13237. $menus.
  13238. filter('[data-am-menu-collapse]').
  13239. find('> .am-menu-toggle').
  13240. on('click', function(e) {
  13241. e.preventDefault();
  13242. var $this = $(this);
  13243. var $nav = $this.next('.am-menu-nav');
  13244. $this.toggleClass('am-active');
  13245. $nav.collapse('toggle');
  13246. });
  13247. // OffCanvas menu
  13248. $menus.
  13249. filter('[data-am-menu-offcanvas]').
  13250. find('> .am-menu-toggle').
  13251. on('click', function(e) {
  13252. e.preventDefault();
  13253. var $this = $(this);
  13254. var $nav = $this.next('.am-offcanvas');
  13255. $this.toggleClass('am-active');
  13256. $nav.offCanvas('open');
  13257. });
  13258. // Close offCanvas when link clicked
  13259. var autoCloseOffCanvas = '.am-offcanvas[data-dismiss-on="click"]';
  13260. var $autoCloseOffCanvas = $(autoCloseOffCanvas);
  13261. $autoCloseOffCanvas.find('a').not('.am-parent>a').on('click', function(e) {
  13262. $(this).parents(autoCloseOffCanvas).offCanvas('close');
  13263. });
  13264. // one theme
  13265. $menus.filter('.am-menu-one').each(function(index) {
  13266. var $this = $(this);
  13267. var $wrap = $('<div class="am-menu-nav-sub-wrap"></div>');
  13268. var allWidth = 0;
  13269. var $nav = $this.find('.am-menu-nav');
  13270. var $navTopItem = $nav.children('li');
  13271. var prevIndex;
  13272. $navTopItem.filter('.am-parent').each(function(index) {
  13273. $(this).attr('data-rel', '#am-menu-sub-' + index);
  13274. $(this).
  13275. find('.am-menu-sub').
  13276. attr('id', 'am-menu-sub-' + index).
  13277. appendTo($wrap);
  13278. });
  13279. $this.append($wrap);
  13280. $nav.wrap('<div class="am-menu-nav-wrap" id="am-menu-' + index + '">');
  13281. // $navTopItem.eq(0).addClass('am-active');
  13282. // 计算出所有 li 宽度
  13283. $navTopItem.each(function(i) {
  13284. allWidth += parseFloat($(this).css('width'));
  13285. });
  13286. $nav.width(allWidth);
  13287. var menuScroll = new IScroll('#am-menu-' + index, {
  13288. eventPassthrough: true,
  13289. scrollX: true,
  13290. scrollY: false,
  13291. preventDefault: false
  13292. });
  13293. $navTopItem.on('click', function() {
  13294. var $clicked = $(this);
  13295. $clicked.addClass('am-active').siblings().removeClass('am-active');
  13296. $wrap.find('.am-menu-sub.am-in').collapse('close');
  13297. if ($clicked.is('.am-parent')) {
  13298. !$clicked.hasClass('.am-open') &&
  13299. $wrap.find($clicked.attr('data-rel')).collapse('open');
  13300. } else {
  13301. $clicked.siblings().removeClass('am-open');
  13302. }
  13303. // 第一次调用,没有prevIndex
  13304. if (prevIndex === undefined) {
  13305. prevIndex = $(this).index() ? 0 : 1;
  13306. }
  13307. // 判断方向
  13308. var dir = $(this).index() > prevIndex;
  13309. var target = $(this)[dir ? 'next' : 'prev']();
  13310. // 点击的按钮,显示一半
  13311. var offset = target.offset() || $(this).offset();
  13312. var within = $this.offset();
  13313. // 父类左边距
  13314. var listOffset;
  13315. var parentLeft = parseInt($this.css('padding-left'));
  13316. if (dir ? offset.left + offset.width > within.left + within.width :
  13317. offset.left < within.left) {
  13318. listOffset = $nav.offset();
  13319. menuScroll.scrollTo(dir ?
  13320. within.width - offset.left + listOffset.left -
  13321. offset.width - parentLeft :
  13322. listOffset.left - offset.left, 0, 400);
  13323. }
  13324. prevIndex = $(this).index();
  13325. });
  13326. $this.on('touchmove', function(event) {
  13327. event.preventDefault();
  13328. });
  13329. });
  13330. };
  13331. $(menuInit);
  13332. module.exports = UI.menu = {
  13333. VERSION: '4.0.3',
  13334. init: menuInit
  13335. };
  13336. /***/ },
  13337. /* 48 */
  13338. /***/ function(module, exports, __webpack_require__) {
  13339. 'use strict';
  13340. var $ = __webpack_require__(1);
  13341. var UI = __webpack_require__(2);
  13342. var share = __webpack_require__(25);
  13343. var QRCode = __webpack_require__(26);
  13344. __webpack_require__(15);
  13345. function navbarInit() {
  13346. var $navBar = $('[data-am-widget="navbar"]');
  13347. if (!$navBar.length) {
  13348. return;
  13349. }
  13350. var $win = $(window);
  13351. var $body = $('body');
  13352. var $navBarNav = $navBar.find('.am-navbar-nav');
  13353. var $navItems = $navBar.find('li');
  13354. var navItemsCounter = $navItems.length;
  13355. var configItems = $navBarNav.attr('class') &&
  13356. parseInt($navBarNav.attr('class').
  13357. match(/am-avg-sm-(\d+)/)[1]) || 3;
  13358. var navMinWidth = 60; // 每个 li 最小宽度
  13359. var offsetWidth = 16;
  13360. var $share = $navItems.filter('[data-am-navbar-share]');
  13361. var $qrcode = $navItems.filter('[data-am-navbar-qrcode]');
  13362. var activeStatus = 'am-active';
  13363. var $moreActions = $('<ul class="am-navbar-actions"></ul>', {
  13364. id: UI.utils.generateGUID('am-navbar-actions')
  13365. });
  13366. var $moreLink = $('<li class="am-navbar-labels am-navbar-more">' +
  13367. '<a href="javascript: void(0);">' +
  13368. '<span class="am-icon-angle-up"></span>' +
  13369. '<span class="am-navbar-label">更多</span></a></li>');
  13370. // 如果有 Fix 的工具栏则设置 body 的 padding-bottom
  13371. if ($navBar.css('position') == 'fixed') {
  13372. $body.addClass('am-with-fixed-navbar');
  13373. }
  13374. if ($qrcode.length) {
  13375. var qrId = 'am-navbar-qrcode';
  13376. $qrModal = $('#' + qrId);
  13377. if (!$qrModal.length) {
  13378. var qrImg = $qrcode.attr('data-am-navbar-qrcode');
  13379. var $qrModal = $('<div class="am-modal am-modal-no-btn" id="">' +
  13380. '<div class="am-modal-dialog">' +
  13381. '<div class="am-modal-bd"></div></div>' +
  13382. '</div>', {
  13383. id: qrId
  13384. });
  13385. var $qrContainer = $qrModal.find('.am-modal-bd');
  13386. // 判断上传自定义的二维码没有,否则生成二维码
  13387. if (qrImg) {
  13388. $qrContainer.html('<img src="' + qrImg + '"/>');
  13389. } else {
  13390. var qrnode = new QRCode({
  13391. render: 'canvas',
  13392. correctLevel: 0,
  13393. text: window.location.href,
  13394. width: 200,
  13395. height: 200,
  13396. background: '#fff',
  13397. foreground: '#000'
  13398. });
  13399. $qrContainer.html(qrnode);
  13400. }
  13401. $body.append($qrModal);
  13402. }
  13403. $qrcode.on('click', function(e) {
  13404. e.preventDefault();
  13405. $qrModal.modal();
  13406. });
  13407. }
  13408. if (navItemsCounter > configItems && navItemsCounter > calcSuiteItems()) {
  13409. initActions();
  13410. }
  13411. // console.log('NavItems: %d, config: %d, best: %d',
  13412. // navItemsCounter, configItems, calcSuiteItems());
  13413. function initActions() {
  13414. $navBarNav.append($moreLink);
  13415. $navBarNav.
  13416. find('li').
  13417. not('.am-navbar-more').
  13418. slice(calcSuiteItems() - 1).
  13419. appendTo($moreActions);
  13420. // Append more actions
  13421. $navBar.append($moreActions);
  13422. }
  13423. function checkNavBarItems() {
  13424. if (calcSuiteItems() >= navItemsCounter) {
  13425. // 显示所有链接,隐藏 more
  13426. $moreLink.hide();
  13427. $moreActions.find('li').insertBefore($moreLink);
  13428. return;
  13429. }
  13430. !$navBar.find('.am-navbar-actions').length && initActions();
  13431. $moreLink.show();
  13432. if ($navBarNav.find('li').length < calcSuiteItems()) {
  13433. $moreActions.find('li').
  13434. slice(0, calcSuiteItems() - $navBarNav.find('li').length).
  13435. insertBefore($moreLink);
  13436. } else if ($navBarNav.find('li').length > calcSuiteItems()) {
  13437. if ($moreActions.find('li').length) {
  13438. $navBarNav.find('li').not($moreLink).slice(calcSuiteItems() - 1).
  13439. insertBefore($moreActions.find('li').first());
  13440. } else {
  13441. $navBarNav.find('li').not($moreLink).slice(calcSuiteItems() - 1).
  13442. appendTo($moreActions);
  13443. }
  13444. }
  13445. }
  13446. /**
  13447. * 计算最适合显示的条目个数
  13448. * @returns {number}
  13449. */
  13450. function calcSuiteItems() {
  13451. return Math.floor(($win.width() - offsetWidth) / navMinWidth);
  13452. }
  13453. $navBar.on('click.navbar.amui', '.am-navbar-more', function(e) {
  13454. e.preventDefault();
  13455. $moreLink[$moreActions.hasClass(activeStatus) ?
  13456. 'removeClass' : 'addClass'](activeStatus);
  13457. $moreActions.toggleClass(activeStatus);
  13458. });
  13459. if ($share.length) {
  13460. $share.on('click.navbar.amui', function(e) {
  13461. e.preventDefault();
  13462. share.toggle();
  13463. });
  13464. }
  13465. $win.on('resize.navbar.amui orientationchange.navbar.amui',
  13466. UI.utils.debounce(checkNavBarItems, 150));
  13467. }
  13468. // DOMContent ready
  13469. $(navbarInit);
  13470. module.exports = UI.navbar = {
  13471. VERSION: '2.0.2',
  13472. init: navbarInit
  13473. };
  13474. /***/ },
  13475. /* 49 */
  13476. /***/ function(module, exports, __webpack_require__) {
  13477. 'use strict';
  13478. var UI = __webpack_require__(2);
  13479. module.exports = UI.pagination = {
  13480. VERSION: '3.0.1'
  13481. };
  13482. /***/ },
  13483. /* 50 */
  13484. /***/ function(module, exports, __webpack_require__) {
  13485. 'use strict';
  13486. var $ = __webpack_require__(1);
  13487. var UI = __webpack_require__(2);
  13488. var IScroll = __webpack_require__(14);
  13489. __webpack_require__(20);
  13490. /**
  13491. * 表格滚动
  13492. * @param {number} index ID 标识,多个 paragraph 里面多个 table
  13493. */
  13494. $.fn.scrollTable = function(index) {
  13495. var $this = $(this);
  13496. var $parent;
  13497. $this.wrap('<div class="am-paragraph-table-container" ' +
  13498. 'id="am-paragraph-table-' + index + '">' +
  13499. '<div class="am-paragraph-table-scroller"></div></div>');
  13500. $parent = $this.parent();
  13501. $parent.width($this.width());
  13502. $parent.height($this.height());
  13503. new IScroll('#am-paragraph-table-' + index, {
  13504. eventPassthrough: true,
  13505. scrollX: true,
  13506. scrollY: false,
  13507. preventDefault: false
  13508. });
  13509. };
  13510. function paragraphInit() {
  13511. var $paragraph = $('[data-am-widget="paragraph"]');
  13512. $paragraph.each(function(index) {
  13513. var $this = $(this);
  13514. var options = UI.utils.parseOptions($this.attr('data-am-paragraph'));
  13515. var $index = index;
  13516. if (options.pureview) {
  13517. $this.pureview();
  13518. }
  13519. if (options.tableScrollable) {
  13520. $this.find('table').each(function(index) {
  13521. if ($(this).width() > $(window).width()) {
  13522. $(this).scrollTable($index + '-' + index);
  13523. }
  13524. });
  13525. }
  13526. });
  13527. }
  13528. $(window).on('load', paragraphInit);
  13529. module.exports = UI.paragraph = {
  13530. VERSION: '2.0.1',
  13531. init: paragraphInit
  13532. };
  13533. /***/ },
  13534. /* 51 */
  13535. /***/ function(module, exports, __webpack_require__) {
  13536. 'use strict';
  13537. var $ = __webpack_require__(1);
  13538. var UI = __webpack_require__(2);
  13539. __webpack_require__(11);
  13540. function sliderInit() {
  13541. var $sliders = $('[data-am-widget="slider"]');
  13542. $sliders.not('.am-slider-manual').each(function(i, item) {
  13543. var options = UI.utils.parseOptions($(item).attr('data-am-slider'));
  13544. $(item).flexslider(options);
  13545. });
  13546. }
  13547. $(sliderInit);
  13548. module.exports = UI.slider = {
  13549. VERSION: '3.0.1',
  13550. init: sliderInit
  13551. };
  13552. /***/ },
  13553. /* 52 */
  13554. /***/ function(module, exports, __webpack_require__) {
  13555. 'use strict';
  13556. var $ = __webpack_require__(1);
  13557. var UI = __webpack_require__(2);
  13558. __webpack_require__(28);
  13559. function tabsInit() {
  13560. $('[data-am-widget="tabs"]').each(function() {
  13561. var options = $(this).data('amTabsNoswipe') ? {noSwipe: 1} : {};
  13562. $(this).tabs(options);
  13563. });
  13564. }
  13565. $(tabsInit);
  13566. module.exports = UI.tab = {
  13567. VERSION: '4.0.1',
  13568. init: tabsInit
  13569. };
  13570. /***/ },
  13571. /* 53 */
  13572. /***/ function(module, exports, __webpack_require__) {
  13573. 'use strict';
  13574. var UI = __webpack_require__(2);
  13575. module.exports = UI.titlebar = {
  13576. VERSION: '4.0.1'
  13577. };
  13578. /***/ },
  13579. /* 54 */
  13580. /***/ function(module, exports, __webpack_require__) {
  13581. 'use strict';
  13582. var $ = __webpack_require__(1);
  13583. var UI = __webpack_require__(2);
  13584. var isWeChat = window.navigator.userAgent.indexOf('MicroMessenger') > -1;
  13585. /* global wx,alert */
  13586. function appendWeChatSDK(callback) {
  13587. var $weChatSDK = $('<script/>', {
  13588. id: 'wechat-sdk'
  13589. });
  13590. $('body').append($weChatSDK);
  13591. $weChatSDK.on('load', function() {
  13592. callback && callback();
  13593. }).attr('src', 'http://res.wx.qq.com/open/js/jweixin-1.0.0.js');
  13594. }
  13595. function payHandler() {
  13596. var $paymentBtn = $('[data-am-widget="wechatpay"]');
  13597. if (!isWeChat) {
  13598. $paymentBtn.hide();
  13599. return false;
  13600. }
  13601. $paymentBtn.on('click', '.am-wechatpay-btn', function(e) {
  13602. e.preventDefault();
  13603. var options = UI.utils.parseOptions($(this).parent().data('wechatPay'));
  13604. // console.log(options);
  13605. // alert('pay button clicked');
  13606. if (!window.wx) {
  13607. alert('没有微信 JS SDK');
  13608. return;
  13609. }
  13610. wx.checkJsApi({
  13611. jsApiList: ['chooseWXPay'],
  13612. success: function(res) {
  13613. if (res.checkResult.chooseWXPay) {
  13614. wx.chooseWXPay(options);
  13615. } else {
  13616. alert('微信版本不支持支付接口或没有开启!');
  13617. }
  13618. },
  13619. fail: function() {
  13620. alert('调用 checkJsApi 接口时发生错误!');
  13621. }
  13622. });
  13623. });
  13624. }
  13625. var payInit = payHandler;
  13626. // Init on DOM ready
  13627. $(payInit);
  13628. module.exports = UI.pay = {
  13629. VERSION: '1.0.0',
  13630. init: payInit
  13631. };
  13632. /***/ }
  13633. /******/ ])
  13634. });
  13635. ;