mui.js 218 KB

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