mui.js 219 KB

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