mui.js 240 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305
  1. /*!
  2. * =====================================================
  3. * Mui v3.7.0 (http://dev.dcloud.net.cn/mui)
  4. * =====================================================
  5. */
  6. /**
  7. * MUI核心JS
  8. * @type _L4.$|Function
  9. */
  10. var mui = (function(document, undefined) {
  11. var readyRE = /complete|loaded|interactive/;
  12. var idSelectorRE = /^#([\w-]+)$/;
  13. var classSelectorRE = /^\.([\w-]+)$/;
  14. var tagSelectorRE = /^[\w-]+$/;
  15. var translateRE = /translate(?:3d)?\((.+?)\)/;
  16. var translateMatrixRE = /matrix(3d)?\((.+?)\)/;
  17. var $ = function(selector, context) {
  18. context = context || document;
  19. if(!selector)
  20. return wrap();
  21. if(typeof selector === 'object')
  22. if($.isArrayLike(selector)) {
  23. return wrap($.slice.call(selector), null);
  24. } else {
  25. return wrap([selector], null);
  26. }
  27. if(typeof selector === 'function')
  28. return $.ready(selector);
  29. if(typeof selector === 'string') {
  30. try {
  31. selector = selector.trim();
  32. if(idSelectorRE.test(selector)) {
  33. var found = document.getElementById(RegExp.$1);
  34. return wrap(found ? [found] : []);
  35. }
  36. return wrap($.qsa(selector, context), selector);
  37. } catch(e) {}
  38. }
  39. return wrap();
  40. };
  41. var wrap = function(dom, selector) {
  42. dom = dom || [];
  43. Object.setPrototypeOf(dom, $.fn);
  44. dom.selector = selector || '';
  45. return dom;
  46. };
  47. $.uuid = 0;
  48. $.data = {};
  49. /**
  50. * extend(simple)
  51. * @param {type} target
  52. * @param {type} source
  53. * @param {type} deep
  54. * @returns {unresolved}
  55. */
  56. $.extend = function() { //from jquery2
  57. var options, name, src, copy, copyIsArray, clone,
  58. target = arguments[0] || {},
  59. i = 1,
  60. length = arguments.length,
  61. deep = false;
  62. if(typeof target === "boolean") {
  63. deep = target;
  64. target = arguments[i] || {};
  65. i++;
  66. }
  67. if(typeof target !== "object" && !$.isFunction(target)) {
  68. target = {};
  69. }
  70. if(i === length) {
  71. target = this;
  72. i--;
  73. }
  74. for(; i < length; i++) {
  75. if((options = arguments[i]) != null) {
  76. for(name in options) {
  77. src = target[name];
  78. copy = options[name];
  79. if(target === copy) {
  80. continue;
  81. }
  82. if(deep && copy && ($.isPlainObject(copy) || (copyIsArray = $.isArray(copy)))) {
  83. if(copyIsArray) {
  84. copyIsArray = false;
  85. clone = src && $.isArray(src) ? src : [];
  86. } else {
  87. clone = src && $.isPlainObject(src) ? src : {};
  88. }
  89. target[name] = $.extend(deep, clone, copy);
  90. } else if(copy !== undefined) {
  91. target[name] = copy;
  92. }
  93. }
  94. }
  95. }
  96. return target;
  97. };
  98. /**
  99. * mui noop(function)
  100. */
  101. $.noop = function() {};
  102. /**
  103. * mui slice(array)
  104. */
  105. $.slice = [].slice;
  106. /**
  107. * mui filter(array)
  108. */
  109. $.filter = [].filter;
  110. $.type = function(obj) {
  111. return obj == null ? String(obj) : class2type[{}.toString.call(obj)] || "object";
  112. };
  113. /**
  114. * mui isArray
  115. */
  116. $.isArray = Array.isArray ||
  117. function(object) {
  118. return object instanceof Array;
  119. };
  120. /**
  121. * mui isArrayLike
  122. * @param {Object} obj
  123. */
  124. $.isArrayLike = function(obj) {
  125. var length = !!obj && "length" in obj && obj.length;
  126. var type = $.type(obj);
  127. if(type === "function" || $.isWindow(obj)) {
  128. return false;
  129. }
  130. return type === "array" || length === 0 ||
  131. typeof length === "number" && length > 0 && (length - 1) in obj;
  132. };
  133. /**
  134. * mui isWindow(需考虑obj为undefined的情况)
  135. */
  136. $.isWindow = function(obj) {
  137. return obj != null && obj === obj.window;
  138. };
  139. /**
  140. * mui isObject
  141. */
  142. $.isObject = function(obj) {
  143. return $.type(obj) === "object";
  144. };
  145. /**
  146. * mui isPlainObject
  147. */
  148. $.isPlainObject = function(obj) {
  149. return $.isObject(obj) && !$.isWindow(obj) && Object.getPrototypeOf(obj) === Object.prototype;
  150. };
  151. /**
  152. * mui isEmptyObject
  153. * @param {Object} o
  154. */
  155. $.isEmptyObject = function(o) {
  156. for(var p in o) {
  157. if(p !== undefined) {
  158. return false;
  159. }
  160. }
  161. return true;
  162. };
  163. /**
  164. * mui isFunction
  165. */
  166. $.isFunction = function(value) {
  167. return $.type(value) === "function";
  168. };
  169. /**
  170. * mui querySelectorAll
  171. * @param {type} selector
  172. * @param {type} context
  173. * @returns {Array}
  174. */
  175. $.qsa = function(selector, context) {
  176. context = context || document;
  177. return $.slice.call(classSelectorRE.test(selector) ? context.getElementsByClassName(RegExp.$1) : tagSelectorRE.test(selector) ? context.getElementsByTagName(selector) : context.querySelectorAll(selector));
  178. };
  179. /**
  180. * ready(DOMContentLoaded)
  181. * @param {type} callback
  182. * @returns {_L6.$}
  183. */
  184. $.ready = function(callback) {
  185. if(readyRE.test(document.readyState)) {
  186. callback($);
  187. } else {
  188. document.addEventListener('DOMContentLoaded', function() {
  189. callback($);
  190. }, false);
  191. }
  192. return this;
  193. };
  194. /**
  195. * 将 fn 缓存一段时间后, 再被调用执行
  196. * 此方法为了避免在 ms 段时间内, 执行 fn 多次. 常用于 resize , scroll , mousemove 等连续性事件中;
  197. * 当 ms 设置为 -1, 表示立即执行 fn, 即和直接调用 fn 一样;
  198. * 调用返回函数的 stop 停止最后一次的 buffer 效果
  199. * @param {Object} fn
  200. * @param {Object} ms
  201. * @param {Object} context
  202. */
  203. $.buffer = function(fn, ms, context) {
  204. var timer;
  205. var lastStart = 0;
  206. var lastEnd = 0;
  207. var ms = ms || 150;
  208. function run() {
  209. if(timer) {
  210. timer.cancel();
  211. timer = 0;
  212. }
  213. lastStart = $.now();
  214. fn.apply(context || this, arguments);
  215. lastEnd = $.now();
  216. }
  217. return $.extend(function() {
  218. if(
  219. (!lastStart) || // 从未运行过
  220. (lastEnd >= lastStart && $.now() - lastEnd > ms) || // 上次运行成功后已经超过ms毫秒
  221. (lastEnd < lastStart && $.now() - lastStart > ms * 8) // 上次运行或未完成,后8*ms毫秒
  222. ) {
  223. run.apply(this, arguments);
  224. } else {
  225. if(timer) {
  226. timer.cancel();
  227. }
  228. timer = $.later(run, ms, null, $.slice.call(arguments));
  229. }
  230. }, {
  231. stop: function() {
  232. if(timer) {
  233. timer.cancel();
  234. timer = 0;
  235. }
  236. }
  237. });
  238. };
  239. /**
  240. * each
  241. * @param {type} elements
  242. * @param {type} callback
  243. * @returns {_L8.$}
  244. */
  245. $.each = function(elements, callback, hasOwnProperty) {
  246. if(!elements) {
  247. return this;
  248. }
  249. if(typeof elements.length === 'number') {
  250. [].every.call(elements, function(el, idx) {
  251. return callback.call(el, idx, el) !== false;
  252. });
  253. } else {
  254. for(var key in elements) {
  255. if(hasOwnProperty) {
  256. if(elements.hasOwnProperty(key)) {
  257. if(callback.call(elements[key], key, elements[key]) === false) return elements;
  258. }
  259. } else {
  260. if(callback.call(elements[key], key, elements[key]) === false) return elements;
  261. }
  262. }
  263. }
  264. return this;
  265. };
  266. $.focus = function(element) {
  267. if($.os.ios) {
  268. setTimeout(function() {
  269. element.focus();
  270. }, 10);
  271. } else {
  272. element.focus();
  273. }
  274. };
  275. /**
  276. * trigger event
  277. * @param {type} element
  278. * @param {type} eventType
  279. * @param {type} eventData
  280. * @returns {_L8.$}
  281. */
  282. $.trigger = function(element, eventType, eventData) {
  283. element.dispatchEvent(new CustomEvent(eventType, {
  284. detail: eventData,
  285. bubbles: true,
  286. cancelable: true
  287. }));
  288. return this;
  289. };
  290. /**
  291. * getStyles
  292. * @param {type} element
  293. * @param {type} property
  294. * @returns {styles}
  295. */
  296. $.getStyles = function(element, property) {
  297. var styles = element.ownerDocument.defaultView.getComputedStyle(element, null);
  298. if(property) {
  299. return styles.getPropertyValue(property) || styles[property];
  300. }
  301. return styles;
  302. };
  303. /**
  304. * parseTranslate
  305. * @param {type} translateString
  306. * @param {type} position
  307. * @returns {Object}
  308. */
  309. $.parseTranslate = function(translateString, position) {
  310. var result = translateString.match(translateRE || '');
  311. if(!result || !result[1]) {
  312. result = ['', '0,0,0'];
  313. }
  314. result = result[1].split(",");
  315. result = {
  316. x: parseFloat(result[0]),
  317. y: parseFloat(result[1]),
  318. z: parseFloat(result[2])
  319. };
  320. if(position && result.hasOwnProperty(position)) {
  321. return result[position];
  322. }
  323. return result;
  324. };
  325. /**
  326. * parseTranslateMatrix
  327. * @param {type} translateString
  328. * @param {type} position
  329. * @returns {Object}
  330. */
  331. $.parseTranslateMatrix = function(translateString, position) {
  332. var matrix = translateString.match(translateMatrixRE);
  333. var is3D = matrix && matrix[1];
  334. if(matrix) {
  335. matrix = matrix[2].split(",");
  336. if(is3D === "3d")
  337. matrix = matrix.slice(12, 15);
  338. else {
  339. matrix.push(0);
  340. matrix = matrix.slice(4, 7);
  341. }
  342. } else {
  343. matrix = [0, 0, 0];
  344. }
  345. var result = {
  346. x: parseFloat(matrix[0]),
  347. y: parseFloat(matrix[1]),
  348. z: parseFloat(matrix[2])
  349. };
  350. if(position && result.hasOwnProperty(position)) {
  351. return result[position];
  352. }
  353. return result;
  354. };
  355. $.hooks = {};
  356. $.addAction = function(type, hook) {
  357. var hooks = $.hooks[type];
  358. if(!hooks) {
  359. hooks = [];
  360. }
  361. hook.index = hook.index || 1000;
  362. hooks.push(hook);
  363. hooks.sort(function(a, b) {
  364. return a.index - b.index;
  365. });
  366. $.hooks[type] = hooks;
  367. return $.hooks[type];
  368. };
  369. $.doAction = function(type, callback) {
  370. if($.isFunction(callback)) { //指定了callback
  371. $.each($.hooks[type], callback);
  372. } else { //未指定callback,直接执行
  373. $.each($.hooks[type], function(index, hook) {
  374. return !hook.handle();
  375. });
  376. }
  377. };
  378. /**
  379. * setTimeout封装
  380. * @param {Object} fn
  381. * @param {Object} when
  382. * @param {Object} context
  383. * @param {Object} data
  384. */
  385. $.later = function(fn, when, context, data) {
  386. when = when || 0;
  387. var m = fn;
  388. var d = data;
  389. var f;
  390. var r;
  391. if(typeof fn === 'string') {
  392. m = context[fn];
  393. }
  394. f = function() {
  395. m.apply(context, $.isArray(d) ? d : [d]);
  396. };
  397. r = setTimeout(f, when);
  398. return {
  399. id: r,
  400. cancel: function() {
  401. clearTimeout(r);
  402. }
  403. };
  404. };
  405. $.now = Date.now || function() {
  406. return +new Date();
  407. };
  408. var class2type = {};
  409. $.each(['Boolean', 'Number', 'String', 'Function', 'Array', 'Date', 'RegExp', 'Object', 'Error'], function(i, name) {
  410. class2type["[object " + name + "]"] = name.toLowerCase();
  411. });
  412. if(window.JSON) {
  413. $.parseJSON = JSON.parse;
  414. }
  415. /**
  416. * $.fn
  417. */
  418. $.fn = {
  419. each: function(callback) {
  420. [].every.call(this, function(el, idx) {
  421. return callback.call(el, idx, el) !== false;
  422. });
  423. return this;
  424. }
  425. };
  426. /**
  427. * 兼容 AMD 模块
  428. **/
  429. if(typeof define === 'function' && define.amd) {
  430. define('mui', [], function() {
  431. return $;
  432. });
  433. }
  434. return $;
  435. })(document);
  436. module.exports = {
  437. install: function(Vue) {
  438. window.mui = mui;
  439. Vue.prototype.$mui = mui
  440. }
  441. };
  442. //window.mui = mui;
  443. //'$' in window || (window.$ = mui);
  444. /**
  445. * $.os
  446. * @param {type} $
  447. * @returns {undefined}
  448. */
  449. (function($, window) {
  450. function detect(ua) {
  451. this.os = {};
  452. var funcs = [
  453. function() { //wechat
  454. var wechat = ua.match(/(MicroMessenger)\/([\d\.]+)/i);
  455. if(wechat) { //wechat
  456. this.os.wechat = {
  457. version: wechat[2].replace(/_/g, '.')
  458. };
  459. }
  460. return false;
  461. },
  462. function() { //android
  463. var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
  464. if(android) {
  465. this.os.android = true;
  466. this.os.version = android[2];
  467. this.os.isBadAndroid = !(/Chrome\/\d/.test(window.navigator.appVersion));
  468. }
  469. return this.os.android === true;
  470. },
  471. function() { //ios
  472. var iphone = ua.match(/(iPhone\sOS)\s([\d_]+)/);
  473. if(iphone) { //iphone
  474. this.os.ios = this.os.iphone = true;
  475. this.os.version = iphone[2].replace(/_/g, '.');
  476. } else {
  477. var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
  478. if(ipad) { //ipad
  479. this.os.ios = this.os.ipad = true;
  480. this.os.version = ipad[2].replace(/_/g, '.');
  481. }
  482. }
  483. return this.os.ios === true;
  484. }
  485. ];
  486. [].every.call(funcs, function(func) {
  487. return !func.call($);
  488. });
  489. }
  490. detect.call($, navigator.userAgent);
  491. })(mui, window);
  492. /**
  493. * $.os.plus
  494. * @param {type} $
  495. * @returns {undefined}
  496. */
  497. (function($, document) {
  498. function detect(ua) {
  499. this.os = this.os || {};
  500. var plus = ua.match(/Html5Plus/i); //TODO 5\+Browser?
  501. if(plus) {
  502. this.os.plus = true;
  503. $(function() {
  504. document.body.classList.add('mui-plus');
  505. });
  506. if(ua.match(/StreamApp/i)) { //TODO 最好有流应用自己的标识
  507. this.os.stream = true;
  508. $(function() {
  509. document.body.classList.add('mui-plus-stream');
  510. });
  511. }
  512. }
  513. }
  514. detect.call($, navigator.userAgent);
  515. })(mui, document);
  516. /**
  517. * 仅提供简单的on,off(仅支持事件委托,不支持当前元素绑定,当前元素绑定请直接使用addEventListener,removeEventListener)
  518. * @param {Object} $
  519. */
  520. (function($) {
  521. if('ontouchstart' in window) {
  522. $.isTouchable = true;
  523. $.EVENT_START = 'touchstart';
  524. $.EVENT_MOVE = 'touchmove';
  525. $.EVENT_END = 'touchend';
  526. } else {
  527. $.isTouchable = false;
  528. $.EVENT_START = 'mousedown';
  529. $.EVENT_MOVE = 'mousemove';
  530. $.EVENT_END = 'mouseup';
  531. }
  532. $.EVENT_CANCEL = 'touchcancel';
  533. $.EVENT_CLICK = 'click';
  534. var _mid = 1;
  535. var delegates = {};
  536. //需要wrap的函数
  537. var eventMethods = {
  538. preventDefault: 'isDefaultPrevented',
  539. stopImmediatePropagation: 'isImmediatePropagationStopped',
  540. stopPropagation: 'isPropagationStopped'
  541. };
  542. //默认true返回函数
  543. var returnTrue = function() {
  544. return true
  545. };
  546. //默认false返回函数
  547. var returnFalse = function() {
  548. return false
  549. };
  550. //wrap浏览器事件
  551. var compatible = function(event, target) {
  552. if(!event.detail) {
  553. event.detail = {
  554. currentTarget: target
  555. };
  556. } else {
  557. event.detail.currentTarget = target;
  558. }
  559. $.each(eventMethods, function(name, predicate) {
  560. var sourceMethod = event[name];
  561. event[name] = function() {
  562. this[predicate] = returnTrue;
  563. return sourceMethod && sourceMethod.apply(event, arguments)
  564. }
  565. event[predicate] = returnFalse;
  566. }, true);
  567. return event;
  568. };
  569. //简单的wrap对象_mid
  570. var mid = function(obj) {
  571. return obj && (obj._mid || (obj._mid = _mid++));
  572. };
  573. //事件委托对象绑定的事件回调列表
  574. var delegateFns = {};
  575. //返回事件委托的wrap事件回调
  576. var delegateFn = function(element, event, selector, callback) {
  577. return function(e) {
  578. //same event
  579. var callbackObjs = delegates[element._mid][event];
  580. var handlerQueue = [];
  581. var target = e.target;
  582. var selectorAlls = {};
  583. for(; target && target !== document; target = target.parentNode) {
  584. if(target === element) {
  585. break;
  586. }
  587. if(~['click', 'tap', 'doubletap', 'longtap', 'hold'].indexOf(event) && (target.disabled || target.classList.contains('mui-disabled'))) {
  588. break;
  589. }
  590. var matches = {};
  591. $.each(callbackObjs, function(selector, callbacks) { //same selector
  592. selectorAlls[selector] || (selectorAlls[selector] = $.qsa(selector, element));
  593. if(selectorAlls[selector] && ~(selectorAlls[selector]).indexOf(target)) {
  594. if(!matches[selector]) {
  595. matches[selector] = callbacks;
  596. }
  597. }
  598. }, true);
  599. if(!$.isEmptyObject(matches)) {
  600. handlerQueue.push({
  601. element: target,
  602. handlers: matches
  603. });
  604. }
  605. }
  606. selectorAlls = null;
  607. e = compatible(e); //compatible event
  608. $.each(handlerQueue, function(index, handler) {
  609. target = handler.element;
  610. var tagName = target.tagName;
  611. if(event === 'tap' && (tagName !== 'INPUT' && tagName !== 'TEXTAREA' && tagName !== 'SELECT')) {
  612. e.preventDefault();
  613. e.detail && e.detail.gesture && e.detail.gesture.preventDefault();
  614. }
  615. $.each(handler.handlers, function(index, handler) {
  616. $.each(handler, function(index, callback) {
  617. if(callback.call(target, e) === false) {
  618. e.preventDefault();
  619. e.stopPropagation();
  620. }
  621. }, true);
  622. }, true)
  623. if(e.isPropagationStopped()) {
  624. return false;
  625. }
  626. }, true);
  627. };
  628. };
  629. var findDelegateFn = function(element, event) {
  630. var delegateCallbacks = delegateFns[mid(element)];
  631. var result = [];
  632. if(delegateCallbacks) {
  633. result = [];
  634. if(event) {
  635. var filterFn = function(fn) {
  636. return fn.type === event;
  637. }
  638. return delegateCallbacks.filter(filterFn);
  639. } else {
  640. result = delegateCallbacks;
  641. }
  642. }
  643. return result;
  644. };
  645. var preventDefaultException = /^(INPUT|TEXTAREA|BUTTON|SELECT)$/;
  646. /**
  647. * mui delegate events
  648. * @param {type} event
  649. * @param {type} selector
  650. * @param {type} callback
  651. * @returns {undefined}
  652. */
  653. $.fn.on = function(event, selector, callback) { //仅支持简单的事件委托,主要是tap事件使用,类似mouse,focus之类暂不封装支持
  654. return this.each(function() {
  655. var element = this;
  656. mid(element);
  657. mid(callback);
  658. var isAddEventListener = false;
  659. var delegateEvents = delegates[element._mid] || (delegates[element._mid] = {});
  660. var delegateCallbackObjs = delegateEvents[event] || ((delegateEvents[event] = {}));
  661. if($.isEmptyObject(delegateCallbackObjs)) {
  662. isAddEventListener = true;
  663. }
  664. var delegateCallbacks = delegateCallbackObjs[selector] || (delegateCallbackObjs[selector] = []);
  665. delegateCallbacks.push(callback);
  666. if(isAddEventListener) {
  667. var delegateFnArray = delegateFns[mid(element)];
  668. if(!delegateFnArray) {
  669. delegateFnArray = [];
  670. }
  671. var delegateCallback = delegateFn(element, event, selector, callback);
  672. delegateFnArray.push(delegateCallback);
  673. delegateCallback.i = delegateFnArray.length - 1;
  674. delegateCallback.type = event;
  675. delegateFns[mid(element)] = delegateFnArray;
  676. element.addEventListener(event, delegateCallback);
  677. if(event === 'tap') { //TODO 需要找个更好的解决方案
  678. element.addEventListener('click', function(e) {
  679. if(e.target) {
  680. var tagName = e.target.tagName;
  681. if(!preventDefaultException.test(tagName)) {
  682. if(tagName === 'A') {
  683. var href = e.target.href;
  684. if(!(href && ~href.indexOf('tel:'))) {
  685. e.preventDefault();
  686. }
  687. } else {
  688. e.preventDefault();
  689. }
  690. }
  691. }
  692. });
  693. }
  694. }
  695. });
  696. };
  697. $.fn.off = function(event, selector, callback) {
  698. return this.each(function() {
  699. var _mid = mid(this);
  700. if(!event) { //mui(selector).off();
  701. delegates[_mid] && delete delegates[_mid];
  702. } else if(!selector) { //mui(selector).off(event);
  703. delegates[_mid] && delete delegates[_mid][event];
  704. } else if(!callback) { //mui(selector).off(event,selector);
  705. delegates[_mid] && delegates[_mid][event] && delete delegates[_mid][event][selector];
  706. } else { //mui(selector).off(event,selector,callback);
  707. var delegateCallbacks = delegates[_mid] && delegates[_mid][event] && delegates[_mid][event][selector];
  708. $.each(delegateCallbacks, function(index, delegateCallback) {
  709. if(mid(delegateCallback) === mid(callback)) {
  710. delegateCallbacks.splice(index, 1);
  711. return false;
  712. }
  713. }, true);
  714. }
  715. if(delegates[_mid]) {
  716. //如果off掉了所有当前element的指定的event事件,则remove掉当前element的delegate回调
  717. if((!delegates[_mid][event] || $.isEmptyObject(delegates[_mid][event]))) {
  718. findDelegateFn(this, event).forEach(function(fn) {
  719. this.removeEventListener(fn.type, fn);
  720. delete delegateFns[_mid][fn.i];
  721. }.bind(this));
  722. }
  723. } else {
  724. //如果delegates[_mid]已不存在,删除所有
  725. findDelegateFn(this).forEach(function(fn) {
  726. this.removeEventListener(fn.type, fn);
  727. delete delegateFns[_mid][fn.i];
  728. }.bind(this));
  729. }
  730. });
  731. };
  732. })(mui);
  733. /**
  734. * mui target(action>popover>modal>tab>toggle)
  735. */
  736. (function($, window, document) {
  737. /**
  738. * targets
  739. */
  740. $.targets = {};
  741. /**
  742. * target handles
  743. */
  744. $.targetHandles = [];
  745. /**
  746. * register target
  747. * @param {type} target
  748. * @returns {$.targets}
  749. */
  750. $.registerTarget = function(target) {
  751. target.index = target.index || 1000;
  752. $.targetHandles.push(target);
  753. $.targetHandles.sort(function(a, b) {
  754. return a.index - b.index;
  755. });
  756. return $.targetHandles;
  757. };
  758. window.addEventListener($.EVENT_START, function(event) {
  759. var target = event.target;
  760. var founds = {};
  761. for(; target && target !== document; target = target.parentNode) {
  762. var isFound = false;
  763. $.each($.targetHandles, function(index, targetHandle) {
  764. var name = targetHandle.name;
  765. if(!isFound && !founds[name] && targetHandle.hasOwnProperty('handle')) {
  766. $.targets[name] = targetHandle.handle(event, target);
  767. if($.targets[name]) {
  768. founds[name] = true;
  769. if(targetHandle.isContinue !== true) {
  770. isFound = true;
  771. }
  772. }
  773. } else {
  774. if(!founds[name]) {
  775. if(targetHandle.isReset !== false)
  776. $.targets[name] = false;
  777. }
  778. }
  779. });
  780. if(isFound) {
  781. break;
  782. }
  783. }
  784. });
  785. window.addEventListener('click', function(event) { //解决touch与click的target不一致的问题(比如链接边缘点击时,touch的target为html,而click的target为A)
  786. var target = event.target;
  787. var isFound = false;
  788. for(; target && target !== document; target = target.parentNode) {
  789. if(target.tagName === 'A') {
  790. $.each($.targetHandles, function(index, targetHandle) {
  791. var name = targetHandle.name;
  792. if(targetHandle.hasOwnProperty('handle')) {
  793. if(targetHandle.handle(event, target)) {
  794. isFound = true;
  795. event.preventDefault();
  796. return false;
  797. }
  798. }
  799. });
  800. if(isFound) {
  801. break;
  802. }
  803. }
  804. }
  805. });
  806. })(mui, window, document);
  807. /**
  808. * fixed trim
  809. * @param {type} undefined
  810. * @returns {undefined}
  811. */
  812. (function(undefined) {
  813. if(String.prototype.trim === undefined) { // fix for iOS 3.2
  814. String.prototype.trim = function() {
  815. return this.replace(/^\s+|\s+$/g, '');
  816. };
  817. }
  818. Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) {
  819. obj['__proto__'] = proto;
  820. return obj;
  821. };
  822. })();
  823. /**
  824. * fixed CustomEvent
  825. */
  826. (function() {
  827. if(typeof window.CustomEvent === 'undefined') {
  828. function CustomEvent(event, params) {
  829. params = params || {
  830. bubbles: false,
  831. cancelable: false,
  832. detail: undefined
  833. };
  834. var evt = document.createEvent('Events');
  835. var bubbles = true;
  836. for(var name in params) {
  837. (name === 'bubbles') ? (bubbles = !!params[name]) : (evt[name] = params[name]);
  838. }
  839. evt.initEvent(event, bubbles, true);
  840. return evt;
  841. };
  842. CustomEvent.prototype = window.Event.prototype;
  843. window.CustomEvent = CustomEvent;
  844. }
  845. })();
  846. /*
  847. A shim for non ES5 supporting browsers.
  848. Adds function bind to Function prototype, so that you can do partial application.
  849. Works even with the nasty thing, where the first word is the opposite of extranet, the second one is the profession of Columbus, and the version number is 9, flipped 180 degrees.
  850. */
  851. Function.prototype.bind = Function.prototype.bind || function(to) {
  852. // Make an array of our arguments, starting from second argument
  853. var partial = Array.prototype.splice.call(arguments, 1),
  854. // We'll need the original function.
  855. fn = this;
  856. var bound = function() {
  857. // Join the already applied arguments to the now called ones (after converting to an array again).
  858. var args = partial.concat(Array.prototype.splice.call(arguments, 0));
  859. // If not being called as a constructor
  860. if(!(this instanceof bound)) {
  861. // return the result of the function called bound to target and partially applied.
  862. return fn.apply(to, args);
  863. }
  864. // If being called as a constructor, apply the function bound to self.
  865. fn.apply(this, args);
  866. }
  867. // Attach the prototype of the function to our newly created function.
  868. bound.prototype = fn.prototype;
  869. return bound;
  870. };
  871. /**
  872. * mui fixed classList
  873. * @param {type} document
  874. * @returns {undefined}
  875. */
  876. (function(document) {
  877. if(!("classList" in document.documentElement) && Object.defineProperty && typeof HTMLElement !== 'undefined') {
  878. Object.defineProperty(HTMLElement.prototype, 'classList', {
  879. get: function() {
  880. var self = this;
  881. function update(fn) {
  882. return function(value) {
  883. var classes = self.className.split(/\s+/),
  884. index = classes.indexOf(value);
  885. fn(classes, index, value);
  886. self.className = classes.join(" ");
  887. };
  888. }
  889. var ret = {
  890. add: update(function(classes, index, value) {
  891. ~index || classes.push(value);
  892. }),
  893. remove: update(function(classes, index) {
  894. ~index && classes.splice(index, 1);
  895. }),
  896. toggle: update(function(classes, index, value) {
  897. ~index ? classes.splice(index, 1) : classes.push(value);
  898. }),
  899. contains: function(value) {
  900. return !!~self.className.split(/\s+/).indexOf(value);
  901. },
  902. item: function(i) {
  903. return self.className.split(/\s+/)[i] || null;
  904. }
  905. };
  906. Object.defineProperty(ret, 'length', {
  907. get: function() {
  908. return self.className.split(/\s+/).length;
  909. }
  910. });
  911. return ret;
  912. }
  913. });
  914. }
  915. })(document);
  916. /**
  917. * mui fixed requestAnimationFrame
  918. * @param {type} window
  919. * @returns {undefined}
  920. */
  921. (function(window) {
  922. if(!window.requestAnimationFrame) {
  923. var lastTime = 0;
  924. window.requestAnimationFrame = window.webkitRequestAnimationFrame || function(callback, element) {
  925. var currTime = new Date().getTime();
  926. var timeToCall = Math.max(0, 16.7 - (currTime - lastTime));
  927. var id = window.setTimeout(function() {
  928. callback(currTime + timeToCall);
  929. }, timeToCall);
  930. lastTime = currTime + timeToCall;
  931. return id;
  932. };
  933. window.cancelAnimationFrame = window.webkitCancelAnimationFrame || window.webkitCancelRequestAnimationFrame || function(id) {
  934. clearTimeout(id);
  935. };
  936. };
  937. }(window));
  938. /**
  939. * fastclick(only for radio,checkbox)
  940. */
  941. (function($, window, name) {
  942. if(!$.os.android && !$.os.ios) { //目前仅识别android和ios
  943. return;
  944. }
  945. if(window.FastClick) {
  946. return;
  947. }
  948. var handle = function(event, target) {
  949. if(target.tagName === 'LABEL') {
  950. if(target.parentNode) {
  951. target = target.parentNode.querySelector('input');
  952. }
  953. }
  954. if(target && (target.type === 'radio' || target.type === 'checkbox')) {
  955. if(!target.disabled) { //disabled
  956. return target;
  957. }
  958. }
  959. return false;
  960. };
  961. $.registerTarget({
  962. name: name,
  963. index: 40,
  964. handle: handle,
  965. target: false
  966. });
  967. var dispatchEvent = function(event) {
  968. var targetElement = $.targets.click;
  969. if(targetElement) {
  970. var clickEvent, touch;
  971. // On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect
  972. if(document.activeElement && document.activeElement !== targetElement) {
  973. document.activeElement.blur();
  974. }
  975. touch = event.detail.gesture.changedTouches[0];
  976. // Synthesise a click event, with an extra attribute so it can be tracked
  977. clickEvent = document.createEvent('MouseEvents');
  978. clickEvent.initMouseEvent('click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
  979. clickEvent.forwardedTouchEvent = true;
  980. targetElement.dispatchEvent(clickEvent);
  981. event.detail && event.detail.gesture.preventDefault();
  982. }
  983. };
  984. window.addEventListener('tap', dispatchEvent);
  985. window.addEventListener('doubletap', dispatchEvent);
  986. //捕获
  987. window.addEventListener('click', function(event) {
  988. if($.targets.click) {
  989. if(!event.forwardedTouchEvent) { //stop click
  990. if(event.stopImmediatePropagation) {
  991. event.stopImmediatePropagation();
  992. } else {
  993. // Part of the hack for browsers that don't support Event#stopImmediatePropagation
  994. event.propagationStopped = true;
  995. }
  996. event.stopPropagation();
  997. event.preventDefault();
  998. return false;
  999. }
  1000. }
  1001. }, true);
  1002. })(mui, window, 'click');
  1003. (function($, document) {
  1004. $(function() {
  1005. if(!$.os.ios) {
  1006. return;
  1007. }
  1008. var CLASS_FOCUSIN = 'mui-focusin';
  1009. var CLASS_BAR_TAB = 'mui-bar-tab';
  1010. var CLASS_BAR_FOOTER = 'mui-bar-footer';
  1011. var CLASS_BAR_FOOTER_SECONDARY = 'mui-bar-footer-secondary';
  1012. var CLASS_BAR_FOOTER_SECONDARY_TAB = 'mui-bar-footer-secondary-tab';
  1013. // var content = document.querySelector('.' + CLASS_CONTENT);
  1014. // if (content) {
  1015. // document.body.insertBefore(content, document.body.firstElementChild);
  1016. // }
  1017. document.addEventListener('focusin', function(e) {
  1018. if($.os.plus) { //在父webview里边不fix
  1019. if(window.plus) {
  1020. if(plus.webview.currentWebview().children().length > 0) {
  1021. return;
  1022. }
  1023. }
  1024. }
  1025. var target = e.target;
  1026. //TODO 需考虑所有键盘弹起的情况
  1027. if(target.tagName && (target.tagName === 'TEXTAREA' || (target.tagName === 'INPUT' && (target.type === 'text' || target.type === 'search' || target.type === 'number')))) {
  1028. if(target.disabled || target.readOnly) {
  1029. return;
  1030. }
  1031. document.body.classList.add(CLASS_FOCUSIN);
  1032. var isFooter = false;
  1033. for(; target && target !== document; target = target.parentNode) {
  1034. var classList = target.classList;
  1035. if(classList && classList.contains(CLASS_BAR_TAB) || classList.contains(CLASS_BAR_FOOTER) || classList.contains(CLASS_BAR_FOOTER_SECONDARY) || classList.contains(CLASS_BAR_FOOTER_SECONDARY_TAB)) {
  1036. isFooter = true;
  1037. break;
  1038. }
  1039. }
  1040. if(isFooter) {
  1041. var scrollTop = document.body.scrollHeight;
  1042. var scrollLeft = document.body.scrollLeft;
  1043. setTimeout(function() {
  1044. window.scrollTo(scrollLeft, scrollTop);
  1045. }, 20);
  1046. }
  1047. }
  1048. });
  1049. document.addEventListener('focusout', function(e) {
  1050. var classList = document.body.classList;
  1051. if(classList.contains(CLASS_FOCUSIN)) {
  1052. classList.remove(CLASS_FOCUSIN);
  1053. setTimeout(function() {
  1054. window.scrollTo(document.body.scrollLeft, document.body.scrollTop);
  1055. }, 20);
  1056. }
  1057. });
  1058. });
  1059. })(mui, document);
  1060. /**
  1061. * mui namespace(optimization)
  1062. * @param {type} $
  1063. * @returns {undefined}
  1064. */
  1065. (function($) {
  1066. $.namespace = 'mui';
  1067. $.classNamePrefix = $.namespace + '-';
  1068. $.classSelectorPrefix = '.' + $.classNamePrefix;
  1069. /**
  1070. * 返回正确的className
  1071. * @param {type} className
  1072. * @returns {String}
  1073. */
  1074. $.className = function(className) {
  1075. return $.classNamePrefix + className;
  1076. };
  1077. /**
  1078. * 返回正确的classSelector
  1079. * @param {type} classSelector
  1080. * @returns {String}
  1081. */
  1082. $.classSelector = function(classSelector) {
  1083. return classSelector.replace(/\./g, $.classSelectorPrefix);
  1084. };
  1085. /**
  1086. * 返回正确的eventName
  1087. * @param {type} event
  1088. * @param {type} module
  1089. * @returns {String}
  1090. */
  1091. $.eventName = function(event, module) {
  1092. return event + ($.namespace ? ('.' + $.namespace) : '') + (module ? ('.' + module) : '');
  1093. };
  1094. })(mui);
  1095. /**
  1096. * mui gestures
  1097. * @param {type} $
  1098. * @param {type} window
  1099. * @returns {undefined}
  1100. */
  1101. (function($, window) {
  1102. $.gestures = {
  1103. session: {}
  1104. };
  1105. /**
  1106. * Gesture preventDefault
  1107. * @param {type} e
  1108. * @returns {undefined}
  1109. */
  1110. $.preventDefault = function(e) {
  1111. e.preventDefault();
  1112. };
  1113. /**
  1114. * Gesture stopPropagation
  1115. * @param {type} e
  1116. * @returns {undefined}
  1117. */
  1118. $.stopPropagation = function(e) {
  1119. e.stopPropagation();
  1120. };
  1121. /**
  1122. * register gesture
  1123. * @param {type} gesture
  1124. * @returns {$.gestures}
  1125. */
  1126. $.addGesture = function(gesture) {
  1127. return $.addAction('gestures', gesture);
  1128. };
  1129. var round = Math.round;
  1130. var abs = Math.abs;
  1131. var sqrt = Math.sqrt;
  1132. var atan = Math.atan;
  1133. var atan2 = Math.atan2;
  1134. /**
  1135. * distance
  1136. * @param {type} p1
  1137. * @param {type} p2
  1138. * @returns {Number}
  1139. */
  1140. var getDistance = function(p1, p2, props) {
  1141. if(!props) {
  1142. props = ['x', 'y'];
  1143. }
  1144. var x = p2[props[0]] - p1[props[0]];
  1145. var y = p2[props[1]] - p1[props[1]];
  1146. return sqrt((x * x) + (y * y));
  1147. };
  1148. /**
  1149. * scale
  1150. * @param {Object} starts
  1151. * @param {Object} moves
  1152. */
  1153. var getScale = function(starts, moves) {
  1154. if(starts.length >= 2 && moves.length >= 2) {
  1155. var props = ['pageX', 'pageY'];
  1156. return getDistance(moves[1], moves[0], props) / getDistance(starts[1], starts[0], props);
  1157. }
  1158. return 1;
  1159. };
  1160. /**
  1161. * angle
  1162. * @param {type} p1
  1163. * @param {type} p2
  1164. * @returns {Number}
  1165. */
  1166. var getAngle = function(p1, p2, props) {
  1167. if(!props) {
  1168. props = ['x', 'y'];
  1169. }
  1170. var x = p2[props[0]] - p1[props[0]];
  1171. var y = p2[props[1]] - p1[props[1]];
  1172. return atan2(y, x) * 180 / Math.PI;
  1173. };
  1174. /**
  1175. * direction
  1176. * @param {Object} x
  1177. * @param {Object} y
  1178. */
  1179. var getDirection = function(x, y) {
  1180. if(x === y) {
  1181. return '';
  1182. }
  1183. if(abs(x) >= abs(y)) {
  1184. return x > 0 ? 'left' : 'right';
  1185. }
  1186. return y > 0 ? 'up' : 'down';
  1187. };
  1188. /**
  1189. * rotation
  1190. * @param {Object} start
  1191. * @param {Object} end
  1192. */
  1193. var getRotation = function(start, end) {
  1194. var props = ['pageX', 'pageY'];
  1195. return getAngle(end[1], end[0], props) - getAngle(start[1], start[0], props);
  1196. };
  1197. /**
  1198. * px per ms
  1199. * @param {Object} deltaTime
  1200. * @param {Object} x
  1201. * @param {Object} y
  1202. */
  1203. var getVelocity = function(deltaTime, x, y) {
  1204. return {
  1205. x: x / deltaTime || 0,
  1206. y: y / deltaTime || 0
  1207. };
  1208. };
  1209. /**
  1210. * detect gestures
  1211. * @param {type} event
  1212. * @param {type} touch
  1213. * @returns {undefined}
  1214. */
  1215. var detect = function(event, touch) {
  1216. if($.gestures.stoped) {
  1217. return;
  1218. }
  1219. $.doAction('gestures', function(index, gesture) {
  1220. if(!$.gestures.stoped) {
  1221. if($.options.gestureConfig[gesture.name] !== false) {
  1222. gesture.handle(event, touch);
  1223. }
  1224. }
  1225. });
  1226. };
  1227. /**
  1228. * 暂时无用
  1229. * @param {Object} node
  1230. * @param {Object} parent
  1231. */
  1232. var hasParent = function(node, parent) {
  1233. while(node) {
  1234. if(node == parent) {
  1235. return true;
  1236. }
  1237. node = node.parentNode;
  1238. }
  1239. return false;
  1240. };
  1241. var uniqueArray = function(src, key, sort) {
  1242. var results = [];
  1243. var values = [];
  1244. var i = 0;
  1245. while(i < src.length) {
  1246. var val = key ? src[i][key] : src[i];
  1247. if(values.indexOf(val) < 0) {
  1248. results.push(src[i]);
  1249. }
  1250. values[i] = val;
  1251. i++;
  1252. }
  1253. if(sort) {
  1254. if(!key) {
  1255. results = results.sort();
  1256. } else {
  1257. results = results.sort(function sortUniqueArray(a, b) {
  1258. return a[key] > b[key];
  1259. });
  1260. }
  1261. }
  1262. return results;
  1263. };
  1264. var getMultiCenter = function(touches) {
  1265. var touchesLength = touches.length;
  1266. if(touchesLength === 1) {
  1267. return {
  1268. x: round(touches[0].pageX),
  1269. y: round(touches[0].pageY)
  1270. };
  1271. }
  1272. var x = 0;
  1273. var y = 0;
  1274. var i = 0;
  1275. while(i < touchesLength) {
  1276. x += touches[i].pageX;
  1277. y += touches[i].pageY;
  1278. i++;
  1279. }
  1280. return {
  1281. x: round(x / touchesLength),
  1282. y: round(y / touchesLength)
  1283. };
  1284. };
  1285. var multiTouch = function() {
  1286. return $.options.gestureConfig.pinch;
  1287. };
  1288. var copySimpleTouchData = function(touch) {
  1289. var touches = [];
  1290. var i = 0;
  1291. while(i < touch.touches.length) {
  1292. touches[i] = {
  1293. pageX: round(touch.touches[i].pageX),
  1294. pageY: round(touch.touches[i].pageY)
  1295. };
  1296. i++;
  1297. }
  1298. return {
  1299. timestamp: $.now(),
  1300. gesture: touch.gesture,
  1301. touches: touches,
  1302. center: getMultiCenter(touch.touches),
  1303. deltaX: touch.deltaX,
  1304. deltaY: touch.deltaY
  1305. };
  1306. };
  1307. var calDelta = function(touch) {
  1308. var session = $.gestures.session;
  1309. var center = touch.center;
  1310. var offset = session.offsetDelta || {};
  1311. var prevDelta = session.prevDelta || {};
  1312. var prevTouch = session.prevTouch || {};
  1313. if(touch.gesture.type === $.EVENT_START || touch.gesture.type === $.EVENT_END) {
  1314. prevDelta = session.prevDelta = {
  1315. x: prevTouch.deltaX || 0,
  1316. y: prevTouch.deltaY || 0
  1317. };
  1318. offset = session.offsetDelta = {
  1319. x: center.x,
  1320. y: center.y
  1321. };
  1322. }
  1323. touch.deltaX = prevDelta.x + (center.x - offset.x);
  1324. touch.deltaY = prevDelta.y + (center.y - offset.y);
  1325. };
  1326. var calTouchData = function(touch) {
  1327. var session = $.gestures.session;
  1328. var touches = touch.touches;
  1329. var touchesLength = touches.length;
  1330. if(!session.firstTouch) {
  1331. session.firstTouch = copySimpleTouchData(touch);
  1332. }
  1333. if(multiTouch() && touchesLength > 1 && !session.firstMultiTouch) {
  1334. session.firstMultiTouch = copySimpleTouchData(touch);
  1335. } else if(touchesLength === 1) {
  1336. session.firstMultiTouch = false;
  1337. }
  1338. var firstTouch = session.firstTouch;
  1339. var firstMultiTouch = session.firstMultiTouch;
  1340. var offsetCenter = firstMultiTouch ? firstMultiTouch.center : firstTouch.center;
  1341. var center = touch.center = getMultiCenter(touches);
  1342. touch.timestamp = $.now();
  1343. touch.deltaTime = touch.timestamp - firstTouch.timestamp;
  1344. touch.angle = getAngle(offsetCenter, center);
  1345. touch.distance = getDistance(offsetCenter, center);
  1346. calDelta(touch);
  1347. touch.offsetDirection = getDirection(touch.deltaX, touch.deltaY);
  1348. touch.scale = firstMultiTouch ? getScale(firstMultiTouch.touches, touches) : 1;
  1349. touch.rotation = firstMultiTouch ? getRotation(firstMultiTouch.touches, touches) : 0;
  1350. calIntervalTouchData(touch);
  1351. };
  1352. var CAL_INTERVAL = 25;
  1353. var calIntervalTouchData = function(touch) {
  1354. var session = $.gestures.session;
  1355. var last = session.lastInterval || touch;
  1356. var deltaTime = touch.timestamp - last.timestamp;
  1357. var velocity;
  1358. var velocityX;
  1359. var velocityY;
  1360. var direction;
  1361. if(touch.gesture.type != $.EVENT_CANCEL && (deltaTime > CAL_INTERVAL || last.velocity === undefined)) {
  1362. var deltaX = last.deltaX - touch.deltaX;
  1363. var deltaY = last.deltaY - touch.deltaY;
  1364. var v = getVelocity(deltaTime, deltaX, deltaY);
  1365. velocityX = v.x;
  1366. velocityY = v.y;
  1367. velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;
  1368. direction = getDirection(deltaX, deltaY) || last.direction;
  1369. session.lastInterval = touch;
  1370. } else {
  1371. velocity = last.velocity;
  1372. velocityX = last.velocityX;
  1373. velocityY = last.velocityY;
  1374. direction = last.direction;
  1375. }
  1376. touch.velocity = velocity;
  1377. touch.velocityX = velocityX;
  1378. touch.velocityY = velocityY;
  1379. touch.direction = direction;
  1380. };
  1381. var targetIds = {};
  1382. var convertTouches = function(touches) {
  1383. for(var i = 0; i < touches.length; i++) {
  1384. !touches['identifier'] && (touches['identifier'] = 0);
  1385. }
  1386. return touches;
  1387. };
  1388. var getTouches = function(event, touch) {
  1389. var allTouches = convertTouches($.slice.call(event.touches || [event]));
  1390. var type = event.type;
  1391. var targetTouches = [];
  1392. var changedTargetTouches = [];
  1393. //当touchstart或touchmove且touches长度为1,直接获得all和changed
  1394. if((type === $.EVENT_START || type === $.EVENT_MOVE) && allTouches.length === 1) {
  1395. targetIds[allTouches[0].identifier] = true;
  1396. targetTouches = allTouches;
  1397. changedTargetTouches = allTouches;
  1398. touch.target = event.target;
  1399. } else {
  1400. var i = 0;
  1401. var targetTouches = [];
  1402. var changedTargetTouches = [];
  1403. var changedTouches = convertTouches($.slice.call(event.changedTouches || [event]));
  1404. touch.target = event.target;
  1405. var sessionTarget = $.gestures.session.target || event.target;
  1406. targetTouches = allTouches.filter(function(touch) {
  1407. return hasParent(touch.target, sessionTarget);
  1408. });
  1409. if(type === $.EVENT_START) {
  1410. i = 0;
  1411. while(i < targetTouches.length) {
  1412. targetIds[targetTouches[i].identifier] = true;
  1413. i++;
  1414. }
  1415. }
  1416. i = 0;
  1417. while(i < changedTouches.length) {
  1418. if(targetIds[changedTouches[i].identifier]) {
  1419. changedTargetTouches.push(changedTouches[i]);
  1420. }
  1421. if(type === $.EVENT_END || type === $.EVENT_CANCEL) {
  1422. delete targetIds[changedTouches[i].identifier];
  1423. }
  1424. i++;
  1425. }
  1426. if(!changedTargetTouches.length) {
  1427. return false;
  1428. }
  1429. }
  1430. targetTouches = uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true);
  1431. var touchesLength = targetTouches.length;
  1432. var changedTouchesLength = changedTargetTouches.length;
  1433. if(type === $.EVENT_START && touchesLength - changedTouchesLength === 0) { //first
  1434. touch.isFirst = true;
  1435. $.gestures.touch = $.gestures.session = {
  1436. target: event.target
  1437. };
  1438. }
  1439. touch.isFinal = ((type === $.EVENT_END || type === $.EVENT_CANCEL) && (touchesLength - changedTouchesLength === 0));
  1440. touch.touches = targetTouches;
  1441. touch.changedTouches = changedTargetTouches;
  1442. return true;
  1443. };
  1444. var handleTouchEvent = function(event) {
  1445. var touch = {
  1446. gesture: event
  1447. };
  1448. var touches = getTouches(event, touch);
  1449. if(!touches) {
  1450. return;
  1451. }
  1452. calTouchData(touch);
  1453. detect(event, touch);
  1454. $.gestures.session.prevTouch = touch;
  1455. if(event.type === $.EVENT_END && !$.isTouchable) {
  1456. $.gestures.touch = $.gestures.session = {};
  1457. }
  1458. };
  1459. window.addEventListener($.EVENT_START, handleTouchEvent);
  1460. window.addEventListener($.EVENT_MOVE, handleTouchEvent);
  1461. window.addEventListener($.EVENT_END, handleTouchEvent);
  1462. window.addEventListener($.EVENT_CANCEL, handleTouchEvent);
  1463. //fixed hashchange(android)
  1464. window.addEventListener($.EVENT_CLICK, function(e) {
  1465. //TODO 应该判断当前target是不是在targets.popover内部,而不是非要相等
  1466. if(($.os.android || $.os.ios) && (($.targets.popover && e.target === $.targets.popover) || ($.targets.tab) || $.targets.offcanvas || $.targets.modal)) {
  1467. e.preventDefault();
  1468. }
  1469. }, true);
  1470. //增加原生滚动识别
  1471. $.isScrolling = false;
  1472. var scrollingTimeout = null;
  1473. window.addEventListener('scroll', function() {
  1474. $.isScrolling = true;
  1475. scrollingTimeout && clearTimeout(scrollingTimeout);
  1476. scrollingTimeout = setTimeout(function() {
  1477. $.isScrolling = false;
  1478. }, 250);
  1479. });
  1480. })(mui, window);
  1481. /**
  1482. * mui gesture flick[left|right|up|down]
  1483. * @param {type} $
  1484. * @param {type} name
  1485. * @returns {undefined}
  1486. */
  1487. (function($, name) {
  1488. var flickStartTime = 0;
  1489. var handle = function(event, touch) {
  1490. var session = $.gestures.session;
  1491. var options = this.options;
  1492. var now = $.now();
  1493. switch(event.type) {
  1494. case $.EVENT_MOVE:
  1495. if(now - flickStartTime > 300) {
  1496. flickStartTime = now;
  1497. session.flickStart = touch.center;
  1498. }
  1499. break;
  1500. case $.EVENT_END:
  1501. case $.EVENT_CANCEL:
  1502. touch.flick = false;
  1503. if(session.flickStart && options.flickMaxTime > (now - flickStartTime) && touch.distance > options.flickMinDistince) {
  1504. touch.flick = true;
  1505. touch.flickTime = now - flickStartTime;
  1506. touch.flickDistanceX = touch.center.x - session.flickStart.x;
  1507. touch.flickDistanceY = touch.center.y - session.flickStart.y;
  1508. $.trigger(session.target, name, touch);
  1509. $.trigger(session.target, name + touch.direction, touch);
  1510. }
  1511. break;
  1512. }
  1513. };
  1514. /**
  1515. * mui gesture flick
  1516. */
  1517. $.addGesture({
  1518. name: name,
  1519. index: 5,
  1520. handle: handle,
  1521. options: {
  1522. flickMaxTime: 200,
  1523. flickMinDistince: 10
  1524. }
  1525. });
  1526. })(mui, 'flick');
  1527. /**
  1528. * mui gesture swipe[left|right|up|down]
  1529. * @param {type} $
  1530. * @param {type} name
  1531. * @returns {undefined}
  1532. */
  1533. (function($, name) {
  1534. var handle = function(event, touch) {
  1535. var session = $.gestures.session;
  1536. if(event.type === $.EVENT_END || event.type === $.EVENT_CANCEL) {
  1537. var options = this.options;
  1538. touch.swipe = false;
  1539. //TODO 后续根据velocity计算
  1540. if(touch.direction && options.swipeMaxTime > touch.deltaTime && touch.distance > options.swipeMinDistince) {
  1541. touch.swipe = true;
  1542. $.trigger(session.target, name, touch);
  1543. $.trigger(session.target, name + touch.direction, touch);
  1544. }
  1545. }
  1546. };
  1547. /**
  1548. * mui gesture swipe
  1549. */
  1550. $.addGesture({
  1551. name: name,
  1552. index: 10,
  1553. handle: handle,
  1554. options: {
  1555. swipeMaxTime: 300,
  1556. swipeMinDistince: 18
  1557. }
  1558. });
  1559. })(mui, 'swipe');
  1560. /**
  1561. * mui gesture drag[start|left|right|up|down|end]
  1562. * @param {type} $
  1563. * @param {type} name
  1564. * @returns {undefined}
  1565. */
  1566. (function($, name) {
  1567. var handle = function(event, touch) {
  1568. var session = $.gestures.session;
  1569. switch(event.type) {
  1570. case $.EVENT_START:
  1571. break;
  1572. case $.EVENT_MOVE:
  1573. if(!touch.direction || !session.target) {
  1574. return;
  1575. }
  1576. //修正direction,可在session期间自行锁定拖拽方向,方便开发scroll类不同方向拖拽插件嵌套
  1577. if(session.lockDirection && session.startDirection) {
  1578. if(session.startDirection && session.startDirection !== touch.direction) {
  1579. if(session.startDirection === 'up' || session.startDirection === 'down') {
  1580. touch.direction = touch.deltaY < 0 ? 'up' : 'down';
  1581. } else {
  1582. touch.direction = touch.deltaX < 0 ? 'left' : 'right';
  1583. }
  1584. }
  1585. }
  1586. if(!session.drag) {
  1587. session.drag = true;
  1588. $.trigger(session.target, name + 'start', touch);
  1589. }
  1590. $.trigger(session.target, name, touch);
  1591. $.trigger(session.target, name + touch.direction, touch);
  1592. break;
  1593. case $.EVENT_END:
  1594. case $.EVENT_CANCEL:
  1595. if(session.drag && touch.isFinal) {
  1596. $.trigger(session.target, name + 'end', touch);
  1597. }
  1598. break;
  1599. }
  1600. };
  1601. /**
  1602. * mui gesture drag
  1603. */
  1604. $.addGesture({
  1605. name: name,
  1606. index: 20,
  1607. handle: handle,
  1608. options: {
  1609. fingers: 1
  1610. }
  1611. });
  1612. })(mui, 'drag');
  1613. /**
  1614. * mui gesture tap and doubleTap
  1615. * @param {type} $
  1616. * @param {type} name
  1617. * @returns {undefined}
  1618. */
  1619. (function($, name) {
  1620. var lastTarget;
  1621. var lastTapTime;
  1622. var handle = function(event, touch) {
  1623. var session = $.gestures.session;
  1624. var options = this.options;
  1625. switch(event.type) {
  1626. case $.EVENT_END:
  1627. if(!touch.isFinal) {
  1628. return;
  1629. }
  1630. var target = session.target;
  1631. if(!target || (target.disabled || (target.classList && target.classList.contains('mui-disabled')))) {
  1632. return;
  1633. }
  1634. if(touch.distance < options.tapMaxDistance && touch.deltaTime < options.tapMaxTime) {
  1635. if($.options.gestureConfig.doubletap && lastTarget && (lastTarget === target)) { //same target
  1636. if(lastTapTime && (touch.timestamp - lastTapTime) < options.tapMaxInterval) {
  1637. $.trigger(target, 'doubletap', touch);
  1638. lastTapTime = $.now();
  1639. lastTarget = target;
  1640. return;
  1641. }
  1642. }
  1643. $.trigger(target, name, touch);
  1644. lastTapTime = $.now();
  1645. lastTarget = target;
  1646. }
  1647. break;
  1648. }
  1649. };
  1650. /**
  1651. * mui gesture tap
  1652. */
  1653. $.addGesture({
  1654. name: name,
  1655. index: 30,
  1656. handle: handle,
  1657. options: {
  1658. fingers: 1,
  1659. tapMaxInterval: 300,
  1660. tapMaxDistance: 5,
  1661. tapMaxTime: 250
  1662. }
  1663. });
  1664. })(mui, 'tap');
  1665. /**
  1666. * mui gesture longtap
  1667. * @param {type} $
  1668. * @param {type} name
  1669. * @returns {undefined}
  1670. */
  1671. (function($, name) {
  1672. var timer;
  1673. var handle = function(event, touch) {
  1674. var session = $.gestures.session;
  1675. var options = this.options;
  1676. switch(event.type) {
  1677. case $.EVENT_START:
  1678. clearTimeout(timer);
  1679. timer = setTimeout(function() {
  1680. $.trigger(session.target, name, touch);
  1681. }, options.holdTimeout);
  1682. break;
  1683. case $.EVENT_MOVE:
  1684. if(touch.distance > options.holdThreshold) {
  1685. clearTimeout(timer);
  1686. }
  1687. break;
  1688. case $.EVENT_END:
  1689. case $.EVENT_CANCEL:
  1690. clearTimeout(timer);
  1691. break;
  1692. }
  1693. };
  1694. /**
  1695. * mui gesture longtap
  1696. */
  1697. $.addGesture({
  1698. name: name,
  1699. index: 10,
  1700. handle: handle,
  1701. options: {
  1702. fingers: 1,
  1703. holdTimeout: 500,
  1704. holdThreshold: 2
  1705. }
  1706. });
  1707. })(mui, 'longtap');
  1708. /**
  1709. * mui gesture hold
  1710. * @param {type} $
  1711. * @param {type} name
  1712. * @returns {undefined}
  1713. */
  1714. (function($, name) {
  1715. var timer;
  1716. var handle = function(event, touch) {
  1717. var session = $.gestures.session;
  1718. var options = this.options;
  1719. switch(event.type) {
  1720. case $.EVENT_START:
  1721. if($.options.gestureConfig.hold) {
  1722. timer && clearTimeout(timer);
  1723. timer = setTimeout(function() {
  1724. touch.hold = true;
  1725. $.trigger(session.target, name, touch);
  1726. }, options.holdTimeout);
  1727. }
  1728. break;
  1729. case $.EVENT_MOVE:
  1730. break;
  1731. case $.EVENT_END:
  1732. case $.EVENT_CANCEL:
  1733. if(timer) {
  1734. clearTimeout(timer) && (timer = null);
  1735. $.trigger(session.target, 'release', touch);
  1736. }
  1737. break;
  1738. }
  1739. };
  1740. /**
  1741. * mui gesture hold
  1742. */
  1743. $.addGesture({
  1744. name: name,
  1745. index: 10,
  1746. handle: handle,
  1747. options: {
  1748. fingers: 1,
  1749. holdTimeout: 0
  1750. }
  1751. });
  1752. })(mui, 'hold');
  1753. /**
  1754. * mui gesture pinch
  1755. * @param {type} $
  1756. * @param {type} name
  1757. * @returns {undefined}
  1758. */
  1759. (function($, name) {
  1760. var handle = function(event, touch) {
  1761. var options = this.options;
  1762. var session = $.gestures.session;
  1763. switch(event.type) {
  1764. case $.EVENT_START:
  1765. break;
  1766. case $.EVENT_MOVE:
  1767. if($.options.gestureConfig.pinch) {
  1768. if(touch.touches.length < 2) {
  1769. return;
  1770. }
  1771. if(!session.pinch) { //start
  1772. session.pinch = true;
  1773. $.trigger(session.target, name + 'start', touch);
  1774. }
  1775. $.trigger(session.target, name, touch);
  1776. var scale = touch.scale;
  1777. var rotation = touch.rotation;
  1778. var lastScale = typeof touch.lastScale === 'undefined' ? 1 : touch.lastScale;
  1779. var scaleDiff = 0.000000000001; //防止scale与lastScale相等,不触发事件的情况。
  1780. if(scale > lastScale) { //out
  1781. lastScale = scale - scaleDiff;
  1782. $.trigger(session.target, name + 'out', touch);
  1783. } //in
  1784. else if(scale < lastScale) {
  1785. lastScale = scale + scaleDiff;
  1786. $.trigger(session.target, name + 'in', touch);
  1787. }
  1788. if(Math.abs(rotation) > options.minRotationAngle) {
  1789. $.trigger(session.target, 'rotate', touch);
  1790. }
  1791. }
  1792. break;
  1793. case $.EVENT_END:
  1794. case $.EVENT_CANCEL:
  1795. if($.options.gestureConfig.pinch && session.pinch && touch.touches.length === 2) {
  1796. session.pinch = false;
  1797. $.trigger(session.target, name + 'end', touch);
  1798. }
  1799. break;
  1800. }
  1801. };
  1802. /**
  1803. * mui gesture pinch
  1804. */
  1805. $.addGesture({
  1806. name: name,
  1807. index: 10,
  1808. handle: handle,
  1809. options: {
  1810. minRotationAngle: 0
  1811. }
  1812. });
  1813. })(mui, 'pinch');
  1814. /**
  1815. * mui.init
  1816. * @param {type} $
  1817. * @returns {undefined}
  1818. */
  1819. (function($) {
  1820. $.global = $.options = {
  1821. gestureConfig: {
  1822. tap: true,
  1823. doubletap: false,
  1824. longtap: false,
  1825. hold: false,
  1826. flick: true,
  1827. swipe: true,
  1828. drag: true,
  1829. pinch: false
  1830. }
  1831. };
  1832. /**
  1833. *
  1834. * @param {type} options
  1835. * @returns {undefined}
  1836. */
  1837. $.initGlobal = function(options) {
  1838. $.options = $.extend(true, $.global, options);
  1839. return this;
  1840. };
  1841. var inits = {};
  1842. /**
  1843. * 单页配置 初始化
  1844. * @param {object} options
  1845. */
  1846. $.init = function(options) {
  1847. $.options = $.extend(true, $.global, options || {});
  1848. $.ready(function() {
  1849. $.doAction('inits', function(index, init) {
  1850. var isInit = !!(!inits[init.name] || init.repeat);
  1851. if(isInit) {
  1852. init.handle.call($);
  1853. inits[init.name] = true;
  1854. }
  1855. });
  1856. });
  1857. return this;
  1858. };
  1859. /**
  1860. * 增加初始化执行流程
  1861. * @param {function} init
  1862. */
  1863. $.addInit = function(init) {
  1864. return $.addAction('inits', init);
  1865. };
  1866. /**
  1867. * 处理html5版本subpages
  1868. */
  1869. $.addInit({
  1870. name: 'iframe',
  1871. index: 100,
  1872. handle: function() {
  1873. var options = $.options;
  1874. var subpages = options.subpages || [];
  1875. if(!$.os.plus && subpages.length) {
  1876. //暂时只处理单个subpage。后续可以考虑支持多个subpage
  1877. createIframe(subpages[0]);
  1878. }
  1879. }
  1880. });
  1881. var createIframe = function(options) {
  1882. var wrapper = document.createElement('div');
  1883. wrapper.className = 'mui-iframe-wrapper';
  1884. var styles = options.styles || {};
  1885. if(typeof styles.top !== 'string') {
  1886. styles.top = '0px';
  1887. }
  1888. if(typeof styles.bottom !== 'string') {
  1889. styles.bottom = '0px';
  1890. }
  1891. wrapper.style.top = styles.top;
  1892. wrapper.style.bottom = styles.bottom;
  1893. var iframe = document.createElement('iframe');
  1894. iframe.src = options.url;
  1895. iframe.id = options.id || options.url;
  1896. iframe.name = iframe.id;
  1897. wrapper.appendChild(iframe);
  1898. document.body.appendChild(wrapper);
  1899. //目前仅处理微信
  1900. $.os.wechat && handleScroll(wrapper, iframe);
  1901. };
  1902. function handleScroll(wrapper, iframe) {
  1903. var key = 'MUI_SCROLL_POSITION_' + document.location.href + '_' + iframe.src;
  1904. var scrollTop = (parseFloat(localStorage.getItem(key)) || 0);
  1905. if(scrollTop) {
  1906. (function(y) {
  1907. iframe.onload = function() {
  1908. window.scrollTo(0, y);
  1909. };
  1910. })(scrollTop);
  1911. }
  1912. setInterval(function() {
  1913. var _scrollTop = window.scrollY;
  1914. if(scrollTop !== _scrollTop) {
  1915. localStorage.setItem(key, _scrollTop + '');
  1916. scrollTop = _scrollTop;
  1917. }
  1918. }, 100);
  1919. };
  1920. $(function() {
  1921. var classList = document.body.classList;
  1922. var os = [];
  1923. if($.os.ios) {
  1924. os.push({
  1925. os: 'ios',
  1926. version: $.os.version
  1927. });
  1928. classList.add('mui-ios');
  1929. } else if($.os.android) {
  1930. os.push({
  1931. os: 'android',
  1932. version: $.os.version
  1933. });
  1934. classList.add('mui-android');
  1935. }
  1936. if($.os.wechat) {
  1937. os.push({
  1938. os: 'wechat',
  1939. version: $.os.wechat.version
  1940. });
  1941. classList.add('mui-wechat');
  1942. }
  1943. if(os.length) {
  1944. $.each(os, function(index, osObj) {
  1945. var version = '';
  1946. var classArray = [];
  1947. if(osObj.version) {
  1948. $.each(osObj.version.split('.'), function(i, v) {
  1949. version = version + (version ? '-' : '') + v;
  1950. classList.add($.className(osObj.os + '-' + version));
  1951. });
  1952. }
  1953. });
  1954. }
  1955. });
  1956. })(mui);
  1957. /**
  1958. * mui.init 5+
  1959. * @param {type} $
  1960. * @returns {undefined}
  1961. */
  1962. (function($) {
  1963. var defaultOptions = {
  1964. swipeBack: false,
  1965. preloadPages: [], //5+ lazyLoad webview
  1966. preloadLimit: 10, //预加载窗口的数量限制(一旦超出,先进先出)
  1967. keyEventBind: {
  1968. backbutton: true,
  1969. menubutton: true
  1970. },
  1971. titleConfig: {
  1972. height: "44px",
  1973. backgroundColor: "#f7f7f7", //导航栏背景色
  1974. bottomBorderColor: "#cccccc", //底部边线颜色
  1975. title: { //标题配置
  1976. text: "", //标题文字
  1977. position: {
  1978. top: 0,
  1979. left: 0,
  1980. width: "100%",
  1981. height: "100%"
  1982. },
  1983. styles: {
  1984. color: "#000000",
  1985. align: "center",
  1986. family: "'Helvetica Neue',Helvetica,sans-serif",
  1987. size: "17px",
  1988. style: "normal",
  1989. weight: "normal",
  1990. fontSrc: ""
  1991. }
  1992. },
  1993. back: {
  1994. image: {
  1995. base64Data: '',
  1996. imgSrc: '',
  1997. sprite: {
  1998. top: '0px',
  1999. left: '0px',
  2000. width: '100%',
  2001. height: '100%'
  2002. },
  2003. position: {
  2004. top: "10px",
  2005. left: "10px",
  2006. width: "24px",
  2007. height: "24px"
  2008. }
  2009. }
  2010. }
  2011. }
  2012. };
  2013. //默认页面动画
  2014. var defaultShow = {
  2015. event: "titleUpdate",
  2016. autoShow: true,
  2017. duration: 300,
  2018. aniShow: 'slide-in-right',
  2019. extras: {}
  2020. };
  2021. //若执行了显示动画初始化操作,则要覆盖默认配置
  2022. if($.options.show) {
  2023. defaultShow = $.extend(true, defaultShow, $.options.show);
  2024. }
  2025. $.currentWebview = null;
  2026. $.extend(true, $.global, defaultOptions);
  2027. $.extend(true, $.options, defaultOptions);
  2028. /**
  2029. * 等待动画配置
  2030. * @param {type} options
  2031. * @returns {Object}
  2032. */
  2033. $.waitingOptions = function(options) {
  2034. return $.extend(true, {}, {
  2035. autoShow: true,
  2036. title: '',
  2037. modal: false
  2038. }, options);
  2039. };
  2040. /**
  2041. * 窗口显示配置
  2042. * @param {type} options
  2043. * @returns {Object}
  2044. */
  2045. $.showOptions = function(options) {
  2046. return $.extend(true, {}, defaultShow, options);
  2047. };
  2048. /**
  2049. * 窗口默认配置
  2050. * @param {type} options
  2051. * @returns {Object}
  2052. */
  2053. $.windowOptions = function(options) {
  2054. return $.extend({
  2055. scalable: false,
  2056. bounce: "" //vertical
  2057. }, options);
  2058. };
  2059. /**
  2060. * plusReady
  2061. * @param {type} callback
  2062. * @returns {_L6.$}
  2063. */
  2064. $.plusReady = function(callback) {
  2065. if(window.plus) {
  2066. setTimeout(function() { //解决callback与plusready事件的执行时机问题(典型案例:showWaiting,closeWaiting)
  2067. callback();
  2068. }, 0);
  2069. } else {
  2070. document.addEventListener("plusready", function() {
  2071. callback();
  2072. }, false);
  2073. }
  2074. return this;
  2075. };
  2076. /**
  2077. * 5+ event(5+没提供之前我自己实现)
  2078. * @param {type} webview
  2079. * @param {type} eventType
  2080. * @param {type} data
  2081. * @returns {undefined}
  2082. */
  2083. $.fire = function(webview, eventType, data) {
  2084. if(webview) {
  2085. if(typeof data === 'undefined') {
  2086. data = '';
  2087. } else if(typeof data === 'boolean' || typeof data === 'number') {
  2088. webview.evalJS("typeof mui!=='undefined'&&mui.receive('" + eventType + "'," + data + ")");
  2089. return;
  2090. } else if($.isPlainObject(data) || $.isArray(data)) {
  2091. data = JSON.stringify(data || {}).replace(/\'/g, "\\u0027").replace(/\\/g, "\\u005c");
  2092. }
  2093. webview.evalJS("typeof mui!=='undefined'&&mui.receive('" + eventType + "','" + data + "')");
  2094. }
  2095. };
  2096. /**
  2097. * 5+ event(5+没提供之前我自己实现)
  2098. * @param {type} eventType
  2099. * @param {type} data
  2100. * @returns {undefined}
  2101. */
  2102. $.receive = function(eventType, data) {
  2103. if(eventType) {
  2104. try {
  2105. if(data && typeof data === 'string') {
  2106. data = JSON.parse(data);
  2107. }
  2108. } catch(e) {}
  2109. $.trigger(document, eventType, data);
  2110. }
  2111. };
  2112. var triggerPreload = function(webview) {
  2113. if(!webview.preloaded) { //保证仅触发一次
  2114. $.fire(webview, 'preload');
  2115. var list = webview.children();
  2116. for(var i = 0; i < list.length; i++) {
  2117. $.fire(list[i], 'preload');
  2118. }
  2119. webview.preloaded = true;
  2120. }
  2121. };
  2122. var trigger = function(webview, eventType, timeChecked) {
  2123. if(timeChecked) {
  2124. if(!webview[eventType + 'ed']) {
  2125. $.fire(webview, eventType);
  2126. var list = webview.children();
  2127. for(var i = 0; i < list.length; i++) {
  2128. $.fire(list[i], eventType);
  2129. }
  2130. webview[eventType + 'ed'] = true;
  2131. }
  2132. } else {
  2133. $.fire(webview, eventType);
  2134. var list = webview.children();
  2135. for(var i = 0; i < list.length; i++) {
  2136. $.fire(list[i], eventType);
  2137. }
  2138. }
  2139. };
  2140. /**
  2141. * 打开新窗口
  2142. * @param {string} url 要打开的页面地址
  2143. * @param {string} id 指定页面ID
  2144. * @param {object} options 可选:参数,等待,窗口,显示配置{params:{},waiting:{},styles:{},show:{}}
  2145. */
  2146. $.openWindow = function(url, id, options) {
  2147. if(typeof url === 'object') {
  2148. options = url;
  2149. url = options.url;
  2150. id = options.id || url;
  2151. } else {
  2152. if(typeof id === 'object') {
  2153. options = id;
  2154. id = options.id || url;
  2155. } else {
  2156. id = id || url;
  2157. }
  2158. }
  2159. if(!$.os.plus) {
  2160. //TODO 先临时这么处理:手机上顶层跳,PC上parent跳
  2161. if($.os.ios || $.os.android) {
  2162. window.top.location.href = url;
  2163. } else {
  2164. window.parent.location.href = url;
  2165. }
  2166. return;
  2167. }
  2168. if(!window.plus) {
  2169. return;
  2170. }
  2171. options = options || {};
  2172. var params = options.params || {};
  2173. var webview = null,
  2174. webviewCache = null,
  2175. nShow, nWaiting;
  2176. if($.webviews[id]) {
  2177. webviewCache = $.webviews[id];
  2178. //webview真实存在,才能获取
  2179. if(plus.webview.getWebviewById(id)) {
  2180. webview = webviewCache.webview;
  2181. }
  2182. } else if(options.createNew !== true) {
  2183. webview = plus.webview.getWebviewById(id);
  2184. }
  2185. if(webview) { //已缓存
  2186. //每次show都需要传递动画参数;
  2187. //预加载的动画参数优先级:openWindow配置>preloadPages配置>mui默认配置;
  2188. nShow = webviewCache ? webviewCache.show : defaultShow;
  2189. nShow = options.show ? $.extend(nShow, options.show) : nShow;
  2190. nShow.autoShow && webview.show(nShow.aniShow, nShow.duration, function() {
  2191. triggerPreload(webview);
  2192. trigger(webview, 'pagebeforeshow', false);
  2193. });
  2194. if(webviewCache) {
  2195. webviewCache.afterShowMethodName && webview.evalJS(webviewCache.afterShowMethodName + '(\'' + JSON.stringify(params) + '\')');
  2196. }
  2197. return webview;
  2198. } else { //新窗口
  2199. if(!url) {
  2200. throw new Error('webview[' + id + '] does not exist');
  2201. }
  2202. //显示waiting
  2203. var waitingConfig = $.waitingOptions(options.waiting);
  2204. if(waitingConfig.autoShow) {
  2205. nWaiting = plus.nativeUI.showWaiting(waitingConfig.title, waitingConfig.options);
  2206. }
  2207. //创建页面
  2208. options = $.extend(options, {
  2209. id: id,
  2210. url: url
  2211. });
  2212. webview = $.createWindow(options);
  2213. //显示
  2214. nShow = $.showOptions(options.show);
  2215. if(nShow.autoShow) {
  2216. var showWebview = function() {
  2217. //关闭等待框
  2218. if(nWaiting) {
  2219. nWaiting.close();
  2220. }
  2221. //显示页面
  2222. webview.show(nShow.aniShow, nShow.duration, function() {}, nShow.extras);
  2223. options.afterShowMethodName && webview.evalJS(options.afterShowMethodName + '(\'' + JSON.stringify(params) + '\')');
  2224. };
  2225. //titleUpdate触发时机早于loaded,更换为titleUpdate后,可以更早的显示webview
  2226. webview.addEventListener(nShow.event, showWebview, false);
  2227. //loaded事件发生后,触发预加载和pagebeforeshow事件
  2228. webview.addEventListener("loaded", function() {
  2229. triggerPreload(webview);
  2230. trigger(webview, 'pagebeforeshow', false);
  2231. }, false);
  2232. }
  2233. }
  2234. return webview;
  2235. };
  2236. $.openWindowWithTitle = function(options, titleConfig) {
  2237. options = options || {};
  2238. var url = options.url;
  2239. var id = options.id || url;
  2240. if(!$.os.plus) {
  2241. //TODO 先临时这么处理:手机上顶层跳,PC上parent跳
  2242. if($.os.ios || $.os.android) {
  2243. window.top.location.href = url;
  2244. } else {
  2245. window.parent.location.href = url;
  2246. }
  2247. return;
  2248. }
  2249. if(!window.plus) {
  2250. return;
  2251. }
  2252. var params = options.params || {};
  2253. var webview = null,
  2254. webviewCache = null,
  2255. nShow, nWaiting;
  2256. if($.webviews[id]) {
  2257. webviewCache = $.webviews[id];
  2258. //webview真实存在,才能获取
  2259. if(plus.webview.getWebviewById(id)) {
  2260. webview = webviewCache.webview;
  2261. }
  2262. } else if(options.createNew !== true) {
  2263. webview = plus.webview.getWebviewById(id);
  2264. }
  2265. if(webview) { //已缓存
  2266. //每次show都需要传递动画参数;
  2267. //预加载的动画参数优先级:openWindow配置>preloadPages配置>mui默认配置;
  2268. nShow = webviewCache ? webviewCache.show : defaultShow;
  2269. nShow = options.show ? $.extend(nShow, options.show) : nShow;
  2270. nShow.autoShow && webview.show(nShow.aniShow, nShow.duration, function() {
  2271. triggerPreload(webview);
  2272. trigger(webview, 'pagebeforeshow', false);
  2273. });
  2274. if(webviewCache) {
  2275. webviewCache.afterShowMethodName && webview.evalJS(webviewCache.afterShowMethodName + '(\'' + JSON.stringify(params) + '\')');
  2276. }
  2277. return webview;
  2278. } else { //新窗口
  2279. if(!url) {
  2280. throw new Error('webview[' + id + '] does not exist');
  2281. }
  2282. //显示waiting
  2283. var waitingConfig = $.waitingOptions(options.waiting);
  2284. if(waitingConfig.autoShow) {
  2285. nWaiting = plus.nativeUI.showWaiting(waitingConfig.title, waitingConfig.options);
  2286. }
  2287. //创建页面
  2288. options = $.extend(options, {
  2289. id: id,
  2290. url: url
  2291. });
  2292. webview = $.createWindow(options);
  2293. if(titleConfig) { //处理原生头
  2294. $.extend(true, $.options.titleConfig, titleConfig);
  2295. var tid = $.options.titleConfig.id ? $.options.titleConfig.id : id + "_title";
  2296. var view = new plus.nativeObj.View(tid, {
  2297. top: 0,
  2298. height: $.options.titleConfig.height,
  2299. width: "100%",
  2300. dock: "top",
  2301. position: "dock"
  2302. });
  2303. view.drawRect($.options.titleConfig.backgroundColor); //绘制背景色
  2304. var _b = parseInt($.options.titleConfig.height) - 1;
  2305. view.drawRect($.options.titleConfig.bottomBorderColor, {
  2306. top: _b + "px",
  2307. left: "0px"
  2308. }); //绘制底部边线
  2309. //绘制文字
  2310. if($.options.titleConfig.title.text) {
  2311. var _title = $.options.titleConfig.title;
  2312. view.drawText(_title.text, _title.position, _title.styles);
  2313. }
  2314. //返回图标绘制
  2315. var _back = $.options.titleConfig.back;
  2316. var backClick = null;
  2317. //优先字体
  2318. //其次是图片
  2319. var _backImage = _back.image;
  2320. if(_backImage.base64Data || _backImage.imgSrc) {
  2321. //TODO 此处需要处理百分比的情况
  2322. backClick = {
  2323. left: parseInt(_backImage.position.left),
  2324. right: parseInt(_backImage.position.left) + parseInt(_backImage.position.width)
  2325. };
  2326. var bitmap = new plus.nativeObj.Bitmap(id + "_back");
  2327. if(_backImage.base64Data) { //优先base64编码字符串
  2328. bitmap.loadBase64Data(_backImage.base64Data);
  2329. } else { //其次加载图片文件
  2330. bitmap.load(_backImage.imgSrc);
  2331. }
  2332. view.drawBitmap(bitmap, _backImage.sprite, _backImage.position);
  2333. }
  2334. //处理点击事件
  2335. view.setTouchEventRect({
  2336. top: "0px",
  2337. left: "0px",
  2338. width: "100%",
  2339. height: "100%"
  2340. });
  2341. view.interceptTouchEvent(true);
  2342. view.addEventListener("click", function(e) {
  2343. var x = e.clientX;
  2344. //返回按钮点击
  2345. if(backClick && x > backClick.left && x < backClick.right) {
  2346. if(_back.click && $.isFunction(_back.click)) {
  2347. _back.click();
  2348. } else {
  2349. webview.evalJS("window.mui&&mui.back();");
  2350. }
  2351. }
  2352. }, false);
  2353. webview.append(view);
  2354. }
  2355. //显示
  2356. nShow = $.showOptions(options.show);
  2357. if(nShow.autoShow) {
  2358. //titleUpdate触发时机早于loaded,更换为titleUpdate后,可以更早的显示webview
  2359. webview.addEventListener(nShow.event, function() {
  2360. //关闭等待框
  2361. if(nWaiting) {
  2362. nWaiting.close();
  2363. }
  2364. //显示页面
  2365. webview.show(nShow.aniShow, nShow.duration, function() {}, nShow.extras);
  2366. }, false);
  2367. }
  2368. }
  2369. return webview;
  2370. };
  2371. /**
  2372. * 根据配置信息创建一个webview
  2373. * @param {type} options
  2374. * @param {type} isCreate
  2375. * @returns {webview}
  2376. */
  2377. $.createWindow = function(options, isCreate) {
  2378. if(!window.plus) {
  2379. return;
  2380. }
  2381. var id = options.id || options.url;
  2382. var webview;
  2383. if(options.preload) {
  2384. if($.webviews[id] && $.webviews[id].webview.getURL()) { //已经cache
  2385. webview = $.webviews[id].webview;
  2386. } else { //新增预加载窗口
  2387. //判断是否携带createNew参数,默认为false
  2388. if(options.createNew !== true) {
  2389. webview = plus.webview.getWebviewById(id);
  2390. }
  2391. //之前没有,那就新创建
  2392. if(!webview) {
  2393. webview = plus.webview.create(options.url, id, $.windowOptions(options.styles), $.extend({
  2394. preload: true
  2395. }, options.extras));
  2396. if(options.subpages) {
  2397. $.each(options.subpages, function(index, subpage) {
  2398. var subpageId = subpage.id || subpage.url;
  2399. if(subpageId) { //过滤空对象
  2400. var subWebview = plus.webview.getWebviewById(subpageId);
  2401. if(!subWebview) { //如果该webview不存在,则创建
  2402. subWebview = plus.webview.create(subpage.url, subpageId, $.windowOptions(subpage.styles), $.extend({
  2403. preload: true
  2404. }, subpage.extras));
  2405. }
  2406. webview.append(subWebview);
  2407. }
  2408. });
  2409. }
  2410. }
  2411. }
  2412. //TODO 理论上,子webview也应该计算到预加载队列中,但这样就麻烦了,要退必须退整体,否则可能出现问题;
  2413. $.webviews[id] = {
  2414. webview: webview, //目前仅preload的缓存webview
  2415. preload: true,
  2416. show: $.showOptions(options.show),
  2417. afterShowMethodName: options.afterShowMethodName //就不应该用evalJS。应该是通过事件消息通讯
  2418. };
  2419. //索引该预加载窗口
  2420. var preloads = $.data.preloads;
  2421. var index = preloads.indexOf(id);
  2422. if(~index) { //删除已存在的(变相调整插入位置)
  2423. preloads.splice(index, 1);
  2424. }
  2425. preloads.push(id);
  2426. if(preloads.length > $.options.preloadLimit) {
  2427. //先进先出
  2428. var first = $.data.preloads.shift();
  2429. var webviewCache = $.webviews[first];
  2430. if(webviewCache && webviewCache.webview) {
  2431. //需要将自己打开的所有页面,全部close;
  2432. //关闭该预加载webview
  2433. $.closeAll(webviewCache.webview);
  2434. }
  2435. //删除缓存
  2436. delete $.webviews[first];
  2437. }
  2438. } else {
  2439. if(isCreate !== false) { //直接创建非预加载窗口
  2440. webview = plus.webview.create(options.url, id, $.windowOptions(options.styles), options.extras);
  2441. if(options.subpages) {
  2442. $.each(options.subpages, function(index, subpage) {
  2443. var subpageId = subpage.id || subpage.url;
  2444. var subWebview = plus.webview.getWebviewById(subpageId);
  2445. if(!subWebview) {
  2446. subWebview = plus.webview.create(subpage.url, subpageId, $.windowOptions(subpage.styles), subpage.extras);
  2447. }
  2448. webview.append(subWebview);
  2449. });
  2450. }
  2451. }
  2452. }
  2453. return webview;
  2454. };
  2455. /**
  2456. * 预加载
  2457. */
  2458. $.preload = function(options) {
  2459. //调用预加载函数,不管是否传递preload参数,强制变为true
  2460. if(!options.preload) {
  2461. options.preload = true;
  2462. }
  2463. return $.createWindow(options);
  2464. };
  2465. /**
  2466. *关闭当前webview打开的所有webview;
  2467. */
  2468. $.closeOpened = function(webview) {
  2469. var opened = webview.opened();
  2470. if(opened) {
  2471. for(var i = 0, len = opened.length; i < len; i++) {
  2472. var openedWebview = opened[i];
  2473. var open_open = openedWebview.opened();
  2474. if(open_open && open_open.length > 0) {
  2475. //关闭打开的webview
  2476. $.closeOpened(openedWebview);
  2477. //关闭自己
  2478. openedWebview.close("none");
  2479. } else {
  2480. //如果直接孩子节点,就不用关闭了,因为父关闭的时候,会自动关闭子;
  2481. if(openedWebview.parent() !== webview) {
  2482. openedWebview.close('none');
  2483. }
  2484. }
  2485. }
  2486. }
  2487. };
  2488. $.closeAll = function(webview, aniShow) {
  2489. $.closeOpened(webview);
  2490. if(aniShow) {
  2491. webview.close(aniShow);
  2492. } else {
  2493. webview.close();
  2494. }
  2495. };
  2496. /**
  2497. * 批量创建webview
  2498. * @param {type} options
  2499. * @returns {undefined}
  2500. */
  2501. $.createWindows = function(options) {
  2502. $.each(options, function(index, option) {
  2503. //初始化预加载窗口(创建)和非预加载窗口(仅配置,不创建)
  2504. $.createWindow(option, false);
  2505. });
  2506. };
  2507. /**
  2508. * 创建当前页面的子webview
  2509. * @param {type} options
  2510. * @returns {webview}
  2511. */
  2512. $.appendWebview = function(options) {
  2513. if(!window.plus) {
  2514. return;
  2515. }
  2516. var id = options.id || options.url;
  2517. var webview;
  2518. if(!$.webviews[id]) { //保证执行一遍
  2519. //TODO 这里也有隐患,比如某个webview不是作为subpage创建的,而是作为target webview的话;
  2520. if(!plus.webview.getWebviewById(id)) {
  2521. webview = plus.webview.create(options.url, id, options.styles, options.extras);
  2522. }
  2523. //之前的实现方案:子窗口loaded之后再append到父窗口中;
  2524. //问题:部分子窗口loaded事件发生较晚,此时执行父窗口的children方法会返回空,导致父子通讯失败;
  2525. // 比如父页面执行完preload事件后,需触发子页面的preload事件,此时未append的话,就无法触发;
  2526. //修改方式:不再监控loaded事件,直接append
  2527. //by chb@20150521
  2528. // webview.addEventListener('loaded', function() {
  2529. plus.webview.currentWebview().append(webview);
  2530. // });
  2531. $.webviews[id] = options;
  2532. }
  2533. return webview;
  2534. };
  2535. //全局webviews
  2536. $.webviews = {};
  2537. //预加载窗口索引
  2538. $.data.preloads = [];
  2539. //$.currentWebview
  2540. $.plusReady(function() {
  2541. $.currentWebview = plus.webview.currentWebview();
  2542. });
  2543. $.addInit({
  2544. name: '5+',
  2545. index: 100,
  2546. handle: function() {
  2547. var options = $.options;
  2548. var subpages = options.subpages || [];
  2549. if($.os.plus) {
  2550. $.plusReady(function() {
  2551. //TODO 这里需要判断一下,最好等子窗口加载完毕后,再调用主窗口的show方法;
  2552. //或者:在openwindow方法中,监听实现;
  2553. $.each(subpages, function(index, subpage) {
  2554. $.appendWebview(subpage);
  2555. });
  2556. //判断是否首页
  2557. if(plus.webview.currentWebview() === plus.webview.getWebviewById(plus.runtime.appid)) {
  2558. //首页需要自己激活预加载;
  2559. //timeout因为子页面loaded之后才append的,防止子页面尚未append、从而导致其preload未触发的问题;
  2560. setTimeout(function() {
  2561. triggerPreload(plus.webview.currentWebview());
  2562. }, 300);
  2563. }
  2564. //设置ios顶部状态栏颜色;
  2565. if($.os.ios && $.options.statusBarBackground) {
  2566. plus.navigator.setStatusBarBackground($.options.statusBarBackground);
  2567. }
  2568. if($.os.android && parseFloat($.os.version) < 4.4) {
  2569. //解决Android平台4.4版本以下,resume后,父窗体标题延迟渲染的问题;
  2570. if(plus.webview.currentWebview().parent() == null) {
  2571. document.addEventListener("resume", function() {
  2572. var body = document.body;
  2573. body.style.display = 'none';
  2574. setTimeout(function() {
  2575. body.style.display = '';
  2576. }, 10);
  2577. });
  2578. }
  2579. }
  2580. });
  2581. } else {
  2582. //已支持iframe嵌入
  2583. // if (subpages.length > 0) {
  2584. // var err = document.createElement('div');
  2585. // err.className = 'mui-error';
  2586. // //文字描述
  2587. // var span = document.createElement('span');
  2588. // span.innerHTML = '在该浏览器下,不支持创建子页面,具体参考';
  2589. // err.appendChild(span);
  2590. // var a = document.createElement('a');
  2591. // a.innerHTML = '"mui框架适用场景"';
  2592. // a.href = 'http://ask.dcloud.net.cn/article/113';
  2593. // err.appendChild(a);
  2594. // document.body.appendChild(err);
  2595. // console.log('在该浏览器下,不支持创建子页面');
  2596. // }
  2597. }
  2598. }
  2599. });
  2600. window.addEventListener('preload', function() {
  2601. //处理预加载部分
  2602. var webviews = $.options.preloadPages || [];
  2603. $.plusReady(function() {
  2604. $.each(webviews, function(index, webview) {
  2605. $.createWindow($.extend(webview, {
  2606. preload: true
  2607. }));
  2608. });
  2609. });
  2610. });
  2611. $.supportStatusbarOffset = function() {
  2612. return $.os.plus && $.os.ios && parseFloat($.os.version) >= 7;
  2613. };
  2614. $.ready(function() {
  2615. //标识当前环境支持statusbar
  2616. if($.supportStatusbarOffset()) {
  2617. document.body.classList.add('mui-statusbar');
  2618. }
  2619. });
  2620. })(mui);
  2621. /**
  2622. * mui back
  2623. * @param {type} $
  2624. * @param {type} window
  2625. * @returns {undefined}
  2626. */
  2627. (function($, window) {
  2628. /**
  2629. * register back
  2630. * @param {type} back
  2631. * @returns {$.gestures}
  2632. */
  2633. $.addBack = function(back) {
  2634. return $.addAction('backs', back);
  2635. };
  2636. /**
  2637. * default
  2638. */
  2639. $.addBack({
  2640. name: 'browser',
  2641. index: 100,
  2642. handle: function() {
  2643. if(window.history.length > 1) {
  2644. window.history.back();
  2645. return true;
  2646. }
  2647. return false;
  2648. }
  2649. });
  2650. /**
  2651. * 后退
  2652. */
  2653. $.back = function() {
  2654. if(typeof $.options.beforeback === 'function') {
  2655. if($.options.beforeback() === false) {
  2656. return;
  2657. }
  2658. }
  2659. $.doAction('backs');
  2660. };
  2661. window.addEventListener('tap', function(e) {
  2662. var action = $.targets.action;
  2663. if(action && action.classList.contains('mui-action-back')) {
  2664. $.back();
  2665. $.targets.action = false;
  2666. }
  2667. });
  2668. window.addEventListener('swiperight', function(e) {
  2669. var detail = e.detail;
  2670. if($.options.swipeBack === true && Math.abs(detail.angle) < 3) {
  2671. $.back();
  2672. }
  2673. });
  2674. })(mui, window);
  2675. /**
  2676. * mui back 5+
  2677. * @param {type} $
  2678. * @param {type} window
  2679. * @returns {undefined}
  2680. */
  2681. (function($, window) {
  2682. if($.os.plus && $.os.android) {
  2683. $.addBack({
  2684. name: 'mui',
  2685. index: 5,
  2686. handle: function() {
  2687. //后续重新设计此处,将back放到各个空间内部实现
  2688. //popover
  2689. if($.targets._popover && $.targets._popover.classList.contains('mui-active')) {
  2690. $($.targets._popover).popover('hide');
  2691. return true;
  2692. }
  2693. //offcanvas
  2694. var offCanvas = document.querySelector('.mui-off-canvas-wrap.mui-active');
  2695. if(offCanvas) {
  2696. $(offCanvas).offCanvas('close');
  2697. return true;
  2698. }
  2699. var previewImage = $.isFunction($.getPreviewImage) && $.getPreviewImage();
  2700. if(previewImage && previewImage.isShown()) {
  2701. previewImage.close();
  2702. return true;
  2703. }
  2704. //popup
  2705. return $.closePopup();
  2706. }
  2707. });
  2708. }
  2709. //首次按下back按键的时间
  2710. $.__back__first = null;
  2711. /**
  2712. * 5+ back
  2713. */
  2714. $.addBack({
  2715. name: '5+',
  2716. index: 10,
  2717. handle: function() {
  2718. if(!window.plus) {
  2719. return false;
  2720. }
  2721. var wobj = plus.webview.currentWebview();
  2722. var parent = wobj.parent();
  2723. if(parent) {
  2724. parent.evalJS('mui&&mui.back();');
  2725. } else {
  2726. wobj.canBack(function(e) {
  2727. //by chb 暂时注释,在碰到类似popover之类的锚点的时候,需多次点击才能返回;
  2728. if(e.canBack) { //webview history back
  2729. window.history.back();
  2730. } else { //webview close or hide
  2731. //fixed by fxy 此处不应该用opener判断,因为用户有可能自己close掉当前窗口的opener。这样的话。opener就为空了,导致不能执行close
  2732. if(wobj.id === plus.runtime.appid) { //首页
  2733. //首页不存在opener的情况下,后退实际上应该是退出应用;
  2734. //首次按键,提示‘再按一次退出应用’
  2735. if(!$.__back__first) {
  2736. $.__back__first = new Date().getTime();
  2737. mui.toast('再按一次退出应用');
  2738. setTimeout(function() {
  2739. $.__back__first = null;
  2740. }, 2000);
  2741. } else {
  2742. if(new Date().getTime() - $.__back__first < 2000) {
  2743. plus.runtime.quit();
  2744. }
  2745. }
  2746. } else { //其他页面,
  2747. if(wobj.preload) {
  2748. wobj.hide("auto");
  2749. } else {
  2750. //关闭页面时,需要将其打开的所有子页面全部关闭;
  2751. $.closeAll(wobj);
  2752. }
  2753. }
  2754. }
  2755. });
  2756. }
  2757. return true;
  2758. }
  2759. });
  2760. $.menu = function() {
  2761. var menu = document.querySelector('.mui-action-menu');
  2762. if(menu) {
  2763. $.trigger(menu, $.EVENT_START); //临时处理menu无touchstart的话,找不到当前targets的问题
  2764. $.trigger(menu, 'tap');
  2765. } else { //执行父窗口的menu
  2766. if(window.plus) {
  2767. var wobj = $.currentWebview;
  2768. var parent = wobj.parent();
  2769. if(parent) { //又得evalJS
  2770. parent.evalJS('mui&&mui.menu();');
  2771. }
  2772. }
  2773. }
  2774. };
  2775. var __back = function() {
  2776. $.back();
  2777. };
  2778. var __menu = function() {
  2779. $.menu();
  2780. };
  2781. //默认监听
  2782. $.plusReady(function() {
  2783. if($.options.keyEventBind.backbutton) {
  2784. plus.key.addEventListener('backbutton', __back, false);
  2785. }
  2786. if($.options.keyEventBind.menubutton) {
  2787. plus.key.addEventListener('menubutton', __menu, false);
  2788. }
  2789. });
  2790. //处理按键监听事件
  2791. $.addInit({
  2792. name: 'keyEventBind',
  2793. index: 1000,
  2794. handle: function() {
  2795. $.plusReady(function() {
  2796. //如果不为true,则移除默认监听
  2797. if(!$.options.keyEventBind.backbutton) {
  2798. plus.key.removeEventListener('backbutton', __back);
  2799. }
  2800. if(!$.options.keyEventBind.menubutton) {
  2801. plus.key.removeEventListener('menubutton', __menu);
  2802. }
  2803. });
  2804. }
  2805. });
  2806. })(mui, window);
  2807. /**
  2808. * mui.init pulldownRefresh
  2809. * @param {type} $
  2810. * @returns {undefined}
  2811. */
  2812. (function($) {
  2813. $.addInit({
  2814. name: 'pullrefresh',
  2815. index: 1000,
  2816. handle: function() {
  2817. var options = $.options;
  2818. var pullRefreshOptions = options.pullRefresh || {};
  2819. var hasPulldown = pullRefreshOptions.down && pullRefreshOptions.down.hasOwnProperty('callback');
  2820. var hasPullup = pullRefreshOptions.up && pullRefreshOptions.up.hasOwnProperty('callback');
  2821. if(hasPulldown || hasPullup) {
  2822. var container = pullRefreshOptions.container;
  2823. if(container) {
  2824. var $container = $(container);
  2825. if($container.length === 1) {
  2826. if($.os.plus) { //5+环境
  2827. if(hasPulldown && pullRefreshOptions.down.style == "circle") { //原生转圈
  2828. $.plusReady(function() {
  2829. //这里改写$.fn.pullRefresh
  2830. $.fn.pullRefresh = $.fn.pullRefresh_native;
  2831. $container.pullRefresh(pullRefreshOptions);
  2832. });
  2833. } else if($.os.android) { //非原生转圈,但是Android环境
  2834. $.plusReady(function() {
  2835. //这里改写$.fn.pullRefresh
  2836. $.fn.pullRefresh = $.fn.pullRefresh_native
  2837. var webview = plus.webview.currentWebview();
  2838. if(window.__NWin_Enable__ === false) { //不支持多webview
  2839. $container.pullRefresh(pullRefreshOptions);
  2840. } else {
  2841. if(hasPullup) {
  2842. //当前页面初始化pullup
  2843. var upOptions = {};
  2844. upOptions.up = pullRefreshOptions.up;
  2845. upOptions.webviewId = webview.id || webview.getURL();
  2846. $container.pullRefresh(upOptions);
  2847. }
  2848. if(hasPulldown) {
  2849. var parent = webview.parent();
  2850. var id = webview.id || webview.getURL();
  2851. if(parent) {
  2852. if(!hasPullup) { //如果没有上拉加载,需要手动初始化一个默认的pullRefresh,以便当前页面容器可以调用endPulldownToRefresh等方法
  2853. $container.pullRefresh({
  2854. webviewId: id
  2855. });
  2856. }
  2857. var downOptions = {
  2858. webviewId: id //子页面id
  2859. };
  2860. downOptions.down = $.extend({}, pullRefreshOptions.down);
  2861. downOptions.down.callback = '_CALLBACK';
  2862. //改写父页面的$.fn.pullRefresh
  2863. parent.evalJS("mui.fn.pullRefresh=mui.fn.pullRefresh_native");
  2864. //父页面初始化pulldown
  2865. parent.evalJS("mui&&mui(document.querySelector('.mui-content')).pullRefresh('" + JSON.stringify(downOptions) + "')");
  2866. }
  2867. }
  2868. }
  2869. });
  2870. } else { //非原生转圈,iOS环境
  2871. $container.pullRefresh(pullRefreshOptions);
  2872. }
  2873. } else {
  2874. $container.pullRefresh(pullRefreshOptions);
  2875. }
  2876. }
  2877. }
  2878. }
  2879. }
  2880. });
  2881. })(mui);
  2882. /**
  2883. * mui ajax
  2884. * @param {type} $
  2885. * @returns {undefined}
  2886. */
  2887. (function($, window, undefined) {
  2888. var jsonType = 'application/json';
  2889. var htmlType = 'text/html';
  2890. var rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi;
  2891. var scriptTypeRE = /^(?:text|application)\/javascript/i;
  2892. var xmlTypeRE = /^(?:text|application)\/xml/i;
  2893. var blankRE = /^\s*$/;
  2894. $.ajaxSettings = {
  2895. type: 'GET',
  2896. beforeSend: $.noop,
  2897. success: $.noop,
  2898. error: $.noop,
  2899. complete: $.noop,
  2900. context: null,
  2901. xhr: function(protocol) {
  2902. return new window.XMLHttpRequest();
  2903. },
  2904. accepts: {
  2905. script: 'text/javascript, application/javascript, application/x-javascript',
  2906. json: jsonType,
  2907. xml: 'application/xml, text/xml',
  2908. html: htmlType,
  2909. text: 'text/plain'
  2910. },
  2911. timeout: 0,
  2912. processData: true,
  2913. cache: true
  2914. };
  2915. var ajaxBeforeSend = function(xhr, settings) {
  2916. var context = settings.context
  2917. if(settings.beforeSend.call(context, xhr, settings) === false) {
  2918. return false;
  2919. }
  2920. };
  2921. var ajaxSuccess = function(data, xhr, settings) {
  2922. settings.success.call(settings.context, data, 'success', xhr);
  2923. ajaxComplete('success', xhr, settings);
  2924. };
  2925. // type: "timeout", "error", "abort", "parsererror"
  2926. var ajaxError = function(error, type, xhr, settings) {
  2927. settings.error.call(settings.context, xhr, type, error);
  2928. ajaxComplete(type, xhr, settings);
  2929. };
  2930. // status: "success", "notmodified", "error", "timeout", "abort", "parsererror"
  2931. var ajaxComplete = function(status, xhr, settings) {
  2932. settings.complete.call(settings.context, xhr, status);
  2933. };
  2934. var serialize = function(params, obj, traditional, scope) {
  2935. var type, array = $.isArray(obj),
  2936. hash = $.isPlainObject(obj);
  2937. $.each(obj, function(key, value) {
  2938. type = $.type(value);
  2939. if(scope) {
  2940. key = traditional ? scope :
  2941. scope + '[' + (hash || type === 'object' || type === 'array' ? key : '') + ']';
  2942. }
  2943. // handle data in serializeArray() format
  2944. if(!scope && array) {
  2945. params.add(value.name, value.value);
  2946. }
  2947. // recurse into nested objects
  2948. else if(type === "array" || (!traditional && type === "object")) {
  2949. serialize(params, value, traditional, key);
  2950. } else {
  2951. params.add(key, value);
  2952. }
  2953. });
  2954. };
  2955. var serializeData = function(options) {
  2956. if(options.processData && options.data && typeof options.data !== "string") {
  2957. var contentType = options.contentType;
  2958. if(!contentType && options.headers) {
  2959. contentType = options.headers['Content-Type'];
  2960. }
  2961. if(contentType && ~contentType.indexOf(jsonType)) { //application/json
  2962. options.data = JSON.stringify(options.data);
  2963. } else {
  2964. options.data = $.param(options.data, options.traditional);
  2965. }
  2966. }
  2967. if(options.data && (!options.type || options.type.toUpperCase() === 'GET')) {
  2968. options.url = appendQuery(options.url, options.data);
  2969. options.data = undefined;
  2970. }
  2971. };
  2972. var appendQuery = function(url, query) {
  2973. if(query === '') {
  2974. return url;
  2975. }
  2976. return(url + '&' + query).replace(/[&?]{1,2}/, '?');
  2977. };
  2978. var mimeToDataType = function(mime) {
  2979. if(mime) {
  2980. mime = mime.split(';', 2)[0];
  2981. }
  2982. return mime && (mime === htmlType ? 'html' :
  2983. mime === jsonType ? 'json' :
  2984. scriptTypeRE.test(mime) ? 'script' :
  2985. xmlTypeRE.test(mime) && 'xml') || 'text';
  2986. };
  2987. var parseArguments = function(url, data, success, dataType) {
  2988. if($.isFunction(data)) {
  2989. dataType = success, success = data, data = undefined;
  2990. }
  2991. if(!$.isFunction(success)) {
  2992. dataType = success, success = undefined;
  2993. }
  2994. return {
  2995. url: url,
  2996. data: data,
  2997. success: success,
  2998. dataType: dataType
  2999. };
  3000. };
  3001. $.ajax = function(url, options) {
  3002. if(typeof url === "object") {
  3003. options = url;
  3004. url = undefined;
  3005. }
  3006. var settings = options || {};
  3007. settings.url = url || settings.url;
  3008. for(var key in $.ajaxSettings) {
  3009. if(settings[key] === undefined) {
  3010. settings[key] = $.ajaxSettings[key];
  3011. }
  3012. }
  3013. serializeData(settings);
  3014. var dataType = settings.dataType;
  3015. if(settings.cache === false || ((!options || options.cache !== true) && ('script' === dataType))) {
  3016. settings.url = appendQuery(settings.url, '_=' + $.now());
  3017. }
  3018. var mime = settings.accepts[dataType && dataType.toLowerCase()];
  3019. var headers = {};
  3020. var setHeader = function(name, value) {
  3021. headers[name.toLowerCase()] = [name, value];
  3022. };
  3023. var protocol = /^([\w-]+:)\/\//.test(settings.url) ? RegExp.$1 : window.location.protocol;
  3024. var xhr = settings.xhr(settings);
  3025. var nativeSetHeader = xhr.setRequestHeader;
  3026. var abortTimeout;
  3027. setHeader('X-Requested-With', 'XMLHttpRequest');
  3028. setHeader('Accept', mime || '*/*');
  3029. if(!!(mime = settings.mimeType || mime)) {
  3030. if(mime.indexOf(',') > -1) {
  3031. mime = mime.split(',', 2)[0];
  3032. }
  3033. xhr.overrideMimeType && xhr.overrideMimeType(mime);
  3034. }
  3035. if(settings.contentType || (settings.contentType !== false && settings.data && settings.type.toUpperCase() !== 'GET')) {
  3036. setHeader('Content-Type', settings.contentType || 'application/x-www-form-urlencoded');
  3037. }
  3038. if(settings.headers) {
  3039. for(var name in settings.headers)
  3040. setHeader(name, settings.headers[name]);
  3041. }
  3042. xhr.setRequestHeader = setHeader;
  3043. xhr.onreadystatechange = function() {
  3044. if(xhr.readyState === 4) {
  3045. xhr.onreadystatechange = $.noop;
  3046. clearTimeout(abortTimeout);
  3047. var result, error = false;
  3048. var isLocal = protocol === 'file:';
  3049. if((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304 || (xhr.status === 0 && isLocal && xhr.responseText)) {
  3050. dataType = dataType || mimeToDataType(settings.mimeType || xhr.getResponseHeader('content-type'));
  3051. result = xhr.responseText;
  3052. try {
  3053. // http://perfectionkills.com/global-eval-what-are-the-options/
  3054. if(dataType === 'script') {
  3055. (1, eval)(result);
  3056. } else if(dataType === 'xml') {
  3057. result = xhr.responseXML;
  3058. } else if(dataType === 'json') {
  3059. result = blankRE.test(result) ? null : $.parseJSON(result);
  3060. }
  3061. } catch(e) {
  3062. error = e;
  3063. }
  3064. if(error) {
  3065. ajaxError(error, 'parsererror', xhr, settings);
  3066. } else {
  3067. ajaxSuccess(result, xhr, settings);
  3068. }
  3069. } else {
  3070. var status = xhr.status ? 'error' : 'abort';
  3071. var statusText = xhr.statusText || null;
  3072. if(isLocal) {
  3073. status = 'error';
  3074. statusText = '404';
  3075. }
  3076. ajaxError(statusText, status, xhr, settings);
  3077. }
  3078. }
  3079. };
  3080. if(ajaxBeforeSend(xhr, settings) === false) {
  3081. xhr.abort();
  3082. ajaxError(null, 'abort', xhr, settings);
  3083. return xhr;
  3084. }
  3085. if(settings.xhrFields) {
  3086. for(var name in settings.xhrFields) {
  3087. xhr[name] = settings.xhrFields[name];
  3088. }
  3089. }
  3090. var async = 'async' in settings ? settings.async : true;
  3091. xhr.open(settings.type.toUpperCase(), settings.url, async, settings.username, settings.password);
  3092. for(var name in headers) {
  3093. if(headers.hasOwnProperty(name)) {
  3094. nativeSetHeader.apply(xhr, headers[name]);
  3095. }
  3096. }
  3097. if(settings.timeout > 0) {
  3098. abortTimeout = setTimeout(function() {
  3099. xhr.onreadystatechange = $.noop;
  3100. xhr.abort();
  3101. ajaxError(null, 'timeout', xhr, settings);
  3102. }, settings.timeout);
  3103. }
  3104. xhr.send(settings.data ? settings.data : null);
  3105. return xhr;
  3106. };
  3107. $.param = function(obj, traditional) {
  3108. var params = [];
  3109. params.add = function(k, v) {
  3110. this.push(encodeURIComponent(k) + '=' + encodeURIComponent(v));
  3111. };
  3112. serialize(params, obj, traditional);
  3113. return params.join('&').replace(/%20/g, '+');
  3114. };
  3115. $.get = function( /* url, data, success, dataType */ ) {
  3116. return $.ajax(parseArguments.apply(null, arguments));
  3117. };
  3118. $.post = function( /* url, data, success, dataType */ ) {
  3119. var options = parseArguments.apply(null, arguments);
  3120. options.type = 'POST';
  3121. return $.ajax(options);
  3122. };
  3123. $.getJSON = function( /* url, data, success */ ) {
  3124. var options = parseArguments.apply(null, arguments);
  3125. options.dataType = 'json';
  3126. return $.ajax(options);
  3127. };
  3128. $.fn.load = function(url, data, success) {
  3129. if(!this.length)
  3130. return this;
  3131. var self = this,
  3132. parts = url.split(/\s/),
  3133. selector,
  3134. options = parseArguments(url, data, success),
  3135. callback = options.success;
  3136. if(parts.length > 1)
  3137. options.url = parts[0], selector = parts[1];
  3138. options.success = function(response) {
  3139. if(selector) {
  3140. var div = document.createElement('div');
  3141. div.innerHTML = response.replace(rscript, "");
  3142. var selectorDiv = document.createElement('div');
  3143. var childs = div.querySelectorAll(selector);
  3144. if(childs && childs.length > 0) {
  3145. for(var i = 0, len = childs.length; i < len; i++) {
  3146. selectorDiv.appendChild(childs[i]);
  3147. }
  3148. }
  3149. self[0].innerHTML = selectorDiv.innerHTML;
  3150. } else {
  3151. self[0].innerHTML = response;
  3152. }
  3153. callback && callback.apply(self, arguments);
  3154. };
  3155. $.ajax(options);
  3156. return this;
  3157. };
  3158. })(mui, window);
  3159. /**
  3160. * 5+ ajax
  3161. */
  3162. (function($) {
  3163. var originAnchor = document.createElement('a');
  3164. originAnchor.href = window.location.href;
  3165. $.plusReady(function() {
  3166. $.ajaxSettings = $.extend($.ajaxSettings, {
  3167. xhr: function(settings) {
  3168. if(settings.crossDomain) { //强制使用plus跨域
  3169. return new plus.net.XMLHttpRequest();
  3170. }
  3171. //仅在webview的url为远程文件,且ajax请求的资源不同源下使用plus.net.XMLHttpRequest
  3172. if(originAnchor.protocol !== 'file:') {
  3173. var urlAnchor = document.createElement('a');
  3174. urlAnchor.href = settings.url;
  3175. urlAnchor.href = urlAnchor.href;
  3176. settings.crossDomain = (originAnchor.protocol + '//' + originAnchor.host) !== (urlAnchor.protocol + '//' + urlAnchor.host);
  3177. if(settings.crossDomain) {
  3178. return new plus.net.XMLHttpRequest();
  3179. }
  3180. }
  3181. if($.os.ios && window.webkit && window.webkit.messageHandlers) { //wkwebview下同样使用5+ xhr
  3182. return new plus.net.XMLHttpRequest();
  3183. }
  3184. return new window.XMLHttpRequest();
  3185. }
  3186. });
  3187. });
  3188. })(mui);
  3189. /**
  3190. * mui layout(offset[,position,width,height...])
  3191. * @param {type} $
  3192. * @param {type} window
  3193. * @param {type} undefined
  3194. * @returns {undefined}
  3195. */
  3196. (function($, window, undefined) {
  3197. $.offset = function(element) {
  3198. var box = {
  3199. top: 0,
  3200. left: 0
  3201. };
  3202. if(typeof element.getBoundingClientRect !== undefined) {
  3203. box = element.getBoundingClientRect();
  3204. }
  3205. return {
  3206. top: box.top + window.pageYOffset - element.clientTop,
  3207. left: box.left + window.pageXOffset - element.clientLeft
  3208. };
  3209. };
  3210. })(mui, window);
  3211. /**
  3212. * mui animation
  3213. */
  3214. (function($, window) {
  3215. /**
  3216. * scrollTo
  3217. */
  3218. $.scrollTo = function(scrollTop, duration, callback) {
  3219. duration = duration || 1000;
  3220. var scroll = function(duration) {
  3221. if(duration <= 0) {
  3222. window.scrollTo(0, scrollTop);
  3223. callback && callback();
  3224. return;
  3225. }
  3226. var distaince = scrollTop - window.scrollY;
  3227. setTimeout(function() {
  3228. window.scrollTo(0, window.scrollY + distaince / duration * 10);
  3229. scroll(duration - 10);
  3230. }, 16.7);
  3231. };
  3232. scroll(duration);
  3233. };
  3234. $.animationFrame = function(cb) {
  3235. var args, isQueued, context;
  3236. return function() {
  3237. args = arguments;
  3238. context = this;
  3239. if(!isQueued) {
  3240. isQueued = true;
  3241. requestAnimationFrame(function() {
  3242. cb.apply(context, args);
  3243. isQueued = false;
  3244. });
  3245. }
  3246. };
  3247. };
  3248. })(mui, window);
  3249. (function($) {
  3250. var initializing = false,
  3251. fnTest = /xyz/.test(function() {
  3252. xyz;
  3253. }) ? /\b_super\b/ : /.*/;
  3254. var Class = function() {};
  3255. Class.extend = function Fn(prop) {
  3256. var _super = this.prototype;
  3257. initializing = true;
  3258. var prototype = new this();
  3259. initializing = false;
  3260. for(var name in prop) {
  3261. prototype[name] = typeof prop[name] == "function" &&
  3262. typeof _super[name] == "function" && fnTest.test(prop[name]) ?
  3263. (function(name, fn) {
  3264. return function() {
  3265. var tmp = this._super;
  3266. this._super = _super[name];
  3267. var ret = fn.apply(this, arguments);
  3268. this._super = tmp;
  3269. return ret;
  3270. };
  3271. })(name, prop[name]) :
  3272. prop[name];
  3273. }
  3274. function Class() {
  3275. if(!initializing && this.init)
  3276. this.init.apply(this, arguments);
  3277. }
  3278. Class.prototype = prototype;
  3279. Class.prototype.constructor = Class;
  3280. //Class.extend = arguments.callee;
  3281. Class.extend = Fn;
  3282. return Class;
  3283. };
  3284. $.Class = Class;
  3285. })(mui);
  3286. (function($, document, undefined) {
  3287. var CLASS_PULL_TOP_POCKET = 'mui-pull-top-pocket';
  3288. var CLASS_PULL_BOTTOM_POCKET = 'mui-pull-bottom-pocket';
  3289. var CLASS_PULL = 'mui-pull';
  3290. var CLASS_PULL_LOADING = 'mui-pull-loading';
  3291. var CLASS_PULL_CAPTION = 'mui-pull-caption';
  3292. var CLASS_PULL_CAPTION_DOWN = 'mui-pull-caption-down';
  3293. var CLASS_PULL_CAPTION_REFRESH = 'mui-pull-caption-refresh';
  3294. var CLASS_PULL_CAPTION_NOMORE = 'mui-pull-caption-nomore';
  3295. var CLASS_ICON = 'mui-icon';
  3296. var CLASS_SPINNER = 'mui-spinner';
  3297. var CLASS_ICON_PULLDOWN = 'mui-icon-pulldown';
  3298. var CLASS_BLOCK = 'mui-block';
  3299. var CLASS_HIDDEN = 'mui-hidden';
  3300. var CLASS_VISIBILITY = 'mui-visibility';
  3301. var CLASS_LOADING_UP = CLASS_PULL_LOADING + ' ' + CLASS_ICON + ' ' + CLASS_ICON_PULLDOWN;
  3302. var CLASS_LOADING_DOWN = CLASS_PULL_LOADING + ' ' + CLASS_ICON + ' ' + CLASS_ICON_PULLDOWN;
  3303. var CLASS_LOADING = CLASS_PULL_LOADING + ' ' + CLASS_ICON + ' ' + CLASS_SPINNER;
  3304. var pocketHtml = ['<div class="' + CLASS_PULL + '">', '<div class="{icon}"></div>', '<div class="' + CLASS_PULL_CAPTION + '">{contentrefresh}</div>', '</div>'].join('');
  3305. var PullRefresh = {
  3306. init: function(element, options) {
  3307. this._super(element, $.extend(true, {
  3308. scrollY: true,
  3309. scrollX: false,
  3310. indicators: true,
  3311. deceleration: 0.003,
  3312. down: {
  3313. height: 50,
  3314. contentinit: '下拉可以刷新',
  3315. contentdown: '下拉可以刷新',
  3316. contentover: '释放立即刷新',
  3317. contentrefresh: '正在刷新...'
  3318. },
  3319. up: {
  3320. height: 50,
  3321. auto: false,
  3322. contentinit: '上拉显示更多',
  3323. contentdown: '上拉显示更多',
  3324. contentrefresh: '正在加载...',
  3325. contentnomore: '没有更多数据了',
  3326. duration: 300
  3327. }
  3328. }, options));
  3329. },
  3330. _init: function() {
  3331. this._super();
  3332. this._initPocket();
  3333. },
  3334. _initPulldownRefresh: function() {
  3335. this.pulldown = true;
  3336. if(this.topPocket) {
  3337. this.pullPocket = this.topPocket;
  3338. this.pullPocket.classList.add(CLASS_BLOCK);
  3339. this.pullPocket.classList.add(CLASS_VISIBILITY);
  3340. this.pullCaption = this.topCaption;
  3341. this.pullLoading = this.topLoading;
  3342. }
  3343. },
  3344. _initPullupRefresh: function() {
  3345. this.pulldown = false;
  3346. if(this.bottomPocket) {
  3347. this.pullPocket = this.bottomPocket;
  3348. this.pullPocket.classList.add(CLASS_BLOCK);
  3349. this.pullPocket.classList.add(CLASS_VISIBILITY);
  3350. this.pullCaption = this.bottomCaption;
  3351. this.pullLoading = this.bottomLoading;
  3352. }
  3353. },
  3354. _initPocket: function() {
  3355. var options = this.options;
  3356. if(options.down && options.down.hasOwnProperty('callback')) {
  3357. this.topPocket = this.scroller.querySelector('.' + CLASS_PULL_TOP_POCKET);
  3358. if(!this.topPocket) {
  3359. this.topPocket = this._createPocket(CLASS_PULL_TOP_POCKET, options.down, CLASS_LOADING_DOWN);
  3360. this.wrapper.insertBefore(this.topPocket, this.wrapper.firstChild);
  3361. }
  3362. this.topLoading = this.topPocket.querySelector('.' + CLASS_PULL_LOADING);
  3363. this.topCaption = this.topPocket.querySelector('.' + CLASS_PULL_CAPTION);
  3364. }
  3365. if(options.up && options.up.hasOwnProperty('callback')) {
  3366. this.bottomPocket = this.scroller.querySelector('.' + CLASS_PULL_BOTTOM_POCKET);
  3367. if(!this.bottomPocket) {
  3368. this.bottomPocket = this._createPocket(CLASS_PULL_BOTTOM_POCKET, options.up, CLASS_LOADING);
  3369. this.scroller.appendChild(this.bottomPocket);
  3370. }
  3371. this.bottomLoading = this.bottomPocket.querySelector('.' + CLASS_PULL_LOADING);
  3372. this.bottomCaption = this.bottomPocket.querySelector('.' + CLASS_PULL_CAPTION);
  3373. //TODO only for h5
  3374. this.wrapper.addEventListener('scrollbottom', this);
  3375. }
  3376. },
  3377. _createPocket: function(clazz, options, iconClass) {
  3378. var pocket = document.createElement('div');
  3379. pocket.className = clazz;
  3380. pocket.innerHTML = pocketHtml.replace('{contentrefresh}', options.contentinit).replace('{icon}', iconClass);
  3381. return pocket;
  3382. },
  3383. _resetPullDownLoading: function() {
  3384. var loading = this.pullLoading;
  3385. if(loading) {
  3386. this.pullCaption.innerHTML = this.options.down.contentdown;
  3387. loading.style.webkitTransition = "";
  3388. loading.style.webkitTransform = "";
  3389. loading.style.webkitAnimation = "";
  3390. loading.className = CLASS_LOADING_DOWN;
  3391. }
  3392. },
  3393. _setCaptionClass: function(isPulldown, caption, title) {
  3394. if(!isPulldown) {
  3395. switch(title) {
  3396. case this.options.up.contentdown:
  3397. caption.className = CLASS_PULL_CAPTION + ' ' + CLASS_PULL_CAPTION_DOWN;
  3398. break;
  3399. case this.options.up.contentrefresh:
  3400. caption.className = CLASS_PULL_CAPTION + ' ' + CLASS_PULL_CAPTION_REFRESH
  3401. break;
  3402. case this.options.up.contentnomore:
  3403. caption.className = CLASS_PULL_CAPTION + ' ' + CLASS_PULL_CAPTION_NOMORE;
  3404. break;
  3405. }
  3406. }
  3407. },
  3408. _setCaption: function(title, reset) {
  3409. if(this.loading) {
  3410. return;
  3411. }
  3412. var options = this.options;
  3413. var pocket = this.pullPocket;
  3414. var caption = this.pullCaption;
  3415. var loading = this.pullLoading;
  3416. var isPulldown = this.pulldown;
  3417. var self = this;
  3418. if(pocket) {
  3419. if(reset) {
  3420. setTimeout(function() {
  3421. caption.innerHTML = self.lastTitle = title;
  3422. if(isPulldown) {
  3423. loading.className = CLASS_LOADING_DOWN;
  3424. } else {
  3425. self._setCaptionClass(false, caption, title);
  3426. loading.className = CLASS_LOADING;
  3427. }
  3428. loading.style.webkitAnimation = "";
  3429. loading.style.webkitTransition = "";
  3430. loading.style.webkitTransform = "";
  3431. }, 100);
  3432. } else {
  3433. if(title !== this.lastTitle) {
  3434. caption.innerHTML = title;
  3435. if(isPulldown) {
  3436. if(title === options.down.contentrefresh) {
  3437. loading.className = CLASS_LOADING;
  3438. loading.style.webkitAnimation = "spinner-spin 1s step-end infinite";
  3439. } else if(title === options.down.contentover) {
  3440. loading.className = CLASS_LOADING_UP;
  3441. loading.style.webkitTransition = "-webkit-transform 0.3s ease-in";
  3442. loading.style.webkitTransform = "rotate(180deg)";
  3443. } else if(title === options.down.contentdown) {
  3444. loading.className = CLASS_LOADING_DOWN;
  3445. loading.style.webkitTransition = "-webkit-transform 0.3s ease-in";
  3446. loading.style.webkitTransform = "rotate(0deg)";
  3447. }
  3448. } else {
  3449. if(title === options.up.contentrefresh) {
  3450. loading.className = CLASS_LOADING + ' ' + CLASS_VISIBILITY;
  3451. } else {
  3452. loading.className = CLASS_LOADING + ' ' + CLASS_HIDDEN;
  3453. }
  3454. self._setCaptionClass(false, caption, title);
  3455. }
  3456. this.lastTitle = title;
  3457. }
  3458. }
  3459. }
  3460. }
  3461. };
  3462. $.PullRefresh = PullRefresh;
  3463. })(mui, document);
  3464. (function($, window, document, undefined) {
  3465. var CLASS_SCROLL = 'mui-scroll';
  3466. var CLASS_SCROLLBAR = 'mui-scrollbar';
  3467. var CLASS_INDICATOR = 'mui-scrollbar-indicator';
  3468. var CLASS_SCROLLBAR_VERTICAL = CLASS_SCROLLBAR + '-vertical';
  3469. var CLASS_SCROLLBAR_HORIZONTAL = CLASS_SCROLLBAR + '-horizontal';
  3470. var CLASS_ACTIVE = 'mui-active';
  3471. var ease = {
  3472. quadratic: {
  3473. style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
  3474. fn: function(k) {
  3475. return k * (2 - k);
  3476. }
  3477. },
  3478. circular: {
  3479. style: 'cubic-bezier(0.1, 0.57, 0.1, 1)',
  3480. fn: function(k) {
  3481. return Math.sqrt(1 - (--k * k));
  3482. }
  3483. },
  3484. outCirc: {
  3485. style: 'cubic-bezier(0.075, 0.82, 0.165, 1)'
  3486. },
  3487. outCubic: {
  3488. style: 'cubic-bezier(0.165, 0.84, 0.44, 1)'
  3489. }
  3490. }
  3491. var Scroll = $.Class.extend({
  3492. init: function(element, options) {
  3493. this.wrapper = this.element = element;
  3494. this.scroller = this.wrapper.children[0];
  3495. this.scrollerStyle = this.scroller && this.scroller.style;
  3496. this.stopped = false;
  3497. this.options = $.extend(true, {
  3498. scrollY: true, //是否竖向滚动
  3499. scrollX: false, //是否横向滚动
  3500. startX: 0, //初始化时滚动至x
  3501. startY: 0, //初始化时滚动至y
  3502. indicators: true, //是否显示滚动条
  3503. stopPropagation: false,
  3504. hardwareAccelerated: true,
  3505. fixedBadAndorid: false,
  3506. preventDefaultException: {
  3507. tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|VIDEO)$/
  3508. },
  3509. momentum: true,
  3510. snapX: 0.5, //横向切换距离(以当前容器宽度为基准)
  3511. snap: false, //图片轮播,拖拽式选项卡
  3512. bounce: true, //是否启用回弹
  3513. bounceTime: 500, //回弹动画时间
  3514. bounceEasing: ease.outCirc, //回弹动画曲线
  3515. scrollTime: 500,
  3516. scrollEasing: ease.outCubic, //轮播动画曲线
  3517. directionLockThreshold: 5,
  3518. parallaxElement: false, //视差元素
  3519. parallaxRatio: 0.5
  3520. }, options);
  3521. this.x = 0;
  3522. this.y = 0;
  3523. this.translateZ = this.options.hardwareAccelerated ? ' translateZ(0)' : '';
  3524. this._init();
  3525. if(this.scroller) {
  3526. this.refresh();
  3527. // if (this.options.startX !== 0 || this.options.startY !== 0) { //需要判断吗?后续根据实际情况再看看
  3528. this.scrollTo(this.options.startX, this.options.startY);
  3529. // }
  3530. }
  3531. },
  3532. _init: function() {
  3533. this._initParallax();
  3534. this._initIndicators();
  3535. this._initEvent();
  3536. },
  3537. _initParallax: function() {
  3538. if(this.options.parallaxElement) {
  3539. this.parallaxElement = document.querySelector(this.options.parallaxElement);
  3540. this.parallaxStyle = this.parallaxElement.style;
  3541. this.parallaxHeight = this.parallaxElement.offsetHeight;
  3542. this.parallaxImgStyle = this.parallaxElement.querySelector('img').style;
  3543. }
  3544. },
  3545. _initIndicators: function() {
  3546. var self = this;
  3547. self.indicators = [];
  3548. if(!this.options.indicators) {
  3549. return;
  3550. }
  3551. var indicators = [],
  3552. indicator;
  3553. // Vertical scrollbar
  3554. if(self.options.scrollY) {
  3555. indicator = {
  3556. el: this._createScrollBar(CLASS_SCROLLBAR_VERTICAL),
  3557. listenX: false
  3558. };
  3559. this.wrapper.appendChild(indicator.el);
  3560. indicators.push(indicator);
  3561. }
  3562. // Horizontal scrollbar
  3563. if(this.options.scrollX) {
  3564. indicator = {
  3565. el: this._createScrollBar(CLASS_SCROLLBAR_HORIZONTAL),
  3566. listenY: false
  3567. };
  3568. this.wrapper.appendChild(indicator.el);
  3569. indicators.push(indicator);
  3570. }
  3571. for(var i = indicators.length; i--;) {
  3572. this.indicators.push(new Indicator(this, indicators[i]));
  3573. }
  3574. },
  3575. _initSnap: function() {
  3576. this.currentPage = {};
  3577. this.pages = [];
  3578. var snaps = this.snaps;
  3579. var length = snaps.length;
  3580. var m = 0;
  3581. var n = -1;
  3582. var x = 0;
  3583. var leftX = 0;
  3584. var rightX = 0;
  3585. var snapX = 0;
  3586. for(var i = 0; i < length; i++) {
  3587. var snap = snaps[i];
  3588. var offsetLeft = snap.offsetLeft;
  3589. var offsetWidth = snap.offsetWidth;
  3590. if(i === 0 || offsetLeft <= snaps[i - 1].offsetLeft) {
  3591. m = 0;
  3592. n++;
  3593. }
  3594. if(!this.pages[m]) {
  3595. this.pages[m] = [];
  3596. }
  3597. x = this._getSnapX(offsetLeft);
  3598. snapX = Math.round((offsetWidth) * this.options.snapX);
  3599. leftX = x - snapX;
  3600. rightX = x - offsetWidth + snapX;
  3601. this.pages[m][n] = {
  3602. x: x,
  3603. leftX: leftX,
  3604. rightX: rightX,
  3605. pageX: m,
  3606. element: snap
  3607. }
  3608. if(snap.classList.contains(CLASS_ACTIVE)) {
  3609. this.currentPage = this.pages[m][0];
  3610. }
  3611. if(x >= this.maxScrollX) {
  3612. m++;
  3613. }
  3614. }
  3615. this.options.startX = this.currentPage.x || 0;
  3616. },
  3617. _getSnapX: function(offsetLeft) {
  3618. return Math.max(Math.min(0, -offsetLeft + (this.wrapperWidth / 2)), this.maxScrollX);
  3619. },
  3620. _gotoPage: function(index) {
  3621. this.currentPage = this.pages[Math.min(index, this.pages.length - 1)][0];
  3622. for(var i = 0, len = this.snaps.length; i < len; i++) {
  3623. if(i === index) {
  3624. this.snaps[i].classList.add(CLASS_ACTIVE);
  3625. } else {
  3626. this.snaps[i].classList.remove(CLASS_ACTIVE);
  3627. }
  3628. }
  3629. this.scrollTo(this.currentPage.x, 0, this.options.scrollTime);
  3630. },
  3631. _nearestSnap: function(x) {
  3632. if(!this.pages.length) {
  3633. return {
  3634. x: 0,
  3635. pageX: 0
  3636. };
  3637. }
  3638. var i = 0;
  3639. var length = this.pages.length;
  3640. if(x > 0) {
  3641. x = 0;
  3642. } else if(x < this.maxScrollX) {
  3643. x = this.maxScrollX;
  3644. }
  3645. for(; i < length; i++) {
  3646. var nearestX = this.direction === 'left' ? this.pages[i][0].leftX : this.pages[i][0].rightX;
  3647. if(x >= nearestX) {
  3648. return this.pages[i][0];
  3649. }
  3650. }
  3651. return {
  3652. x: 0,
  3653. pageX: 0
  3654. };
  3655. },
  3656. _initEvent: function(detach) {
  3657. var action = detach ? 'removeEventListener' : 'addEventListener';
  3658. window[action]('orientationchange', this);
  3659. window[action]('resize', this);
  3660. this.scroller[action]('webkitTransitionEnd', this);
  3661. this.wrapper[action]($.EVENT_START, this);
  3662. this.wrapper[action]($.EVENT_CANCEL, this);
  3663. this.wrapper[action]($.EVENT_END, this);
  3664. this.wrapper[action]('drag', this);
  3665. this.wrapper[action]('dragend', this);
  3666. this.wrapper[action]('flick', this);
  3667. this.wrapper[action]('scrollend', this);
  3668. if(this.options.scrollX) {
  3669. this.wrapper[action]('swiperight', this);
  3670. }
  3671. var segmentedControl = this.wrapper.querySelector('.mui-segmented-control');
  3672. if(segmentedControl) { //靠,这个bug排查了一下午,阻止hash跳转,一旦hash跳转会导致可拖拽选项卡的tab不见
  3673. mui(segmentedControl)[detach ? 'off' : 'on']('click', 'a', $.preventDefault);
  3674. }
  3675. this.wrapper[action]('scrollstart', this);
  3676. this.wrapper[action]('refresh', this);
  3677. },
  3678. _handleIndicatorScrollend: function() {
  3679. this.indicators.map(function(indicator) {
  3680. indicator.fade();
  3681. });
  3682. },
  3683. _handleIndicatorScrollstart: function() {
  3684. this.indicators.map(function(indicator) {
  3685. indicator.fade(1);
  3686. });
  3687. },
  3688. _handleIndicatorRefresh: function() {
  3689. this.indicators.map(function(indicator) {
  3690. indicator.refresh();
  3691. });
  3692. },
  3693. handleEvent: function(e) {
  3694. if(this.stopped) {
  3695. this.resetPosition();
  3696. return;
  3697. }
  3698. switch(e.type) {
  3699. case $.EVENT_START:
  3700. this._start(e);
  3701. break;
  3702. case 'drag':
  3703. this.options.stopPropagation && e.stopPropagation();
  3704. this._drag(e);
  3705. break;
  3706. case 'dragend':
  3707. case 'flick':
  3708. this.options.stopPropagation && e.stopPropagation();
  3709. this._flick(e);
  3710. break;
  3711. case $.EVENT_CANCEL:
  3712. case $.EVENT_END:
  3713. this._end(e);
  3714. break;
  3715. case 'webkitTransitionEnd':
  3716. this.transitionTimer && this.transitionTimer.cancel();
  3717. this._transitionEnd(e);
  3718. break;
  3719. case 'scrollstart':
  3720. this._handleIndicatorScrollstart(e);
  3721. break;
  3722. case 'scrollend':
  3723. this._handleIndicatorScrollend(e);
  3724. this._scrollend(e);
  3725. e.stopPropagation();
  3726. break;
  3727. case 'orientationchange':
  3728. case 'resize':
  3729. this._resize();
  3730. break;
  3731. case 'swiperight':
  3732. e.stopPropagation();
  3733. break;
  3734. case 'refresh':
  3735. this._handleIndicatorRefresh(e);
  3736. break;
  3737. }
  3738. },
  3739. _start: function(e) {
  3740. this.moved = this.needReset = false;
  3741. this._transitionTime();
  3742. if(this.isInTransition) {
  3743. this.needReset = true;
  3744. this.isInTransition = false;
  3745. var pos = $.parseTranslateMatrix($.getStyles(this.scroller, 'webkitTransform'));
  3746. this.setTranslate(Math.round(pos.x), Math.round(pos.y));
  3747. // this.resetPosition(); //reset
  3748. $.trigger(this.scroller, 'scrollend', this);
  3749. // e.stopPropagation();
  3750. e.preventDefault();
  3751. }
  3752. this.reLayout();
  3753. $.trigger(this.scroller, 'beforescrollstart', this);
  3754. },
  3755. _getDirectionByAngle: function(angle) {
  3756. if(angle < -80 && angle > -100) {
  3757. return 'up';
  3758. } else if(angle >= 80 && angle < 100) {
  3759. return 'down';
  3760. } else if(angle >= 170 || angle <= -170) {
  3761. return 'left';
  3762. } else if(angle >= -35 && angle <= 10) {
  3763. return 'right';
  3764. }
  3765. return null;
  3766. },
  3767. _drag: function(e) {
  3768. // if (this.needReset) {
  3769. // e.stopPropagation(); //disable parent drag(nested scroller)
  3770. // return;
  3771. // }
  3772. var detail = e.detail;
  3773. if(this.options.scrollY || detail.direction === 'up' || detail.direction === 'down') { //如果是竖向滚动或手势方向是上或下
  3774. //ios8 hack
  3775. if($.os.ios && parseFloat($.os.version) >= 8) { //多webview时,离开当前webview会导致后续touch事件不触发
  3776. var clientY = detail.gesture.touches[0].clientY;
  3777. //下拉刷新 or 上拉加载
  3778. if((clientY + 10) > window.innerHeight || clientY < 10) {
  3779. this.resetPosition(this.options.bounceTime);
  3780. return;
  3781. }
  3782. }
  3783. }
  3784. var isPreventDefault = isReturn = false;
  3785. var direction = this._getDirectionByAngle(detail.angle);
  3786. if(detail.direction === 'left' || detail.direction === 'right') {
  3787. if(this.options.scrollX) {
  3788. isPreventDefault = true;
  3789. if(!this.moved) { //识别角度(该角度导致轮播不灵敏)
  3790. // if (direction !== 'left' && direction !== 'right') {
  3791. // isReturn = true;
  3792. // } else {
  3793. $.gestures.session.lockDirection = true; //锁定方向
  3794. $.gestures.session.startDirection = detail.direction;
  3795. // }
  3796. }
  3797. } else if(this.options.scrollY && !this.moved) {
  3798. isReturn = true;
  3799. }
  3800. } else if(detail.direction === 'up' || detail.direction === 'down') {
  3801. if(this.options.scrollY) {
  3802. isPreventDefault = true;
  3803. // if (!this.moved) { //识别角度,竖向滚动似乎没必要进行小角度验证
  3804. // if (direction !== 'up' && direction !== 'down') {
  3805. // isReturn = true;
  3806. // }
  3807. // }
  3808. if(!this.moved) {
  3809. $.gestures.session.lockDirection = true; //锁定方向
  3810. $.gestures.session.startDirection = detail.direction;
  3811. }
  3812. } else if(this.options.scrollX && !this.moved) {
  3813. isReturn = true;
  3814. }
  3815. } else {
  3816. isReturn = true;
  3817. }
  3818. if(this.moved || isPreventDefault) {
  3819. e.stopPropagation(); //阻止冒泡(scroll类嵌套)
  3820. detail.gesture && detail.gesture.preventDefault();
  3821. }
  3822. if(isReturn) { //禁止非法方向滚动
  3823. return;
  3824. }
  3825. if(!this.moved) {
  3826. $.trigger(this.scroller, 'scrollstart', this);
  3827. } else {
  3828. e.stopPropagation(); //move期间阻止冒泡(scroll嵌套)
  3829. }
  3830. var deltaX = 0;
  3831. var deltaY = 0;
  3832. if(!this.moved) { //start
  3833. deltaX = detail.deltaX;
  3834. deltaY = detail.deltaY;
  3835. } else { //move
  3836. deltaX = detail.deltaX - $.gestures.session.prevTouch.deltaX;
  3837. deltaY = detail.deltaY - $.gestures.session.prevTouch.deltaY;
  3838. }
  3839. var absDeltaX = Math.abs(detail.deltaX);
  3840. var absDeltaY = Math.abs(detail.deltaY);
  3841. if(absDeltaX > absDeltaY + this.options.directionLockThreshold) {
  3842. deltaY = 0;
  3843. } else if(absDeltaY >= absDeltaX + this.options.directionLockThreshold) {
  3844. deltaX = 0;
  3845. }
  3846. deltaX = this.hasHorizontalScroll ? deltaX : 0;
  3847. deltaY = this.hasVerticalScroll ? deltaY : 0;
  3848. var newX = this.x + deltaX;
  3849. var newY = this.y + deltaY;
  3850. // Slow down if outside of the boundaries
  3851. if(newX > 0 || newX < this.maxScrollX) {
  3852. newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
  3853. }
  3854. if(newY > 0 || newY < this.maxScrollY) {
  3855. newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
  3856. }
  3857. if(!this.requestAnimationFrame) {
  3858. this._updateTranslate();
  3859. }
  3860. this.direction = detail.deltaX > 0 ? 'right' : 'left';
  3861. this.moved = true;
  3862. this.x = newX;
  3863. this.y = newY;
  3864. $.trigger(this.scroller, 'scroll', this);
  3865. },
  3866. _flick: function(e) {
  3867. // if (!this.moved || this.needReset) {
  3868. // return;
  3869. // }
  3870. if(!this.moved) {
  3871. return;
  3872. }
  3873. e.stopPropagation();
  3874. var detail = e.detail;
  3875. this._clearRequestAnimationFrame();
  3876. if(e.type === 'dragend' && detail.flick) { //dragend
  3877. return;
  3878. }
  3879. var newX = Math.round(this.x);
  3880. var newY = Math.round(this.y);
  3881. this.isInTransition = false;
  3882. // reset if we are outside of the boundaries
  3883. if(this.resetPosition(this.options.bounceTime)) {
  3884. return;
  3885. }
  3886. this.scrollTo(newX, newY); // ensures that the last position is rounded
  3887. if(e.type === 'dragend') { //dragend
  3888. $.trigger(this.scroller, 'scrollend', this);
  3889. return;
  3890. }
  3891. var time = 0;
  3892. var easing = '';
  3893. // start momentum animation if needed
  3894. if(this.options.momentum && detail.flickTime < 300) {
  3895. momentumX = this.hasHorizontalScroll ? this._momentum(this.x, detail.flickDistanceX, detail.flickTime, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : {
  3896. destination: newX,
  3897. duration: 0
  3898. };
  3899. momentumY = this.hasVerticalScroll ? this._momentum(this.y, detail.flickDistanceY, detail.flickTime, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : {
  3900. destination: newY,
  3901. duration: 0
  3902. };
  3903. newX = momentumX.destination;
  3904. newY = momentumY.destination;
  3905. time = Math.max(momentumX.duration, momentumY.duration);
  3906. this.isInTransition = true;
  3907. }
  3908. if(newX != this.x || newY != this.y) {
  3909. if(newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY) {
  3910. easing = ease.quadratic;
  3911. }
  3912. this.scrollTo(newX, newY, time, easing);
  3913. return;
  3914. }
  3915. $.trigger(this.scroller, 'scrollend', this);
  3916. // e.stopPropagation();
  3917. },
  3918. _end: function(e) {
  3919. this.needReset = false;
  3920. if((!this.moved && this.needReset) || e.type === $.EVENT_CANCEL) {
  3921. this.resetPosition();
  3922. }
  3923. },
  3924. _transitionEnd: function(e) {
  3925. if(e.target != this.scroller || !this.isInTransition) {
  3926. return;
  3927. }
  3928. this._transitionTime();
  3929. if(!this.resetPosition(this.options.bounceTime)) {
  3930. this.isInTransition = false;
  3931. $.trigger(this.scroller, 'scrollend', this);
  3932. }
  3933. },
  3934. _scrollend: function(e) {
  3935. if((this.y === 0 && this.maxScrollY === 0) || (Math.abs(this.y) > 0 && this.y <= this.maxScrollY)) {
  3936. $.trigger(this.scroller, 'scrollbottom', this);
  3937. }
  3938. },
  3939. _resize: function() {
  3940. var that = this;
  3941. clearTimeout(that.resizeTimeout);
  3942. that.resizeTimeout = setTimeout(function() {
  3943. that.refresh();
  3944. }, that.options.resizePolling);
  3945. },
  3946. _transitionTime: function(time) {
  3947. time = time || 0;
  3948. this.scrollerStyle['webkitTransitionDuration'] = time + 'ms';
  3949. if(this.parallaxElement && this.options.scrollY) { //目前仅支持竖向视差效果
  3950. this.parallaxStyle['webkitTransitionDuration'] = time + 'ms';
  3951. }
  3952. if(this.options.fixedBadAndorid && !time && $.os.isBadAndroid) {
  3953. this.scrollerStyle['webkitTransitionDuration'] = '0.001s';
  3954. if(this.parallaxElement && this.options.scrollY) { //目前仅支持竖向视差效果
  3955. this.parallaxStyle['webkitTransitionDuration'] = '0.001s';
  3956. }
  3957. }
  3958. if(this.indicators) {
  3959. for(var i = this.indicators.length; i--;) {
  3960. this.indicators[i].transitionTime(time);
  3961. }
  3962. }
  3963. if(time) { //自定义timer,保证webkitTransitionEnd始终触发
  3964. this.transitionTimer && this.transitionTimer.cancel();
  3965. this.transitionTimer = $.later(function() {
  3966. $.trigger(this.scroller, 'webkitTransitionEnd');
  3967. }, time + 100, this);
  3968. }
  3969. },
  3970. _transitionTimingFunction: function(easing) {
  3971. this.scrollerStyle['webkitTransitionTimingFunction'] = easing;
  3972. if(this.parallaxElement && this.options.scrollY) { //目前仅支持竖向视差效果
  3973. this.parallaxStyle['webkitTransitionDuration'] = easing;
  3974. }
  3975. if(this.indicators) {
  3976. for(var i = this.indicators.length; i--;) {
  3977. this.indicators[i].transitionTimingFunction(easing);
  3978. }
  3979. }
  3980. },
  3981. _translate: function(x, y) {
  3982. this.x = x;
  3983. this.y = y;
  3984. },
  3985. _clearRequestAnimationFrame: function() {
  3986. if(this.requestAnimationFrame) {
  3987. cancelAnimationFrame(this.requestAnimationFrame);
  3988. this.requestAnimationFrame = null;
  3989. }
  3990. },
  3991. _updateTranslate: function() {
  3992. var self = this;
  3993. if(self.x !== self.lastX || self.y !== self.lastY) {
  3994. self.setTranslate(self.x, self.y);
  3995. }
  3996. self.requestAnimationFrame = requestAnimationFrame(function() {
  3997. self._updateTranslate();
  3998. });
  3999. },
  4000. _createScrollBar: function(clazz) {
  4001. var scrollbar = document.createElement('div');
  4002. var indicator = document.createElement('div');
  4003. scrollbar.className = CLASS_SCROLLBAR + ' ' + clazz;
  4004. indicator.className = CLASS_INDICATOR;
  4005. scrollbar.appendChild(indicator);
  4006. if(clazz === CLASS_SCROLLBAR_VERTICAL) {
  4007. this.scrollbarY = scrollbar;
  4008. this.scrollbarIndicatorY = indicator;
  4009. } else if(clazz === CLASS_SCROLLBAR_HORIZONTAL) {
  4010. this.scrollbarX = scrollbar;
  4011. this.scrollbarIndicatorX = indicator;
  4012. }
  4013. this.wrapper.appendChild(scrollbar);
  4014. return scrollbar;
  4015. },
  4016. _preventDefaultException: function(el, exceptions) {
  4017. for(var i in exceptions) {
  4018. if(exceptions[i].test(el[i])) {
  4019. return true;
  4020. }
  4021. }
  4022. return false;
  4023. },
  4024. _reLayout: function() {
  4025. if(!this.hasHorizontalScroll) {
  4026. this.maxScrollX = 0;
  4027. this.scrollerWidth = this.wrapperWidth;
  4028. }
  4029. if(!this.hasVerticalScroll) {
  4030. this.maxScrollY = 0;
  4031. this.scrollerHeight = this.wrapperHeight;
  4032. }
  4033. this.indicators.map(function(indicator) {
  4034. indicator.refresh();
  4035. });
  4036. //以防slider类嵌套使用
  4037. if(this.options.snap && typeof this.options.snap === 'string') {
  4038. var items = this.scroller.querySelectorAll(this.options.snap);
  4039. this.itemLength = 0;
  4040. this.snaps = [];
  4041. for(var i = 0, len = items.length; i < len; i++) {
  4042. var item = items[i];
  4043. if(item.parentNode === this.scroller) {
  4044. this.itemLength++;
  4045. this.snaps.push(item);
  4046. }
  4047. }
  4048. this._initSnap(); //需要每次都_initSnap么。其实init的时候执行一次,后续resize的时候执行一次就行了吧.先这么做吧,如果影响性能,再调整
  4049. }
  4050. },
  4051. _momentum: function(current, distance, time, lowerMargin, wrapperSize, deceleration) {
  4052. var speed = parseFloat(Math.abs(distance) / time),
  4053. destination,
  4054. duration;
  4055. deceleration = deceleration === undefined ? 0.0006 : deceleration;
  4056. destination = current + (speed * speed) / (2 * deceleration) * (distance < 0 ? -1 : 1);
  4057. duration = speed / deceleration;
  4058. if(destination < lowerMargin) {
  4059. destination = wrapperSize ? lowerMargin - (wrapperSize / 2.5 * (speed / 8)) : lowerMargin;
  4060. distance = Math.abs(destination - current);
  4061. duration = distance / speed;
  4062. } else if(destination > 0) {
  4063. destination = wrapperSize ? wrapperSize / 2.5 * (speed / 8) : 0;
  4064. distance = Math.abs(current) + destination;
  4065. duration = distance / speed;
  4066. }
  4067. return {
  4068. destination: Math.round(destination),
  4069. duration: duration
  4070. };
  4071. },
  4072. _getTranslateStr: function(x, y) {
  4073. if(this.options.hardwareAccelerated) {
  4074. return 'translate3d(' + x + 'px,' + y + 'px,0px) ' + this.translateZ;
  4075. }
  4076. return 'translate(' + x + 'px,' + y + 'px) ';
  4077. },
  4078. //API
  4079. setStopped: function(stopped) {
  4080. this.stopped = !!stopped;
  4081. },
  4082. setTranslate: function(x, y) {
  4083. this.x = x;
  4084. this.y = y;
  4085. this.scrollerStyle['webkitTransform'] = this._getTranslateStr(x, y);
  4086. if(this.parallaxElement && this.options.scrollY) { //目前仅支持竖向视差效果
  4087. var parallaxY = y * this.options.parallaxRatio;
  4088. var scale = 1 + parallaxY / ((this.parallaxHeight - parallaxY) / 2);
  4089. if(scale > 1) {
  4090. this.parallaxImgStyle['opacity'] = 1 - parallaxY / 100 * this.options.parallaxRatio;
  4091. this.parallaxStyle['webkitTransform'] = this._getTranslateStr(0, -parallaxY) + ' scale(' + scale + ',' + scale + ')';
  4092. } else {
  4093. this.parallaxImgStyle['opacity'] = 1;
  4094. this.parallaxStyle['webkitTransform'] = this._getTranslateStr(0, -1) + ' scale(1,1)';
  4095. }
  4096. }
  4097. if(this.indicators) {
  4098. for(var i = this.indicators.length; i--;) {
  4099. this.indicators[i].updatePosition();
  4100. }
  4101. }
  4102. this.lastX = this.x;
  4103. this.lastY = this.y;
  4104. $.trigger(this.scroller, 'scroll', this);
  4105. },
  4106. reLayout: function() {
  4107. this.wrapper.offsetHeight;
  4108. var paddingLeft = parseFloat($.getStyles(this.wrapper, 'padding-left')) || 0;
  4109. var paddingRight = parseFloat($.getStyles(this.wrapper, 'padding-right')) || 0;
  4110. var paddingTop = parseFloat($.getStyles(this.wrapper, 'padding-top')) || 0;
  4111. var paddingBottom = parseFloat($.getStyles(this.wrapper, 'padding-bottom')) || 0;
  4112. var clientWidth = this.wrapper.clientWidth;
  4113. var clientHeight = this.wrapper.clientHeight;
  4114. this.scrollerWidth = this.scroller.offsetWidth;
  4115. this.scrollerHeight = this.scroller.offsetHeight;
  4116. this.wrapperWidth = clientWidth - paddingLeft - paddingRight;
  4117. this.wrapperHeight = clientHeight - paddingTop - paddingBottom;
  4118. this.maxScrollX = Math.min(this.wrapperWidth - this.scrollerWidth, 0);
  4119. this.maxScrollY = Math.min(this.wrapperHeight - this.scrollerHeight, 0);
  4120. this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0;
  4121. this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0;
  4122. this._reLayout();
  4123. },
  4124. resetPosition: function(time) {
  4125. var x = this.x,
  4126. y = this.y;
  4127. time = time || 0;
  4128. if(!this.hasHorizontalScroll || this.x > 0) {
  4129. x = 0;
  4130. } else if(this.x < this.maxScrollX) {
  4131. x = this.maxScrollX;
  4132. }
  4133. if(!this.hasVerticalScroll || this.y > 0) {
  4134. y = 0;
  4135. } else if(this.y < this.maxScrollY) {
  4136. y = this.maxScrollY;
  4137. }
  4138. if(x == this.x && y == this.y) {
  4139. return false;
  4140. }
  4141. this.scrollTo(x, y, time, this.options.scrollEasing);
  4142. return true;
  4143. },
  4144. _reInit: function() {
  4145. var groups = this.wrapper.querySelectorAll('.' + CLASS_SCROLL);
  4146. for(var i = 0, len = groups.length; i < len; i++) {
  4147. if(groups[i].parentNode === this.wrapper) {
  4148. this.scroller = groups[i];
  4149. break;
  4150. }
  4151. }
  4152. this.scrollerStyle = this.scroller && this.scroller.style;
  4153. },
  4154. refresh: function() {
  4155. this._reInit();
  4156. this.reLayout();
  4157. $.trigger(this.scroller, 'refresh', this);
  4158. this.resetPosition();
  4159. },
  4160. scrollTo: function(x, y, time, easing) {
  4161. var easing = easing || ease.circular;
  4162. // this.isInTransition = time > 0 && (this.lastX != x || this.lastY != y);
  4163. //暂不严格判断x,y,否则会导致部分版本上不正常触发轮播
  4164. this.isInTransition = time > 0;
  4165. if(this.isInTransition) {
  4166. this._clearRequestAnimationFrame();
  4167. this._transitionTimingFunction(easing.style);
  4168. this._transitionTime(time);
  4169. this.setTranslate(x, y);
  4170. } else {
  4171. this.setTranslate(x, y);
  4172. }
  4173. },
  4174. scrollToBottom: function(time, easing) {
  4175. time = time || this.options.scrollTime;
  4176. this.scrollTo(0, this.maxScrollY, time, easing);
  4177. },
  4178. gotoPage: function(index) {
  4179. this._gotoPage(index);
  4180. },
  4181. destroy: function() {
  4182. this._initEvent(true); //detach
  4183. delete $.data[this.wrapper.getAttribute('data-scroll')];
  4184. this.wrapper.setAttribute('data-scroll', '');
  4185. }
  4186. });
  4187. //Indicator
  4188. var Indicator = function(scroller, options) {
  4189. this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
  4190. this.wrapperStyle = this.wrapper.style;
  4191. this.indicator = this.wrapper.children[0];
  4192. this.indicatorStyle = this.indicator.style;
  4193. this.scroller = scroller;
  4194. this.options = $.extend({
  4195. listenX: true,
  4196. listenY: true,
  4197. fade: false,
  4198. speedRatioX: 0,
  4199. speedRatioY: 0
  4200. }, options);
  4201. this.sizeRatioX = 1;
  4202. this.sizeRatioY = 1;
  4203. this.maxPosX = 0;
  4204. this.maxPosY = 0;
  4205. if(this.options.fade) {
  4206. this.wrapperStyle['webkitTransform'] = this.scroller.translateZ;
  4207. this.wrapperStyle['webkitTransitionDuration'] = this.options.fixedBadAndorid && $.os.isBadAndroid ? '0.001s' : '0ms';
  4208. this.wrapperStyle.opacity = '0';
  4209. }
  4210. }
  4211. Indicator.prototype = {
  4212. handleEvent: function(e) {
  4213. },
  4214. transitionTime: function(time) {
  4215. time = time || 0;
  4216. this.indicatorStyle['webkitTransitionDuration'] = time + 'ms';
  4217. if(this.scroller.options.fixedBadAndorid && !time && $.os.isBadAndroid) {
  4218. this.indicatorStyle['webkitTransitionDuration'] = '0.001s';
  4219. }
  4220. },
  4221. transitionTimingFunction: function(easing) {
  4222. this.indicatorStyle['webkitTransitionTimingFunction'] = easing;
  4223. },
  4224. refresh: function() {
  4225. this.transitionTime();
  4226. if(this.options.listenX && !this.options.listenY) {
  4227. this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
  4228. } else if(this.options.listenY && !this.options.listenX) {
  4229. this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
  4230. } else {
  4231. this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
  4232. }
  4233. this.wrapper.offsetHeight; // force refresh
  4234. if(this.options.listenX) {
  4235. this.wrapperWidth = this.wrapper.clientWidth;
  4236. this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
  4237. this.indicatorStyle.width = this.indicatorWidth + 'px';
  4238. this.maxPosX = this.wrapperWidth - this.indicatorWidth;
  4239. this.minBoundaryX = 0;
  4240. this.maxBoundaryX = this.maxPosX;
  4241. this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
  4242. }
  4243. if(this.options.listenY) {
  4244. this.wrapperHeight = this.wrapper.clientHeight;
  4245. this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
  4246. this.indicatorStyle.height = this.indicatorHeight + 'px';
  4247. this.maxPosY = this.wrapperHeight - this.indicatorHeight;
  4248. this.minBoundaryY = 0;
  4249. this.maxBoundaryY = this.maxPosY;
  4250. this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
  4251. }
  4252. this.updatePosition();
  4253. },
  4254. updatePosition: function() {
  4255. var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
  4256. y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
  4257. if(x < this.minBoundaryX) {
  4258. this.width = Math.max(this.indicatorWidth + x, 8);
  4259. this.indicatorStyle.width = this.width + 'px';
  4260. x = this.minBoundaryX;
  4261. } else if(x > this.maxBoundaryX) {
  4262. this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
  4263. this.indicatorStyle.width = this.width + 'px';
  4264. x = this.maxPosX + this.indicatorWidth - this.width;
  4265. } else if(this.width != this.indicatorWidth) {
  4266. this.width = this.indicatorWidth;
  4267. this.indicatorStyle.width = this.width + 'px';
  4268. }
  4269. if(y < this.minBoundaryY) {
  4270. this.height = Math.max(this.indicatorHeight + y * 3, 8);
  4271. this.indicatorStyle.height = this.height + 'px';
  4272. y = this.minBoundaryY;
  4273. } else if(y > this.maxBoundaryY) {
  4274. this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
  4275. this.indicatorStyle.height = this.height + 'px';
  4276. y = this.maxPosY + this.indicatorHeight - this.height;
  4277. } else if(this.height != this.indicatorHeight) {
  4278. this.height = this.indicatorHeight;
  4279. this.indicatorStyle.height = this.height + 'px';
  4280. }
  4281. this.x = x;
  4282. this.y = y;
  4283. this.indicatorStyle['webkitTransform'] = this.scroller._getTranslateStr(x, y);
  4284. },
  4285. fade: function(val, hold) {
  4286. if(hold && !this.visible) {
  4287. return;
  4288. }
  4289. clearTimeout(this.fadeTimeout);
  4290. this.fadeTimeout = null;
  4291. var time = val ? 250 : 500,
  4292. delay = val ? 0 : 300;
  4293. val = val ? '1' : '0';
  4294. this.wrapperStyle['webkitTransitionDuration'] = time + 'ms';
  4295. this.fadeTimeout = setTimeout((function(val) {
  4296. this.wrapperStyle.opacity = val;
  4297. this.visible = +val;
  4298. }).bind(this, val), delay);
  4299. }
  4300. };
  4301. $.Scroll = Scroll;
  4302. $.fn.scroll = function(options) {
  4303. var scrollApis = [];
  4304. this.each(function() {
  4305. var scrollApi = null;
  4306. var self = this;
  4307. var id = self.getAttribute('data-scroll');
  4308. if(!id) {
  4309. id = ++$.uuid;
  4310. var _options = $.extend({}, options);
  4311. if(self.classList.contains('mui-segmented-control')) {
  4312. _options = $.extend(_options, {
  4313. scrollY: false,
  4314. scrollX: true,
  4315. indicators: false,
  4316. snap: '.mui-control-item'
  4317. });
  4318. }
  4319. $.data[id] = scrollApi = new Scroll(self, _options);
  4320. self.setAttribute('data-scroll', id);
  4321. } else {
  4322. scrollApi = $.data[id];
  4323. }
  4324. scrollApis.push(scrollApi);
  4325. });
  4326. return scrollApis.length === 1 ? scrollApis[0] : scrollApis;
  4327. };
  4328. })(mui, window, document);
  4329. (function($, window, document, undefined) {
  4330. var CLASS_VISIBILITY = 'mui-visibility';
  4331. var CLASS_HIDDEN = 'mui-hidden';
  4332. var PullRefresh = $.Scroll.extend($.extend({
  4333. handleEvent: function(e) {
  4334. this._super(e);
  4335. if(e.type === 'scrollbottom') {
  4336. if(e.target === this.scroller) {
  4337. this._scrollbottom();
  4338. }
  4339. }
  4340. },
  4341. _scrollbottom: function() {
  4342. if(!this.pulldown && !this.loading) {
  4343. this.pulldown = false;
  4344. this._initPullupRefresh();
  4345. this.pullupLoading();
  4346. }
  4347. },
  4348. _start: function(e) {
  4349. //仅下拉刷新在start阻止默认事件
  4350. if(e.touches && e.touches.length && e.touches[0].clientX > 30) {
  4351. e.target && !this._preventDefaultException(e.target, this.options.preventDefaultException) && e.preventDefault();
  4352. }
  4353. if(!this.loading) {
  4354. this.pulldown = this.pullPocket = this.pullCaption = this.pullLoading = false
  4355. }
  4356. this._super(e);
  4357. },
  4358. _drag: function(e) {
  4359. this._super(e);
  4360. if(!this.pulldown && !this.loading && this.topPocket && e.detail.direction === 'down' && this.y >= 0) {
  4361. this._initPulldownRefresh();
  4362. }
  4363. if(this.pulldown) {
  4364. this._setCaption(this.y > this.options.down.height ? this.options.down.contentover : this.options.down.contentdown);
  4365. }
  4366. },
  4367. _reLayout: function() {
  4368. this.hasVerticalScroll = true;
  4369. this._super();
  4370. },
  4371. //API
  4372. resetPosition: function(time) {
  4373. if(this.pulldown) {
  4374. if(this.y >= this.options.down.height) {
  4375. this.pulldownLoading(undefined, time || 0);
  4376. return true;
  4377. } else {
  4378. !this.loading && this.topPocket.classList.remove(CLASS_VISIBILITY);
  4379. }
  4380. }
  4381. return this._super(time);
  4382. },
  4383. pulldownLoading: function(y, time) {
  4384. typeof y === 'undefined' && (y = this.options.down.height); //默认高度
  4385. this.scrollTo(0, y, time, this.options.bounceEasing);
  4386. if(this.loading) {
  4387. return;
  4388. }
  4389. // if (!this.pulldown) {
  4390. this._initPulldownRefresh();
  4391. // }
  4392. this._setCaption(this.options.down.contentrefresh);
  4393. this.loading = true;
  4394. this.indicators.map(function(indicator) {
  4395. indicator.fade(0);
  4396. });
  4397. var callback = this.options.down.callback;
  4398. callback && callback.call(this);
  4399. },
  4400. endPulldownToRefresh: function() {
  4401. var self = this;
  4402. if(self.topPocket && self.loading && this.pulldown) {
  4403. self.scrollTo(0, 0, self.options.bounceTime, self.options.bounceEasing);
  4404. self.loading = false;
  4405. self._setCaption(self.options.down.contentdown, true);
  4406. setTimeout(function() {
  4407. self.loading || self.topPocket.classList.remove(CLASS_VISIBILITY);
  4408. }, 350);
  4409. }
  4410. },
  4411. pullupLoading: function(callback, x, time) {
  4412. x = x || 0;
  4413. this.scrollTo(x, this.maxScrollY, time, this.options.bounceEasing);
  4414. if(this.loading) {
  4415. return;
  4416. }
  4417. this._initPullupRefresh();
  4418. this._setCaption(this.options.up.contentrefresh);
  4419. this.indicators.map(function(indicator) {
  4420. indicator.fade(0);
  4421. });
  4422. this.loading = true;
  4423. callback = callback || this.options.up.callback;
  4424. callback && callback.call(this);
  4425. },
  4426. endPullupToRefresh: function(finished) {
  4427. var self = this;
  4428. if(self.bottomPocket) { // && self.loading && !this.pulldown
  4429. self.loading = false;
  4430. if(finished) {
  4431. this.finished = true;
  4432. self._setCaption(self.options.up.contentnomore);
  4433. // self.bottomPocket.classList.remove(CLASS_VISIBILITY);
  4434. // self.bottomPocket.classList.add(CLASS_HIDDEN);
  4435. self.wrapper.removeEventListener('scrollbottom', self);
  4436. } else {
  4437. self._setCaption(self.options.up.contentdown);
  4438. // setTimeout(function() {
  4439. self.loading || self.bottomPocket.classList.remove(CLASS_VISIBILITY);
  4440. // }, 300);
  4441. }
  4442. }
  4443. },
  4444. disablePullupToRefresh: function() {
  4445. this._initPullupRefresh();
  4446. this.bottomPocket.className = 'mui-pull-bottom-pocket' + ' ' + CLASS_HIDDEN;
  4447. this.wrapper.removeEventListener('scrollbottom', this);
  4448. },
  4449. enablePullupToRefresh: function() {
  4450. this._initPullupRefresh();
  4451. this.bottomPocket.classList.remove(CLASS_HIDDEN);
  4452. this._setCaption(this.options.up.contentdown);
  4453. this.wrapper.addEventListener('scrollbottom', this);
  4454. },
  4455. refresh: function(isReset) {
  4456. if(isReset && this.finished) {
  4457. this.enablePullupToRefresh();
  4458. this.finished = false;
  4459. }
  4460. this._super();
  4461. },
  4462. }, $.PullRefresh));
  4463. $.fn.pullRefresh = function(options) {
  4464. if(this.length === 1) {
  4465. var self = this[0];
  4466. var pullRefreshApi = null;
  4467. var id = self.getAttribute('data-pullrefresh');
  4468. if(!id && typeof options === 'undefined') {
  4469. return false;
  4470. }
  4471. options = options || {};
  4472. if(!id) {
  4473. id = ++$.uuid;
  4474. $.data[id] = pullRefreshApi = new PullRefresh(self, options);
  4475. self.setAttribute('data-pullrefresh', id);
  4476. } else {
  4477. pullRefreshApi = $.data[id];
  4478. }
  4479. if(options.down && options.down.auto) { //如果设置了auto,则自动下拉一次
  4480. pullRefreshApi.pulldownLoading(options.down.autoY);
  4481. } else if(options.up && options.up.auto) { //如果设置了auto,则自动上拉一次
  4482. pullRefreshApi.pullupLoading();
  4483. }
  4484. //暂不提供这种调用方式吧
  4485. // if (typeof options === 'string') {
  4486. // var methodValue = pullRefreshApi[options].apply(pullRefreshApi, $.slice.call(arguments, 1));
  4487. // if (methodValue !== undefined) {
  4488. // return methodValue;
  4489. // }
  4490. // }
  4491. return pullRefreshApi;
  4492. }
  4493. };
  4494. })(mui, window, document);
  4495. /**
  4496. * snap 重构
  4497. * @param {Object} $
  4498. * @param {Object} window
  4499. */
  4500. (function($, window) {
  4501. var CLASS_SLIDER = 'mui-slider';
  4502. var CLASS_SLIDER_GROUP = 'mui-slider-group';
  4503. var CLASS_SLIDER_LOOP = 'mui-slider-loop';
  4504. var CLASS_SLIDER_INDICATOR = 'mui-slider-indicator';
  4505. var CLASS_ACTION_PREVIOUS = 'mui-action-previous';
  4506. var CLASS_ACTION_NEXT = 'mui-action-next';
  4507. var CLASS_SLIDER_ITEM = 'mui-slider-item';
  4508. var CLASS_ACTIVE = 'mui-active';
  4509. var SELECTOR_SLIDER_ITEM = '.' + CLASS_SLIDER_ITEM;
  4510. var SELECTOR_SLIDER_INDICATOR = '.' + CLASS_SLIDER_INDICATOR;
  4511. var SELECTOR_SLIDER_PROGRESS_BAR = '.mui-slider-progress-bar';
  4512. var Slider = $.Slider = $.Scroll.extend({
  4513. init: function(element, options) {
  4514. this._super(element, $.extend(true, {
  4515. fingers: 1,
  4516. interval: 0, //设置为0,则不定时轮播
  4517. scrollY: false,
  4518. scrollX: true,
  4519. indicators: false,
  4520. scrollTime: 1000,
  4521. startX: false,
  4522. slideTime: 0, //滑动动画时间
  4523. snap: SELECTOR_SLIDER_ITEM
  4524. }, options));
  4525. if(this.options.startX) {
  4526. // $.trigger(this.wrapper, 'scrollend', this);
  4527. }
  4528. },
  4529. _init: function() {
  4530. this._reInit();
  4531. if(this.scroller) {
  4532. this.scrollerStyle = this.scroller.style;
  4533. this.progressBar = this.wrapper.querySelector(SELECTOR_SLIDER_PROGRESS_BAR);
  4534. if(this.progressBar) {
  4535. this.progressBarWidth = this.progressBar.offsetWidth;
  4536. this.progressBarStyle = this.progressBar.style;
  4537. }
  4538. //忘记这个代码是干什么的了?
  4539. // this.x = this._getScroll();
  4540. // if (this.options.startX === false) {
  4541. // this.options.startX = this.x;
  4542. // }
  4543. //根据active修正startX
  4544. this._super();
  4545. this._initTimer();
  4546. }
  4547. },
  4548. _triggerSlide: function() {
  4549. var self = this;
  4550. self.isInTransition = false;
  4551. var page = self.currentPage;
  4552. self.slideNumber = self._fixedSlideNumber();
  4553. if(self.loop) {
  4554. if(self.slideNumber === 0) {
  4555. self.setTranslate(self.pages[1][0].x, 0);
  4556. } else if(self.slideNumber === self.itemLength - 3) {
  4557. self.setTranslate(self.pages[self.itemLength - 2][0].x, 0);
  4558. }
  4559. }
  4560. if(self.lastSlideNumber != self.slideNumber) {
  4561. self.lastSlideNumber = self.slideNumber;
  4562. self.lastPage = self.currentPage;
  4563. $.trigger(self.wrapper, 'slide', {
  4564. slideNumber: self.slideNumber
  4565. });
  4566. }
  4567. self._initTimer();
  4568. },
  4569. _handleSlide: function(e) {
  4570. var self = this;
  4571. if(e.target !== self.wrapper) {
  4572. return;
  4573. }
  4574. var detail = e.detail;
  4575. detail.slideNumber = detail.slideNumber || 0;
  4576. var temps = self.scroller.querySelectorAll(SELECTOR_SLIDER_ITEM);
  4577. var items = [];
  4578. for(var i = 0, len = temps.length; i < len; i++) {
  4579. var item = temps[i];
  4580. if(item.parentNode === self.scroller) {
  4581. items.push(item);
  4582. }
  4583. }
  4584. var _slideNumber = detail.slideNumber;
  4585. if(self.loop) {
  4586. _slideNumber += 1;
  4587. }
  4588. if(!self.wrapper.classList.contains('mui-segmented-control')) {
  4589. for(var i = 0, len = items.length; i < len; i++) {
  4590. var item = items[i];
  4591. if(item.parentNode === self.scroller) {
  4592. if(i === _slideNumber) {
  4593. item.classList.add(CLASS_ACTIVE);
  4594. } else {
  4595. item.classList.remove(CLASS_ACTIVE);
  4596. }
  4597. }
  4598. }
  4599. }
  4600. var indicatorWrap = self.wrapper.querySelector('.mui-slider-indicator');
  4601. if(indicatorWrap) {
  4602. if(indicatorWrap.getAttribute('data-scroll')) { //scroll
  4603. $(indicatorWrap).scroll().gotoPage(detail.slideNumber);
  4604. }
  4605. var indicators = indicatorWrap.querySelectorAll('.mui-indicator');
  4606. if(indicators.length > 0) { //图片轮播
  4607. for(var i = 0, len = indicators.length; i < len; i++) {
  4608. indicators[i].classList[i === detail.slideNumber ? 'add' : 'remove'](CLASS_ACTIVE);
  4609. }
  4610. } else {
  4611. var number = indicatorWrap.querySelector('.mui-number span');
  4612. if(number) { //图文表格
  4613. number.innerText = (detail.slideNumber + 1);
  4614. } else { //segmented controls
  4615. var controlItems = indicatorWrap.querySelectorAll('.mui-control-item');
  4616. for(var i = 0, len = controlItems.length; i < len; i++) {
  4617. controlItems[i].classList[i === detail.slideNumber ? 'add' : 'remove'](CLASS_ACTIVE);
  4618. }
  4619. }
  4620. }
  4621. }
  4622. e.stopPropagation();
  4623. },
  4624. _handleTabShow: function(e) {
  4625. var self = this;
  4626. self.gotoItem((e.detail.tabNumber || 0), self.options.slideTime);
  4627. },
  4628. _handleIndicatorTap: function(event) {
  4629. var self = this;
  4630. var target = event.target;
  4631. if(target.classList.contains(CLASS_ACTION_PREVIOUS) || target.classList.contains(CLASS_ACTION_NEXT)) {
  4632. self[target.classList.contains(CLASS_ACTION_PREVIOUS) ? 'prevItem' : 'nextItem']();
  4633. event.stopPropagation();
  4634. }
  4635. },
  4636. _initEvent: function(detach) {
  4637. var self = this;
  4638. self._super(detach);
  4639. var action = detach ? 'removeEventListener' : 'addEventListener';
  4640. self.wrapper[action]('slide', this);
  4641. self.wrapper[action]($.eventName('shown', 'tab'), this);
  4642. },
  4643. handleEvent: function(e) {
  4644. this._super(e);
  4645. switch(e.type) {
  4646. case 'slide':
  4647. this._handleSlide(e);
  4648. break;
  4649. case $.eventName('shown', 'tab'):
  4650. if(~this.snaps.indexOf(e.target)) { //避免嵌套监听错误的tab show
  4651. this._handleTabShow(e);
  4652. }
  4653. break;
  4654. }
  4655. },
  4656. _scrollend: function(e) {
  4657. this._super(e);
  4658. this._triggerSlide(e);
  4659. },
  4660. _drag: function(e) {
  4661. this._super(e);
  4662. var direction = e.detail.direction;
  4663. if(direction === 'left' || direction === 'right') {
  4664. //拖拽期间取消定时
  4665. var slidershowTimer = this.wrapper.getAttribute('data-slidershowTimer');
  4666. slidershowTimer && window.clearTimeout(slidershowTimer);
  4667. e.stopPropagation();
  4668. }
  4669. },
  4670. _initTimer: function() {
  4671. var self = this;
  4672. var slider = self.wrapper;
  4673. var interval = self.options.interval;
  4674. var slidershowTimer = slider.getAttribute('data-slidershowTimer');
  4675. slidershowTimer && window.clearTimeout(slidershowTimer);
  4676. if(interval) {
  4677. slidershowTimer = window.setTimeout(function() {
  4678. if(!slider) {
  4679. return;
  4680. }
  4681. //仅slider显示状态进行自动轮播
  4682. if(!!(slider.offsetWidth || slider.offsetHeight)) {
  4683. self.nextItem(true);
  4684. //下一个
  4685. }
  4686. self._initTimer();
  4687. }, interval);
  4688. slider.setAttribute('data-slidershowTimer', slidershowTimer);
  4689. }
  4690. },
  4691. _fixedSlideNumber: function(page) {
  4692. page = page || this.currentPage;
  4693. var slideNumber = page.pageX;
  4694. if(this.loop) {
  4695. if(page.pageX === 0) {
  4696. slideNumber = this.itemLength - 3;
  4697. } else if(page.pageX === (this.itemLength - 1)) {
  4698. slideNumber = 0;
  4699. } else {
  4700. slideNumber = page.pageX - 1;
  4701. }
  4702. }
  4703. return slideNumber;
  4704. },
  4705. _reLayout: function() {
  4706. this.hasHorizontalScroll = true;
  4707. this.loop = this.scroller.classList.contains(CLASS_SLIDER_LOOP);
  4708. this._super();
  4709. },
  4710. _getScroll: function() {
  4711. var result = $.parseTranslateMatrix($.getStyles(this.scroller, 'webkitTransform'));
  4712. return result ? result.x : 0;
  4713. },
  4714. _transitionEnd: function(e) {
  4715. if(e.target !== this.scroller || !this.isInTransition) {
  4716. return;
  4717. }
  4718. this._transitionTime();
  4719. this.isInTransition = false;
  4720. $.trigger(this.wrapper, 'scrollend', this);
  4721. },
  4722. _flick: function(e) {
  4723. if(!this.moved) { //无moved
  4724. return;
  4725. }
  4726. var detail = e.detail;
  4727. var direction = detail.direction;
  4728. this._clearRequestAnimationFrame();
  4729. this.isInTransition = true;
  4730. // if (direction === 'up' || direction === 'down') {
  4731. // this.resetPosition(this.options.bounceTime);
  4732. // return;
  4733. // }
  4734. if(e.type === 'flick') {
  4735. if(detail.deltaTime < 200) { //flick,太容易触发,额外校验一下deltaTime
  4736. this.x = this._getPage((this.slideNumber + (direction === 'right' ? -1 : 1)), true).x;
  4737. }
  4738. this.resetPosition(this.options.bounceTime);
  4739. } else if(e.type === 'dragend' && !detail.flick) {
  4740. this.resetPosition(this.options.bounceTime);
  4741. }
  4742. e.stopPropagation();
  4743. },
  4744. _initSnap: function() {
  4745. this.scrollerWidth = this.itemLength * this.scrollerWidth;
  4746. this.maxScrollX = Math.min(this.wrapperWidth - this.scrollerWidth, 0);
  4747. this._super();
  4748. if(!this.currentPage.x) {
  4749. //当slider处于隐藏状态时,导致snap计算是错误的,临时先这么判断一下,后续要考虑解决所有scroll在隐藏状态下初始化属性不正确的问题
  4750. var currentPage = this.pages[this.loop ? 1 : 0];
  4751. currentPage = currentPage || this.pages[0];
  4752. if(!currentPage) {
  4753. return;
  4754. }
  4755. this.currentPage = currentPage[0];
  4756. this.slideNumber = 0;
  4757. this.lastSlideNumber = typeof this.lastSlideNumber === 'undefined' ? 0 : this.lastSlideNumber;
  4758. } else {
  4759. this.slideNumber = this._fixedSlideNumber();
  4760. this.lastSlideNumber = typeof this.lastSlideNumber === 'undefined' ? this.slideNumber : this.lastSlideNumber;
  4761. }
  4762. this.options.startX = this.currentPage.x || 0;
  4763. },
  4764. _getSnapX: function(offsetLeft) {
  4765. return Math.max(-offsetLeft, this.maxScrollX);
  4766. },
  4767. _getPage: function(slideNumber, isFlick) {
  4768. if(this.loop) {
  4769. if(slideNumber > (this.itemLength - (isFlick ? 2 : 3))) {
  4770. slideNumber = 1;
  4771. time = 0;
  4772. } else if(slideNumber < (isFlick ? -1 : 0)) {
  4773. slideNumber = this.itemLength - 2;
  4774. time = 0;
  4775. } else {
  4776. slideNumber += 1;
  4777. }
  4778. } else {
  4779. if(!isFlick) {
  4780. if(slideNumber > (this.itemLength - 1)) {
  4781. slideNumber = 0;
  4782. time = 0;
  4783. } else if(slideNumber < 0) {
  4784. slideNumber = this.itemLength - 1;
  4785. time = 0;
  4786. }
  4787. }
  4788. slideNumber = Math.min(Math.max(0, slideNumber), this.itemLength - 1);
  4789. }
  4790. return this.pages[slideNumber][0];
  4791. },
  4792. _gotoItem: function(slideNumber, time) {
  4793. this.currentPage = this._getPage(slideNumber, true); //此处传true。可保证程序切换时,动画与人手操作一致(第一张,最后一张的切换动画)
  4794. this.scrollTo(this.currentPage.x, 0, time, this.options.scrollEasing);
  4795. if(time === 0) {
  4796. $.trigger(this.wrapper, 'scrollend', this);
  4797. }
  4798. },
  4799. //API
  4800. setTranslate: function(x, y) {
  4801. this._super(x, y);
  4802. var progressBar = this.progressBar;
  4803. if(progressBar) {
  4804. this.progressBarStyle.webkitTransform = this._getTranslateStr((-x * (this.progressBarWidth / this.wrapperWidth)), 0);
  4805. }
  4806. },
  4807. resetPosition: function(time) {
  4808. time = time || 0;
  4809. if(this.x > 0) {
  4810. this.x = 0;
  4811. } else if(this.x < this.maxScrollX) {
  4812. this.x = this.maxScrollX;
  4813. }
  4814. this.currentPage = this._nearestSnap(this.x);
  4815. this.scrollTo(this.currentPage.x, 0, time, this.options.scrollEasing);
  4816. return true;
  4817. },
  4818. gotoItem: function(slideNumber, time) {
  4819. this._gotoItem(slideNumber, typeof time === 'undefined' ? this.options.scrollTime : time);
  4820. },
  4821. nextItem: function() {
  4822. this._gotoItem(this.slideNumber + 1, this.options.scrollTime);
  4823. },
  4824. prevItem: function() {
  4825. this._gotoItem(this.slideNumber - 1, this.options.scrollTime);
  4826. },
  4827. getSlideNumber: function() {
  4828. return this.slideNumber || 0;
  4829. },
  4830. _reInit: function() {
  4831. var groups = this.wrapper.querySelectorAll('.' + CLASS_SLIDER_GROUP);
  4832. for(var i = 0, len = groups.length; i < len; i++) {
  4833. if(groups[i].parentNode === this.wrapper) {
  4834. this.scroller = groups[i];
  4835. break;
  4836. }
  4837. }
  4838. this.scrollerStyle = this.scroller && this.scroller.style;
  4839. if(this.progressBar) {
  4840. this.progressBarWidth = this.progressBar.offsetWidth;
  4841. this.progressBarStyle = this.progressBar.style;
  4842. }
  4843. },
  4844. refresh: function(options) {
  4845. if(options) {
  4846. $.extend(this.options, options);
  4847. this._super();
  4848. this._initTimer();
  4849. } else {
  4850. this._super();
  4851. }
  4852. },
  4853. destroy: function() {
  4854. this._initEvent(true); //detach
  4855. delete $.data[this.wrapper.getAttribute('data-slider')];
  4856. this.wrapper.setAttribute('data-slider', '');
  4857. }
  4858. });
  4859. $.fn.slider = function(options) {
  4860. var slider = null;
  4861. this.each(function() {
  4862. var sliderElement = this;
  4863. if(!this.classList.contains(CLASS_SLIDER)) {
  4864. sliderElement = this.querySelector('.' + CLASS_SLIDER);
  4865. }
  4866. if(sliderElement && sliderElement.querySelector(SELECTOR_SLIDER_ITEM)) {
  4867. var id = sliderElement.getAttribute('data-slider');
  4868. if(!id) {
  4869. id = ++$.uuid;
  4870. $.data[id] = slider = new Slider(sliderElement, options);
  4871. sliderElement.setAttribute('data-slider', id);
  4872. } else {
  4873. slider = $.data[id];
  4874. if(slider && options) {
  4875. slider.refresh(options);
  4876. }
  4877. }
  4878. }
  4879. });
  4880. return slider;
  4881. };
  4882. $.ready(function() {
  4883. // setTimeout(function() {
  4884. $('.mui-slider').slider();
  4885. $('.mui-scroll-wrapper.mui-slider-indicator.mui-segmented-control').scroll({
  4886. scrollY: false,
  4887. scrollX: true,
  4888. indicators: false,
  4889. snap: '.mui-control-item'
  4890. });
  4891. // }, 500); //临时处理slider宽度计算不正确的问题(初步确认是scrollbar导致的)
  4892. });
  4893. })(mui, window);
  4894. /**
  4895. * pullRefresh 5+
  4896. * @param {type} $
  4897. * @returns {undefined}
  4898. */
  4899. (function($, document) {
  4900. if(!($.os.plus)) { //仅在5+android支持多webview的使用
  4901. return;
  4902. }
  4903. $.plusReady(function() {
  4904. if(window.__NWin_Enable__ === false) { //不支持多webview,则不用5+下拉刷新
  4905. return;
  4906. }
  4907. var CLASS_PLUS_PULLREFRESH = 'mui-plus-pullrefresh';
  4908. var CLASS_VISIBILITY = 'mui-visibility';
  4909. var CLASS_HIDDEN = 'mui-hidden';
  4910. var CLASS_BLOCK = 'mui-block';
  4911. var CLASS_PULL_CAPTION = 'mui-pull-caption';
  4912. var CLASS_PULL_CAPTION_DOWN = 'mui-pull-caption-down';
  4913. var CLASS_PULL_CAPTION_REFRESH = 'mui-pull-caption-refresh';
  4914. var CLASS_PULL_CAPTION_NOMORE = 'mui-pull-caption-nomore';
  4915. var PlusPullRefresh = $.Class.extend({
  4916. init: function(element, options) {
  4917. this.element = element;
  4918. this.options = options;
  4919. this.wrapper = this.scroller = element;
  4920. this._init();
  4921. this._initPulldownRefreshEvent();
  4922. },
  4923. _init: function() {
  4924. var self = this;
  4925. //document.addEventListener('plusscrollbottom', this);
  4926. window.addEventListener('dragup', self);
  4927. document.addEventListener("plusscrollbottom", self);
  4928. self.scrollInterval = window.setInterval(function() {
  4929. if(self.isScroll && !self.loading) {
  4930. if(window.pageYOffset + window.innerHeight + 10 >= document.documentElement.scrollHeight) {
  4931. self.isScroll = false; //放在这里是因为快速滚动的话,有可能检测时,还没到底,所以只要有滚动,没到底之前一直检测高度变化
  4932. if(self.bottomPocket) {
  4933. self.pullupLoading();
  4934. }
  4935. }
  4936. }
  4937. }, 100);
  4938. },
  4939. _initPulldownRefreshEvent: function() {
  4940. var self = this;
  4941. $.plusReady(function() {
  4942. if(self.options.down.style == "circle") {
  4943. //单webview、原生转圈
  4944. self.options.webview = plus.webview.currentWebview();
  4945. self.options.webview.setPullToRefresh({
  4946. support: true,
  4947. color: self.options.down.color || '#2BD009',
  4948. height: self.options.down.height || '50px',
  4949. range: self.options.down.range || '100px',
  4950. style: 'circle',
  4951. offset: self.options.down.offset || '0px'
  4952. }, function() {
  4953. self.options.down.callback();
  4954. });
  4955. } else if(self.topPocket && self.options.webviewId) {
  4956. var webview = plus.webview.getWebviewById(self.options.webviewId); //子窗口
  4957. if(!webview) {
  4958. return;
  4959. }
  4960. self.options.webview = webview;
  4961. var downOptions = self.options.down;
  4962. var height = downOptions.height;
  4963. webview.addEventListener('close', function() {
  4964. var attrWebviewId = self.options.webviewId && self.options.webviewId.replace(/\//g, "_"); //替换所有"/"
  4965. self.element.removeAttribute('data-pullrefresh-plus-' + attrWebviewId);
  4966. });
  4967. webview.addEventListener("dragBounce", function(e) {
  4968. if(!self.pulldown) {
  4969. self._initPulldownRefresh();
  4970. } else {
  4971. self.pullPocket.classList.add(CLASS_BLOCK);
  4972. }
  4973. switch(e.status) {
  4974. case "beforeChangeOffset": //下拉可刷新状态
  4975. self._setCaption(downOptions.contentdown);
  4976. break;
  4977. case "afterChangeOffset": //松开可刷新状态
  4978. self._setCaption(downOptions.contentover);
  4979. break;
  4980. case "dragEndAfterChangeOffset": //正在刷新状态
  4981. //执行下拉刷新所在webview的回调函数
  4982. webview.evalJS("window.mui&&mui.options.pullRefresh.down.callback()");
  4983. self._setCaption(downOptions.contentrefresh);
  4984. break;
  4985. default:
  4986. break;
  4987. }
  4988. }, false);
  4989. webview.setBounce({
  4990. position: {
  4991. top: height * 2 + 'px'
  4992. },
  4993. changeoffset: {
  4994. top: height + 'px'
  4995. }
  4996. });
  4997. }
  4998. });
  4999. },
  5000. handleEvent: function(e) {
  5001. var self = this;
  5002. if(self.stopped) {
  5003. return;
  5004. }
  5005. self.isScroll = false;
  5006. if(e.type === 'dragup' || e.type === 'plusscrollbottom') {
  5007. self.isScroll = true;
  5008. setTimeout(function() {
  5009. self.isScroll = false;
  5010. }, 1000);
  5011. }
  5012. }
  5013. }).extend($.extend({
  5014. setStopped: function(stopped) { //该方法是子页面调用的
  5015. this.stopped = !!stopped;
  5016. //TODO 此处需要设置当前webview的bounce为none,目前5+有BUG
  5017. var webview = plus.webview.currentWebview();
  5018. if(this.stopped) {
  5019. webview.setStyle({
  5020. bounce: 'none'
  5021. });
  5022. webview.setBounce({
  5023. position: {
  5024. top: 'none'
  5025. }
  5026. });
  5027. } else {
  5028. var height = this.options.down.height;
  5029. webview.setStyle({
  5030. bounce: 'vertical'
  5031. });
  5032. webview.setBounce({
  5033. position: {
  5034. top: height * 2 + 'px'
  5035. },
  5036. changeoffset: {
  5037. top: height + 'px'
  5038. }
  5039. });
  5040. }
  5041. },
  5042. beginPulldown: function() {
  5043. var self = this;
  5044. $.plusReady(function() {
  5045. //这里延时的目的是为了保证下拉刷新组件初始化完成,后续应该做成有状态的
  5046. setTimeout(function() {
  5047. if(self.options.down.style == "circle") { //单webview下拉刷新
  5048. plus.webview.currentWebview().beginPullToRefresh();
  5049. } else { //双webview模式
  5050. var webview = self.options.webview;
  5051. if(webview) {
  5052. webview.setBounce({
  5053. offset: {
  5054. top: self.options.down.height + "px"
  5055. }
  5056. });
  5057. }
  5058. }
  5059. }, 15);
  5060. }.bind(this));
  5061. },
  5062. pulldownLoading: function() { //该方法是子页面调用的,兼容老的历史API
  5063. this.beginPulldown();
  5064. },
  5065. _pulldownLoading: function() { //该方法是父页面调用的
  5066. var self = this;
  5067. $.plusReady(function() {
  5068. var childWebview = plus.webview.getWebviewById(self.options.webviewId);
  5069. childWebview && childWebview.setBounce({
  5070. offset: {
  5071. top: self.options.down.height + "px"
  5072. }
  5073. });
  5074. });
  5075. },
  5076. endPulldown: function() {
  5077. var _wv = plus.webview.currentWebview();
  5078. //双webview的下拉刷新,需要修改父窗口提示信息
  5079. if(_wv.parent() && this.options.down.style !== "circle") {
  5080. _wv.parent().evalJS("mui&&mui(document.querySelector('.mui-content')).pullRefresh('" + JSON.stringify({
  5081. webviewId: _wv.id
  5082. }) + "')._endPulldownToRefresh()");
  5083. } else {
  5084. _wv.endPullToRefresh();
  5085. }
  5086. },
  5087. endPulldownToRefresh: function() { //该方法是子页面调用的,兼容老的历史API
  5088. this.endPulldown();
  5089. },
  5090. _endPulldownToRefresh: function() { //该方法是父页面调用的
  5091. var self = this;
  5092. if(self.topPocket && self.options.webview) {
  5093. self.options.webview.endPullToRefresh(); //下拉刷新所在webview回弹
  5094. self.loading = false;
  5095. self._setCaption(self.options.down.contentdown, true);
  5096. setTimeout(function() {
  5097. self.loading || self.topPocket.classList.remove(CLASS_BLOCK);
  5098. }, 350);
  5099. }
  5100. },
  5101. beginPullup: function(callback) { //开始上拉加载
  5102. var self = this;
  5103. if(self.isLoading) return;
  5104. self.isLoading = true;
  5105. if(self.pulldown !== false) {
  5106. self._initPullupRefresh();
  5107. } else {
  5108. this.pullPocket.classList.add(CLASS_BLOCK);
  5109. }
  5110. setTimeout(function() {
  5111. self.pullLoading.classList.add(CLASS_VISIBILITY);
  5112. self.pullLoading.classList.remove(CLASS_HIDDEN);
  5113. self.pullCaption.innerHTML = ''; //修正5+里边第一次加载时,文字显示的bug(还会显示出来个“多”,猜测应该是渲染问题导致的)
  5114. self.pullCaption.className = CLASS_PULL_CAPTION + ' ' + CLASS_PULL_CAPTION_REFRESH;
  5115. self.pullCaption.innerHTML = self.options.up.contentrefresh;
  5116. callback = callback || self.options.up.callback;
  5117. callback && callback.call(self);
  5118. }, 300);
  5119. },
  5120. pullupLoading: function(callback) { //兼容老的API
  5121. this.beginPullup(callback);
  5122. },
  5123. endPullup: function(finished) { //上拉加载结束
  5124. var self = this;
  5125. if(self.pullLoading) {
  5126. self.pullLoading.classList.remove(CLASS_VISIBILITY);
  5127. self.pullLoading.classList.add(CLASS_HIDDEN);
  5128. self.isLoading = false;
  5129. if(finished) {
  5130. self.finished = true;
  5131. self.pullCaption.className = CLASS_PULL_CAPTION + ' ' + CLASS_PULL_CAPTION_NOMORE;
  5132. self.pullCaption.innerHTML = self.options.up.contentnomore;
  5133. //取消5+的plusscrollbottom事件
  5134. document.removeEventListener('plusscrollbottom', self);
  5135. window.removeEventListener('dragup', self);
  5136. } else { //初始化时隐藏,后续不再隐藏
  5137. self.pullCaption.className = CLASS_PULL_CAPTION + ' ' + CLASS_PULL_CAPTION_DOWN;
  5138. self.pullCaption.innerHTML = self.options.up.contentdown;
  5139. }
  5140. }
  5141. },
  5142. endPullupToRefresh: function(finished) { //上拉加载结束,兼容老的API
  5143. this.endPullup(finished);
  5144. },
  5145. disablePullupToRefresh: function() {
  5146. this._initPullupRefresh();
  5147. this.bottomPocket.className = 'mui-pull-bottom-pocket' + ' ' + CLASS_HIDDEN;
  5148. window.removeEventListener('dragup', this);
  5149. },
  5150. enablePullupToRefresh: function() {
  5151. this._initPullupRefresh();
  5152. this.bottomPocket.classList.remove(CLASS_HIDDEN);
  5153. this.pullCaption.className = CLASS_PULL_CAPTION + ' ' + CLASS_PULL_CAPTION_DOWN;
  5154. this.pullCaption.innerHTML = this.options.up.contentdown;
  5155. document.addEventListener("plusscrollbottom", this);
  5156. window.addEventListener('dragup', this);
  5157. },
  5158. scrollTo: function(x, y, time) {
  5159. $.scrollTo(y, time);
  5160. },
  5161. scrollToBottom: function(time) {
  5162. $.scrollTo(document.documentElement.scrollHeight, time);
  5163. },
  5164. refresh: function(isReset) {
  5165. if(isReset && this.finished) {
  5166. this.enablePullupToRefresh();
  5167. this.finished = false;
  5168. }
  5169. }
  5170. }, $.PullRefresh));
  5171. //override h5 pullRefresh
  5172. $.fn.pullRefresh_native = function(options) {
  5173. var self;
  5174. if(this.length === 0) {
  5175. self = document.createElement('div');
  5176. self.className = 'mui-content';
  5177. document.body.appendChild(self);
  5178. } else {
  5179. self = this[0];
  5180. }
  5181. var args = options;
  5182. //一个父需要支持多个子下拉刷新
  5183. options = options || {}
  5184. if(typeof options === 'string') {
  5185. options = $.parseJSON(options);
  5186. };
  5187. !options.webviewId && (options.webviewId = (plus.webview.currentWebview().id || plus.webview.currentWebview().getURL()));
  5188. var pullRefreshApi = null;
  5189. var attrWebviewId = options.webviewId && options.webviewId.replace(/\//g, "_"); //替换所有"/"
  5190. var id = self.getAttribute('data-pullrefresh-plus-' + attrWebviewId);
  5191. if(!id && typeof args === 'undefined') {
  5192. return false;
  5193. }
  5194. if(!id) { //避免重复初始化5+ pullrefresh
  5195. id = ++$.uuid;
  5196. self.setAttribute('data-pullrefresh-plus-' + attrWebviewId, id);
  5197. document.body.classList.add(CLASS_PLUS_PULLREFRESH);
  5198. $.data[id] = pullRefreshApi = new PlusPullRefresh(self, options);
  5199. } else {
  5200. pullRefreshApi = $.data[id];
  5201. }
  5202. if(options.down && options.down.auto) { //如果设置了auto,则自动下拉一次
  5203. //pullRefreshApi._pulldownLoading(); //parent webview
  5204. pullRefreshApi.beginPulldown();
  5205. } else if(options.up && options.up.auto) { //如果设置了auto,则自动上拉一次
  5206. pullRefreshApi.beginPullup();
  5207. }
  5208. return pullRefreshApi;
  5209. };
  5210. });
  5211. })(mui, document);
  5212. /**
  5213. * off-canvas
  5214. * @param {type} $
  5215. * @param {type} window
  5216. * @param {type} document
  5217. * @param {type} action
  5218. * @returns {undefined}
  5219. */
  5220. (function($, window, document, name) {
  5221. var CLASS_OFF_CANVAS_LEFT = 'mui-off-canvas-left';
  5222. var CLASS_OFF_CANVAS_RIGHT = 'mui-off-canvas-right';
  5223. var CLASS_ACTION_BACKDROP = 'mui-off-canvas-backdrop';
  5224. var CLASS_OFF_CANVAS_WRAP = 'mui-off-canvas-wrap';
  5225. var CLASS_SLIDE_IN = 'mui-slide-in';
  5226. var CLASS_ACTIVE = 'mui-active';
  5227. var CLASS_TRANSITIONING = 'mui-transitioning';
  5228. var SELECTOR_INNER_WRAP = '.mui-inner-wrap';
  5229. var OffCanvas = $.Class.extend({
  5230. init: function(element, options) {
  5231. this.wrapper = this.element = element;
  5232. this.scroller = this.wrapper.querySelector(SELECTOR_INNER_WRAP);
  5233. this.classList = this.wrapper.classList;
  5234. if(this.scroller) {
  5235. this.options = $.extend(true, {
  5236. dragThresholdX: 10,
  5237. scale: 0.8,
  5238. opacity: 0.1,
  5239. preventDefaultException: {
  5240. tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|VIDEO)$/
  5241. },
  5242. }, options);
  5243. document.body.classList.add('mui-fullscreen'); //fullscreen
  5244. this.refresh();
  5245. this.initEvent();
  5246. }
  5247. },
  5248. _preventDefaultException: function(el, exceptions) {
  5249. for(var i in exceptions) {
  5250. if(exceptions[i].test(el[i])) {
  5251. return true;
  5252. }
  5253. }
  5254. return false;
  5255. },
  5256. refresh: function(offCanvas) {
  5257. // offCanvas && !offCanvas.classList.contains(CLASS_ACTIVE) && this.classList.remove(CLASS_ACTIVE);
  5258. this.slideIn = this.classList.contains(CLASS_SLIDE_IN);
  5259. this.scalable = this.classList.contains('mui-scalable') && !this.slideIn;
  5260. this.scroller = this.wrapper.querySelector(SELECTOR_INNER_WRAP);
  5261. // !offCanvas && this.scroller.classList.remove(CLASS_TRANSITIONING);
  5262. // !offCanvas && this.scroller.setAttribute('style', '');
  5263. this.offCanvasLefts = this.wrapper.querySelectorAll('.' + CLASS_OFF_CANVAS_LEFT);
  5264. this.offCanvasRights = this.wrapper.querySelectorAll('.' + CLASS_OFF_CANVAS_RIGHT);
  5265. if(offCanvas) {
  5266. if(offCanvas.classList.contains(CLASS_OFF_CANVAS_LEFT)) {
  5267. this.offCanvasLeft = offCanvas;
  5268. } else if(offCanvas.classList.contains(CLASS_OFF_CANVAS_RIGHT)) {
  5269. this.offCanvasRight = offCanvas;
  5270. }
  5271. } else {
  5272. this.offCanvasRight = this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_RIGHT);
  5273. this.offCanvasLeft = this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_LEFT);
  5274. }
  5275. this.offCanvasRightWidth = this.offCanvasLeftWidth = 0;
  5276. this.offCanvasLeftSlideIn = this.offCanvasRightSlideIn = false;
  5277. if(this.offCanvasRight) {
  5278. this.offCanvasRightWidth = this.offCanvasRight.offsetWidth;
  5279. this.offCanvasRightSlideIn = this.slideIn && (this.offCanvasRight.parentNode === this.wrapper);
  5280. // this.offCanvasRight.classList.remove(CLASS_TRANSITIONING);
  5281. // this.offCanvasRight.classList.remove(CLASS_ACTIVE);
  5282. // this.offCanvasRight.setAttribute('style', '');
  5283. }
  5284. if(this.offCanvasLeft) {
  5285. this.offCanvasLeftWidth = this.offCanvasLeft.offsetWidth;
  5286. this.offCanvasLeftSlideIn = this.slideIn && (this.offCanvasLeft.parentNode === this.wrapper);
  5287. // this.offCanvasLeft.classList.remove(CLASS_TRANSITIONING);
  5288. // this.offCanvasLeft.classList.remove(CLASS_ACTIVE);
  5289. // this.offCanvasLeft.setAttribute('style', '');
  5290. }
  5291. this.backdrop = this.scroller.querySelector('.' + CLASS_ACTION_BACKDROP);
  5292. this.options.dragThresholdX = this.options.dragThresholdX || 10;
  5293. this.visible = false;
  5294. this.startX = null;
  5295. this.lastX = null;
  5296. this.offsetX = null;
  5297. this.lastTranslateX = null;
  5298. },
  5299. handleEvent: function(e) {
  5300. switch(e.type) {
  5301. case $.EVENT_START:
  5302. e.target && !this._preventDefaultException(e.target, this.options.preventDefaultException) && e.preventDefault();
  5303. break;
  5304. case 'webkitTransitionEnd': //有个bug需要处理,需要考虑假设没有触发webkitTransitionEnd的情况
  5305. if(e.target === this.scroller) {
  5306. this._dispatchEvent();
  5307. }
  5308. break;
  5309. case 'drag':
  5310. var detail = e.detail;
  5311. if(!this.startX) {
  5312. this.startX = detail.center.x;
  5313. this.lastX = this.startX;
  5314. } else {
  5315. this.lastX = detail.center.x;
  5316. }
  5317. if(!this.isDragging && Math.abs(this.lastX - this.startX) > this.options.dragThresholdX && (detail.direction === 'left' || (detail.direction === 'right'))) {
  5318. if(this.slideIn) {
  5319. this.scroller = this.wrapper.querySelector(SELECTOR_INNER_WRAP);
  5320. if(this.classList.contains(CLASS_ACTIVE)) {
  5321. if(this.offCanvasRight && this.offCanvasRight.classList.contains(CLASS_ACTIVE)) {
  5322. this.offCanvas = this.offCanvasRight;
  5323. this.offCanvasWidth = this.offCanvasRightWidth;
  5324. } else {
  5325. this.offCanvas = this.offCanvasLeft;
  5326. this.offCanvasWidth = this.offCanvasLeftWidth;
  5327. }
  5328. } else {
  5329. if(detail.direction === 'left' && this.offCanvasRight) {
  5330. this.offCanvas = this.offCanvasRight;
  5331. this.offCanvasWidth = this.offCanvasRightWidth;
  5332. } else if(detail.direction === 'right' && this.offCanvasLeft) {
  5333. this.offCanvas = this.offCanvasLeft;
  5334. this.offCanvasWidth = this.offCanvasLeftWidth;
  5335. } else {
  5336. this.scroller = null;
  5337. }
  5338. }
  5339. } else {
  5340. if(this.classList.contains(CLASS_ACTIVE)) {
  5341. if(detail.direction === 'left') {
  5342. this.offCanvas = this.offCanvasLeft;
  5343. this.offCanvasWidth = this.offCanvasLeftWidth;
  5344. } else {
  5345. this.offCanvas = this.offCanvasRight;
  5346. this.offCanvasWidth = this.offCanvasRightWidth;
  5347. }
  5348. } else {
  5349. if(detail.direction === 'right') {
  5350. this.offCanvas = this.offCanvasLeft;
  5351. this.offCanvasWidth = this.offCanvasLeftWidth;
  5352. } else {
  5353. this.offCanvas = this.offCanvasRight;
  5354. this.offCanvasWidth = this.offCanvasRightWidth;
  5355. }
  5356. }
  5357. }
  5358. if(this.offCanvas && this.scroller) {
  5359. this.startX = this.lastX;
  5360. this.isDragging = true;
  5361. $.gestures.session.lockDirection = true; //锁定方向
  5362. $.gestures.session.startDirection = detail.direction;
  5363. this.offCanvas.classList.remove(CLASS_TRANSITIONING);
  5364. this.scroller.classList.remove(CLASS_TRANSITIONING);
  5365. this.offsetX = this.getTranslateX();
  5366. this._initOffCanvasVisible();
  5367. }
  5368. }
  5369. if(this.isDragging) {
  5370. this.updateTranslate(this.offsetX + (this.lastX - this.startX));
  5371. detail.gesture.preventDefault();
  5372. e.stopPropagation();
  5373. }
  5374. break;
  5375. case 'dragend':
  5376. if(this.isDragging) {
  5377. var detail = e.detail;
  5378. var direction = detail.direction;
  5379. this.isDragging = false;
  5380. this.offCanvas.classList.add(CLASS_TRANSITIONING);
  5381. this.scroller.classList.add(CLASS_TRANSITIONING);
  5382. var ratio = 0;
  5383. var x = this.getTranslateX();
  5384. if(!this.slideIn) {
  5385. if(x >= 0) {
  5386. ratio = (this.offCanvasLeftWidth && (x / this.offCanvasLeftWidth)) || 0;
  5387. } else {
  5388. ratio = (this.offCanvasRightWidth && (x / this.offCanvasRightWidth)) || 0;
  5389. }
  5390. if(ratio === 0) {
  5391. this.openPercentage(0);
  5392. this._dispatchEvent(); //此处不触发webkitTransitionEnd,所以手动dispatch
  5393. return;
  5394. }
  5395. if(direction === 'right' && ratio >= 0 && (ratio >= 0.5 || detail.swipe)) { //右滑打开
  5396. this.openPercentage(100);
  5397. } else if(direction === 'right' && ratio < 0 && (ratio > -0.5 || detail.swipe)) { //右滑关闭
  5398. this.openPercentage(0);
  5399. } else if(direction === 'right' && ratio > 0 && ratio < 0.5) { //右滑还原关闭
  5400. this.openPercentage(0);
  5401. } else if(direction === 'right' && ratio < 0.5) { //右滑还原打开
  5402. this.openPercentage(-100);
  5403. } else if(direction === 'left' && ratio <= 0 && (ratio <= -0.5 || detail.swipe)) { //左滑打开
  5404. this.openPercentage(-100);
  5405. } else if(direction === 'left' && ratio > 0 && (ratio <= 0.5 || detail.swipe)) { //左滑关闭
  5406. this.openPercentage(0);
  5407. } else if(direction === 'left' && ratio < 0 && ratio >= -0.5) { //左滑还原关闭
  5408. this.openPercentage(0);
  5409. } else if(direction === 'left' && ratio > 0.5) { //左滑还原打开
  5410. this.openPercentage(100);
  5411. } else { //默认关闭
  5412. this.openPercentage(0);
  5413. }
  5414. if(ratio === 1 || ratio === -1) { //此处不触发webkitTransitionEnd,所以手动dispatch
  5415. this._dispatchEvent();
  5416. }
  5417. } else {
  5418. if(x >= 0) {
  5419. ratio = (this.offCanvasRightWidth && (x / this.offCanvasRightWidth)) || 0;
  5420. } else {
  5421. ratio = (this.offCanvasLeftWidth && (x / this.offCanvasLeftWidth)) || 0;
  5422. }
  5423. if(direction === 'right' && ratio <= 0 && (ratio >= -0.5 || detail.swipe)) { //右滑打开
  5424. this.openPercentage(100);
  5425. } else if(direction === 'right' && ratio > 0 && (ratio >= 0.5 || detail.swipe)) { //右滑关闭
  5426. this.openPercentage(0);
  5427. } else if(direction === 'right' && ratio <= -0.5) { //右滑还原关闭
  5428. this.openPercentage(0);
  5429. } else if(direction === 'right' && ratio > 0 && ratio <= 0.5) { //右滑还原打开
  5430. this.openPercentage(-100);
  5431. } else if(direction === 'left' && ratio >= 0 && (ratio <= 0.5 || detail.swipe)) { //左滑打开
  5432. this.openPercentage(-100);
  5433. } else if(direction === 'left' && ratio < 0 && (ratio <= -0.5 || detail.swipe)) { //左滑关闭
  5434. this.openPercentage(0);
  5435. } else if(direction === 'left' && ratio >= 0.5) { //左滑还原关闭
  5436. this.openPercentage(0);
  5437. } else if(direction === 'left' && ratio >= -0.5 && ratio < 0) { //左滑还原打开
  5438. this.openPercentage(100);
  5439. } else {
  5440. this.openPercentage(0);
  5441. }
  5442. if(ratio === 1 || ratio === -1 || ratio === 0) {
  5443. this._dispatchEvent();
  5444. return;
  5445. }
  5446. }
  5447. }
  5448. break;
  5449. }
  5450. },
  5451. _dispatchEvent: function() {
  5452. if(this.classList.contains(CLASS_ACTIVE)) {
  5453. $.trigger(this.wrapper, 'shown', this);
  5454. } else {
  5455. $.trigger(this.wrapper, 'hidden', this);
  5456. }
  5457. },
  5458. _initOffCanvasVisible: function() {
  5459. if(!this.visible) {
  5460. this.visible = true;
  5461. if(this.offCanvasLeft) {
  5462. this.offCanvasLeft.style.visibility = 'visible';
  5463. }
  5464. if(this.offCanvasRight) {
  5465. this.offCanvasRight.style.visibility = 'visible';
  5466. }
  5467. }
  5468. },
  5469. initEvent: function() {
  5470. var self = this;
  5471. if(self.backdrop) {
  5472. self.backdrop.addEventListener('tap', function(e) {
  5473. self.close();
  5474. e.detail.gesture.preventDefault();
  5475. });
  5476. }
  5477. if(this.classList.contains('mui-draggable')) {
  5478. this.wrapper.addEventListener($.EVENT_START, this); //临时处理
  5479. this.wrapper.addEventListener('drag', this);
  5480. this.wrapper.addEventListener('dragend', this);
  5481. }
  5482. this.wrapper.addEventListener('webkitTransitionEnd', this);
  5483. },
  5484. openPercentage: function(percentage) {
  5485. var p = percentage / 100;
  5486. if(!this.slideIn) {
  5487. if(this.offCanvasLeft && percentage >= 0) {
  5488. this.updateTranslate(this.offCanvasLeftWidth * p);
  5489. this.offCanvasLeft.classList[p !== 0 ? 'add' : 'remove'](CLASS_ACTIVE);
  5490. } else if(this.offCanvasRight && percentage <= 0) {
  5491. this.updateTranslate(this.offCanvasRightWidth * p);
  5492. this.offCanvasRight.classList[p !== 0 ? 'add' : 'remove'](CLASS_ACTIVE);
  5493. }
  5494. this.classList[p !== 0 ? 'add' : 'remove'](CLASS_ACTIVE);
  5495. } else {
  5496. if(this.offCanvasLeft && percentage >= 0) {
  5497. p = p === 0 ? -1 : 0;
  5498. this.updateTranslate(this.offCanvasLeftWidth * p);
  5499. this.offCanvasLeft.classList[percentage !== 0 ? 'add' : 'remove'](CLASS_ACTIVE);
  5500. } else if(this.offCanvasRight && percentage <= 0) {
  5501. p = p === 0 ? 1 : 0;
  5502. this.updateTranslate(this.offCanvasRightWidth * p);
  5503. this.offCanvasRight.classList[percentage !== 0 ? 'add' : 'remove'](CLASS_ACTIVE);
  5504. }
  5505. this.classList[percentage !== 0 ? 'add' : 'remove'](CLASS_ACTIVE);
  5506. }
  5507. },
  5508. updateTranslate: function(x) {
  5509. if(x !== this.lastTranslateX) {
  5510. if(!this.slideIn) {
  5511. if((!this.offCanvasLeft && x > 0) || (!this.offCanvasRight && x < 0)) {
  5512. this.setTranslateX(0);
  5513. return;
  5514. }
  5515. if(this.leftShowing && x > this.offCanvasLeftWidth) {
  5516. this.setTranslateX(this.offCanvasLeftWidth);
  5517. return;
  5518. }
  5519. if(this.rightShowing && x < -this.offCanvasRightWidth) {
  5520. this.setTranslateX(-this.offCanvasRightWidth);
  5521. return;
  5522. }
  5523. this.setTranslateX(x);
  5524. if(x >= 0) {
  5525. this.leftShowing = true;
  5526. this.rightShowing = false;
  5527. if(x > 0) {
  5528. if(this.offCanvasLeft) {
  5529. $.each(this.offCanvasLefts, function(index, offCanvas) {
  5530. if(offCanvas === this.offCanvasLeft) {
  5531. this.offCanvasLeft.style.zIndex = 0;
  5532. } else {
  5533. offCanvas.style.zIndex = -1;
  5534. }
  5535. }.bind(this));
  5536. }
  5537. if(this.offCanvasRight) {
  5538. this.offCanvasRight.style.zIndex = -1;
  5539. }
  5540. }
  5541. } else {
  5542. this.rightShowing = true;
  5543. this.leftShowing = false;
  5544. if(this.offCanvasRight) {
  5545. $.each(this.offCanvasRights, function(index, offCanvas) {
  5546. if(offCanvas === this.offCanvasRight) {
  5547. offCanvas.style.zIndex = 0;
  5548. } else {
  5549. offCanvas.style.zIndex = -1;
  5550. }
  5551. }.bind(this));
  5552. }
  5553. if(this.offCanvasLeft) {
  5554. this.offCanvasLeft.style.zIndex = -1;
  5555. }
  5556. }
  5557. } else {
  5558. if(this.offCanvas.classList.contains(CLASS_OFF_CANVAS_RIGHT)) {
  5559. if(x < 0) {
  5560. this.setTranslateX(0);
  5561. return;
  5562. }
  5563. if(x > this.offCanvasRightWidth) {
  5564. this.setTranslateX(this.offCanvasRightWidth);
  5565. return;
  5566. }
  5567. } else {
  5568. if(x > 0) {
  5569. this.setTranslateX(0);
  5570. return;
  5571. }
  5572. if(x < -this.offCanvasLeftWidth) {
  5573. this.setTranslateX(-this.offCanvasLeftWidth);
  5574. return;
  5575. }
  5576. }
  5577. this.setTranslateX(x);
  5578. }
  5579. this.lastTranslateX = x;
  5580. }
  5581. },
  5582. setTranslateX: $.animationFrame(function(x) {
  5583. if(this.scroller) {
  5584. if(this.scalable && this.offCanvas.parentNode === this.wrapper) {
  5585. var percent = Math.abs(x) / this.offCanvasWidth;
  5586. var zoomOutScale = 1 - (1 - this.options.scale) * percent;
  5587. var zoomInScale = this.options.scale + (1 - this.options.scale) * percent;
  5588. var zoomOutOpacity = 1 - (1 - this.options.opacity) * percent;
  5589. var zoomInOpacity = this.options.opacity + (1 - this.options.opacity) * percent;
  5590. if(this.offCanvas.classList.contains(CLASS_OFF_CANVAS_LEFT)) {
  5591. this.offCanvas.style.webkitTransformOrigin = '-100%';
  5592. this.scroller.style.webkitTransformOrigin = 'left';
  5593. } else {
  5594. this.offCanvas.style.webkitTransformOrigin = '200%';
  5595. this.scroller.style.webkitTransformOrigin = 'right';
  5596. }
  5597. this.offCanvas.style.opacity = zoomInOpacity;
  5598. this.offCanvas.style.webkitTransform = 'translate3d(0,0,0) scale(' + zoomInScale + ')';
  5599. this.scroller.style.webkitTransform = 'translate3d(' + x + 'px,0,0) scale(' + zoomOutScale + ')';
  5600. } else {
  5601. if(this.slideIn) {
  5602. this.offCanvas.style.webkitTransform = 'translate3d(' + x + 'px,0,0)';
  5603. } else {
  5604. this.scroller.style.webkitTransform = 'translate3d(' + x + 'px,0,0)';
  5605. }
  5606. }
  5607. }
  5608. }),
  5609. getTranslateX: function() {
  5610. if(this.offCanvas) {
  5611. var scroller = this.slideIn ? this.offCanvas : this.scroller;
  5612. var result = $.parseTranslateMatrix($.getStyles(scroller, 'webkitTransform'));
  5613. return(result && result.x) || 0;
  5614. }
  5615. return 0;
  5616. },
  5617. isShown: function(direction) {
  5618. var shown = false;
  5619. if(!this.slideIn) {
  5620. var x = this.getTranslateX();
  5621. if(direction === 'right') {
  5622. shown = this.classList.contains(CLASS_ACTIVE) && x < 0;
  5623. } else if(direction === 'left') {
  5624. shown = this.classList.contains(CLASS_ACTIVE) && x > 0;
  5625. } else {
  5626. shown = this.classList.contains(CLASS_ACTIVE) && x !== 0;
  5627. }
  5628. } else {
  5629. if(direction === 'left') {
  5630. shown = this.classList.contains(CLASS_ACTIVE) && this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_LEFT + '.' + CLASS_ACTIVE);
  5631. } else if(direction === 'right') {
  5632. shown = this.classList.contains(CLASS_ACTIVE) && this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_RIGHT + '.' + CLASS_ACTIVE);
  5633. } else {
  5634. shown = this.classList.contains(CLASS_ACTIVE) && (this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_LEFT + '.' + CLASS_ACTIVE) || this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_RIGHT + '.' + CLASS_ACTIVE));
  5635. }
  5636. }
  5637. return shown;
  5638. },
  5639. close: function() {
  5640. this._initOffCanvasVisible();
  5641. this.offCanvas = this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_RIGHT + '.' + CLASS_ACTIVE) || this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_LEFT + '.' + CLASS_ACTIVE);
  5642. this.offCanvasWidth = this.offCanvas.offsetWidth;
  5643. if(this.scroller) {
  5644. this.offCanvas.offsetHeight;
  5645. this.offCanvas.classList.add(CLASS_TRANSITIONING);
  5646. this.scroller.classList.add(CLASS_TRANSITIONING);
  5647. this.openPercentage(0);
  5648. }
  5649. },
  5650. show: function(direction) {
  5651. this._initOffCanvasVisible();
  5652. if(this.isShown(direction)) {
  5653. return false;
  5654. }
  5655. if(!direction) {
  5656. direction = this.wrapper.querySelector('.' + CLASS_OFF_CANVAS_RIGHT) ? 'right' : 'left';
  5657. }
  5658. if(direction === 'right') {
  5659. this.offCanvas = this.offCanvasRight;
  5660. this.offCanvasWidth = this.offCanvasRightWidth;
  5661. } else {
  5662. this.offCanvas = this.offCanvasLeft;
  5663. this.offCanvasWidth = this.offCanvasLeftWidth;
  5664. }
  5665. if(this.scroller) {
  5666. this.offCanvas.offsetHeight;
  5667. this.offCanvas.classList.add(CLASS_TRANSITIONING);
  5668. this.scroller.classList.add(CLASS_TRANSITIONING);
  5669. this.openPercentage(direction === 'left' ? 100 : -100);
  5670. }
  5671. return true;
  5672. },
  5673. toggle: function(directionOrOffCanvas) {
  5674. var direction = directionOrOffCanvas;
  5675. if(directionOrOffCanvas && directionOrOffCanvas.classList) {
  5676. direction = directionOrOffCanvas.classList.contains(CLASS_OFF_CANVAS_LEFT) ? 'left' : 'right';
  5677. this.refresh(directionOrOffCanvas);
  5678. }
  5679. if(!this.show(direction)) {
  5680. this.close();
  5681. }
  5682. }
  5683. });
  5684. //hash to offcanvas
  5685. var findOffCanvasContainer = function(target) {
  5686. parentNode = target.parentNode;
  5687. if(parentNode) {
  5688. if(parentNode.classList.contains(CLASS_OFF_CANVAS_WRAP)) {
  5689. return parentNode;
  5690. } else {
  5691. parentNode = parentNode.parentNode;
  5692. if(parentNode.classList.contains(CLASS_OFF_CANVAS_WRAP)) {
  5693. return parentNode;
  5694. }
  5695. }
  5696. }
  5697. };
  5698. var handle = function(event, target) {
  5699. if(target.tagName === 'A' && target.hash) {
  5700. var offcanvas = document.getElementById(target.hash.replace('#', ''));
  5701. if(offcanvas) {
  5702. var container = findOffCanvasContainer(offcanvas);
  5703. if(container) {
  5704. $.targets._container = container;
  5705. return offcanvas;
  5706. }
  5707. }
  5708. }
  5709. return false;
  5710. };
  5711. $.registerTarget({
  5712. name: name,
  5713. index: 60,
  5714. handle: handle,
  5715. target: false,
  5716. isReset: false,
  5717. isContinue: true
  5718. });
  5719. window.addEventListener('tap', function(e) {
  5720. if(!$.targets.offcanvas) {
  5721. return;
  5722. }
  5723. //TODO 此处类型的代码后续考虑统一优化(target机制),现在的实现费力不讨好
  5724. var target = e.target;
  5725. for(; target && target !== document; target = target.parentNode) {
  5726. if(target.tagName === 'A' && target.hash && target.hash === ('#' + $.targets.offcanvas.id)) {
  5727. e.detail && e.detail.gesture && e.detail.gesture.preventDefault(); //fixed hashchange
  5728. $($.targets._container).offCanvas().toggle($.targets.offcanvas);
  5729. $.targets.offcanvas = $.targets._container = null;
  5730. break;
  5731. }
  5732. }
  5733. });
  5734. $.fn.offCanvas = function(options) {
  5735. var offCanvasApis = [];
  5736. this.each(function() {
  5737. var offCanvasApi = null;
  5738. var self = this;
  5739. //hack old version
  5740. if(!self.classList.contains(CLASS_OFF_CANVAS_WRAP)) {
  5741. self = findOffCanvasContainer(self);
  5742. }
  5743. var id = self.getAttribute('data-offCanvas');
  5744. if(!id) {
  5745. id = ++$.uuid;
  5746. $.data[id] = offCanvasApi = new OffCanvas(self, options);
  5747. self.setAttribute('data-offCanvas', id);
  5748. } else {
  5749. offCanvasApi = $.data[id];
  5750. }
  5751. if(options === 'show' || options === 'close' || options === 'toggle') {
  5752. offCanvasApi.toggle();
  5753. }
  5754. offCanvasApis.push(offCanvasApi);
  5755. });
  5756. return offCanvasApis.length === 1 ? offCanvasApis[0] : offCanvasApis;
  5757. };
  5758. $.ready(function() {
  5759. $('.mui-off-canvas-wrap').offCanvas();
  5760. });
  5761. })(mui, window, document, 'offcanvas');
  5762. /**
  5763. * actions
  5764. * @param {type} $
  5765. * @param {type} name
  5766. * @returns {undefined}
  5767. */
  5768. (function($, name) {
  5769. var CLASS_ACTION = 'mui-action';
  5770. var handle = function(event, target) {
  5771. var className = target.className || '';
  5772. if(typeof className !== 'string') { //svg className(SVGAnimatedString)
  5773. className = '';
  5774. }
  5775. if(className && ~className.indexOf(CLASS_ACTION)) {
  5776. if(target.classList.contains('mui-action-back')) {
  5777. event.preventDefault();
  5778. }
  5779. return target;
  5780. }
  5781. return false;
  5782. };
  5783. $.registerTarget({
  5784. name: name,
  5785. index: 50,
  5786. handle: handle,
  5787. target: false,
  5788. isContinue: true
  5789. });
  5790. })(mui, 'action');
  5791. /**
  5792. * Modals
  5793. * @param {type} $
  5794. * @param {type} window
  5795. * @param {type} document
  5796. * @param {type} name
  5797. * @returns {undefined}
  5798. */
  5799. (function($, window, document, name) {
  5800. var CLASS_MODAL = 'mui-modal';
  5801. var handle = function(event, target) {
  5802. if(target.tagName === 'A' && target.hash) {
  5803. var modal = document.getElementById(target.hash.replace('#', ''));
  5804. if(modal && modal.classList.contains(CLASS_MODAL)) {
  5805. return modal;
  5806. }
  5807. }
  5808. return false;
  5809. };
  5810. $.registerTarget({
  5811. name: name,
  5812. index: 50,
  5813. handle: handle,
  5814. target: false,
  5815. isReset: false,
  5816. isContinue: true
  5817. });
  5818. window.addEventListener('tap', function(event) {
  5819. if($.targets.modal) {
  5820. event.detail.gesture.preventDefault(); //fixed hashchange
  5821. $.targets.modal.classList.toggle('mui-active');
  5822. }
  5823. });
  5824. })(mui, window, document, 'modal');
  5825. /**
  5826. * Popovers
  5827. * @param {type} $
  5828. * @param {type} window
  5829. * @param {type} document
  5830. * @param {type} name
  5831. * @param {type} undefined
  5832. * @returns {undefined}
  5833. */
  5834. (function($, window, document, name) {
  5835. var CLASS_POPOVER = 'mui-popover';
  5836. var CLASS_POPOVER_ARROW = 'mui-popover-arrow';
  5837. var CLASS_ACTION_POPOVER = 'mui-popover-action';
  5838. var CLASS_BACKDROP = 'mui-backdrop';
  5839. var CLASS_BAR_POPOVER = 'mui-bar-popover';
  5840. var CLASS_BAR_BACKDROP = 'mui-bar-backdrop';
  5841. var CLASS_ACTION_BACKDROP = 'mui-backdrop-action';
  5842. var CLASS_ACTIVE = 'mui-active';
  5843. var CLASS_BOTTOM = 'mui-bottom';
  5844. var handle = function(event, target) {
  5845. if(target.tagName === 'A' && target.hash) {
  5846. $.targets._popover = document.getElementById(target.hash.replace('#', ''));
  5847. if($.targets._popover && $.targets._popover.classList.contains(CLASS_POPOVER)) {
  5848. return target;
  5849. } else {
  5850. $.targets._popover = null;
  5851. }
  5852. }
  5853. return false;
  5854. };
  5855. $.registerTarget({
  5856. name: name,
  5857. index: 60,
  5858. handle: handle,
  5859. target: false,
  5860. isReset: false,
  5861. isContinue: true
  5862. });
  5863. var onPopoverShown = function(e) {
  5864. this.removeEventListener('webkitTransitionEnd', onPopoverShown);
  5865. this.addEventListener($.EVENT_MOVE, $.preventDefault);
  5866. $.trigger(this, 'shown', this);
  5867. }
  5868. var onPopoverHidden = function(e) {
  5869. setStyle(this, 'none');
  5870. this.removeEventListener('webkitTransitionEnd', onPopoverHidden);
  5871. this.removeEventListener($.EVENT_MOVE, $.preventDefault);
  5872. $.trigger(this, 'hidden', this);
  5873. };
  5874. var backdrop = (function() {
  5875. var element = document.createElement('div');
  5876. element.classList.add(CLASS_BACKDROP);
  5877. element.addEventListener($.EVENT_MOVE, $.preventDefault);
  5878. element.addEventListener('tap', function(e) {
  5879. var popover = $.targets._popover;
  5880. if(popover) {
  5881. popover.addEventListener('webkitTransitionEnd', onPopoverHidden);
  5882. popover.classList.remove(CLASS_ACTIVE);
  5883. removeBackdrop(popover);
  5884. }
  5885. });
  5886. return element;
  5887. }());
  5888. var removeBackdropTimer;
  5889. var removeBackdrop = function(popover) {
  5890. backdrop.setAttribute('style', 'opacity:0');
  5891. $.targets.popover = $.targets._popover = null; //reset
  5892. removeBackdropTimer = $.later(function() {
  5893. if(!popover.classList.contains(CLASS_ACTIVE) && backdrop.parentNode && backdrop.parentNode === document.body) {
  5894. document.body.removeChild(backdrop);
  5895. }
  5896. }, 350);
  5897. };
  5898. window.addEventListener('tap', function(e) {
  5899. if(!$.targets.popover) {
  5900. return;
  5901. }
  5902. var toggle = false;
  5903. var target = e.target;
  5904. for(; target && target !== document; target = target.parentNode) {
  5905. if(target === $.targets.popover) {
  5906. toggle = true;
  5907. }
  5908. }
  5909. if(toggle) {
  5910. e.detail.gesture.preventDefault(); //fixed hashchange
  5911. togglePopover($.targets._popover, $.targets.popover);
  5912. }
  5913. });
  5914. var togglePopover = function(popover, anchor, state) {
  5915. if((state === 'show' && popover.classList.contains(CLASS_ACTIVE)) || (state === 'hide' && !popover.classList.contains(CLASS_ACTIVE))) {
  5916. return;
  5917. }
  5918. removeBackdropTimer && removeBackdropTimer.cancel(); //取消remove的timer
  5919. //remove一遍,以免来回快速切换,导致webkitTransitionEnd不触发,无法remove
  5920. popover.removeEventListener('webkitTransitionEnd', onPopoverShown);
  5921. popover.removeEventListener('webkitTransitionEnd', onPopoverHidden);
  5922. backdrop.classList.remove(CLASS_BAR_BACKDROP);
  5923. backdrop.classList.remove(CLASS_ACTION_BACKDROP);
  5924. var _popover = document.querySelector('.mui-popover.mui-active');
  5925. if(_popover) {
  5926. // _popover.setAttribute('style', '');
  5927. _popover.addEventListener('webkitTransitionEnd', onPopoverHidden);
  5928. _popover.classList.remove(CLASS_ACTIVE);
  5929. // _popover.removeEventListener('webkitTransitionEnd', onPopoverHidden);
  5930. //同一个弹出则直接返回,解决同一个popover的toggle
  5931. if(popover === _popover) {
  5932. removeBackdrop(_popover);
  5933. return;
  5934. }
  5935. }
  5936. var isActionSheet = false;
  5937. if(popover.classList.contains(CLASS_BAR_POPOVER) || popover.classList.contains(CLASS_ACTION_POPOVER)) { //navBar
  5938. if(popover.classList.contains(CLASS_ACTION_POPOVER)) { //action sheet popover
  5939. isActionSheet = true;
  5940. backdrop.classList.add(CLASS_ACTION_BACKDROP);
  5941. } else { //bar popover
  5942. backdrop.classList.add(CLASS_BAR_BACKDROP);
  5943. // if (anchor) {
  5944. // if (anchor.parentNode) {
  5945. // var offsetWidth = anchor.offsetWidth;
  5946. // var offsetLeft = anchor.offsetLeft;
  5947. // var innerWidth = window.innerWidth;
  5948. // popover.style.left = (Math.min(Math.max(offsetLeft, defaultPadding), innerWidth - offsetWidth - defaultPadding)) + "px";
  5949. // } else {
  5950. // //TODO anchor is position:{left,top,bottom,right}
  5951. // }
  5952. // }
  5953. }
  5954. }
  5955. setStyle(popover, 'block'); //actionsheet transform
  5956. popover.offsetHeight;
  5957. popover.classList.add(CLASS_ACTIVE);
  5958. backdrop.setAttribute('style', '');
  5959. document.body.appendChild(backdrop);
  5960. calPosition(popover, anchor, isActionSheet); //position
  5961. backdrop.classList.add(CLASS_ACTIVE);
  5962. popover.addEventListener('webkitTransitionEnd', onPopoverShown);
  5963. };
  5964. var setStyle = function(popover, display, top, left) {
  5965. var style = popover.style;
  5966. if(typeof display !== 'undefined')
  5967. style.display = display;
  5968. if(typeof top !== 'undefined')
  5969. style.top = top + 'px';
  5970. if(typeof left !== 'undefined')
  5971. style.left = left + 'px';
  5972. };
  5973. var calPosition = function(popover, anchor, isActionSheet) {
  5974. if(!popover || !anchor) {
  5975. return;
  5976. }
  5977. if(isActionSheet) { //actionsheet
  5978. setStyle(popover, 'block')
  5979. return;
  5980. }
  5981. var wWidth = window.innerWidth;
  5982. var wHeight = window.innerHeight;
  5983. var pWidth = popover.offsetWidth;
  5984. var pHeight = popover.offsetHeight;
  5985. var aWidth = anchor.offsetWidth;
  5986. var aHeight = anchor.offsetHeight;
  5987. var offset = $.offset(anchor);
  5988. var arrow = popover.querySelector('.' + CLASS_POPOVER_ARROW);
  5989. if(!arrow) {
  5990. arrow = document.createElement('div');
  5991. arrow.className = CLASS_POPOVER_ARROW;
  5992. popover.appendChild(arrow);
  5993. }
  5994. var arrowSize = arrow && arrow.offsetWidth / 2 || 0;
  5995. var pTop = 0;
  5996. var pLeft = 0;
  5997. var diff = 0;
  5998. var arrowLeft = 0;
  5999. var defaultPadding = popover.classList.contains(CLASS_ACTION_POPOVER) ? 0 : 5;
  6000. var position = 'top';
  6001. if((pHeight + arrowSize) < (offset.top - window.pageYOffset)) { //top
  6002. pTop = offset.top - pHeight - arrowSize;
  6003. } else if((pHeight + arrowSize) < (wHeight - (offset.top - window.pageYOffset) - aHeight)) { //bottom
  6004. position = 'bottom';
  6005. pTop = offset.top + aHeight + arrowSize;
  6006. } else { //middle
  6007. position = 'middle';
  6008. pTop = Math.max((wHeight - pHeight) / 2 + window.pageYOffset, 0);
  6009. pLeft = Math.max((wWidth - pWidth) / 2 + window.pageXOffset, 0);
  6010. }
  6011. if(position === 'top' || position === 'bottom') {
  6012. pLeft = aWidth / 2 + offset.left - pWidth / 2;
  6013. diff = pLeft;
  6014. if(pLeft < defaultPadding) pLeft = defaultPadding;
  6015. if(pLeft + pWidth > wWidth) pLeft = wWidth - pWidth - defaultPadding;
  6016. if(arrow) {
  6017. if(position === 'top') {
  6018. arrow.classList.add(CLASS_BOTTOM);
  6019. } else {
  6020. arrow.classList.remove(CLASS_BOTTOM);
  6021. }
  6022. diff = diff - pLeft;
  6023. arrowLeft = (pWidth / 2 - arrowSize / 2 + diff);
  6024. arrowLeft = Math.max(Math.min(arrowLeft, pWidth - arrowSize * 2 - 6), 6);
  6025. arrow.setAttribute('style', 'left:' + arrowLeft + 'px');
  6026. }
  6027. } else if(position === 'middle') {
  6028. arrow.setAttribute('style', 'display:none');
  6029. }
  6030. setStyle(popover, 'block', pTop, pLeft);
  6031. };
  6032. $.createMask = function(callback) {
  6033. var element = document.createElement('div');
  6034. element.classList.add(CLASS_BACKDROP);
  6035. element.addEventListener($.EVENT_MOVE, $.preventDefault);
  6036. element.addEventListener('tap', function() {
  6037. mask.close();
  6038. });
  6039. var mask = [element];
  6040. mask._show = false;
  6041. mask.show = function() {
  6042. mask._show = true;
  6043. element.setAttribute('style', 'opacity:1');
  6044. document.body.appendChild(element);
  6045. return mask;
  6046. };
  6047. mask._remove = function() {
  6048. if(mask._show) {
  6049. mask._show = false;
  6050. element.setAttribute('style', 'opacity:0');
  6051. $.later(function() {
  6052. var body = document.body;
  6053. element.parentNode === body && body.removeChild(element);
  6054. }, 350);
  6055. }
  6056. return mask;
  6057. };
  6058. mask.close = function() {
  6059. if(callback) {
  6060. if(callback() !== false) {
  6061. mask._remove();
  6062. }
  6063. } else {
  6064. mask._remove();
  6065. }
  6066. };
  6067. return mask;
  6068. };
  6069. $.fn.popover = function() {
  6070. var args = arguments;
  6071. this.each(function() {
  6072. $.targets._popover = this;
  6073. if(args[0] === 'show' || args[0] === 'hide' || args[0] === 'toggle') {
  6074. togglePopover(this, args[1], args[0]);
  6075. }
  6076. });
  6077. };
  6078. })(mui, window, document, 'popover');
  6079. /**
  6080. * segmented-controllers
  6081. * @param {type} $
  6082. * @param {type} window
  6083. * @param {type} document
  6084. * @param {type} undefined
  6085. * @returns {undefined}
  6086. */
  6087. (function($, window, document, name, undefined) {
  6088. var CLASS_CONTROL_ITEM = 'mui-control-item';
  6089. var CLASS_SEGMENTED_CONTROL = 'mui-segmented-control';
  6090. var CLASS_SEGMENTED_CONTROL_VERTICAL = 'mui-segmented-control-vertical';
  6091. var CLASS_CONTROL_CONTENT = 'mui-control-content';
  6092. var CLASS_TAB_BAR = 'mui-bar-tab';
  6093. var CLASS_TAB_ITEM = 'mui-tab-item';
  6094. var CLASS_SLIDER_ITEM = 'mui-slider-item';
  6095. var handle = function(event, target) {
  6096. if(target.classList && (target.classList.contains(CLASS_CONTROL_ITEM) || target.classList.contains(CLASS_TAB_ITEM))) {
  6097. if(target.parentNode && target.parentNode.classList && target.parentNode.classList.contains(CLASS_SEGMENTED_CONTROL_VERTICAL)) {
  6098. //vertical 如果preventDefault会导致无法滚动
  6099. } else {
  6100. event.preventDefault(); //stop hash change
  6101. }
  6102. // if (target.hash) {
  6103. return target;
  6104. // }
  6105. }
  6106. return false;
  6107. };
  6108. $.registerTarget({
  6109. name: name,
  6110. index: 80,
  6111. handle: handle,
  6112. target: false
  6113. });
  6114. window.addEventListener('tap', function(e) {
  6115. var targetTab = $.targets.tab;
  6116. if(!targetTab) {
  6117. return;
  6118. }
  6119. var activeTab;
  6120. var activeBodies;
  6121. var targetBody;
  6122. var className = 'mui-active';
  6123. var classSelector = '.' + className;
  6124. var segmentedControl = targetTab.parentNode;
  6125. for(; segmentedControl && segmentedControl !== document; segmentedControl = segmentedControl.parentNode) {
  6126. if(segmentedControl.classList.contains(CLASS_SEGMENTED_CONTROL)) {
  6127. activeTab = segmentedControl.querySelector(classSelector + '.' + CLASS_CONTROL_ITEM);
  6128. break;
  6129. } else if(segmentedControl.classList.contains(CLASS_TAB_BAR)) {
  6130. activeTab = segmentedControl.querySelector(classSelector + '.' + CLASS_TAB_ITEM);
  6131. }
  6132. }
  6133. if(activeTab) {
  6134. activeTab.classList.remove(className);
  6135. }
  6136. var isLastActive = targetTab === activeTab;
  6137. if(targetTab) {
  6138. targetTab.classList.add(className);
  6139. }
  6140. if(!targetTab.hash) {
  6141. return;
  6142. }
  6143. targetBody = document.getElementById(targetTab.hash.replace('#', ''));
  6144. if(!targetBody) {
  6145. return;
  6146. }
  6147. if(!targetBody.classList.contains(CLASS_CONTROL_CONTENT)) { //tab bar popover
  6148. targetTab.classList[isLastActive ? 'remove' : 'add'](className);
  6149. return;
  6150. }
  6151. if(isLastActive) { //same
  6152. return;
  6153. }
  6154. var parentNode = targetBody.parentNode;
  6155. activeBodies = parentNode.querySelectorAll('.' + CLASS_CONTROL_CONTENT + classSelector);
  6156. for(var i = 0; i < activeBodies.length; i++) {
  6157. var activeBody = activeBodies[i];
  6158. activeBody.parentNode === parentNode && activeBody.classList.remove(className);
  6159. }
  6160. targetBody.classList.add(className);
  6161. var contents = [];
  6162. var _contents = parentNode.querySelectorAll('.' + CLASS_CONTROL_CONTENT);
  6163. for(var i = 0; i < _contents.length; i++) { //查找直属子节点
  6164. _contents[i].parentNode === parentNode && (contents.push(_contents[i]));
  6165. }
  6166. $.trigger(targetBody, $.eventName('shown', name), {
  6167. tabNumber: Array.prototype.indexOf.call(contents, targetBody)
  6168. });
  6169. e.detail && e.detail.gesture.preventDefault(); //fixed hashchange
  6170. });
  6171. })(mui, window, document, 'tab');
  6172. /**
  6173. * Toggles switch
  6174. * @param {type} $
  6175. * @param {type} window
  6176. * @param {type} name
  6177. * @returns {undefined}
  6178. */
  6179. (function($, window, name) {
  6180. var CLASS_SWITCH = 'mui-switch';
  6181. var CLASS_SWITCH_HANDLE = 'mui-switch-handle';
  6182. var CLASS_ACTIVE = 'mui-active';
  6183. var CLASS_DRAGGING = 'mui-dragging';
  6184. var CLASS_DISABLED = 'mui-disabled';
  6185. var SELECTOR_SWITCH_HANDLE = '.' + CLASS_SWITCH_HANDLE;
  6186. var handle = function(event, target) {
  6187. if(target.classList && target.classList.contains(CLASS_SWITCH)) {
  6188. return target;
  6189. }
  6190. return false;
  6191. };
  6192. $.registerTarget({
  6193. name: name,
  6194. index: 100,
  6195. handle: handle,
  6196. target: false
  6197. });
  6198. var Toggle = function(element) {
  6199. this.element = element;
  6200. this.classList = this.element.classList;
  6201. this.handle = this.element.querySelector(SELECTOR_SWITCH_HANDLE);
  6202. this.init();
  6203. this.initEvent();
  6204. };
  6205. Toggle.prototype.init = function() {
  6206. this.toggleWidth = this.element.offsetWidth;
  6207. this.handleWidth = this.handle.offsetWidth;
  6208. this.handleX = this.toggleWidth - this.handleWidth - 3;
  6209. };
  6210. Toggle.prototype.initEvent = function() {
  6211. this.element.addEventListener($.EVENT_START, this);
  6212. this.element.addEventListener('drag', this);
  6213. this.element.addEventListener('swiperight', this);
  6214. this.element.addEventListener($.EVENT_END, this);
  6215. this.element.addEventListener($.EVENT_CANCEL, this);
  6216. };
  6217. Toggle.prototype.handleEvent = function(e) {
  6218. if(this.classList.contains(CLASS_DISABLED)) {
  6219. return;
  6220. }
  6221. switch(e.type) {
  6222. case $.EVENT_START:
  6223. this.start(e);
  6224. break;
  6225. case 'drag':
  6226. this.drag(e);
  6227. break;
  6228. case 'swiperight':
  6229. this.swiperight();
  6230. break;
  6231. case $.EVENT_END:
  6232. case $.EVENT_CANCEL:
  6233. this.end(e);
  6234. break;
  6235. }
  6236. };
  6237. Toggle.prototype.start = function(e) {
  6238. this.handle.style.webkitTransitionDuration = this.element.style.webkitTransitionDuration = '.2s';
  6239. this.classList.add(CLASS_DRAGGING);
  6240. if(this.toggleWidth === 0 || this.handleWidth === 0) { //当switch处于隐藏状态时,width为0,需要重新初始化
  6241. this.init();
  6242. }
  6243. };
  6244. Toggle.prototype.drag = function(e) {
  6245. var detail = e.detail;
  6246. if(!this.isDragging) {
  6247. if(detail.direction === 'left' || detail.direction === 'right') {
  6248. this.isDragging = true;
  6249. this.lastChanged = undefined;
  6250. this.initialState = this.classList.contains(CLASS_ACTIVE);
  6251. }
  6252. }
  6253. if(this.isDragging) {
  6254. this.setTranslateX(detail.deltaX);
  6255. e.stopPropagation();
  6256. detail.gesture.preventDefault();
  6257. }
  6258. };
  6259. Toggle.prototype.swiperight = function(e) {
  6260. if(this.isDragging) {
  6261. e.stopPropagation();
  6262. }
  6263. };
  6264. Toggle.prototype.end = function(e) {
  6265. this.classList.remove(CLASS_DRAGGING);
  6266. if(this.isDragging) {
  6267. this.isDragging = false;
  6268. e.stopPropagation();
  6269. $.trigger(this.element, 'toggle', {
  6270. isActive: this.classList.contains(CLASS_ACTIVE)
  6271. });
  6272. } else {
  6273. this.toggle();
  6274. }
  6275. };
  6276. Toggle.prototype.toggle = function(animate) {
  6277. var classList = this.classList;
  6278. if(animate === false) {
  6279. this.handle.style.webkitTransitionDuration = this.element.style.webkitTransitionDuration = '0s';
  6280. } else {
  6281. this.handle.style.webkitTransitionDuration = this.element.style.webkitTransitionDuration = '.2s';
  6282. }
  6283. if(classList.contains(CLASS_ACTIVE)) {
  6284. classList.remove(CLASS_ACTIVE);
  6285. this.handle.style.webkitTransform = 'translate(0,0)';
  6286. } else {
  6287. classList.add(CLASS_ACTIVE);
  6288. this.handle.style.webkitTransform = 'translate(' + this.handleX + 'px,0)';
  6289. }
  6290. $.trigger(this.element, 'toggle', {
  6291. isActive: this.classList.contains(CLASS_ACTIVE)
  6292. });
  6293. };
  6294. Toggle.prototype.setTranslateX = $.animationFrame(function(x) {
  6295. if(!this.isDragging) {
  6296. return;
  6297. }
  6298. var isChanged = false;
  6299. if((this.initialState && -x > (this.handleX / 2)) || (!this.initialState && x > (this.handleX / 2))) {
  6300. isChanged = true;
  6301. }
  6302. if(this.lastChanged !== isChanged) {
  6303. if(isChanged) {
  6304. this.handle.style.webkitTransform = 'translate(' + (this.initialState ? 0 : this.handleX) + 'px,0)';
  6305. this.classList[this.initialState ? 'remove' : 'add'](CLASS_ACTIVE);
  6306. } else {
  6307. this.handle.style.webkitTransform = 'translate(' + (this.initialState ? this.handleX : 0) + 'px,0)';
  6308. this.classList[this.initialState ? 'add' : 'remove'](CLASS_ACTIVE);
  6309. }
  6310. this.lastChanged = isChanged;
  6311. }
  6312. });
  6313. $.fn['switch'] = function(options) {
  6314. var switchApis = [];
  6315. this.each(function() {
  6316. var switchApi = null;
  6317. var id = this.getAttribute('data-switch');
  6318. if(!id) {
  6319. id = ++$.uuid;
  6320. $.data[id] = new Toggle(this);
  6321. this.setAttribute('data-switch', id);
  6322. } else {
  6323. switchApi = $.data[id];
  6324. }
  6325. switchApis.push(switchApi);
  6326. });
  6327. return switchApis.length > 1 ? switchApis : switchApis[0];
  6328. };
  6329. $.ready(function() {
  6330. $('.' + CLASS_SWITCH)['switch']();
  6331. });
  6332. })(mui, window, 'toggle');
  6333. /**
  6334. * Tableviews
  6335. * @param {type} $
  6336. * @param {type} window
  6337. * @param {type} document
  6338. * @returns {undefined}
  6339. */
  6340. (function($, window, document) {
  6341. var CLASS_ACTIVE = 'mui-active';
  6342. var CLASS_SELECTED = 'mui-selected';
  6343. var CLASS_GRID_VIEW = 'mui-grid-view';
  6344. var CLASS_RADIO_VIEW = 'mui-table-view-radio';
  6345. var CLASS_TABLE_VIEW_CELL = 'mui-table-view-cell';
  6346. var CLASS_COLLAPSE_CONTENT = 'mui-collapse-content';
  6347. var CLASS_DISABLED = 'mui-disabled';
  6348. var CLASS_TOGGLE = 'mui-switch';
  6349. var CLASS_BTN = 'mui-btn';
  6350. var CLASS_SLIDER_HANDLE = 'mui-slider-handle';
  6351. var CLASS_SLIDER_LEFT = 'mui-slider-left';
  6352. var CLASS_SLIDER_RIGHT = 'mui-slider-right';
  6353. var CLASS_TRANSITIONING = 'mui-transitioning';
  6354. var SELECTOR_SLIDER_HANDLE = '.' + CLASS_SLIDER_HANDLE;
  6355. var SELECTOR_SLIDER_LEFT = '.' + CLASS_SLIDER_LEFT;
  6356. var SELECTOR_SLIDER_RIGHT = '.' + CLASS_SLIDER_RIGHT;
  6357. var SELECTOR_SELECTED = '.' + CLASS_SELECTED;
  6358. var SELECTOR_BUTTON = '.' + CLASS_BTN;
  6359. var overFactor = 0.8;
  6360. var cell, a;
  6361. var isMoved = isOpened = openedActions = progress = false;
  6362. var sliderHandle = sliderActionLeft = sliderActionRight = buttonsLeft = buttonsRight = sliderDirection = sliderRequestAnimationFrame = false;
  6363. var timer = translateX = lastTranslateX = sliderActionLeftWidth = sliderActionRightWidth = 0;
  6364. var toggleActive = function(isActive) {
  6365. if(isActive) {
  6366. if(a) {
  6367. a.classList.add(CLASS_ACTIVE);
  6368. } else if(cell) {
  6369. cell.classList.add(CLASS_ACTIVE);
  6370. }
  6371. } else {
  6372. timer && timer.cancel();
  6373. if(a) {
  6374. a.classList.remove(CLASS_ACTIVE);
  6375. } else if(cell) {
  6376. cell.classList.remove(CLASS_ACTIVE);
  6377. }
  6378. }
  6379. };
  6380. var updateTranslate = function() {
  6381. if(translateX !== lastTranslateX) {
  6382. if(buttonsRight && buttonsRight.length > 0) {
  6383. progress = translateX / sliderActionRightWidth;
  6384. if(translateX < -sliderActionRightWidth) {
  6385. translateX = -sliderActionRightWidth - Math.pow(-translateX - sliderActionRightWidth, overFactor);
  6386. }
  6387. for(var i = 0, len = buttonsRight.length; i < len; i++) {
  6388. var buttonRight = buttonsRight[i];
  6389. if(typeof buttonRight._buttonOffset === 'undefined') {
  6390. buttonRight._buttonOffset = buttonRight.offsetLeft;
  6391. }
  6392. buttonOffset = buttonRight._buttonOffset;
  6393. setTranslate(buttonRight, (translateX - buttonOffset * (1 + Math.max(progress, -1))));
  6394. }
  6395. }
  6396. if(buttonsLeft && buttonsLeft.length > 0) {
  6397. progress = translateX / sliderActionLeftWidth;
  6398. if(translateX > sliderActionLeftWidth) {
  6399. translateX = sliderActionLeftWidth + Math.pow(translateX - sliderActionLeftWidth, overFactor);
  6400. }
  6401. for(var i = 0, len = buttonsLeft.length; i < len; i++) {
  6402. var buttonLeft = buttonsLeft[i];
  6403. if(typeof buttonLeft._buttonOffset === 'undefined') {
  6404. buttonLeft._buttonOffset = sliderActionLeftWidth - buttonLeft.offsetLeft - buttonLeft.offsetWidth;
  6405. }
  6406. buttonOffset = buttonLeft._buttonOffset;
  6407. if(buttonsLeft.length > 1) {
  6408. buttonLeft.style.zIndex = buttonsLeft.length - i;
  6409. }
  6410. setTranslate(buttonLeft, (translateX + buttonOffset * (1 - Math.min(progress, 1))));
  6411. }
  6412. }
  6413. setTranslate(sliderHandle, translateX);
  6414. lastTranslateX = translateX;
  6415. }
  6416. sliderRequestAnimationFrame = requestAnimationFrame(function() {
  6417. updateTranslate();
  6418. });
  6419. };
  6420. var setTranslate = function(element, x) {
  6421. if(element) {
  6422. element.style.webkitTransform = 'translate(' + x + 'px,0)';
  6423. }
  6424. };
  6425. window.addEventListener($.EVENT_START, function(event) {
  6426. if(cell) {
  6427. toggleActive(false);
  6428. }
  6429. cell = a = false;
  6430. isMoved = isOpened = openedActions = false;
  6431. var target = event.target;
  6432. var isDisabled = false;
  6433. for(; target && target !== document; target = target.parentNode) {
  6434. if(target.classList) {
  6435. var classList = target.classList;
  6436. if((target.tagName === 'INPUT' && target.type !== 'radio' && target.type !== 'checkbox') || target.tagName === 'BUTTON' || classList.contains(CLASS_TOGGLE) || classList.contains(CLASS_BTN) || classList.contains(CLASS_DISABLED)) {
  6437. isDisabled = true;
  6438. }
  6439. if(classList.contains(CLASS_COLLAPSE_CONTENT)) { //collapse content
  6440. break;
  6441. }
  6442. if(classList.contains(CLASS_TABLE_VIEW_CELL)) {
  6443. cell = target;
  6444. //TODO swipe to delete close
  6445. var selected = cell.parentNode.querySelector(SELECTOR_SELECTED);
  6446. if(!cell.parentNode.classList.contains(CLASS_RADIO_VIEW) && selected && selected !== cell) {
  6447. $.swipeoutClose(selected);
  6448. cell = isDisabled = false;
  6449. return;
  6450. }
  6451. if(!cell.parentNode.classList.contains(CLASS_GRID_VIEW)) {
  6452. var link = cell.querySelector('a');
  6453. if(link && link.parentNode === cell) { //li>a
  6454. a = link;
  6455. }
  6456. }
  6457. var handle = cell.querySelector(SELECTOR_SLIDER_HANDLE);
  6458. if(handle) {
  6459. toggleEvents(cell);
  6460. event.stopPropagation();
  6461. }
  6462. if(!isDisabled) {
  6463. if(handle) {
  6464. if(timer) {
  6465. timer.cancel();
  6466. }
  6467. timer = $.later(function() {
  6468. toggleActive(true);
  6469. }, 100);
  6470. } else {
  6471. toggleActive(true);
  6472. }
  6473. }
  6474. break;
  6475. }
  6476. }
  6477. }
  6478. });
  6479. window.addEventListener($.EVENT_MOVE, function(event) {
  6480. toggleActive(false);
  6481. });
  6482. var handleEvent = {
  6483. handleEvent: function(event) {
  6484. switch(event.type) {
  6485. case 'drag':
  6486. this.drag(event);
  6487. break;
  6488. case 'dragend':
  6489. this.dragend(event);
  6490. break;
  6491. case 'flick':
  6492. this.flick(event);
  6493. break;
  6494. case 'swiperight':
  6495. this.swiperight(event);
  6496. break;
  6497. case 'swipeleft':
  6498. this.swipeleft(event);
  6499. break;
  6500. }
  6501. },
  6502. drag: function(event) {
  6503. if(!cell) {
  6504. return;
  6505. }
  6506. if(!isMoved) { //init
  6507. sliderHandle = sliderActionLeft = sliderActionRight = buttonsLeft = buttonsRight = sliderDirection = sliderRequestAnimationFrame = false;
  6508. sliderHandle = cell.querySelector(SELECTOR_SLIDER_HANDLE);
  6509. if(sliderHandle) {
  6510. sliderActionLeft = cell.querySelector(SELECTOR_SLIDER_LEFT);
  6511. sliderActionRight = cell.querySelector(SELECTOR_SLIDER_RIGHT);
  6512. if(sliderActionLeft) {
  6513. sliderActionLeftWidth = sliderActionLeft.offsetWidth;
  6514. buttonsLeft = sliderActionLeft.querySelectorAll(SELECTOR_BUTTON);
  6515. }
  6516. if(sliderActionRight) {
  6517. sliderActionRightWidth = sliderActionRight.offsetWidth;
  6518. buttonsRight = sliderActionRight.querySelectorAll(SELECTOR_BUTTON);
  6519. }
  6520. cell.classList.remove(CLASS_TRANSITIONING);
  6521. isOpened = cell.classList.contains(CLASS_SELECTED);
  6522. if(isOpened) {
  6523. openedActions = cell.querySelector(SELECTOR_SLIDER_LEFT + SELECTOR_SELECTED) ? 'left' : 'right';
  6524. }
  6525. }
  6526. }
  6527. var detail = event.detail;
  6528. var direction = detail.direction;
  6529. var angle = detail.angle;
  6530. if(direction === 'left' && (angle > 150 || angle < -150)) {
  6531. if(buttonsRight || (buttonsLeft && isOpened)) { //存在右侧按钮或存在左侧按钮且是已打开状态
  6532. isMoved = true;
  6533. }
  6534. } else if(direction === 'right' && (angle > -30 && angle < 30)) {
  6535. if(buttonsLeft || (buttonsRight && isOpened)) { //存在左侧按钮或存在右侧按钮且是已打开状态
  6536. isMoved = true;
  6537. }
  6538. }
  6539. if(isMoved) {
  6540. event.stopPropagation();
  6541. event.detail.gesture.preventDefault();
  6542. var translate = event.detail.deltaX;
  6543. if(isOpened) {
  6544. if(openedActions === 'right') {
  6545. translate = translate - sliderActionRightWidth;
  6546. } else {
  6547. translate = translate + sliderActionLeftWidth;
  6548. }
  6549. }
  6550. if((translate > 0 && !buttonsLeft) || (translate < 0 && !buttonsRight)) {
  6551. if(!isOpened) {
  6552. return;
  6553. }
  6554. translate = 0;
  6555. }
  6556. if(translate < 0) {
  6557. sliderDirection = 'toLeft';
  6558. } else if(translate > 0) {
  6559. sliderDirection = 'toRight';
  6560. } else {
  6561. if(!sliderDirection) {
  6562. sliderDirection = 'toLeft';
  6563. }
  6564. }
  6565. if(!sliderRequestAnimationFrame) {
  6566. updateTranslate();
  6567. }
  6568. translateX = translate;
  6569. }
  6570. },
  6571. flick: function(event) {
  6572. if(isMoved) {
  6573. event.stopPropagation();
  6574. }
  6575. },
  6576. swipeleft: function(event) {
  6577. if(isMoved) {
  6578. event.stopPropagation();
  6579. }
  6580. },
  6581. swiperight: function(event) {
  6582. if(isMoved) {
  6583. event.stopPropagation();
  6584. }
  6585. },
  6586. dragend: function(event) {
  6587. if(!isMoved) {
  6588. return;
  6589. }
  6590. event.stopPropagation();
  6591. if(sliderRequestAnimationFrame) {
  6592. cancelAnimationFrame(sliderRequestAnimationFrame);
  6593. sliderRequestAnimationFrame = null;
  6594. }
  6595. var detail = event.detail;
  6596. isMoved = false;
  6597. var action = 'close';
  6598. var actionsWidth = sliderDirection === 'toLeft' ? sliderActionRightWidth : sliderActionLeftWidth;
  6599. var isToggle = detail.swipe || (Math.abs(translateX) > actionsWidth / 2);
  6600. if(isToggle) {
  6601. if(!isOpened) {
  6602. action = 'open';
  6603. } else if(detail.direction === 'left' && openedActions === 'right') {
  6604. action = 'open';
  6605. } else if(detail.direction === 'right' && openedActions === 'left') {
  6606. action = 'open';
  6607. }
  6608. }
  6609. cell.classList.add(CLASS_TRANSITIONING);
  6610. var buttons;
  6611. if(action === 'open') {
  6612. var newTranslate = sliderDirection === 'toLeft' ? -actionsWidth : actionsWidth;
  6613. setTranslate(sliderHandle, newTranslate);
  6614. buttons = sliderDirection === 'toLeft' ? buttonsRight : buttonsLeft;
  6615. if(typeof buttons !== 'undefined') {
  6616. var button = null;
  6617. for(var i = 0; i < buttons.length; i++) {
  6618. button = buttons[i];
  6619. setTranslate(button, newTranslate);
  6620. }
  6621. button.parentNode.classList.add(CLASS_SELECTED);
  6622. cell.classList.add(CLASS_SELECTED);
  6623. if(!isOpened) {
  6624. $.trigger(cell, sliderDirection === 'toLeft' ? 'slideleft' : 'slideright');
  6625. }
  6626. }
  6627. } else {
  6628. setTranslate(sliderHandle, 0);
  6629. sliderActionLeft && sliderActionLeft.classList.remove(CLASS_SELECTED);
  6630. sliderActionRight && sliderActionRight.classList.remove(CLASS_SELECTED);
  6631. cell.classList.remove(CLASS_SELECTED);
  6632. }
  6633. var buttonOffset;
  6634. if(buttonsLeft && buttonsLeft.length > 0 && buttonsLeft !== buttons) {
  6635. for(var i = 0, len = buttonsLeft.length; i < len; i++) {
  6636. var buttonLeft = buttonsLeft[i];
  6637. buttonOffset = buttonLeft._buttonOffset;
  6638. if(typeof buttonOffset === 'undefined') {
  6639. buttonLeft._buttonOffset = sliderActionLeftWidth - buttonLeft.offsetLeft - buttonLeft.offsetWidth;
  6640. }
  6641. setTranslate(buttonLeft, buttonOffset);
  6642. }
  6643. }
  6644. if(buttonsRight && buttonsRight.length > 0 && buttonsRight !== buttons) {
  6645. for(var i = 0, len = buttonsRight.length; i < len; i++) {
  6646. var buttonRight = buttonsRight[i];
  6647. buttonOffset = buttonRight._buttonOffset;
  6648. if(typeof buttonOffset === 'undefined') {
  6649. buttonRight._buttonOffset = buttonRight.offsetLeft;
  6650. }
  6651. setTranslate(buttonRight, -buttonOffset);
  6652. }
  6653. }
  6654. }
  6655. };
  6656. function toggleEvents(element, isRemove) {
  6657. var method = !!isRemove ? 'removeEventListener' : 'addEventListener';
  6658. element[method]('drag', handleEvent);
  6659. element[method]('dragend', handleEvent);
  6660. element[method]('swiperight', handleEvent);
  6661. element[method]('swipeleft', handleEvent);
  6662. element[method]('flick', handleEvent);
  6663. };
  6664. /**
  6665. * 打开滑动菜单
  6666. * @param {Object} el
  6667. * @param {Object} direction
  6668. */
  6669. $.swipeoutOpen = function(el, direction) {
  6670. if(!el) return;
  6671. var classList = el.classList;
  6672. if(classList.contains(CLASS_SELECTED)) return;
  6673. if(!direction) {
  6674. if(el.querySelector(SELECTOR_SLIDER_RIGHT)) {
  6675. direction = 'right';
  6676. } else {
  6677. direction = 'left';
  6678. }
  6679. }
  6680. var swipeoutAction = el.querySelector($.classSelector(".slider-" + direction));
  6681. if(!swipeoutAction) return;
  6682. swipeoutAction.classList.add(CLASS_SELECTED);
  6683. classList.add(CLASS_SELECTED);
  6684. classList.remove(CLASS_TRANSITIONING);
  6685. var buttons = swipeoutAction.querySelectorAll(SELECTOR_BUTTON);
  6686. var swipeoutWidth = swipeoutAction.offsetWidth;
  6687. var translate = (direction === 'right') ? -swipeoutWidth : swipeoutWidth;
  6688. var length = buttons.length;
  6689. var button;
  6690. for(var i = 0; i < length; i++) {
  6691. button = buttons[i];
  6692. if(direction === 'right') {
  6693. setTranslate(button, -button.offsetLeft);
  6694. } else {
  6695. setTranslate(button, (swipeoutWidth - button.offsetWidth - button.offsetLeft));
  6696. }
  6697. }
  6698. classList.add(CLASS_TRANSITIONING);
  6699. for(var i = 0; i < length; i++) {
  6700. setTranslate(buttons[i], translate);
  6701. }
  6702. setTranslate(el.querySelector(SELECTOR_SLIDER_HANDLE), translate);
  6703. };
  6704. /**
  6705. * 关闭滑动菜单
  6706. * @param {Object} el
  6707. */
  6708. $.swipeoutClose = function(el) {
  6709. if(!el) return;
  6710. var classList = el.classList;
  6711. if(!classList.contains(CLASS_SELECTED)) return;
  6712. var direction = el.querySelector(SELECTOR_SLIDER_RIGHT + SELECTOR_SELECTED) ? 'right' : 'left';
  6713. var swipeoutAction = el.querySelector($.classSelector(".slider-" + direction));
  6714. if(!swipeoutAction) return;
  6715. swipeoutAction.classList.remove(CLASS_SELECTED);
  6716. classList.remove(CLASS_SELECTED);
  6717. classList.add(CLASS_TRANSITIONING);
  6718. var buttons = swipeoutAction.querySelectorAll(SELECTOR_BUTTON);
  6719. var swipeoutWidth = swipeoutAction.offsetWidth;
  6720. var length = buttons.length;
  6721. var button;
  6722. setTranslate(el.querySelector(SELECTOR_SLIDER_HANDLE), 0);
  6723. for(var i = 0; i < length; i++) {
  6724. button = buttons[i];
  6725. if(direction === 'right') {
  6726. setTranslate(button, (-button.offsetLeft));
  6727. } else {
  6728. setTranslate(button, (swipeoutWidth - button.offsetWidth - button.offsetLeft));
  6729. }
  6730. }
  6731. };
  6732. window.addEventListener($.EVENT_END, function(event) { //使用touchend来取消高亮,避免一次点击既不触发tap,doubletap,longtap的事件
  6733. if(!cell) {
  6734. return;
  6735. }
  6736. toggleActive(false);
  6737. sliderHandle && toggleEvents(cell, true);
  6738. });
  6739. window.addEventListener($.EVENT_CANCEL, function(event) { //使用touchcancel来取消高亮,避免一次点击既不触发tap,doubletap,longtap的事件
  6740. if(!cell) {
  6741. return;
  6742. }
  6743. toggleActive(false);
  6744. sliderHandle && toggleEvents(cell, true);
  6745. });
  6746. var radioOrCheckboxClick = function(event) {
  6747. var type = event.target && event.target.type || '';
  6748. if(type === 'radio' || type === 'checkbox') {
  6749. return;
  6750. }
  6751. var classList = cell.classList;
  6752. if(classList.contains('mui-radio')) {
  6753. var input = cell.querySelector('input[type=radio]');
  6754. if(input) {
  6755. // input.click();
  6756. if(!input.disabled && !input.readOnly) {
  6757. input.checked = !input.checked;
  6758. $.trigger(input, 'change');
  6759. }
  6760. }
  6761. } else if(classList.contains('mui-checkbox')) {
  6762. var input = cell.querySelector('input[type=checkbox]');
  6763. if(input) {
  6764. // input.click();
  6765. if(!input.disabled && !input.readOnly) {
  6766. input.checked = !input.checked;
  6767. $.trigger(input, 'change');
  6768. }
  6769. }
  6770. }
  6771. };
  6772. //fixed hashchange(android)
  6773. window.addEventListener($.EVENT_CLICK, function(e) {
  6774. if(cell && cell.classList.contains('mui-collapse')) {
  6775. e.preventDefault();
  6776. }
  6777. });
  6778. window.addEventListener('doubletap', function(event) {
  6779. if(cell) {
  6780. radioOrCheckboxClick(event);
  6781. }
  6782. });
  6783. var preventDefaultException = /^(INPUT|TEXTAREA|BUTTON|SELECT)$/;
  6784. window.addEventListener('tap', function(event) {
  6785. if(!cell) {
  6786. return;
  6787. }
  6788. var isExpand = false;
  6789. var classList = cell.classList;
  6790. var ul = cell.parentNode;
  6791. if(ul && ul.classList.contains(CLASS_RADIO_VIEW)) {
  6792. if(classList.contains(CLASS_SELECTED)) {
  6793. return;
  6794. }
  6795. var selected = ul.querySelector('li' + SELECTOR_SELECTED);
  6796. if(selected) {
  6797. selected.classList.remove(CLASS_SELECTED);
  6798. }
  6799. classList.add(CLASS_SELECTED);
  6800. $.trigger(cell, 'selected', {
  6801. el: cell
  6802. });
  6803. return;
  6804. }
  6805. if(classList.contains('mui-collapse') && !cell.parentNode.classList.contains('mui-unfold')) {
  6806. if(!preventDefaultException.test(event.target.tagName)) {
  6807. event.detail.gesture.preventDefault();
  6808. }
  6809. if(!classList.contains(CLASS_ACTIVE)) { //展开时,需要收缩其他同类
  6810. var collapse = cell.parentNode.querySelector('.mui-collapse.mui-active');
  6811. if(collapse) {
  6812. collapse.classList.remove(CLASS_ACTIVE);
  6813. }
  6814. isExpand = true;
  6815. }
  6816. classList.toggle(CLASS_ACTIVE);
  6817. if(isExpand) {
  6818. //触发展开事件
  6819. $.trigger(cell, 'expand');
  6820. //scroll
  6821. //暂不滚动
  6822. // var offsetTop = $.offset(cell).top;
  6823. // var scrollTop = document.body.scrollTop;
  6824. // var height = window.innerHeight;
  6825. // var offsetHeight = cell.offsetHeight;
  6826. // var cellHeight = (offsetTop - scrollTop + offsetHeight);
  6827. // if (offsetHeight > height) {
  6828. // $.scrollTo(offsetTop, 300);
  6829. // } else if (cellHeight > height) {
  6830. // $.scrollTo(cellHeight - height + scrollTop, 300);
  6831. // }
  6832. }
  6833. } else {
  6834. radioOrCheckboxClick(event);
  6835. }
  6836. });
  6837. })(mui, window, document);
  6838. (function($, window) {
  6839. /**
  6840. * 警告消息框
  6841. */
  6842. $.alert = function(message, title, btnValue, callback) {
  6843. if($.os.plus) {
  6844. if(typeof message === 'undefined') {
  6845. return;
  6846. } else {
  6847. if(typeof title === 'function') {
  6848. callback = title;
  6849. title = null;
  6850. btnValue = '确定';
  6851. } else if(typeof btnValue === 'function') {
  6852. callback = btnValue;
  6853. btnValue = null;
  6854. }
  6855. $.plusReady(function() {
  6856. plus.nativeUI.alert(message, callback, title, btnValue);
  6857. });
  6858. }
  6859. } else {
  6860. //TODO H5版本
  6861. window.alert(message);
  6862. }
  6863. };
  6864. })(mui, window);
  6865. (function($, window) {
  6866. /**
  6867. * 确认消息框
  6868. */
  6869. $.confirm = function(message, title, btnArray, callback) {
  6870. if($.os.plus) {
  6871. if(typeof message === 'undefined') {
  6872. return;
  6873. } else {
  6874. if(typeof title === 'function') {
  6875. callback = title;
  6876. title = null;
  6877. btnArray = null;
  6878. } else if(typeof btnArray === 'function') {
  6879. callback = btnArray;
  6880. btnArray = null;
  6881. }
  6882. $.plusReady(function() {
  6883. plus.nativeUI.confirm(message, callback, title, btnArray);
  6884. });
  6885. }
  6886. } else {
  6887. //H5版本,0为确认,1为取消
  6888. if(window.confirm(message)) {
  6889. callback({
  6890. index: 0
  6891. });
  6892. } else {
  6893. callback({
  6894. index: 1
  6895. });
  6896. }
  6897. }
  6898. };
  6899. })(mui, window);
  6900. (function($, window) {
  6901. /**
  6902. * 输入对话框
  6903. */
  6904. $.prompt = function(text, defaultText, title, btnArray, callback) {
  6905. if($.os.plus) {
  6906. if(typeof message === 'undefined') {
  6907. return;
  6908. } else {
  6909. if(typeof defaultText === 'function') {
  6910. callback = defaultText;
  6911. defaultText = null;
  6912. title = null;
  6913. btnArray = null;
  6914. } else if(typeof title === 'function') {
  6915. callback = title;
  6916. title = null;
  6917. btnArray = null;
  6918. } else if(typeof btnArray === 'function') {
  6919. callback = btnArray;
  6920. btnArray = null;
  6921. }
  6922. $.plusReady(function() {
  6923. plus.nativeUI.prompt(text, callback, title, defaultText, btnArray);
  6924. });
  6925. }
  6926. } else {
  6927. //H5版本(确认index为0,取消index为1)
  6928. var result = window.prompt(text);
  6929. if(result) {
  6930. callback({
  6931. index: 0,
  6932. value: result
  6933. });
  6934. } else {
  6935. callback({
  6936. index: 1,
  6937. value: ''
  6938. });
  6939. }
  6940. }
  6941. };
  6942. })(mui, window);
  6943. (function($, window) {
  6944. var CLASS_ACTIVE = 'mui-active';
  6945. /**
  6946. * 自动消失提示框
  6947. */
  6948. $.toast = function(message, options) {
  6949. var durations = {
  6950. 'long': 3500,
  6951. 'short': 2000
  6952. };
  6953. //计算显示时间
  6954. options = $.extend({
  6955. duration: 'short'
  6956. }, options || {});
  6957. if($.os.plus && options.type !== 'div') {
  6958. //默认显示在底部;
  6959. $.plusReady(function() {
  6960. plus.nativeUI.toast(message, {
  6961. verticalAlign: 'bottom',
  6962. duration: options.duration
  6963. });
  6964. });
  6965. } else {
  6966. if(typeof options.duration === 'number') {
  6967. duration = options.duration > 0 ? options.duration : durations['short'];
  6968. } else {
  6969. duration = durations[options.duration];
  6970. }
  6971. if(!duration) {
  6972. duration = durations['short'];
  6973. }
  6974. var toast = document.createElement('div');
  6975. toast.classList.add('mui-toast-container');
  6976. toast.innerHTML = '<div class="' + 'mui-toast-message' + '">' + message + '</div>';
  6977. toast.addEventListener('webkitTransitionEnd', function() {
  6978. if(!toast.classList.contains(CLASS_ACTIVE)) {
  6979. toast.parentNode.removeChild(toast);
  6980. toast = null;
  6981. }
  6982. });
  6983. //点击则自动消失
  6984. toast.addEventListener('click', function() {
  6985. toast.parentNode.removeChild(toast);
  6986. toast = null;
  6987. });
  6988. document.body.appendChild(toast);
  6989. toast.offsetHeight;
  6990. toast.classList.add(CLASS_ACTIVE);
  6991. setTimeout(function() {
  6992. toast && toast.classList.remove(CLASS_ACTIVE);
  6993. }, duration);
  6994. return {
  6995. isVisible: function() {
  6996. return !!toast;
  6997. }
  6998. }
  6999. }
  7000. };
  7001. })(mui, window);
  7002. /**
  7003. * Popup(alert,confirm,prompt)
  7004. * @param {Object} $
  7005. * @param {Object} window
  7006. * @param {Object} document
  7007. */
  7008. (function($, window, document) {
  7009. var CLASS_POPUP = 'mui-popup';
  7010. var CLASS_POPUP_BACKDROP = 'mui-popup-backdrop';
  7011. var CLASS_POPUP_IN = 'mui-popup-in';
  7012. var CLASS_POPUP_OUT = 'mui-popup-out';
  7013. var CLASS_POPUP_INNER = 'mui-popup-inner';
  7014. var CLASS_POPUP_TITLE = 'mui-popup-title';
  7015. var CLASS_POPUP_TEXT = 'mui-popup-text';
  7016. var CLASS_POPUP_INPUT = 'mui-popup-input';
  7017. var CLASS_POPUP_BUTTONS = 'mui-popup-buttons';
  7018. var CLASS_POPUP_BUTTON = 'mui-popup-button';
  7019. var CLASS_POPUP_BUTTON_BOLD = 'mui-popup-button-bold';
  7020. var CLASS_POPUP_BACKDROP = 'mui-popup-backdrop';
  7021. var CLASS_ACTIVE = 'mui-active';
  7022. var popupStack = [];
  7023. var backdrop = (function() {
  7024. var element = document.createElement('div');
  7025. element.classList.add(CLASS_POPUP_BACKDROP);
  7026. element.addEventListener($.EVENT_MOVE, $.preventDefault);
  7027. element.addEventListener('webkitTransitionEnd', function() {
  7028. if(!this.classList.contains(CLASS_ACTIVE)) {
  7029. element.parentNode && element.parentNode.removeChild(element);
  7030. }
  7031. });
  7032. return element;
  7033. }());
  7034. var createInput = function(placeholder) {
  7035. return '<div class="' + CLASS_POPUP_INPUT + '"><input type="text" autofocus placeholder="' + (placeholder || '') + '"/></div>';
  7036. };
  7037. var createInner = function(message, title, extra) {
  7038. return '<div class="' + CLASS_POPUP_INNER + '"><div class="' + CLASS_POPUP_TITLE + '">' + title + '</div><div class="' + CLASS_POPUP_TEXT + '">' + message.replace(/\r\n/g, "<br/>").replace(/\n/g, "<br/>") + '</div>' + (extra || '') + '</div>';
  7039. };
  7040. var createButtons = function(btnArray) {
  7041. var length = btnArray.length;
  7042. var btns = [];
  7043. for(var i = 0; i < length; i++) {
  7044. btns.push('<span class="' + CLASS_POPUP_BUTTON + (i === length - 1 ? (' ' + CLASS_POPUP_BUTTON_BOLD) : '') + '">' + btnArray[i] + '</span>');
  7045. }
  7046. return '<div class="' + CLASS_POPUP_BUTTONS + '">' + btns.join('') + '</div>';
  7047. };
  7048. var createPopup = function(html, callback) {
  7049. var popupElement = document.createElement('div');
  7050. popupElement.className = CLASS_POPUP;
  7051. popupElement.innerHTML = html;
  7052. var removePopupElement = function() {
  7053. popupElement.parentNode && popupElement.parentNode.removeChild(popupElement);
  7054. popupElement = null;
  7055. };
  7056. popupElement.addEventListener($.EVENT_MOVE, $.preventDefault);
  7057. popupElement.addEventListener('webkitTransitionEnd', function(e) {
  7058. if(popupElement && e.target === popupElement && popupElement.classList.contains(CLASS_POPUP_OUT)) {
  7059. removePopupElement();
  7060. }
  7061. });
  7062. popupElement.style.display = 'block';
  7063. document.body.appendChild(popupElement);
  7064. popupElement.offsetHeight;
  7065. popupElement.classList.add(CLASS_POPUP_IN);
  7066. if(!backdrop.classList.contains(CLASS_ACTIVE)) {
  7067. backdrop.style.display = 'block';
  7068. document.body.appendChild(backdrop);
  7069. backdrop.offsetHeight;
  7070. backdrop.classList.add(CLASS_ACTIVE);
  7071. }
  7072. var btns = $.qsa('.' + CLASS_POPUP_BUTTON, popupElement);
  7073. var input = popupElement.querySelector('.' + CLASS_POPUP_INPUT + ' input');
  7074. var popup = {
  7075. element: popupElement,
  7076. close: function(index, animate) {
  7077. if(popupElement) {
  7078. var result = callback && callback({
  7079. index: index || 0,
  7080. value: input && input.value || ''
  7081. });
  7082. if(result === false) { //返回false则不关闭当前popup
  7083. return;
  7084. }
  7085. if(animate !== false) {
  7086. popupElement.classList.remove(CLASS_POPUP_IN);
  7087. popupElement.classList.add(CLASS_POPUP_OUT);
  7088. } else {
  7089. removePopupElement();
  7090. }
  7091. popupStack.pop();
  7092. //如果还有其他popup,则不remove backdrop
  7093. if(popupStack.length) {
  7094. popupStack[popupStack.length - 1]['show'](animate);
  7095. } else {
  7096. backdrop.classList.remove(CLASS_ACTIVE);
  7097. }
  7098. }
  7099. }
  7100. };
  7101. var handleEvent = function(e) {
  7102. popup.close(btns.indexOf(e.target));
  7103. };
  7104. $(popupElement).on('tap', '.' + CLASS_POPUP_BUTTON, handleEvent);
  7105. if(popupStack.length) {
  7106. popupStack[popupStack.length - 1]['hide']();
  7107. }
  7108. popupStack.push({
  7109. close: popup.close,
  7110. show: function(animate) {
  7111. popupElement.style.display = 'block';
  7112. popupElement.offsetHeight;
  7113. popupElement.classList.add(CLASS_POPUP_IN);
  7114. },
  7115. hide: function() {
  7116. popupElement.style.display = 'none';
  7117. popupElement.classList.remove(CLASS_POPUP_IN);
  7118. }
  7119. });
  7120. return popup;
  7121. };
  7122. var createAlert = function(message, title, btnValue, callback, type) {
  7123. if(typeof message === 'undefined') {
  7124. return;
  7125. } else {
  7126. if(typeof title === 'function') {
  7127. callback = title;
  7128. type = btnValue;
  7129. title = null;
  7130. btnValue = null;
  7131. } else if(typeof btnValue === 'function') {
  7132. type = callback;
  7133. callback = btnValue;
  7134. btnValue = null;
  7135. }
  7136. }
  7137. if(!$.os.plus || type === 'div') {
  7138. return createPopup(createInner(message, title || '提示') + createButtons([btnValue || '确定']), callback);
  7139. }
  7140. return plus.nativeUI.alert(message, callback, title || '提示', btnValue || '确定');
  7141. };
  7142. var createConfirm = function(message, title, btnArray, callback, type) {
  7143. if(typeof message === 'undefined') {
  7144. return;
  7145. } else {
  7146. if(typeof title === 'function') {
  7147. callback = title;
  7148. type = btnArray;
  7149. title = null;
  7150. btnArray = null;
  7151. } else if(typeof btnArray === 'function') {
  7152. type = callback;
  7153. callback = btnArray;
  7154. btnArray = null;
  7155. }
  7156. }
  7157. if(!$.os.plus || type === 'div') {
  7158. return createPopup(createInner(message, title || '提示') + createButtons(btnArray || ['取消', '确认']), callback);
  7159. }
  7160. return plus.nativeUI.confirm(message, callback, title, btnArray || ['取消', '确认']);
  7161. };
  7162. var createPrompt = function(message, placeholder, title, btnArray, callback, type) {
  7163. if(typeof message === 'undefined') {
  7164. return;
  7165. } else {
  7166. if(typeof placeholder === 'function') {
  7167. callback = placeholder;
  7168. type = title;
  7169. placeholder = null;
  7170. title = null;
  7171. btnArray = null;
  7172. } else if(typeof title === 'function') {
  7173. callback = title;
  7174. type = btnArray;
  7175. title = null;
  7176. btnArray = null;
  7177. } else if(typeof btnArray === 'function') {
  7178. type = callback;
  7179. callback = btnArray;
  7180. btnArray = null;
  7181. }
  7182. }
  7183. if(!$.os.plus || type === 'div') {
  7184. return createPopup(createInner(message, title || '提示', createInput(placeholder)) + createButtons(btnArray || ['取消', '确认']), callback);
  7185. }
  7186. return plus.nativeUI.prompt(message, callback, title || '提示', placeholder, btnArray || ['取消', '确认']);
  7187. };
  7188. var closePopup = function() {
  7189. if(popupStack.length) {
  7190. popupStack[popupStack.length - 1]['close']();
  7191. return true;
  7192. } else {
  7193. return false;
  7194. }
  7195. };
  7196. var closePopups = function() {
  7197. while(popupStack.length) {
  7198. popupStack[popupStack.length - 1]['close']();
  7199. }
  7200. };
  7201. $.closePopup = closePopup;
  7202. $.closePopups = closePopups;
  7203. $.alert = createAlert;
  7204. $.confirm = createConfirm;
  7205. $.prompt = createPrompt;
  7206. })(mui, window, document);
  7207. (function($, document) {
  7208. var CLASS_PROGRESSBAR = 'mui-progressbar';
  7209. var CLASS_PROGRESSBAR_IN = 'mui-progressbar-in';
  7210. var CLASS_PROGRESSBAR_OUT = 'mui-progressbar-out';
  7211. var CLASS_PROGRESSBAR_INFINITE = 'mui-progressbar-infinite';
  7212. var SELECTOR_PROGRESSBAR = '.mui-progressbar';
  7213. var _findProgressbar = function(container) {
  7214. container = $(container || 'body');
  7215. if(container.length === 0) return;
  7216. container = container[0];
  7217. if(container.classList.contains(CLASS_PROGRESSBAR)) {
  7218. return container;
  7219. }
  7220. var progressbars = container.querySelectorAll(SELECTOR_PROGRESSBAR);
  7221. if(progressbars) {
  7222. for(var i = 0, len = progressbars.length; i < len; i++) {
  7223. var progressbar = progressbars[i];
  7224. if(progressbar.parentNode === container) {
  7225. return progressbar;
  7226. }
  7227. }
  7228. }
  7229. };
  7230. /**
  7231. * 创建并显示进度条
  7232. * @param {Object} container 可选,默认body,支持selector,DOM Node,mui wrapper
  7233. * @param {Object} progress 可选,undefined表示循环,数字表示具体进度
  7234. * @param {Object} color 可选,指定颜色样式(目前暂未提供实际样式,可暂时不暴露此参数)
  7235. */
  7236. var showProgressbar = function(container, progress, color) {
  7237. if(typeof container === 'number') {
  7238. color = progress;
  7239. progress = container;
  7240. container = 'body';
  7241. }
  7242. container = $(container || 'body');
  7243. if(container.length === 0) return;
  7244. container = container[0];
  7245. var progressbar;
  7246. if(container.classList.contains(CLASS_PROGRESSBAR)) {
  7247. progressbar = container;
  7248. } else {
  7249. var progressbars = container.querySelectorAll(SELECTOR_PROGRESSBAR + ':not(.' + CLASS_PROGRESSBAR_OUT + ')');
  7250. if(progressbars) {
  7251. for(var i = 0, len = progressbars.length; i < len; i++) {
  7252. var _progressbar = progressbars[i];
  7253. if(_progressbar.parentNode === container) {
  7254. progressbar = _progressbar;
  7255. break;
  7256. }
  7257. }
  7258. }
  7259. if(!progressbar) {
  7260. progressbar = document.createElement('span');
  7261. progressbar.className = CLASS_PROGRESSBAR + ' ' + CLASS_PROGRESSBAR_IN + (typeof progress !== 'undefined' ? '' : (' ' + CLASS_PROGRESSBAR_INFINITE)) + (color ? (' ' + CLASS_PROGRESSBAR + '-' + color) : '');
  7262. if(typeof progress !== 'undefined') {
  7263. progressbar.innerHTML = '<span></span>';
  7264. }
  7265. container.appendChild(progressbar);
  7266. } else {
  7267. progressbar.classList.add(CLASS_PROGRESSBAR_IN);
  7268. }
  7269. }
  7270. if(progress) setProgressbar(container, progress);
  7271. return progressbar;
  7272. };
  7273. /**
  7274. * 关闭进度条
  7275. * @param {Object} container 可选,默认body,支持selector,DOM Node,mui wrapper
  7276. */
  7277. var hideProgressbar = function(container) {
  7278. var progressbar = _findProgressbar(container);
  7279. if(!progressbar) {
  7280. return;
  7281. }
  7282. var classList = progressbar.classList;
  7283. if(!classList.contains(CLASS_PROGRESSBAR_IN) || classList.contains(CLASS_PROGRESSBAR_OUT)) {
  7284. return;
  7285. }
  7286. classList.remove(CLASS_PROGRESSBAR_IN);
  7287. classList.add(CLASS_PROGRESSBAR_OUT);
  7288. progressbar.addEventListener('webkitAnimationEnd', function() {
  7289. progressbar.parentNode && progressbar.parentNode.removeChild(progressbar);
  7290. progressbar = null;
  7291. });
  7292. return;
  7293. };
  7294. /**
  7295. * 设置指定进度条进度
  7296. * @param {Object} container 可选,默认body,支持selector,DOM Node,mui wrapper
  7297. * @param {Object} progress 可选,默认0 取值范围[0-100]
  7298. * @param {Object} speed 进度条动画时间
  7299. */
  7300. var setProgressbar = function(container, progress, speed) {
  7301. if(typeof container === 'number') {
  7302. speed = progress;
  7303. progress = container;
  7304. container = false;
  7305. }
  7306. var progressbar = _findProgressbar(container);
  7307. if(!progressbar || progressbar.classList.contains(CLASS_PROGRESSBAR_INFINITE)) {
  7308. return;
  7309. }
  7310. if(progress) progress = Math.min(Math.max(progress, 0), 100);
  7311. progressbar.offsetHeight;
  7312. var span = progressbar.querySelector('span');
  7313. if(span) {
  7314. var style = span.style;
  7315. style.webkitTransform = 'translate3d(' + (-100 + progress) + '%,0,0)';
  7316. if(typeof speed !== 'undefined') {
  7317. style.webkitTransitionDuration = speed + 'ms';
  7318. } else {
  7319. style.webkitTransitionDuration = '';
  7320. }
  7321. }
  7322. return progressbar;
  7323. };
  7324. $.fn.progressbar = function(options) {
  7325. var progressbarApis = [];
  7326. options = options || {};
  7327. this.each(function() {
  7328. var self = this;
  7329. var progressbarApi = self.mui_plugin_progressbar;
  7330. if(!progressbarApi) {
  7331. self.mui_plugin_progressbar = progressbarApi = {
  7332. options: options,
  7333. setOptions: function(options) {
  7334. this.options = options;
  7335. },
  7336. show: function() {
  7337. return showProgressbar(self, this.options.progress, this.options.color);
  7338. },
  7339. setProgress: function(progress) {
  7340. return setProgressbar(self, progress);
  7341. },
  7342. hide: function() {
  7343. return hideProgressbar(self);
  7344. }
  7345. };
  7346. } else if(options) {
  7347. progressbarApi.setOptions(options);
  7348. }
  7349. progressbarApis.push(progressbarApi);
  7350. });
  7351. return progressbarApis.length === 1 ? progressbarApis[0] : progressbarApis;
  7352. };
  7353. // $.setProgressbar = setProgressbar;
  7354. // $.showProgressbar = showProgressbar;
  7355. // $.hideProgressbar = hideProgressbar;
  7356. })(mui, document);
  7357. /**
  7358. * Input(TODO resize)
  7359. * @param {type} $
  7360. * @param {type} window
  7361. * @param {type} document
  7362. * @returns {undefined}
  7363. */
  7364. (function($, window, document) {
  7365. var CLASS_ICON = 'mui-icon';
  7366. var CLASS_ICON_CLEAR = 'mui-icon-clear';
  7367. var CLASS_ICON_SPEECH = 'mui-icon-speech';
  7368. var CLASS_ICON_SEARCH = 'mui-icon-search';
  7369. var CLASS_ICON_PASSWORD = 'mui-icon-eye';
  7370. var CLASS_INPUT_ROW = 'mui-input-row';
  7371. var CLASS_PLACEHOLDER = 'mui-placeholder';
  7372. var CLASS_TOOLTIP = 'mui-tooltip';
  7373. var CLASS_HIDDEN = 'mui-hidden';
  7374. var CLASS_FOCUSIN = 'mui-focusin';
  7375. var SELECTOR_ICON_CLOSE = '.' + CLASS_ICON_CLEAR;
  7376. var SELECTOR_ICON_SPEECH = '.' + CLASS_ICON_SPEECH;
  7377. var SELECTOR_ICON_PASSWORD = '.' + CLASS_ICON_PASSWORD;
  7378. var SELECTOR_PLACEHOLDER = '.' + CLASS_PLACEHOLDER;
  7379. var SELECTOR_TOOLTIP = '.' + CLASS_TOOLTIP;
  7380. var findRow = function(target) {
  7381. for(; target && target !== document; target = target.parentNode) {
  7382. if(target.classList && target.classList.contains(CLASS_INPUT_ROW)) {
  7383. return target;
  7384. }
  7385. }
  7386. return null;
  7387. };
  7388. var Input = function(element, options) {
  7389. this.element = element;
  7390. this.options = options || {
  7391. actions: 'clear'
  7392. };
  7393. if(~this.options.actions.indexOf('slider')) { //slider
  7394. this.sliderActionClass = CLASS_TOOLTIP + ' ' + CLASS_HIDDEN;
  7395. this.sliderActionSelector = SELECTOR_TOOLTIP;
  7396. } else { //clear,speech,search
  7397. if(~this.options.actions.indexOf('clear')) {
  7398. this.clearActionClass = CLASS_ICON + ' ' + CLASS_ICON_CLEAR + ' ' + CLASS_HIDDEN;
  7399. this.clearActionSelector = SELECTOR_ICON_CLOSE;
  7400. }
  7401. if(~this.options.actions.indexOf('speech')) { //only for 5+
  7402. this.speechActionClass = CLASS_ICON + ' ' + CLASS_ICON_SPEECH;
  7403. this.speechActionSelector = SELECTOR_ICON_SPEECH;
  7404. }
  7405. if(~this.options.actions.indexOf('search')) {
  7406. this.searchActionClass = CLASS_PLACEHOLDER;
  7407. this.searchActionSelector = SELECTOR_PLACEHOLDER;
  7408. }
  7409. if(~this.options.actions.indexOf('password')) {
  7410. this.passwordActionClass = CLASS_ICON + ' ' + CLASS_ICON_PASSWORD;
  7411. this.passwordActionSelector = SELECTOR_ICON_PASSWORD;
  7412. }
  7413. }
  7414. this.init();
  7415. };
  7416. Input.prototype.init = function() {
  7417. this.initAction();
  7418. this.initElementEvent();
  7419. };
  7420. Input.prototype.initAction = function() {
  7421. var self = this;
  7422. var row = self.element.parentNode;
  7423. if(row) {
  7424. if(self.sliderActionClass) {
  7425. self.sliderAction = self.createAction(row, self.sliderActionClass, self.sliderActionSelector);
  7426. } else {
  7427. if(self.searchActionClass) {
  7428. self.searchAction = self.createAction(row, self.searchActionClass, self.searchActionSelector);
  7429. self.searchAction.addEventListener('tap', function(e) {
  7430. $.focus(self.element);
  7431. e.stopPropagation();
  7432. });
  7433. }
  7434. if(self.speechActionClass) {
  7435. self.speechAction = self.createAction(row, self.speechActionClass, self.speechActionSelector);
  7436. self.speechAction.addEventListener('click', $.stopPropagation);
  7437. self.speechAction.addEventListener('tap', function(event) {
  7438. self.speechActionClick(event);
  7439. });
  7440. }
  7441. if(self.clearActionClass) {
  7442. self.clearAction = self.createAction(row, self.clearActionClass, self.clearActionSelector);
  7443. self.clearAction.addEventListener('tap', function(event) {
  7444. self.clearActionClick(event);
  7445. });
  7446. }
  7447. if(self.passwordActionClass) {
  7448. self.passwordAction = self.createAction(row, self.passwordActionClass, self.passwordActionSelector);
  7449. self.passwordAction.addEventListener('tap', function(event) {
  7450. self.passwordActionClick(event);
  7451. });
  7452. }
  7453. }
  7454. }
  7455. };
  7456. Input.prototype.createAction = function(row, actionClass, actionSelector) {
  7457. var action = row.querySelector(actionSelector);
  7458. if(!action) {
  7459. var action = document.createElement('span');
  7460. action.className = actionClass;
  7461. if(actionClass === this.searchActionClass) {
  7462. action.innerHTML = '<span class="' + CLASS_ICON + ' ' + CLASS_ICON_SEARCH + '"></span><span>' + this.element.getAttribute('placeholder') + '</span>';
  7463. this.element.setAttribute('placeholder', '');
  7464. if(this.element.value.trim()) {
  7465. row.classList.add('mui-active');
  7466. }
  7467. }
  7468. row.insertBefore(action, this.element.nextSibling);
  7469. }
  7470. return action;
  7471. };
  7472. Input.prototype.initElementEvent = function() {
  7473. var element = this.element;
  7474. if(this.sliderActionClass) {
  7475. var tooltip = this.sliderAction;
  7476. var timer = null;
  7477. var showTip = function() { //每次重新计算是因为控件可能被隐藏,初始化时计算是不正确的
  7478. tooltip.classList.remove(CLASS_HIDDEN);
  7479. var offsetLeft = element.offsetLeft;
  7480. var width = element.offsetWidth - 28;
  7481. var tooltipWidth = tooltip.offsetWidth;
  7482. var distince = Math.abs(element.max - element.min);
  7483. var scaleWidth = (width / distince) * Math.abs(element.value - element.min);
  7484. tooltip.style.left = (14 + offsetLeft + scaleWidth - tooltipWidth / 2) + 'px';
  7485. tooltip.innerText = element.value;
  7486. if(timer) {
  7487. clearTimeout(timer);
  7488. }
  7489. timer = setTimeout(function() {
  7490. tooltip.classList.add(CLASS_HIDDEN);
  7491. }, 1000);
  7492. };
  7493. element.addEventListener('input', showTip);
  7494. element.addEventListener('tap', showTip);
  7495. element.addEventListener($.EVENT_MOVE, function(e) {
  7496. e.stopPropagation();
  7497. });
  7498. } else {
  7499. if(this.clearActionClass) {
  7500. var action = this.clearAction;
  7501. if(!action) {
  7502. return;
  7503. }
  7504. $.each(['keyup', 'change', 'input', 'focus', 'cut', 'paste'], function(index, type) {
  7505. (function(type) {
  7506. element.addEventListener(type, function() {
  7507. action.classList[element.value.trim() ? 'remove' : 'add'](CLASS_HIDDEN);
  7508. });
  7509. })(type);
  7510. });
  7511. element.addEventListener('blur', function() {
  7512. action.classList.add(CLASS_HIDDEN);
  7513. });
  7514. }
  7515. if(this.searchActionClass) {
  7516. element.addEventListener('focus', function() {
  7517. element.parentNode.classList.add('mui-active');
  7518. });
  7519. element.addEventListener('blur', function() {
  7520. if(!element.value.trim()) {
  7521. element.parentNode.classList.remove('mui-active');
  7522. }
  7523. });
  7524. }
  7525. }
  7526. };
  7527. Input.prototype.setPlaceholder = function(text) {
  7528. if(this.searchActionClass) {
  7529. var placeholder = this.element.parentNode.querySelector(SELECTOR_PLACEHOLDER);
  7530. placeholder && (placeholder.getElementsByTagName('span')[1].innerText = text);
  7531. } else {
  7532. this.element.setAttribute('placeholder', text);
  7533. }
  7534. };
  7535. Input.prototype.passwordActionClick = function(event) {
  7536. if(this.element.type === 'text') {
  7537. this.element.type = 'password';
  7538. } else {
  7539. this.element.type = 'text';
  7540. }
  7541. this.passwordAction.classList.toggle('mui-active');
  7542. event.preventDefault();
  7543. };
  7544. Input.prototype.clearActionClick = function(event) {
  7545. var self = this;
  7546. self.element.value = '';
  7547. $.focus(self.element);
  7548. self.clearAction.classList.add(CLASS_HIDDEN);
  7549. event.preventDefault();
  7550. };
  7551. Input.prototype.speechActionClick = function(event) {
  7552. if(window.plus) {
  7553. var self = this;
  7554. var oldValue = self.element.value;
  7555. self.element.value = '';
  7556. document.body.classList.add(CLASS_FOCUSIN);
  7557. plus.speech.startRecognize({
  7558. engine: 'iFly'
  7559. }, function(s) {
  7560. self.element.value += s;
  7561. $.focus(self.element);
  7562. plus.speech.stopRecognize();
  7563. $.trigger(self.element, 'recognized', {
  7564. value: self.element.value
  7565. });
  7566. if(oldValue !== self.element.value) {
  7567. $.trigger(self.element, 'change');
  7568. $.trigger(self.element, 'input');
  7569. }
  7570. // document.body.classList.remove(CLASS_FOCUSIN);
  7571. }, function(e) {
  7572. document.body.classList.remove(CLASS_FOCUSIN);
  7573. });
  7574. } else {
  7575. alert('only for 5+');
  7576. }
  7577. event.preventDefault();
  7578. };
  7579. $.fn.input = function(options) {
  7580. var inputApis = [];
  7581. this.each(function() {
  7582. var inputApi = null;
  7583. var actions = [];
  7584. var row = findRow(this.parentNode);
  7585. if(this.type === 'range' && row.classList.contains('mui-input-range')) {
  7586. actions.push('slider');
  7587. } else {
  7588. var classList = this.classList;
  7589. if(classList.contains('mui-input-clear')) {
  7590. actions.push('clear');
  7591. }
  7592. if(!($.os.android && $.os.stream) && classList.contains('mui-input-speech')) {
  7593. actions.push('speech');
  7594. }
  7595. if(classList.contains('mui-input-password')) {
  7596. actions.push('password');
  7597. }
  7598. if(this.type === 'search' && row.classList.contains('mui-search')) {
  7599. actions.push('search');
  7600. }
  7601. }
  7602. var id = this.getAttribute('data-input-' + actions[0]);
  7603. if(!id) {
  7604. id = ++$.uuid;
  7605. inputApi = $.data[id] = new Input(this, {
  7606. actions: actions.join(',')
  7607. });
  7608. for(var i = 0, len = actions.length; i < len; i++) {
  7609. this.setAttribute('data-input-' + actions[i], id);
  7610. }
  7611. } else {
  7612. inputApi = $.data[id];
  7613. }
  7614. inputApis.push(inputApi);
  7615. });
  7616. return inputApis.length === 1 ? inputApis[0] : inputApis;
  7617. };
  7618. $.ready(function() {
  7619. $('.mui-input-row input').input();
  7620. });
  7621. })(mui, window, document);
  7622. (function($, window) {
  7623. var CLASS_ACTIVE = 'mui-active';
  7624. var rgbaRegex = /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d*(?:\.\d+)?)\)$/;
  7625. var getColor = function(colorStr) {
  7626. var matches = colorStr.match(rgbaRegex);
  7627. if(matches && matches.length === 5) {
  7628. return [
  7629. matches[1],
  7630. matches[2],
  7631. matches[3],
  7632. matches[4]
  7633. ];
  7634. }
  7635. return [];
  7636. };
  7637. var Transparent = function(element, options) {
  7638. this.element = element;
  7639. this.options = $.extend({
  7640. top: 0, //距离顶部高度(到达该高度即触发)
  7641. offset: 150, //滚动透明距离
  7642. duration: 16, //过渡时间
  7643. scrollby: window //监听滚动距离容器
  7644. }, options || {});
  7645. this.scrollByElem = this.options.scrollby || window;
  7646. if(!this.scrollByElem) {
  7647. throw new Error("监听滚动的元素不存在");
  7648. }
  7649. this.isNativeScroll = false;
  7650. if(this.scrollByElem === window) {
  7651. this.isNativeScroll = true;
  7652. } else if(!~this.scrollByElem.className.indexOf('mui-scroll-wrapper')) {
  7653. this.isNativeScroll = true;
  7654. }
  7655. this._style = this.element.style;
  7656. this._bgColor = this._style.backgroundColor;
  7657. var color = getColor(mui.getStyles(this.element, 'backgroundColor'));
  7658. if(color.length) {
  7659. this._R = color[0];
  7660. this._G = color[1];
  7661. this._B = color[2];
  7662. this._A = parseFloat(color[3]);
  7663. this.lastOpacity = this._A;
  7664. this._bufferFn = $.buffer(this.handleScroll, this.options.duration, this);
  7665. this.initEvent();
  7666. } else {
  7667. throw new Error("元素背景颜色必须为RGBA");
  7668. }
  7669. };
  7670. Transparent.prototype.initEvent = function() {
  7671. this.scrollByElem.addEventListener('scroll', this._bufferFn);
  7672. if(this.isNativeScroll) { //原生scroll
  7673. this.scrollByElem.addEventListener($.EVENT_MOVE, this._bufferFn);
  7674. }
  7675. }
  7676. Transparent.prototype.handleScroll = function(e) {
  7677. var y = window.scrollY;
  7678. if(!this.isNativeScroll && e && e.detail) {
  7679. y = -e.detail.y;
  7680. }
  7681. var opacity = (y - this.options.top) / this.options.offset + this._A;
  7682. opacity = Math.min(Math.max(this._A, opacity), 1);
  7683. this._style.backgroundColor = 'rgba(' + this._R + ',' + this._G + ',' + this._B + ',' + opacity + ')';
  7684. if(opacity > this._A) {
  7685. this.element.classList.add(CLASS_ACTIVE);
  7686. } else {
  7687. this.element.classList.remove(CLASS_ACTIVE);
  7688. }
  7689. if(this.lastOpacity !== opacity) {
  7690. $.trigger(this.element, 'alpha', {
  7691. alpha: opacity
  7692. });
  7693. this.lastOpacity = opacity;
  7694. }
  7695. };
  7696. Transparent.prototype.destory = function() {
  7697. this.scrollByElem.removeEventListener('scroll', this._bufferFn);
  7698. this.scrollByElem.removeEventListener($.EVENT_MOVE, this._bufferFn);
  7699. this.element.style.backgroundColor = this._bgColor;
  7700. this.element.mui_plugin_transparent = null;
  7701. };
  7702. $.fn.transparent = function(options) {
  7703. options = options || {};
  7704. var transparentApis = [];
  7705. this.each(function() {
  7706. var transparentApi = this.mui_plugin_transparent;
  7707. if(!transparentApi) {
  7708. var top = this.getAttribute('data-top');
  7709. var offset = this.getAttribute('data-offset');
  7710. var duration = this.getAttribute('data-duration');
  7711. var scrollby = this.getAttribute('data-scrollby');
  7712. if(top !== null && typeof options.top === 'undefined') {
  7713. options.top = top;
  7714. }
  7715. if(offset !== null && typeof options.offset === 'undefined') {
  7716. options.offset = offset;
  7717. }
  7718. if(duration !== null && typeof options.duration === 'undefined') {
  7719. options.duration = duration;
  7720. }
  7721. if(scrollby !== null && typeof options.scrollby === 'undefined') {
  7722. options.scrollby = document.querySelector(scrollby) || window;
  7723. }
  7724. transparentApi = this.mui_plugin_transparent = new Transparent(this, options);
  7725. }
  7726. transparentApis.push(transparentApi);
  7727. });
  7728. return transparentApis.length === 1 ? transparentApis[0] : transparentApis;
  7729. };
  7730. $.ready(function() {
  7731. $('.mui-bar-transparent').transparent();
  7732. });
  7733. })(mui, window);
  7734. /**
  7735. * 数字输入框
  7736. * varstion 1.0.1
  7737. * by Houfeng
  7738. * Houfeng@DCloud.io
  7739. */
  7740. (function($) {
  7741. var touchSupport = ('ontouchstart' in document);
  7742. var tapEventName = touchSupport ? 'tap' : 'click';
  7743. var changeEventName = 'change';
  7744. var holderClassName = 'mui-numbox';
  7745. var plusClassSelector = '.mui-btn-numbox-plus,.mui-numbox-btn-plus';
  7746. var minusClassSelector = '.mui-btn-numbox-minus,.mui-numbox-btn-minus';
  7747. var inputClassSelector = '.mui-input-numbox,.mui-numbox-input';
  7748. var Numbox = $.Numbox = $.Class.extend({
  7749. /**
  7750. * 构造函数
  7751. **/
  7752. init: function(holder, options) {
  7753. var self = this;
  7754. if(!holder) {
  7755. throw "构造 numbox 时缺少容器元素";
  7756. }
  7757. self.holder = holder;
  7758. options = options || {};
  7759. options.step = parseInt(options.step || 1);
  7760. self.options = options;
  7761. self.input = $.qsa(inputClassSelector, self.holder)[0];
  7762. self.plus = $.qsa(plusClassSelector, self.holder)[0];
  7763. self.minus = $.qsa(minusClassSelector, self.holder)[0];
  7764. self.checkValue();
  7765. self.initEvent();
  7766. },
  7767. /**
  7768. * 初始化事件绑定
  7769. **/
  7770. initEvent: function() {
  7771. var self = this;
  7772. self.plus.addEventListener(tapEventName, function(event) {
  7773. var val = parseInt(self.input.value) + self.options.step;
  7774. self.input.value = val.toString();
  7775. $.trigger(self.input, changeEventName, null);
  7776. });
  7777. self.minus.addEventListener(tapEventName, function(event) {
  7778. var val = parseInt(self.input.value) - self.options.step;
  7779. self.input.value = val.toString();
  7780. $.trigger(self.input, changeEventName, null);
  7781. });
  7782. self.input.addEventListener(changeEventName, function(event) {
  7783. self.checkValue();
  7784. var val = parseInt(self.input.value);
  7785. //触发顶层容器
  7786. $.trigger(self.holder, changeEventName, {
  7787. value: val
  7788. });
  7789. });
  7790. },
  7791. /**
  7792. * 获取当前值
  7793. **/
  7794. getValue: function() {
  7795. var self = this;
  7796. return parseInt(self.input.value);
  7797. },
  7798. /**
  7799. * 验证当前值是法合法
  7800. **/
  7801. checkValue: function() {
  7802. var self = this;
  7803. var val = self.input.value;
  7804. if(val == null || val == '' || isNaN(val)) {
  7805. self.input.value = self.options.min || 0;
  7806. self.minus.disabled = self.options.min != null;
  7807. } else {
  7808. var val = parseInt(val);
  7809. if(self.options.max != null && !isNaN(self.options.max) && val >= parseInt(self.options.max)) {
  7810. val = self.options.max;
  7811. self.plus.disabled = true;
  7812. } else {
  7813. self.plus.disabled = false;
  7814. }
  7815. if(self.options.min != null && !isNaN(self.options.min) && val <= parseInt(self.options.min)) {
  7816. val = self.options.min;
  7817. self.minus.disabled = true;
  7818. } else {
  7819. self.minus.disabled = false;
  7820. }
  7821. self.input.value = val;
  7822. }
  7823. },
  7824. /**
  7825. * 更新选项
  7826. **/
  7827. setOption: function(name, value) {
  7828. var self = this;
  7829. self.options[name] = value;
  7830. },
  7831. /**
  7832. * 动态设置新值
  7833. **/
  7834. setValue: function(value) {
  7835. this.input.value = value;
  7836. this.checkValue();
  7837. }
  7838. });
  7839. $.fn.numbox = function(options) {
  7840. var instanceArray = [];
  7841. //遍历选择的元素
  7842. this.each(function(i, element) {
  7843. if(element.numbox) {
  7844. return;
  7845. }
  7846. if(options) {
  7847. element.numbox = new Numbox(element, options);
  7848. } else {
  7849. var optionsText = element.getAttribute('data-numbox-options');
  7850. var options = optionsText ? JSON.parse(optionsText) : {};
  7851. options.step = element.getAttribute('data-numbox-step') || options.step;
  7852. options.min = element.getAttribute('data-numbox-min') || options.min;
  7853. options.max = element.getAttribute('data-numbox-max') || options.max;
  7854. element.numbox = new Numbox(element, options);
  7855. }
  7856. });
  7857. return this[0] ? this[0].numbox : null;
  7858. }
  7859. //自动处理 class='mui-locker' 的 dom
  7860. $.ready(function() {
  7861. $('.' + holderClassName).numbox();
  7862. });
  7863. }(mui));
  7864. /**
  7865. * Button
  7866. * @param {type} $
  7867. * @param {type} window
  7868. * @param {type} document
  7869. * @returns {undefined}
  7870. */
  7871. (function($, window, document) {
  7872. var CLASS_ICON = 'mui-icon';
  7873. var CLASS_DISABLED = 'mui-disabled';
  7874. var STATE_RESET = 'reset';
  7875. var STATE_LOADING = 'loading';
  7876. var defaultOptions = {
  7877. loadingText: 'Loading...', //文案
  7878. loadingIcon: 'mui-spinner' + ' ' + 'mui-spinner-white', //图标,可为空
  7879. loadingIconPosition: 'left' //图标所处位置,仅支持left|right
  7880. };
  7881. var Button = function(element, options) {
  7882. this.element = element;
  7883. this.options = $.extend({}, defaultOptions, options);
  7884. if(!this.options.loadingText) {
  7885. this.options.loadingText = defaultOptions.loadingText;
  7886. }
  7887. if(this.options.loadingIcon === null) {
  7888. this.options.loadingIcon = 'mui-spinner';
  7889. if($.getStyles(this.element, 'color') === 'rgb(255, 255, 255)') {
  7890. this.options.loadingIcon += ' ' + 'mui-spinner-white';
  7891. }
  7892. }
  7893. this.isInput = this.element.tagName === 'INPUT';
  7894. this.resetHTML = this.isInput ? this.element.value : this.element.innerHTML;
  7895. this.state = '';
  7896. };
  7897. Button.prototype.loading = function() {
  7898. this.setState(STATE_LOADING);
  7899. };
  7900. Button.prototype.reset = function() {
  7901. this.setState(STATE_RESET);
  7902. };
  7903. Button.prototype.setState = function(state) {
  7904. if(this.state === state) {
  7905. return false;
  7906. }
  7907. this.state = state;
  7908. if(state === STATE_RESET) {
  7909. this.element.disabled = false;
  7910. this.element.classList.remove(CLASS_DISABLED);
  7911. this.setHtml(this.resetHTML);
  7912. } else if(state === STATE_LOADING) {
  7913. this.element.disabled = true;
  7914. this.element.classList.add(CLASS_DISABLED);
  7915. var html = this.isInput ? this.options.loadingText : ('<span>' + this.options.loadingText + '</span>');
  7916. if(this.options.loadingIcon && !this.isInput) {
  7917. if(this.options.loadingIconPosition === 'right') {
  7918. html += '&nbsp;<span class="' + this.options.loadingIcon + '"></span>';
  7919. } else {
  7920. html = '<span class="' + this.options.loadingIcon + '"></span>&nbsp;' + html;
  7921. }
  7922. }
  7923. this.setHtml(html);
  7924. }
  7925. };
  7926. Button.prototype.setHtml = function(html) {
  7927. if(this.isInput) {
  7928. this.element.value = html;
  7929. } else {
  7930. this.element.innerHTML = html;
  7931. }
  7932. }
  7933. $.fn.button = function(state) {
  7934. var buttonApis = [];
  7935. this.each(function() {
  7936. var buttonApi = this.mui_plugin_button;
  7937. if(!buttonApi) {
  7938. var loadingText = this.getAttribute('data-loading-text');
  7939. var loadingIcon = this.getAttribute('data-loading-icon');
  7940. var loadingIconPosition = this.getAttribute('data-loading-icon-position');
  7941. this.mui_plugin_button = buttonApi = new Button(this, {
  7942. loadingText: loadingText,
  7943. loadingIcon: loadingIcon,
  7944. loadingIconPosition: loadingIconPosition
  7945. });
  7946. }
  7947. if(state === STATE_LOADING || state === STATE_RESET) {
  7948. buttonApi.setState(state);
  7949. }
  7950. buttonApis.push(buttonApi);
  7951. });
  7952. return buttonApis.length === 1 ? buttonApis[0] : buttonApis;
  7953. };
  7954. })(mui, window, document);