mui.js 219 KB

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