app.js.uncompressed.js 378 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616
  1. require({cache:{
  2. 'dojo/uacss':function(){
  3. define(["./dom-geometry", "./_base/lang", "./ready", "./_base/sniff", "./_base/window"],
  4. function(geometry, lang, ready, has, baseWindow){
  5. // module:
  6. // dojo/uacss
  7. // summary:
  8. // Applies pre-set CSS classes to the top-level HTML node, based on:
  9. // - browser (ex: dj_ie)
  10. // - browser version (ex: dj_ie6)
  11. // - box model (ex: dj_contentBox)
  12. // - text direction (ex: dijitRtl)
  13. //
  14. // In addition, browser, browser version, and box model are
  15. // combined with an RTL flag when browser text is RTL. ex: dj_ie-rtl.
  16. var
  17. html = baseWindow.doc.documentElement,
  18. ie = has("ie"),
  19. opera = has("opera"),
  20. maj = Math.floor,
  21. ff = has("ff"),
  22. boxModel = geometry.boxModel.replace(/-/,''),
  23. classes = {
  24. "dj_quirks": has("quirks"),
  25. // NOTE: Opera not supported by dijit
  26. "dj_opera": opera,
  27. "dj_khtml": has("khtml"),
  28. "dj_webkit": has("webkit"),
  29. "dj_safari": has("safari"),
  30. "dj_chrome": has("chrome"),
  31. "dj_gecko": has("mozilla")
  32. }; // no dojo unsupported browsers
  33. if(ie){
  34. classes["dj_ie"] = true;
  35. classes["dj_ie" + maj(ie)] = true;
  36. classes["dj_iequirks"] = has("quirks");
  37. }
  38. if(ff){
  39. classes["dj_ff" + maj(ff)] = true;
  40. }
  41. classes["dj_" + boxModel] = true;
  42. // apply browser, browser version, and box model class names
  43. var classStr = "";
  44. for(var clz in classes){
  45. if(classes[clz]){
  46. classStr += clz + " ";
  47. }
  48. }
  49. html.className = lang.trim(html.className + " " + classStr);
  50. // If RTL mode, then add dj_rtl flag plus repeat existing classes with -rtl extension.
  51. // We can't run the code below until the <body> tag has loaded (so we can check for dir=rtl).
  52. // priority is 90 to run ahead of parser priority of 100
  53. ready(90, function(){
  54. if(!geometry.isBodyLtr()){
  55. var rtlClassStr = "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl ");
  56. html.className = lang.trim(html.className + " " + rtlClassStr + "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl "));
  57. }
  58. });
  59. return has;
  60. });
  61. },
  62. 'dojox/mobile/app/_Widget':function(){
  63. // wrapped by build app
  64. define("dojox/mobile/app/_Widget", ["dijit","dojo","dojox","dojo/require!dijit/_WidgetBase"], function(dijit,dojo,dojox){
  65. dojo.provide("dojox.mobile.app._Widget");
  66. dojo.experimental("dojox.mobile.app._Widget");
  67. dojo.require("dijit._WidgetBase");
  68. dojo.declare("dojox.mobile.app._Widget", dijit._WidgetBase, {
  69. // summary:
  70. // The base mobile app widget.
  71. getScroll: function(){
  72. // summary:
  73. // Returns the scroll position.
  74. return {
  75. x: dojo.global.scrollX,
  76. y: dojo.global.scrollY
  77. };
  78. },
  79. connect: function(target, event, fn){
  80. if(event.toLowerCase() == "dblclick"
  81. || event.toLowerCase() == "ondblclick"){
  82. if(dojo.global["Mojo"]){
  83. // Handle webOS tap event
  84. return this.connect(target, Mojo.Event.tap, fn);
  85. }
  86. }
  87. return this.inherited(arguments);
  88. }
  89. });
  90. });
  91. },
  92. 'dojox/mobile/app/ImageThumbView':function(){
  93. // wrapped by build app
  94. define("dojox/mobile/app/ImageThumbView", ["dijit","dojo","dojox","dojo/require!dijit/_WidgetBase,dojo/string"], function(dijit,dojo,dojox){
  95. dojo.provide("dojox.mobile.app.ImageThumbView");
  96. dojo.experimental("dojox.mobile.app.ImageThumbView");
  97. dojo.require("dijit._WidgetBase");
  98. dojo.require("dojo.string");
  99. dojo.declare("dojox.mobile.app.ImageThumbView", dijit._WidgetBase, {
  100. // summary:
  101. // An image thumbnail gallery
  102. // items: Array
  103. // The data items from which the image urls are retrieved.
  104. // If an item is a string, it is expected to be a URL. Otherwise
  105. // by default it is expected to have a 'url' member. This can
  106. // be configured using the 'urlParam' attribute on this widget.
  107. items: [],
  108. // urlParam: String
  109. // The paramter name used to retrieve an image url from a JSON object
  110. urlParam: "url",
  111. labelParam: null,
  112. itemTemplate: '<div class="mblThumbInner">' +
  113. '<div class="mblThumbOverlay"></div>' +
  114. '<div class="mblThumbMask">' +
  115. '<div class="mblThumbSrc" style="background-image:url(${url})"></div>' +
  116. '</div>' +
  117. '</div>',
  118. minPadding: 4,
  119. maxPerRow: 3,
  120. maxRows: -1,
  121. baseClass: "mblImageThumbView",
  122. thumbSize: "medium",
  123. animationEnabled: true,
  124. selectedIndex: -1,
  125. cache: null,
  126. cacheMustMatch: false,
  127. clickEvent: "onclick",
  128. cacheBust: false,
  129. disableHide: false,
  130. constructor: function(params, node){
  131. },
  132. postCreate: function(){
  133. this.inherited(arguments);
  134. var _this = this;
  135. var hoverCls = "mblThumbHover";
  136. this.addThumb = dojo.hitch(this, this.addThumb);
  137. this.handleImgLoad = dojo.hitch(this, this.handleImgLoad);
  138. this.hideCached = dojo.hitch(this, this.hideCached);
  139. this._onLoadImages = {};
  140. this.cache = [];
  141. this.visibleImages = [];
  142. this._cacheCounter = 0;
  143. this.connect(this.domNode, this.clickEvent, function(event){
  144. var itemNode = _this._getItemNodeFromEvent(event);
  145. if(itemNode && !itemNode._cached){
  146. _this.onSelect(itemNode._item, itemNode._index, _this.items);
  147. dojo.query(".selected", this.domNode).removeClass("selected");
  148. dojo.addClass(itemNode, "selected");
  149. }
  150. });
  151. dojo.addClass(this.domNode, this.thumbSize);
  152. this.resize();
  153. this.render();
  154. },
  155. onSelect: function(item, index, items){
  156. // summary:
  157. // Dummy function that is triggered when an image is selected.
  158. },
  159. _setAnimationEnabledAttr: function(value){
  160. this.animationEnabled = value;
  161. dojo[value ? "addClass" : "removeClass"](this.domNode, "animated");
  162. },
  163. _setItemsAttr: function(items){
  164. this.items = items || [];
  165. var urls = {};
  166. var i;
  167. for(i = 0; i < this.items.length; i++){
  168. urls[this.items[i][this.urlParam]] = 1;
  169. }
  170. var clearedUrls = [];
  171. for(var url in this._onLoadImages){
  172. if(!urls[url] && this._onLoadImages[url]._conn){
  173. dojo.disconnect(this._onLoadImages[url]._conn);
  174. this._onLoadImages[url].src = null;
  175. clearedUrls.push(url);
  176. }
  177. }
  178. for(i = 0; i < clearedUrls.length; i++){
  179. delete this._onLoadImages[url];
  180. }
  181. this.render();
  182. },
  183. _getItemNode: function(node){
  184. while(node && !dojo.hasClass(node, "mblThumb") && node != this.domNode){
  185. node = node.parentNode;
  186. }
  187. return (node == this.domNode) ? null : node;
  188. },
  189. _getItemNodeFromEvent: function(event){
  190. if(event.touches && event.touches.length > 0){
  191. event = event.touches[0];
  192. }
  193. return this._getItemNode(event.target);
  194. },
  195. resize: function(){
  196. this._thumbSize = null;
  197. this._size = dojo.contentBox(this.domNode);
  198. this.disableHide = true;
  199. this.render();
  200. this.disableHide = false;
  201. },
  202. hideCached: function(){
  203. // summary:
  204. // Hides all cached nodes, so that they're no invisible and overlaying
  205. // other screen elements.
  206. for(var i = 0; i < this.cache.length; i++){
  207. if (this.cache[i]) {
  208. dojo.style(this.cache[i], "display", "none");
  209. }
  210. }
  211. },
  212. render: function(){
  213. var i;
  214. var url;
  215. var item;
  216. var thumb;
  217. while(this.visibleImages && this.visibleImages.length > 0){
  218. thumb = this.visibleImages.pop();
  219. this.cache.push(thumb);
  220. if (!this.disableHide) {
  221. dojo.addClass(thumb, "hidden");
  222. }
  223. thumb._cached = true;
  224. }
  225. if(this.cache && this.cache.length > 0){
  226. setTimeout(this.hideCached, 1000);
  227. }
  228. if(!this.items || this.items.length == 0){
  229. return;
  230. }
  231. for(i = 0; i < this.items.length; i++){
  232. item = this.items[i];
  233. url = (dojo.isString(item) ? item : item[this.urlParam]);
  234. this.addThumb(item, url, i);
  235. if(this.maxRows > 0 && (i + 1) / this.maxPerRow >= this.maxRows){
  236. break;
  237. }
  238. }
  239. if(!this._thumbSize){
  240. return;
  241. }
  242. var column = 0;
  243. var row = -1;
  244. var totalThumbWidth = this._thumbSize.w + (this.padding * 2);
  245. var totalThumbHeight = this._thumbSize.h + (this.padding * 2);
  246. var nodes = this.thumbNodes =
  247. dojo.query(".mblThumb", this.domNode);
  248. var pos = 0;
  249. nodes = this.visibleImages;
  250. for(i = 0; i < nodes.length; i++){
  251. if(nodes[i]._cached){
  252. continue;
  253. }
  254. if(pos % this.maxPerRow == 0){
  255. row ++;
  256. }
  257. column = pos % this.maxPerRow;
  258. this.place(
  259. nodes[i],
  260. (column * totalThumbWidth) + this.padding, // x position
  261. (row * totalThumbHeight) + this.padding // y position
  262. );
  263. if(!nodes[i]._loading){
  264. dojo.removeClass(nodes[i], "hidden");
  265. }
  266. if(pos == this.selectedIndex){
  267. dojo[pos == this.selectedIndex ? "addClass" : "removeClass"]
  268. (nodes[i], "selected");
  269. }
  270. pos++;
  271. }
  272. var numRows = Math.ceil(pos / this.maxPerRow);
  273. this._numRows = numRows;
  274. this.setContainerHeight((numRows * (this._thumbSize.h + this.padding * 2)));
  275. },
  276. setContainerHeight: function(amount){
  277. dojo.style(this.domNode, "height", amount + "px");
  278. },
  279. addThumb: function(item, url, index){
  280. var thumbDiv;
  281. var cacheHit = false;
  282. if(this.cache.length > 0){
  283. // Reuse a previously created node if possible
  284. var found = false;
  285. // Search for an image with the same url first
  286. for(var i = 0; i < this.cache.length; i++){
  287. if(this.cache[i]._url == url){
  288. thumbDiv = this.cache.splice(i, 1)[0];
  289. found = true;
  290. break
  291. }
  292. }
  293. // if no image with the same url is found, just take the last one
  294. if(!thumbDiv && !this.cacheMustMatch){
  295. thumbDiv = this.cache.pop();
  296. dojo.removeClass(thumbDiv, "selected");
  297. } else {
  298. cacheHit = true;
  299. }
  300. }
  301. if(!thumbDiv){
  302. // Create a new thumb
  303. thumbDiv = dojo.create("div", {
  304. "class": "mblThumb hidden",
  305. innerHTML: dojo.string.substitute(this.itemTemplate, {
  306. url: url
  307. }, null, this)
  308. }, this.domNode);
  309. }
  310. if(this.labelParam) {
  311. var labelNode = dojo.query(".mblThumbLabel", thumbDiv)[0];
  312. if(!labelNode) {
  313. labelNode = dojo.create("div", {
  314. "class": "mblThumbLabel"
  315. }, thumbDiv);
  316. }
  317. labelNode.innerHTML = item[this.labelParam] || "";
  318. }
  319. dojo.style(thumbDiv, "display", "");
  320. if (!this.disableHide) {
  321. dojo.addClass(thumbDiv, "hidden");
  322. }
  323. if (!cacheHit) {
  324. var loader = dojo.create("img", {});
  325. loader._thumbDiv = thumbDiv;
  326. loader._conn = dojo.connect(loader, "onload", this.handleImgLoad);
  327. loader._url = url;
  328. thumbDiv._loading = true;
  329. this._onLoadImages[url] = loader;
  330. if (loader) {
  331. loader.src = url;
  332. }
  333. }
  334. this.visibleImages.push(thumbDiv);
  335. thumbDiv._index = index;
  336. thumbDiv._item = item;
  337. thumbDiv._url = url;
  338. thumbDiv._cached = false;
  339. if(!this._thumbSize){
  340. this._thumbSize = dojo.marginBox(thumbDiv);
  341. if(this._thumbSize.h == 0){
  342. this._thumbSize.h = 100;
  343. this._thumbSize.w = 100;
  344. }
  345. if(this.labelParam){
  346. this._thumbSize.h += 8;
  347. }
  348. this.calcPadding();
  349. }
  350. },
  351. handleImgLoad: function(event){
  352. var img = event.target;
  353. dojo.disconnect(img._conn);
  354. dojo.removeClass(img._thumbDiv, "hidden");
  355. img._thumbDiv._loading = false;
  356. img._conn = null;
  357. var url = img._url;
  358. if(this.cacheBust){
  359. url += (url.indexOf("?") > -1 ? "&" : "?")
  360. + "cacheBust=" + (new Date()).getTime() + "_" + (this._cacheCounter++);
  361. }
  362. dojo.query(".mblThumbSrc", img._thumbDiv)
  363. .style("backgroundImage", "url(" + url + ")");
  364. delete this._onLoadImages[img._url];
  365. },
  366. calcPadding: function(){
  367. var width = this._size.w;
  368. var thumbWidth = this._thumbSize.w;
  369. var imgBounds = thumbWidth + this.minPadding;
  370. this.maxPerRow = Math.floor(width / imgBounds);
  371. this.padding = Math.floor((width - (thumbWidth * this.maxPerRow)) / (this.maxPerRow * 2));
  372. },
  373. place: function(node, x, y){
  374. dojo.style(node, {
  375. "-webkit-transform" :"translate(" + x + "px," + y + "px)"
  376. });
  377. },
  378. destroy: function(){
  379. // Stop the loading of any more images
  380. var img;
  381. var counter = 0;
  382. for (var url in this._onLoadImages){
  383. img = this._onLoadImages[url];
  384. if (img) {
  385. img.src = null;
  386. counter++;
  387. }
  388. }
  389. this.inherited(arguments);
  390. }
  391. });
  392. });
  393. },
  394. 'dojox/mobile/TransitionEvent':function(){
  395. define("dojox/mobile/TransitionEvent", [
  396. "dojo/_base/declare",
  397. "dojo/_base/Deferred",
  398. "dojo/_base/lang",
  399. "dojo/on",
  400. "./transition"
  401. ], function(declare, Deferred, lang, on, transitDeferred){
  402. return declare("dojox.mobile.TransitionEvent", null, {
  403. constructor: function(target, transitionOptions, triggerEvent){
  404. this.transitionOptions=transitionOptions;
  405. this.target = target;
  406. this.triggerEvent=triggerEvent||null;
  407. },
  408. dispatch: function(){
  409. var opts = {bubbles:true, cancelable:true, detail: this.transitionOptions, triggerEvent: this.triggerEvent};
  410. //console.log("Target: ", this.target, " opts: ", opts);
  411. var evt = on.emit(this.target,"startTransition", opts);
  412. //console.log('evt: ', evt);
  413. if(evt){
  414. Deferred.when(transitDeferred, lang.hitch(this, function(transition){
  415. Deferred.when(transition.call(this, evt), lang.hitch(this, function(results){
  416. this.endTransition(results);
  417. }));
  418. }));
  419. }
  420. },
  421. endTransition: function(results){
  422. on.emit(this.target, "endTransition" , {detail: results.transitionOptions});
  423. }
  424. });
  425. });
  426. },
  427. 'dojox/mobile/ViewController':function(){
  428. define([
  429. "dojo/_base/kernel",
  430. "dojo/_base/array",
  431. "dojo/_base/connect",
  432. "dojo/_base/declare",
  433. "dojo/_base/lang",
  434. "dojo/_base/window",
  435. "dojo/dom",
  436. "dojo/dom-class",
  437. "dojo/dom-construct",
  438. // "dojo/hash", // optionally prereq'ed
  439. "dojo/on",
  440. "dojo/ready",
  441. "dijit/registry", // registry.byId
  442. "./ProgressIndicator",
  443. "./TransitionEvent"
  444. ], function(dojo, array, connect, declare, lang, win, dom, domClass, domConstruct, on, ready, registry, ProgressIndicator, TransitionEvent){
  445. // module:
  446. // dojox/mobile/ViewController
  447. // summary:
  448. // A singleton class that controlls view transition.
  449. var dm = lang.getObject("dojox.mobile", true);
  450. var Controller = declare("dojox.mobile.ViewController", null, {
  451. // summary:
  452. // A singleton class that controlls view transition.
  453. // description:
  454. // This class listens to the "startTransition" events and performs
  455. // view transitions. If the transition destination is an external
  456. // view specified with the url parameter, retrieves the view
  457. // content and parses it to create a new target view.
  458. constructor: function(){
  459. this.viewMap={};
  460. this.currentView=null;
  461. this.defaultView=null;
  462. ready(lang.hitch(this, function(){
  463. on(win.body(), "startTransition", lang.hitch(this, "onStartTransition"));
  464. }));
  465. },
  466. findCurrentView: function(moveTo,src){
  467. // summary:
  468. // Searches for the currently showing view.
  469. if(moveTo){
  470. var w = registry.byId(moveTo);
  471. if(w && w.getShowingView){ return w.getShowingView(); }
  472. }
  473. if(dm.currentView){
  474. return dm.currentView; //TODO:1.8 may not return an expected result especially when views are nested
  475. }
  476. //TODO:1.8 probably never reaches here
  477. w = src;
  478. while(true){
  479. w = w.getParent();
  480. if(!w){ return null; }
  481. if(domClass.contains(w.domNode, "mblView")){ break; }
  482. }
  483. return w;
  484. },
  485. onStartTransition: function(evt){
  486. // summary:
  487. // A handler that performs view transition.
  488. evt.preventDefault();
  489. if(!evt.detail || (evt.detail && !evt.detail.moveTo && !evt.detail.href && !evt.detail.url && !evt.detail.scene)){ return; }
  490. var w = this.findCurrentView(evt.detail.moveTo, (evt.target && evt.target.id)?registry.byId(evt.target.id):registry.byId(evt.target)); // the current view widget
  491. if(!w || (evt.detail && evt.detail.moveTo && w === registry.byId(evt.detail.moveTo))){ return; }
  492. if(evt.detail.href){
  493. var t = registry.byId(evt.target.id).hrefTarget;
  494. if(t){
  495. dm.openWindow(evt.detail.href, t);
  496. }else{
  497. w.performTransition(null, evt.detail.transitionDir, evt.detail.transition, evt.target, function(){location.href = evt.detail.href;});
  498. }
  499. return;
  500. } else if(evt.detail.scene){
  501. connect.publish("/dojox/mobile/app/pushScene", [evt.detail.scene]);
  502. return;
  503. }
  504. var moveTo = evt.detail.moveTo;
  505. if(evt.detail.url){
  506. var id;
  507. if(dm._viewMap && dm._viewMap[evt.detail.url]){
  508. // external view has already been loaded
  509. id = dm._viewMap[evt.detail.url];
  510. }else{
  511. // get the specified external view and append it to the <body>
  512. var text = this._text;
  513. if(!text){
  514. if(registry.byId(evt.target.id).sync){
  515. // We do not add explicit dependency on dojo/_base/xhr to this module
  516. // to be able to create a build that does not contain dojo/_base/xhr.
  517. // User applications that do sync loading here need to explicitly
  518. // require dojo/_base/xhr up front.
  519. dojo.xhrGet({url:evt.detail.url, sync:true, load:function(result){
  520. text = lang.trim(result);
  521. }});
  522. }else{
  523. var s = "dojo/_base/xhr"; // assign to a variable so as not to be picked up by the build tool
  524. require([s], lang.hitch(this, function(xhr){
  525. var prog = ProgressIndicator.getInstance();
  526. win.body().appendChild(prog.domNode);
  527. prog.start();
  528. var obj = xhr.get({
  529. url: evt.detail.url,
  530. handleAs: "text"
  531. });
  532. obj.addCallback(lang.hitch(this, function(response, ioArgs){
  533. prog.stop();
  534. if(response){
  535. this._text = response;
  536. new TransitionEvent(evt.target, {
  537. transition: evt.detail.transition,
  538. transitionDir: evt.detail.transitionDir,
  539. moveTo: moveTo,
  540. href: evt.detail.href,
  541. url: evt.detail.url,
  542. scene: evt.detail.scene},
  543. evt.detail)
  544. .dispatch();
  545. }
  546. }));
  547. obj.addErrback(function(error){
  548. prog.stop();
  549. console.log("Failed to load "+evt.detail.url+"\n"+(error.description||error));
  550. });
  551. }));
  552. return;
  553. }
  554. }
  555. this._text = null;
  556. id = this._parse(text, registry.byId(evt.target.id).urlTarget);
  557. if(!dm._viewMap){
  558. dm._viewMap = [];
  559. }
  560. dm._viewMap[evt.detail.url] = id;
  561. }
  562. moveTo = id;
  563. w = this.findCurrentView(moveTo,registry.byId(evt.target.id)) || w; // the current view widget
  564. }
  565. var src = registry.getEnclosingWidget(evt.target);
  566. var context, method;
  567. if(src && src.callback){
  568. context = src;
  569. method = src.callback;
  570. }
  571. w.performTransition(moveTo, evt.detail.transitionDir, evt.detail.transition, context, method);
  572. },
  573. _parse: function(text, id){
  574. // summary:
  575. // Parses the given view content.
  576. // description:
  577. // If the content is html fragment, constructs dom tree with it
  578. // and runs the parser. If the content is json data, passes it
  579. // to _instantiate().
  580. var container, view, i, j, len;
  581. var currentView = this.findCurrentView();
  582. var target = registry.byId(id) && registry.byId(id).containerNode
  583. || dom.byId(id)
  584. || currentView && currentView.domNode.parentNode
  585. || win.body();
  586. // if a fixed bottom bar exists, a new view should be placed before it.
  587. var refNode = null;
  588. for(j = target.childNodes.length - 1; j >= 0; j--){
  589. var c = target.childNodes[j];
  590. if(c.nodeType === 1){
  591. if(c.getAttribute("fixed") === "bottom"){
  592. refNode = c;
  593. break;
  594. }
  595. }
  596. }
  597. if(text.charAt(0) === "<"){ // html markup
  598. container = domConstruct.create("DIV", {innerHTML: text});
  599. for(i = 0; i < container.childNodes.length; i++){
  600. var n = container.childNodes[i];
  601. if(n.nodeType === 1){
  602. view = n; // expecting <div dojoType="dojox.mobile.View">
  603. break;
  604. }
  605. }
  606. if(!view){
  607. console.log("dojox.mobile.ViewController#_parse: invalid view content");
  608. return;
  609. }
  610. view.style.visibility = "hidden";
  611. target.insertBefore(container, refNode);
  612. var ws = dojo.parser.parse(container);
  613. array.forEach(ws, function(w){
  614. if(w && !w._started && w.startup){
  615. w.startup();
  616. }
  617. });
  618. // allows multiple root nodes in the fragment,
  619. // but transition will be performed to the 1st view.
  620. for(i = 0, len = container.childNodes.length; i < len; i++){
  621. target.insertBefore(container.firstChild, refNode); // reparent
  622. }
  623. target.removeChild(container);
  624. registry.byNode(view)._visible = true;
  625. }else if(text.charAt(0) === "{"){ // json
  626. container = domConstruct.create("DIV");
  627. target.insertBefore(container, refNode);
  628. this._ws = [];
  629. view = this._instantiate(eval('('+text+')'), container);
  630. for(i = 0; i < this._ws.length; i++){
  631. var w = this._ws[i];
  632. w.startup && !w._started && (!w.getParent || !w.getParent()) && w.startup();
  633. }
  634. this._ws = null;
  635. }
  636. view.style.display = "none";
  637. view.style.visibility = "visible";
  638. return dojo.hash ? "#" + view.id : view.id;
  639. },
  640. _instantiate: function(/*Object*/obj, /*DomNode*/node, /*Widget*/parent){
  641. // summary:
  642. // Given the evaluated json data, does the same thing as what
  643. // the parser does.
  644. var widget;
  645. for(var key in obj){
  646. if(key.charAt(0) == "@"){ continue; }
  647. var cls = lang.getObject(key);
  648. if(!cls){ continue; }
  649. var params = {};
  650. var proto = cls.prototype;
  651. var objs = lang.isArray(obj[key]) ? obj[key] : [obj[key]];
  652. for(var i = 0; i < objs.length; i++){
  653. for(var prop in objs[i]){
  654. if(prop.charAt(0) == "@"){
  655. var val = objs[i][prop];
  656. prop = prop.substring(1);
  657. if(typeof proto[prop] == "string"){
  658. params[prop] = val;
  659. }else if(typeof proto[prop] == "number"){
  660. params[prop] = val - 0;
  661. }else if(typeof proto[prop] == "boolean"){
  662. params[prop] = (val != "false");
  663. }else if(typeof proto[prop] == "object"){
  664. params[prop] = eval("(" + val + ")");
  665. }
  666. }
  667. }
  668. widget = new cls(params, node);
  669. if(node){ // to call View's startup()
  670. widget._visible = true;
  671. this._ws.push(widget);
  672. }
  673. if(parent && parent.addChild){
  674. parent.addChild(widget);
  675. }
  676. this._instantiate(objs[i], null, widget);
  677. }
  678. }
  679. return widget && widget.domNode;
  680. }
  681. });
  682. new Controller(); // singleton
  683. return Controller;
  684. });
  685. },
  686. 'dojox/mobile/ToolBarButton':function(){
  687. define("dojox/mobile/ToolBarButton", [
  688. "dojo/_base/declare",
  689. "dojo/_base/window",
  690. "dojo/dom-class",
  691. "dojo/dom-construct",
  692. "dojo/dom-style",
  693. "./common",
  694. "./_ItemBase"
  695. ], function(declare, win, domClass, domConstruct, domStyle, common, ItemBase){
  696. /*=====
  697. var ItemBase = dojox.mobile._ItemBase;
  698. =====*/
  699. // module:
  700. // dojox/mobile/ToolBarButton
  701. // summary:
  702. // A button widget that is placed in the Heading widget.
  703. return declare("dojox.mobile.ToolBarButton", ItemBase, {
  704. // summary:
  705. // A button widget that is placed in the Heading widget.
  706. // description:
  707. // ToolBarButton is a button that is placed in the Heading
  708. // widget. It is a subclass of dojox.mobile._ItemBase just like
  709. // ListItem or IconItem. So, unlike Button, it has basically the
  710. // same capability as ListItem or IconItem, such as icon support,
  711. // transition, etc.
  712. // selected: Boolean
  713. // If true, the button is in the selected status.
  714. selected: false,
  715. // btnClass: String
  716. // Deprecated.
  717. btnClass: "",
  718. /* internal properties */
  719. _defaultColor: "mblColorDefault",
  720. _selColor: "mblColorDefaultSel",
  721. buildRendering: function(){
  722. this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement("div");
  723. this.inheritParams();
  724. domClass.add(this.domNode, "mblToolBarButton mblArrowButtonText");
  725. var color;
  726. if(this.selected){
  727. color = this._selColor;
  728. }else if(this.domNode.className.indexOf("mblColor") == -1){
  729. color = this._defaultColor;
  730. }
  731. domClass.add(this.domNode, color);
  732. if(!this.label){
  733. this.label = this.domNode.innerHTML;
  734. }
  735. if(this.icon && this.icon != "none"){
  736. this.iconNode = domConstruct.create("div", {className:"mblToolBarButtonIcon"}, this.domNode);
  737. common.createIcon(this.icon, this.iconPos, null, this.alt, this.iconNode);
  738. if(this.iconPos){
  739. domClass.add(this.iconNode.firstChild, "mblToolBarButtonSpriteIcon");
  740. }
  741. }else{
  742. if(common.createDomButton(this.domNode)){
  743. domClass.add(this.domNode, "mblToolBarButtonDomButton");
  744. }else{
  745. domClass.add(this.domNode, "mblToolBarButtonText");
  746. }
  747. }
  748. this.connect(this.domNode, "onclick", "onClick");
  749. },
  750. select: function(){
  751. // summary:
  752. // Makes this widget in the selected state.
  753. domClass.toggle(this.domNode, this._selColor, !arguments[0]);
  754. this.selected = !arguments[0];
  755. },
  756. deselect: function(){
  757. // summary:
  758. // Makes this widget in the deselected state.
  759. this.select(true);
  760. },
  761. onClick: function(e){
  762. this.setTransitionPos(e);
  763. this.defaultClickAction();
  764. },
  765. _setBtnClassAttr: function(/*String*/btnClass){
  766. var node = this.domNode;
  767. if(node.className.match(/(mblDomButton\w+)/)){
  768. domClass.remove(node, RegExp.$1);
  769. }
  770. domClass.add(node, btnClass);
  771. if(common.createDomButton(this.domNode)){
  772. domClass.add(this.domNode, "mblToolBarButtonDomButton");
  773. }
  774. },
  775. _setLabelAttr: function(/*String*/text){
  776. this.label = text;
  777. this.domNode.innerHTML = this._cv ? this._cv(text) : text;
  778. }
  779. });
  780. });
  781. },
  782. 'dojox/mobile/_ItemBase':function(){
  783. define("dojox/mobile/_ItemBase", [
  784. "dojo/_base/kernel",
  785. "dojo/_base/config",
  786. "dojo/_base/declare",
  787. "dijit/registry", // registry.getEnclosingWidget
  788. "dijit/_Contained",
  789. "dijit/_Container",
  790. "dijit/_WidgetBase",
  791. "./TransitionEvent",
  792. "./View"
  793. ], function(kernel, config, declare, registry, Contained, Container, WidgetBase, TransitionEvent, View){
  794. /*=====
  795. var Contained = dijit._Contained;
  796. var Container = dijit._Container;
  797. var WidgetBase = dijit._WidgetBase;
  798. var TransitionEvent = dojox.mobile.TransitionEvent;
  799. var View = dojox.mobile.View;
  800. =====*/
  801. // module:
  802. // dojox/mobile/_ItemBase
  803. // summary:
  804. // A base class for item classes (e.g. ListItem, IconItem, etc.)
  805. return declare("dojox.mobile._ItemBase", [WidgetBase, Container, Contained],{
  806. // summary:
  807. // A base class for item classes (e.g. ListItem, IconItem, etc.)
  808. // description:
  809. // _ItemBase is a base class for widgets that have capability to
  810. // make a view transition when clicked.
  811. // icon: String
  812. // An icon image to display. The value can be either a path for an
  813. // image file or a class name of a DOM button. If icon is not
  814. // specified, the iconBase parameter of the parent widget is used.
  815. icon: "",
  816. // iconPos: String
  817. // The position of an aggregated icon. IconPos is comma separated
  818. // values like top,left,width,height (ex. "0,0,29,29"). If iconPos
  819. // is not specified, the iconPos parameter of the parent widget is
  820. // used.
  821. iconPos: "", // top,left,width,height (ex. "0,0,29,29")
  822. // alt: String
  823. // An alt text for the icon image.
  824. alt: "",
  825. // href: String
  826. // A URL of another web page to go to.
  827. href: "",
  828. // hrefTarget: String
  829. // A target that specifies where to open a page specified by
  830. // href. The value will be passed to the 2nd argument of
  831. // window.open().
  832. hrefTarget: "",
  833. // moveTo: String
  834. // The id of the transition destination view which resides in the
  835. // current page.
  836. //
  837. // If the value has a hash sign ('#') before the id (e.g. #view1)
  838. // and the dojo.hash module is loaded by the user application, the
  839. // view transition updates the hash in the browser URL so that the
  840. // user can bookmark the destination view. In this case, the user
  841. // can also use the browser's back/forward button to navigate
  842. // through the views in the browser history.
  843. //
  844. // If null, transitions to a blank view.
  845. // If '#', returns immediately without transition.
  846. moveTo: "",
  847. // scene: String
  848. // The name of a scene. Used from dojox.mobile.app.
  849. scene: "",
  850. // clickable: Boolean
  851. // If true, this item becomes clickable even if a transition
  852. // destination (moveTo, etc.) is not specified.
  853. clickable: false,
  854. // url: String
  855. // A URL of an html fragment page or JSON data that represents a
  856. // new view content. The view content is loaded with XHR and
  857. // inserted in the current page. Then a view transition occurs to
  858. // the newly created view. The view is cached so that subsequent
  859. // requests would not load the content again.
  860. url: "",
  861. // urlTarget: String
  862. // Node id under which a new view will be created according to the
  863. // url parameter. If not specified, The new view will be created as
  864. // a sibling of the current view.
  865. urlTarget: "",
  866. // transition: String
  867. // A type of animated transition effect. You can choose from the
  868. // standard transition types, "slide", "fade", "flip", or from the
  869. // extended transition types, "cover", "coverv", "dissolve",
  870. // "reveal", "revealv", "scaleIn", "scaleOut", "slidev",
  871. // "swirl", "zoomIn", "zoomOut". If "none" is specified, transition
  872. // occurs immediately without animation.
  873. transition: "",
  874. // transitionDir: Number
  875. // The transition direction. If 1, transition forward. If -1,
  876. // transition backward. For example, the slide transition slides
  877. // the view from right to left when dir == 1, and from left to
  878. // right when dir == -1.
  879. transitionDir: 1,
  880. // transitionOptions: Object
  881. // A hash object that holds transition options.
  882. transitionOptions: null,
  883. // callback: Function|String
  884. // A callback function that is called when the transition has been
  885. // finished. A function reference, or name of a function in
  886. // context.
  887. callback: null,
  888. // sync: Boolean
  889. // If true, XHR for the view content specified with the url
  890. // parameter is performed synchronously. If false, it is done
  891. // asynchronously and the progress indicator is displayed while
  892. // loading the content. This parameter is effective only when the
  893. // url parameter is used.
  894. sync: true,
  895. // label: String
  896. // A label of the item. If the label is not specified, innerHTML is
  897. // used as a label.
  898. label: "",
  899. // toggle: Boolean
  900. // If true, the item acts like a toggle button.
  901. toggle: false,
  902. // _duration: Number
  903. // Duration of selection, milliseconds.
  904. _duration: 800,
  905. inheritParams: function(){
  906. var parent = this.getParent();
  907. if(parent){
  908. if(!this.transition){ this.transition = parent.transition; }
  909. if(this.icon && parent.iconBase &&
  910. parent.iconBase.charAt(parent.iconBase.length - 1) === '/'){
  911. this.icon = parent.iconBase + this.icon;
  912. }
  913. if(!this.icon){ this.icon = parent.iconBase; }
  914. if(!this.iconPos){ this.iconPos = parent.iconPos; }
  915. }
  916. },
  917. select: function(){
  918. // summary:
  919. // Makes this widget in the selected state.
  920. // description:
  921. // Subclass must implement.
  922. },
  923. deselect: function(){
  924. // summary:
  925. // Makes this widget in the deselected state.
  926. // description:
  927. // Subclass must implement.
  928. },
  929. defaultClickAction: function(e){
  930. if(this.toggle){
  931. if(this.selected){
  932. this.deselect();
  933. }else{
  934. this.select();
  935. }
  936. }else if(!this.selected){
  937. this.select();
  938. if(!this.selectOne){
  939. var _this = this;
  940. setTimeout(function(){
  941. _this.deselect();
  942. }, this._duration);
  943. }
  944. var transOpts;
  945. if(this.moveTo || this.href || this.url || this.scene){
  946. transOpts = {moveTo: this.moveTo, href: this.href, url: this.url, scene: this.scene, transition: this.transition, transitionDir: this.transitionDir};
  947. }else if(this.transitionOptions){
  948. transOpts = this.transitionOptions;
  949. }
  950. if(transOpts){
  951. return new TransitionEvent(this.domNode,transOpts,e).dispatch();
  952. }
  953. }
  954. },
  955. getParent: function(){
  956. // summary:
  957. // Gets the parent widget.
  958. // description:
  959. // Almost equivalent to _Contained#getParent, but this method
  960. // does not cause a script error even if this widget has no
  961. // parent yet.
  962. var ref = this.srcNodeRef || this.domNode;
  963. return ref && ref.parentNode ? registry.getEnclosingWidget(ref.parentNode) : null;
  964. },
  965. setTransitionPos: function(e){
  966. // summary:
  967. // Stores the clicked position for later use.
  968. // description:
  969. // Some of the transition animations (e.g. ScaleIn) needs the
  970. // clicked position.
  971. var w = this;
  972. while(true){
  973. w = w.getParent();
  974. if(!w || w instanceof View){ break; }
  975. }
  976. if(w){
  977. w.clickedPosX = e.clientX;
  978. w.clickedPosY = e.clientY;
  979. }
  980. },
  981. transitionTo: function(moveTo, href, url, scene){
  982. // summary:
  983. // Performs a view transition.
  984. // description:
  985. // Given a transition destination, this method performs a view
  986. // transition. This method is typically called when this item
  987. // is clicked.
  988. if(config.isDebug){
  989. var alreadyCalledHash = arguments.callee._ach || (arguments.callee._ach = {}),
  990. caller = (arguments.callee.caller || "unknown caller").toString();
  991. if(!alreadyCalledHash[caller]){
  992. kernel.deprecated(this.declaredClass + "::transitionTo() is deprecated." +
  993. caller, "", "2.0");
  994. alreadyCalledHash[caller] = true;
  995. }
  996. }
  997. new TransitionEvent(this.domNode, {moveTo: moveTo, href: href, url: url, scene: scene,
  998. transition: this.transition, transitionDir: this.transitionDir}).dispatch();
  999. }
  1000. });
  1001. });
  1002. },
  1003. 'dijit/hccss':function(){
  1004. define("dijit/hccss", [
  1005. "require", // require.toUrl
  1006. "dojo/_base/config", // config.blankGif
  1007. "dojo/dom-class", // domClass.add domConstruct.create domStyle.getComputedStyle
  1008. "dojo/dom-construct", // domClass.add domConstruct.create domStyle.getComputedStyle
  1009. "dojo/dom-style", // domClass.add domConstruct.create domStyle.getComputedStyle
  1010. "dojo/ready", // ready
  1011. "dojo/_base/sniff", // has("ie") has("mozilla")
  1012. "dojo/_base/window" // win.body
  1013. ], function(require, config, domClass, domConstruct, domStyle, ready, has, win){
  1014. // module:
  1015. // dijit/hccss
  1016. // summary:
  1017. // Test if computer is in high contrast mode, and sets dijit_a11y flag on <body> if it is.
  1018. if(has("ie") || has("mozilla")){ // NOTE: checking in Safari messes things up
  1019. // priority is 90 to run ahead of parser priority of 100
  1020. ready(90, function(){
  1021. // summary:
  1022. // Detects if we are in high-contrast mode or not
  1023. // create div for testing if high contrast mode is on or images are turned off
  1024. var div = domConstruct.create("div",{
  1025. id: "a11yTestNode",
  1026. style:{
  1027. cssText:'border: 1px solid;'
  1028. + 'border-color:red green;'
  1029. + 'position: absolute;'
  1030. + 'height: 5px;'
  1031. + 'top: -999px;'
  1032. + 'background-image: url("' + (config.blankGif || require.toUrl("dojo/resources/blank.gif")) + '");'
  1033. }
  1034. }, win.body());
  1035. // test it
  1036. var cs = domStyle.getComputedStyle(div);
  1037. if(cs){
  1038. var bkImg = cs.backgroundImage;
  1039. var needsA11y = (cs.borderTopColor == cs.borderRightColor) || (bkImg != null && (bkImg == "none" || bkImg == "url(invalid-url:)" ));
  1040. if(needsA11y){
  1041. domClass.add(win.body(), "dijit_a11y");
  1042. }
  1043. if(has("ie")){
  1044. div.outerHTML = ""; // prevent mixed-content warning, see http://support.microsoft.com/kb/925014
  1045. }else{
  1046. win.body().removeChild(div);
  1047. }
  1048. }
  1049. });
  1050. }
  1051. });
  1052. },
  1053. 'dijit/_Contained':function(){
  1054. define("dijit/_Contained", [
  1055. "dojo/_base/declare", // declare
  1056. "./registry" // registry.getEnclosingWidget(), registry.byNode()
  1057. ], function(declare, registry){
  1058. // module:
  1059. // dijit/_Contained
  1060. // summary:
  1061. // Mixin for widgets that are children of a container widget
  1062. return declare("dijit._Contained", null, {
  1063. // summary:
  1064. // Mixin for widgets that are children of a container widget
  1065. //
  1066. // example:
  1067. // | // make a basic custom widget that knows about it's parents
  1068. // | declare("my.customClass",[dijit._Widget,dijit._Contained],{});
  1069. _getSibling: function(/*String*/ which){
  1070. // summary:
  1071. // Returns next or previous sibling
  1072. // which:
  1073. // Either "next" or "previous"
  1074. // tags:
  1075. // private
  1076. var node = this.domNode;
  1077. do{
  1078. node = node[which+"Sibling"];
  1079. }while(node && node.nodeType != 1);
  1080. return node && registry.byNode(node); // dijit._Widget
  1081. },
  1082. getPreviousSibling: function(){
  1083. // summary:
  1084. // Returns null if this is the first child of the parent,
  1085. // otherwise returns the next element sibling to the "left".
  1086. return this._getSibling("previous"); // dijit._Widget
  1087. },
  1088. getNextSibling: function(){
  1089. // summary:
  1090. // Returns null if this is the last child of the parent,
  1091. // otherwise returns the next element sibling to the "right".
  1092. return this._getSibling("next"); // dijit._Widget
  1093. },
  1094. getIndexInParent: function(){
  1095. // summary:
  1096. // Returns the index of this widget within its container parent.
  1097. // It returns -1 if the parent does not exist, or if the parent
  1098. // is not a dijit._Container
  1099. var p = this.getParent();
  1100. if(!p || !p.getIndexOfChild){
  1101. return -1; // int
  1102. }
  1103. return p.getIndexOfChild(this); // int
  1104. }
  1105. });
  1106. });
  1107. },
  1108. 'dijit/form/_TextBoxMixin':function(){
  1109. define("dijit/form/_TextBoxMixin", [
  1110. "dojo/_base/array", // array.forEach
  1111. "dojo/_base/declare", // declare
  1112. "dojo/dom", // dom.byId
  1113. "dojo/_base/event", // event.stop
  1114. "dojo/keys", // keys.ALT keys.CAPS_LOCK keys.CTRL keys.META keys.SHIFT
  1115. "dojo/_base/lang", // lang.mixin
  1116. ".." // for exporting dijit._setSelectionRange, dijit.selectInputText
  1117. ], function(array, declare, dom, event, keys, lang, dijit){
  1118. // module:
  1119. // dijit/form/_TextBoxMixin
  1120. // summary:
  1121. // A mixin for textbox form input widgets
  1122. var _TextBoxMixin = declare("dijit.form._TextBoxMixin", null, {
  1123. // summary:
  1124. // A mixin for textbox form input widgets
  1125. // trim: Boolean
  1126. // Removes leading and trailing whitespace if true. Default is false.
  1127. trim: false,
  1128. // uppercase: Boolean
  1129. // Converts all characters to uppercase if true. Default is false.
  1130. uppercase: false,
  1131. // lowercase: Boolean
  1132. // Converts all characters to lowercase if true. Default is false.
  1133. lowercase: false,
  1134. // propercase: Boolean
  1135. // Converts the first character of each word to uppercase if true.
  1136. propercase: false,
  1137. // maxLength: String
  1138. // HTML INPUT tag maxLength declaration.
  1139. maxLength: "",
  1140. // selectOnClick: [const] Boolean
  1141. // If true, all text will be selected when focused with mouse
  1142. selectOnClick: false,
  1143. // placeHolder: String
  1144. // Defines a hint to help users fill out the input field (as defined in HTML 5).
  1145. // This should only contain plain text (no html markup).
  1146. placeHolder: "",
  1147. _getValueAttr: function(){
  1148. // summary:
  1149. // Hook so get('value') works as we like.
  1150. // description:
  1151. // For `dijit.form.TextBox` this basically returns the value of the <input>.
  1152. //
  1153. // For `dijit.form.MappedTextBox` subclasses, which have both
  1154. // a "displayed value" and a separate "submit value",
  1155. // This treats the "displayed value" as the master value, computing the
  1156. // submit value from it via this.parse().
  1157. return this.parse(this.get('displayedValue'), this.constraints);
  1158. },
  1159. _setValueAttr: function(value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
  1160. // summary:
  1161. // Hook so set('value', ...) works.
  1162. //
  1163. // description:
  1164. // Sets the value of the widget to "value" which can be of
  1165. // any type as determined by the widget.
  1166. //
  1167. // value:
  1168. // The visual element value is also set to a corresponding,
  1169. // but not necessarily the same, value.
  1170. //
  1171. // formattedValue:
  1172. // If specified, used to set the visual element value,
  1173. // otherwise a computed visual value is used.
  1174. //
  1175. // priorityChange:
  1176. // If true, an onChange event is fired immediately instead of
  1177. // waiting for the next blur event.
  1178. var filteredValue;
  1179. if(value !== undefined){
  1180. // TODO: this is calling filter() on both the display value and the actual value.
  1181. // I added a comment to the filter() definition about this, but it should be changed.
  1182. filteredValue = this.filter(value);
  1183. if(typeof formattedValue != "string"){
  1184. if(filteredValue !== null && ((typeof filteredValue != "number") || !isNaN(filteredValue))){
  1185. formattedValue = this.filter(this.format(filteredValue, this.constraints));
  1186. }else{ formattedValue = ''; }
  1187. }
  1188. }
  1189. if(formattedValue != null && formattedValue != undefined && ((typeof formattedValue) != "number" || !isNaN(formattedValue)) && this.textbox.value != formattedValue){
  1190. this.textbox.value = formattedValue;
  1191. this._set("displayedValue", this.get("displayedValue"));
  1192. }
  1193. if(this.textDir == "auto"){
  1194. this.applyTextDir(this.focusNode, formattedValue);
  1195. }
  1196. this.inherited(arguments, [filteredValue, priorityChange]);
  1197. },
  1198. // displayedValue: String
  1199. // For subclasses like ComboBox where the displayed value
  1200. // (ex: Kentucky) and the serialized value (ex: KY) are different,
  1201. // this represents the displayed value.
  1202. //
  1203. // Setting 'displayedValue' through set('displayedValue', ...)
  1204. // updates 'value', and vice-versa. Otherwise 'value' is updated
  1205. // from 'displayedValue' periodically, like onBlur etc.
  1206. //
  1207. // TODO: move declaration to MappedTextBox?
  1208. // Problem is that ComboBox references displayedValue,
  1209. // for benefit of FilteringSelect.
  1210. displayedValue: "",
  1211. _getDisplayedValueAttr: function(){
  1212. // summary:
  1213. // Hook so get('displayedValue') works.
  1214. // description:
  1215. // Returns the displayed value (what the user sees on the screen),
  1216. // after filtering (ie, trimming spaces etc.).
  1217. //
  1218. // For some subclasses of TextBox (like ComboBox), the displayed value
  1219. // is different from the serialized value that's actually
  1220. // sent to the server (see dijit.form.ValidationTextBox.serialize)
  1221. // TODO: maybe we should update this.displayedValue on every keystroke so that we don't need
  1222. // this method
  1223. // TODO: this isn't really the displayed value when the user is typing
  1224. return this.filter(this.textbox.value);
  1225. },
  1226. _setDisplayedValueAttr: function(/*String*/ value){
  1227. // summary:
  1228. // Hook so set('displayedValue', ...) works.
  1229. // description:
  1230. // Sets the value of the visual element to the string "value".
  1231. // The widget value is also set to a corresponding,
  1232. // but not necessarily the same, value.
  1233. if(value === null || value === undefined){ value = '' }
  1234. else if(typeof value != "string"){ value = String(value) }
  1235. this.textbox.value = value;
  1236. // sets the serialized value to something corresponding to specified displayedValue
  1237. // (if possible), and also updates the textbox.value, for example converting "123"
  1238. // to "123.00"
  1239. this._setValueAttr(this.get('value'), undefined);
  1240. this._set("displayedValue", this.get('displayedValue'));
  1241. // textDir support
  1242. if(this.textDir == "auto"){
  1243. this.applyTextDir(this.focusNode, value);
  1244. }
  1245. },
  1246. format: function(value /*=====, constraints =====*/){
  1247. // summary:
  1248. // Replaceable function to convert a value to a properly formatted string.
  1249. // value: String
  1250. // constraints: Object
  1251. // tags:
  1252. // protected extension
  1253. return ((value == null || value == undefined) ? "" : (value.toString ? value.toString() : value));
  1254. },
  1255. parse: function(value /*=====, constraints =====*/){
  1256. // summary:
  1257. // Replaceable function to convert a formatted string to a value
  1258. // value: String
  1259. // constraints: Object
  1260. // tags:
  1261. // protected extension
  1262. return value; // String
  1263. },
  1264. _refreshState: function(){
  1265. // summary:
  1266. // After the user types some characters, etc., this method is
  1267. // called to check the field for validity etc. The base method
  1268. // in `dijit.form.TextBox` does nothing, but subclasses override.
  1269. // tags:
  1270. // protected
  1271. },
  1272. /*=====
  1273. onInput: function(event){
  1274. // summary:
  1275. // Connect to this function to receive notifications of various user data-input events.
  1276. // Return false to cancel the event and prevent it from being processed.
  1277. // event:
  1278. // keydown | keypress | cut | paste | input
  1279. // tags:
  1280. // callback
  1281. },
  1282. =====*/
  1283. onInput: function(){},
  1284. __skipInputEvent: false,
  1285. _onInput: function(){
  1286. // summary:
  1287. // Called AFTER the input event has happened
  1288. // set text direction according to textDir that was defined in creation
  1289. if(this.textDir == "auto"){
  1290. this.applyTextDir(this.focusNode, this.focusNode.value);
  1291. }
  1292. this._refreshState();
  1293. // In case someone is watch()'ing for changes to displayedValue
  1294. this._set("displayedValue", this.get("displayedValue"));
  1295. },
  1296. postCreate: function(){
  1297. // setting the value here is needed since value="" in the template causes "undefined"
  1298. // and setting in the DOM (instead of the JS object) helps with form reset actions
  1299. this.textbox.setAttribute("value", this.textbox.value); // DOM and JS values should be the same
  1300. this.inherited(arguments);
  1301. // normalize input events to reduce spurious event processing
  1302. // onkeydown: do not forward modifier keys
  1303. // set charOrCode to numeric keycode
  1304. // onkeypress: do not forward numeric charOrCode keys (already sent through onkeydown)
  1305. // onpaste & oncut: set charOrCode to 229 (IME)
  1306. // oninput: if primary event not already processed, set charOrCode to 229 (IME), else do not forward
  1307. var handleEvent = function(e){
  1308. var charCode = e.charOrCode || e.keyCode || 229;
  1309. if(e.type == "keydown"){
  1310. switch(charCode){ // ignore "state" keys
  1311. case keys.SHIFT:
  1312. case keys.ALT:
  1313. case keys.CTRL:
  1314. case keys.META:
  1315. case keys.CAPS_LOCK:
  1316. return;
  1317. default:
  1318. if(charCode >= 65 && charCode <= 90){ return; } // keydown for A-Z can be processed with keypress
  1319. }
  1320. }
  1321. if(e.type == "keypress" && typeof charCode != "string"){ return; }
  1322. if(e.type == "input"){
  1323. if(this.__skipInputEvent){ // duplicate event
  1324. this.__skipInputEvent = false;
  1325. return;
  1326. }
  1327. }else{
  1328. this.__skipInputEvent = true;
  1329. }
  1330. // create fake event to set charOrCode and to know if preventDefault() was called
  1331. var faux = lang.mixin({}, e, {
  1332. charOrCode: charCode,
  1333. wasConsumed: false,
  1334. preventDefault: function(){
  1335. faux.wasConsumed = true;
  1336. e.preventDefault();
  1337. },
  1338. stopPropagation: function(){ e.stopPropagation(); }
  1339. });
  1340. // give web page author a chance to consume the event
  1341. if(this.onInput(faux) === false){
  1342. event.stop(faux); // return false means stop
  1343. }
  1344. if(faux.wasConsumed){ return; } // if preventDefault was called
  1345. setTimeout(lang.hitch(this, "_onInput", faux), 0); // widget notification after key has posted
  1346. };
  1347. array.forEach([ "onkeydown", "onkeypress", "onpaste", "oncut", "oninput", "oncompositionend" ], function(event){
  1348. this.connect(this.textbox, event, handleEvent);
  1349. }, this);
  1350. },
  1351. _blankValue: '', // if the textbox is blank, what value should be reported
  1352. filter: function(val){
  1353. // summary:
  1354. // Auto-corrections (such as trimming) that are applied to textbox
  1355. // value on blur or form submit.
  1356. // description:
  1357. // For MappedTextBox subclasses, this is called twice
  1358. // - once with the display value
  1359. // - once the value as set/returned by set('value', ...)
  1360. // and get('value'), ex: a Number for NumberTextBox.
  1361. //
  1362. // In the latter case it does corrections like converting null to NaN. In
  1363. // the former case the NumberTextBox.filter() method calls this.inherited()
  1364. // to execute standard trimming code in TextBox.filter().
  1365. //
  1366. // TODO: break this into two methods in 2.0
  1367. //
  1368. // tags:
  1369. // protected extension
  1370. if(val === null){ return this._blankValue; }
  1371. if(typeof val != "string"){ return val; }
  1372. if(this.trim){
  1373. val = lang.trim(val);
  1374. }
  1375. if(this.uppercase){
  1376. val = val.toUpperCase();
  1377. }
  1378. if(this.lowercase){
  1379. val = val.toLowerCase();
  1380. }
  1381. if(this.propercase){
  1382. val = val.replace(/[^\s]+/g, function(word){
  1383. return word.substring(0,1).toUpperCase() + word.substring(1);
  1384. });
  1385. }
  1386. return val;
  1387. },
  1388. _setBlurValue: function(){
  1389. this._setValueAttr(this.get('value'), true);
  1390. },
  1391. _onBlur: function(e){
  1392. if(this.disabled){ return; }
  1393. this._setBlurValue();
  1394. this.inherited(arguments);
  1395. if(this._selectOnClickHandle){
  1396. this.disconnect(this._selectOnClickHandle);
  1397. }
  1398. },
  1399. _isTextSelected: function(){
  1400. return this.textbox.selectionStart == this.textbox.selectionEnd;
  1401. },
  1402. _onFocus: function(/*String*/ by){
  1403. if(this.disabled || this.readOnly){ return; }
  1404. // Select all text on focus via click if nothing already selected.
  1405. // Since mouse-up will clear the selection need to defer selection until after mouse-up.
  1406. // Don't do anything on focus by tabbing into the widget since there's no associated mouse-up event.
  1407. if(this.selectOnClick && by == "mouse"){
  1408. this._selectOnClickHandle = this.connect(this.domNode, "onmouseup", function(){
  1409. // Only select all text on first click; otherwise users would have no way to clear
  1410. // the selection.
  1411. this.disconnect(this._selectOnClickHandle);
  1412. // Check if the user selected some text manually (mouse-down, mouse-move, mouse-up)
  1413. // and if not, then select all the text
  1414. if(this._isTextSelected()){
  1415. _TextBoxMixin.selectInputText(this.textbox);
  1416. }
  1417. });
  1418. }
  1419. // call this.inherited() before refreshState(), since this.inherited() will possibly scroll the viewport
  1420. // (to scroll the TextBox into view), which will affect how _refreshState() positions the tooltip
  1421. this.inherited(arguments);
  1422. this._refreshState();
  1423. },
  1424. reset: function(){
  1425. // Overrides dijit._FormWidget.reset().
  1426. // Additionally resets the displayed textbox value to ''
  1427. this.textbox.value = '';
  1428. this.inherited(arguments);
  1429. },
  1430. _setTextDirAttr: function(/*String*/ textDir){
  1431. // summary:
  1432. // Setter for textDir.
  1433. // description:
  1434. // Users shouldn't call this function; they should be calling
  1435. // set('textDir', value)
  1436. // tags:
  1437. // private
  1438. // only if new textDir is different from the old one
  1439. // and on widgets creation.
  1440. if(!this._created
  1441. || this.textDir != textDir){
  1442. this._set("textDir", textDir);
  1443. // so the change of the textDir will take place immediately.
  1444. this.applyTextDir(this.focusNode, this.focusNode.value);
  1445. }
  1446. }
  1447. });
  1448. _TextBoxMixin._setSelectionRange = dijit._setSelectionRange = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){
  1449. if(element.setSelectionRange){
  1450. element.setSelectionRange(start, stop);
  1451. }
  1452. };
  1453. _TextBoxMixin.selectInputText = dijit.selectInputText = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){
  1454. // summary:
  1455. // Select text in the input element argument, from start (default 0), to stop (default end).
  1456. // TODO: use functions in _editor/selection.js?
  1457. element = dom.byId(element);
  1458. if(isNaN(start)){ start = 0; }
  1459. if(isNaN(stop)){ stop = element.value ? element.value.length : 0; }
  1460. try{
  1461. element.focus();
  1462. _TextBoxMixin._setSelectionRange(element, start, stop);
  1463. }catch(e){ /* squelch random errors (esp. on IE) from unexpected focus changes or DOM nodes being hidden */ }
  1464. };
  1465. return _TextBoxMixin;
  1466. });
  1467. },
  1468. 'dijit/Viewport':function(){
  1469. define("dijit/Viewport", [
  1470. "dojo/Evented",
  1471. "dojo/on",
  1472. "dojo/ready",
  1473. "dojo/_base/sniff",
  1474. "dojo/_base/window", // global
  1475. "dojo/window" // getBox()
  1476. ], function(Evented, on, ready, has, win, winUtils){
  1477. // module:
  1478. // dijit/Viewport
  1479. /*=====
  1480. return {
  1481. // summary:
  1482. // Utility singleton to watch for viewport resizes, avoiding duplicate notifications
  1483. // which can lead to infinite loops.
  1484. // description:
  1485. // Usage: Viewport.on("resize", myCallback).
  1486. //
  1487. // myCallback() is called without arguments in case it's _WidgetBase.resize(),
  1488. // which would interpret the argument as the size to make the widget.
  1489. };
  1490. =====*/
  1491. var Viewport = new Evented();
  1492. var focusedNode;
  1493. ready(200, function(){
  1494. var oldBox = winUtils.getBox();
  1495. Viewport._rlh = on(win.global, "resize", function(){
  1496. var newBox = winUtils.getBox();
  1497. if(oldBox.h == newBox.h && oldBox.w == newBox.w){ return; }
  1498. oldBox = newBox;
  1499. Viewport.emit("resize");
  1500. });
  1501. // Also catch zoom changes on IE8, since they don't naturally generate resize events
  1502. if(has("ie") == 8){
  1503. var deviceXDPI = screen.deviceXDPI;
  1504. setInterval(function(){
  1505. if(screen.deviceXDPI != deviceXDPI){
  1506. deviceXDPI = screen.deviceXDPI;
  1507. Viewport.emit("resize");
  1508. }
  1509. }, 500);
  1510. }
  1511. // On iOS, keep track of the focused node so we can guess when the keyboard is/isn't being displayed.
  1512. if(has("ios")){
  1513. on(document, "focusin", function(evt){
  1514. focusedNode = evt.target;
  1515. });
  1516. on(document, "focusout", function(evt){
  1517. focusedNode = null;
  1518. });
  1519. }
  1520. });
  1521. Viewport.getEffectiveBox = function(/*Document*/ doc){
  1522. // summary:
  1523. // Get the size of the viewport, or on mobile devices, the part of the viewport not obscured by the
  1524. // virtual keyboard.
  1525. var box = winUtils.getBox(doc);
  1526. // Account for iOS virtual keyboard, if it's being shown. Unfortunately no direct way to check or measure.
  1527. var tag = focusedNode && focusedNode.tagName && focusedNode.tagName.toLowerCase();
  1528. if(has("ios") && focusedNode && !focusedNode.readOnly && (tag == "textarea" || (tag == "input" &&
  1529. /^(color|email|number|password|search|tel|text|url)$/.test(focusedNode.type)))){
  1530. // Box represents the size of the viewport. Some of the viewport is likely covered by the keyboard.
  1531. // Estimate height of visible viewport assuming viewport goes to bottom of screen, but is covered by keyboard.
  1532. box.h *= (orientation == 0 || orientation == 180 ? 0.66 : 0.40);
  1533. // Above measurement will be inaccurate if viewport was scrolled up so far that it ends before the bottom
  1534. // of the screen. In this case, keyboard isn't covering as much of the viewport as we thought.
  1535. // We know the visible size is at least the distance from the top of the viewport to the focused node.
  1536. var rect = focusedNode.getBoundingClientRect();
  1537. box.h = Math.max(box.h, rect.top + rect.height);
  1538. }
  1539. return box;
  1540. };
  1541. return Viewport;
  1542. });
  1543. },
  1544. 'dojox/mobile/parser':function(){
  1545. define("dojox/mobile/parser", [
  1546. "dojo/_base/kernel",
  1547. "dojo/_base/config",
  1548. "dojo/_base/lang",
  1549. "dojo/_base/window",
  1550. "dojo/ready"
  1551. ], function(dojo, config, lang, win, ready){
  1552. // module:
  1553. // dojox/mobile/parser
  1554. // summary:
  1555. // A lightweight parser.
  1556. var dm = lang.getObject("dojox.mobile", true);
  1557. var parser = new function(){
  1558. // summary:
  1559. // A lightweight parser.
  1560. // description:
  1561. // dojox.mobile.parser is an extremely small subset of
  1562. // dojo.parser. It has no extended features over dojo.parser, so
  1563. // there is no reason you have to use dojox.mobile.parser instead
  1564. // of dojo.parser. However, if dojox.mobile.parser's capability is
  1565. // enough for your application, use of it could reduce the total
  1566. // code size.
  1567. this.instantiate = function(/* Array */nodes, /* Object? */mixin, /* Object? */args){
  1568. // summary:
  1569. // Function for instantiating a list of widget nodes.
  1570. // nodes:
  1571. // The list of DOMNodes to walk and instantiate widgets on.
  1572. mixin = mixin || {};
  1573. args = args || {};
  1574. var i, ws = [];
  1575. if(nodes){
  1576. for(i = 0; i < nodes.length; i++){
  1577. var n = nodes[i];
  1578. var cls = lang.getObject(n.getAttribute("dojoType") || n.getAttribute("data-dojo-type"));
  1579. var proto = cls.prototype;
  1580. var params = {}, prop, v, t;
  1581. lang.mixin(params, eval('({'+(n.getAttribute("data-dojo-props")||"")+'})'));
  1582. lang.mixin(params, args.defaults);
  1583. lang.mixin(params, mixin);
  1584. for(prop in proto){
  1585. v = n.getAttributeNode(prop);
  1586. v = v && v.nodeValue;
  1587. t = typeof proto[prop];
  1588. if(!v && (t !== "boolean" || v !== "")){ continue; }
  1589. if(t === "string"){
  1590. params[prop] = v;
  1591. }else if(t === "number"){
  1592. params[prop] = v - 0;
  1593. }else if(t === "boolean"){
  1594. params[prop] = (v !== "false");
  1595. }else if(t === "object"){
  1596. params[prop] = eval("(" + v + ")");
  1597. }
  1598. }
  1599. params["class"] = n.className;
  1600. params.style = n.style && n.style.cssText;
  1601. v = n.getAttribute("data-dojo-attach-point");
  1602. if(v){ params.dojoAttachPoint = v; }
  1603. v = n.getAttribute("data-dojo-attach-event");
  1604. if(v){ params.dojoAttachEvent = v; }
  1605. var instance = new cls(params, n);
  1606. ws.push(instance);
  1607. var jsId = n.getAttribute("jsId") || n.getAttribute("data-dojo-id");
  1608. if(jsId){
  1609. lang.setObject(jsId, instance);
  1610. }
  1611. }
  1612. for(i = 0; i < ws.length; i++){
  1613. var w = ws[i];
  1614. !args.noStart && w.startup && !w._started && w.startup();
  1615. }
  1616. }
  1617. return ws;
  1618. };
  1619. this.parse = function(rootNode, args){
  1620. // summary:
  1621. // Function to handle parsing for widgets in the current document.
  1622. // It is not as powerful as the full parser, but it will handle basic
  1623. // use cases fine.
  1624. // rootNode:
  1625. // The root node in the document to parse from
  1626. if(!rootNode){
  1627. rootNode = win.body();
  1628. }else if(!args && rootNode.rootNode){
  1629. // Case where 'rootNode' is really a params object.
  1630. args = rootNode;
  1631. rootNode = rootNode.rootNode;
  1632. }
  1633. var nodes = rootNode.getElementsByTagName("*");
  1634. var i, list = [];
  1635. for(i = 0; i < nodes.length; i++){
  1636. var n = nodes[i];
  1637. if(n.getAttribute("dojoType") || n.getAttribute("data-dojo-type")){
  1638. list.push(n);
  1639. }
  1640. }
  1641. var mixin = args && args.template ? {template: true} : null;
  1642. return this.instantiate(list, mixin, args);
  1643. };
  1644. }();
  1645. if(config.parseOnLoad){
  1646. ready(100, parser, "parse");
  1647. }
  1648. dm.parser = parser; // for backward compatibility
  1649. dojo.parser = parser; // in case user application calls dojo.parser
  1650. return parser;
  1651. });
  1652. },
  1653. 'dijit/_Container':function(){
  1654. define("dijit/_Container", [
  1655. "dojo/_base/array", // array.forEach array.indexOf
  1656. "dojo/_base/declare", // declare
  1657. "dojo/dom-construct", // domConstruct.place
  1658. "./registry" // registry.byNode()
  1659. ], function(array, declare, domConstruct, registry){
  1660. // module:
  1661. // dijit/_Container
  1662. // summary:
  1663. // Mixin for widgets that contain a set of widget children.
  1664. return declare("dijit._Container", null, {
  1665. // summary:
  1666. // Mixin for widgets that contain a set of widget children.
  1667. // description:
  1668. // Use this mixin for widgets that needs to know about and
  1669. // keep track of their widget children. Suitable for widgets like BorderContainer
  1670. // and TabContainer which contain (only) a set of child widgets.
  1671. //
  1672. // It's not suitable for widgets like ContentPane
  1673. // which contains mixed HTML (plain DOM nodes in addition to widgets),
  1674. // and where contained widgets are not necessarily directly below
  1675. // this.containerNode. In that case calls like addChild(node, position)
  1676. // wouldn't make sense.
  1677. buildRendering: function(){
  1678. this.inherited(arguments);
  1679. if(!this.containerNode){
  1680. // all widgets with descendants must set containerNode
  1681. this.containerNode = this.domNode;
  1682. }
  1683. },
  1684. addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
  1685. // summary:
  1686. // Makes the given widget a child of this widget.
  1687. // description:
  1688. // Inserts specified child widget's dom node as a child of this widget's
  1689. // container node, and possibly does other processing (such as layout).
  1690. var refNode = this.containerNode;
  1691. if(insertIndex && typeof insertIndex == "number"){
  1692. var children = this.getChildren();
  1693. if(children && children.length >= insertIndex){
  1694. refNode = children[insertIndex-1].domNode;
  1695. insertIndex = "after";
  1696. }
  1697. }
  1698. domConstruct.place(widget.domNode, refNode, insertIndex);
  1699. // If I've been started but the child widget hasn't been started,
  1700. // start it now. Make sure to do this after widget has been
  1701. // inserted into the DOM tree, so it can see that it's being controlled by me,
  1702. // so it doesn't try to size itself.
  1703. if(this._started && !widget._started){
  1704. widget.startup();
  1705. }
  1706. },
  1707. removeChild: function(/*Widget|int*/ widget){
  1708. // summary:
  1709. // Removes the passed widget instance from this widget but does
  1710. // not destroy it. You can also pass in an integer indicating
  1711. // the index within the container to remove
  1712. if(typeof widget == "number"){
  1713. widget = this.getChildren()[widget];
  1714. }
  1715. if(widget){
  1716. var node = widget.domNode;
  1717. if(node && node.parentNode){
  1718. node.parentNode.removeChild(node); // detach but don't destroy
  1719. }
  1720. }
  1721. },
  1722. hasChildren: function(){
  1723. // summary:
  1724. // Returns true if widget has children, i.e. if this.containerNode contains something.
  1725. return this.getChildren().length > 0; // Boolean
  1726. },
  1727. _getSiblingOfChild: function(/*dijit._Widget*/ child, /*int*/ dir){
  1728. // summary:
  1729. // Get the next or previous widget sibling of child
  1730. // dir:
  1731. // if 1, get the next sibling
  1732. // if -1, get the previous sibling
  1733. // tags:
  1734. // private
  1735. var node = child.domNode,
  1736. which = (dir>0 ? "nextSibling" : "previousSibling");
  1737. do{
  1738. node = node[which];
  1739. }while(node && (node.nodeType != 1 || !registry.byNode(node)));
  1740. return node && registry.byNode(node); // dijit._Widget
  1741. },
  1742. getIndexOfChild: function(/*dijit._Widget*/ child){
  1743. // summary:
  1744. // Gets the index of the child in this container or -1 if not found
  1745. return array.indexOf(this.getChildren(), child); // int
  1746. }
  1747. });
  1748. });
  1749. },
  1750. 'dojox/mobile/app/SceneController':function(){
  1751. // wrapped by build app
  1752. define(["dijit","dojo","dojox","dojo/require!dojox/mobile/_base"], function(dijit,dojo,dojox){
  1753. dojo.provide("dojox.mobile.app.SceneController");
  1754. dojo.experimental("dojox.mobile.app.SceneController");
  1755. dojo.require("dojox.mobile._base");
  1756. (function(){
  1757. var app = dojox.mobile.app;
  1758. var templates = {};
  1759. dojo.declare("dojox.mobile.app.SceneController", dojox.mobile.View, {
  1760. stageController: null,
  1761. keepScrollPos: false,
  1762. init: function(sceneName, params){
  1763. // summary:
  1764. // Initializes the scene by loading the HTML template and code, if it has
  1765. // not already been loaded
  1766. this.sceneName = sceneName;
  1767. this.params = params;
  1768. var templateUrl = app.resolveTemplate(sceneName);
  1769. this._deferredInit = new dojo.Deferred();
  1770. if(templates[sceneName]){
  1771. // If the template has been cached, do not load it again.
  1772. this._setContents(templates[sceneName]);
  1773. }else{
  1774. // Otherwise load the template
  1775. dojo.xhrGet({
  1776. url: templateUrl,
  1777. handleAs: "text"
  1778. }).addCallback(dojo.hitch(this, this._setContents));
  1779. }
  1780. return this._deferredInit;
  1781. },
  1782. _setContents: function(templateHtml){
  1783. // summary:
  1784. // Sets the content of the View, and invokes either the loading or
  1785. // initialization of the scene assistant.
  1786. templates[this.sceneName] = templateHtml;
  1787. this.domNode.innerHTML = "<div>" + templateHtml + "</div>";
  1788. var sceneAssistantName = "";
  1789. var nameParts = this.sceneName.split("-");
  1790. for(var i = 0; i < nameParts.length; i++){
  1791. sceneAssistantName += nameParts[i].substring(0, 1).toUpperCase()
  1792. + nameParts[i].substring(1);
  1793. }
  1794. sceneAssistantName += "Assistant";
  1795. this.sceneAssistantName = sceneAssistantName;
  1796. var _this = this;
  1797. dojox.mobile.app.loadResourcesForScene(this.sceneName, function(){
  1798. console.log("All resources for ",_this.sceneName," loaded");
  1799. var assistant;
  1800. if(typeof(dojo.global[sceneAssistantName]) != "undefined"){
  1801. _this._initAssistant();
  1802. }else{
  1803. var assistantUrl = app.resolveAssistant(_this.sceneName);
  1804. dojo.xhrGet({
  1805. url: assistantUrl,
  1806. handleAs: "text"
  1807. }).addCallback(function(text){
  1808. try{
  1809. dojo.eval(text);
  1810. }catch(e){
  1811. console.log("Error initializing code for scene " + _this.sceneName
  1812. + '. Please check for syntax errors');
  1813. throw e;
  1814. }
  1815. _this._initAssistant();
  1816. });
  1817. }
  1818. });
  1819. },
  1820. _initAssistant: function(){
  1821. // summary:
  1822. // Initializes the scene assistant. At this point, the View is
  1823. // populated with the HTML template, and the scene assistant type
  1824. // is declared.
  1825. console.log("Instantiating the scene assistant " + this.sceneAssistantName);
  1826. var cls = dojo.getObject(this.sceneAssistantName);
  1827. if(!cls){
  1828. throw Error("Unable to resolve scene assistant "
  1829. + this.sceneAssistantName);
  1830. }
  1831. this.assistant = new cls(this.params);
  1832. this.assistant.controller = this;
  1833. this.assistant.domNode = this.domNode.firstChild;
  1834. this.assistant.setup();
  1835. this._deferredInit.callback();
  1836. },
  1837. query: function(selector, node){
  1838. // summary:
  1839. // Queries for DOM nodes within either the node passed in as an argument
  1840. // or within this view.
  1841. return dojo.query(selector, node || this.domNode)
  1842. },
  1843. parse: function(node){
  1844. var widgets = this._widgets =
  1845. dojox.mobile.parser.parse(node || this.domNode, {
  1846. controller: this
  1847. });
  1848. // Tell all widgets what their controller is.
  1849. for(var i = 0; i < widgets.length; i++){
  1850. widgets[i].set("controller", this);
  1851. }
  1852. },
  1853. getWindowSize: function(){
  1854. // TODO, this needs cross browser testing
  1855. return {
  1856. w: dojo.global.innerWidth,
  1857. h: dojo.global.innerHeight
  1858. }
  1859. },
  1860. showAlertDialog: function(props){
  1861. var size = dojo.marginBox(this.assistant.domNode);
  1862. var dialog = new dojox.mobile.app.AlertDialog(
  1863. dojo.mixin(props, {controller: this}));
  1864. this.assistant.domNode.appendChild(dialog.domNode);
  1865. console.log("Appended " , dialog.domNode, " to ", this.assistant.domNode);
  1866. dialog.show();
  1867. },
  1868. popupSubMenu: function(info){
  1869. var widget = new dojox.mobile.app.ListSelector({
  1870. controller: this,
  1871. destroyOnHide: true,
  1872. onChoose: info.onChoose
  1873. });
  1874. this.assistant.domNode.appendChild(widget.domNode);
  1875. widget.set("data", info.choices);
  1876. widget.show(info.fromNode);
  1877. }
  1878. });
  1879. })();
  1880. });
  1881. },
  1882. 'dojox/mobile/app/_base':function(){
  1883. // wrapped by build app
  1884. define("dojox/mobile/app/_base", ["dijit","dojo","dojox","dojo/require!dijit/_base,dijit/_WidgetBase,dojox/mobile,dojox/mobile/parser,dojox/mobile/Button,dojox/mobile/app/_event,dojox/mobile/app/_Widget,dojox/mobile/app/StageController,dojox/mobile/app/SceneController,dojox/mobile/app/SceneAssistant,dojox/mobile/app/AlertDialog,dojox/mobile/app/List,dojox/mobile/app/ListSelector,dojox/mobile/app/TextBox,dojox/mobile/app/ImageView,dojox/mobile/app/ImageThumbView"], function(dijit,dojo,dojox){
  1885. dojo.provide("dojox.mobile.app._base");
  1886. dojo.experimental("dojox.mobile.app._base");
  1887. dojo.require("dijit._base");
  1888. dojo.require("dijit._WidgetBase");
  1889. dojo.require("dojox.mobile");
  1890. dojo.require("dojox.mobile.parser");
  1891. dojo.require("dojox.mobile.Button");
  1892. dojo.require("dojox.mobile.app._event");
  1893. dojo.require("dojox.mobile.app._Widget");
  1894. dojo.require("dojox.mobile.app.StageController");
  1895. dojo.require("dojox.mobile.app.SceneController");
  1896. dojo.require("dojox.mobile.app.SceneAssistant");
  1897. dojo.require("dojox.mobile.app.AlertDialog");
  1898. dojo.require("dojox.mobile.app.List");
  1899. dojo.require("dojox.mobile.app.ListSelector");
  1900. dojo.require("dojox.mobile.app.TextBox");
  1901. dojo.require("dojox.mobile.app.ImageView");
  1902. dojo.require("dojox.mobile.app.ImageThumbView");
  1903. (function(){
  1904. var stageController;
  1905. var appInfo;
  1906. var jsDependencies = [
  1907. "dojox.mobile",
  1908. "dojox.mobile.parser"
  1909. ];
  1910. var loadedResources = {};
  1911. var loadingDependencies;
  1912. var rootNode;
  1913. var sceneResources = [];
  1914. // Load the required resources asynchronously, since not all mobile OSes
  1915. // support dojo.require and sync XHR
  1916. function loadResources(resources, callback){
  1917. // summary:
  1918. // Loads one or more JavaScript files asynchronously. When complete,
  1919. // the first scene is pushed onto the stack.
  1920. // resources:
  1921. // An array of module names, e.g. 'dojox.mobile.AlertDialog'
  1922. var resource;
  1923. var url;
  1924. do {
  1925. resource = resources.pop();
  1926. if (resource.source) {
  1927. url = resource.source;
  1928. }else if (resource.module) {
  1929. url= dojo.moduleUrl(resource.module)+".js";
  1930. }else {
  1931. console.log("Error: invalid JavaScript resource " + dojo.toJson(resource));
  1932. return;
  1933. }
  1934. }while (resources.length > 0 && loadedResources[url]);
  1935. if(resources.length < 1 && loadedResources[url]){
  1936. // All resources have already been loaded
  1937. callback();
  1938. return;
  1939. }
  1940. dojo.xhrGet({
  1941. url: url,
  1942. sync: false
  1943. }).addCallbacks(function(text){
  1944. dojo["eval"](text);
  1945. loadedResources[url] = true;
  1946. if(resources.length > 0){
  1947. loadResources(resources, callback);
  1948. }else{
  1949. callback();
  1950. }
  1951. },
  1952. function(){
  1953. console.log("Failed to load resource " + url);
  1954. });
  1955. }
  1956. var pushFirstScene = function(){
  1957. // summary:
  1958. // Pushes the first scene onto the stack.
  1959. stageController = new dojox.mobile.app.StageController(rootNode);
  1960. var defaultInfo = {
  1961. id: "com.test.app",
  1962. version: "1.0.0",
  1963. initialScene: "main"
  1964. };
  1965. // If the application info has been defined, as it should be,
  1966. // use it.
  1967. if(dojo.global["appInfo"]){
  1968. dojo.mixin(defaultInfo, dojo.global["appInfo"]);
  1969. }
  1970. appInfo = dojox.mobile.app.info = defaultInfo;
  1971. // Set the document title from the app info title if it exists
  1972. if(appInfo.title){
  1973. var titleNode = dojo.query("head title")[0] ||
  1974. dojo.create("title", {},dojo.query("head")[0]);
  1975. document.title = appInfo.title;
  1976. }
  1977. stageController.pushScene(appInfo.initialScene);
  1978. };
  1979. var initBackButton = function(){
  1980. var hasNativeBack = false;
  1981. if(dojo.global.BackButton){
  1982. // Android phonegap support
  1983. BackButton.override();
  1984. dojo.connect(document, 'backKeyDown', function(e) {
  1985. dojo.publish("/dojox/mobile/app/goback");
  1986. });
  1987. hasNativeBack = true;
  1988. }else if(dojo.global.Mojo){
  1989. // TODO: add webOS support
  1990. }
  1991. if(hasNativeBack){
  1992. dojo.addClass(dojo.body(), "mblNativeBack");
  1993. }
  1994. };
  1995. dojo.mixin(dojox.mobile.app, {
  1996. init: function(node){
  1997. // summary:
  1998. // Initializes the mobile app. Creates the
  1999. rootNode = node || dojo.body();
  2000. dojox.mobile.app.STAGE_CONTROLLER_ACTIVE = true;
  2001. dojo.subscribe("/dojox/mobile/app/goback", function(){
  2002. stageController.popScene();
  2003. });
  2004. dojo.subscribe("/dojox/mobile/app/alert", function(params){
  2005. dojox.mobile.app.getActiveSceneController().showAlertDialog(params);
  2006. });
  2007. dojo.subscribe("/dojox/mobile/app/pushScene", function(sceneName, params){
  2008. stageController.pushScene(sceneName, params || {});
  2009. });
  2010. // Get the list of files to load per scene/view
  2011. dojo.xhrGet({
  2012. url: "view-resources.json",
  2013. load: function(data){
  2014. var resources = [];
  2015. if(data){
  2016. // Should be an array
  2017. sceneResources = data = dojo.fromJson(data);
  2018. // Get the list of files to load that have no scene
  2019. // specified, and therefore should be loaded on
  2020. // startup
  2021. for(var i = 0; i < data.length; i++){
  2022. if(!data[i].scene){
  2023. resources.push(data[i]);
  2024. }
  2025. }
  2026. }
  2027. if(resources.length > 0){
  2028. loadResources(resources, pushFirstScene);
  2029. }else{
  2030. pushFirstScene();
  2031. }
  2032. },
  2033. error: pushFirstScene
  2034. });
  2035. initBackButton();
  2036. },
  2037. getActiveSceneController: function(){
  2038. // summary:
  2039. // Gets the controller for the active scene.
  2040. return stageController.getActiveSceneController();
  2041. },
  2042. getStageController: function(){
  2043. // summary:
  2044. // Gets the stage controller.
  2045. return stageController;
  2046. },
  2047. loadResources: function(resources, callback){
  2048. loadResources(resources, callback);
  2049. },
  2050. loadResourcesForScene: function(sceneName, callback){
  2051. var resources = [];
  2052. // Get the list of files to load that have no scene
  2053. // specified, and therefore should be loaded on
  2054. // startup
  2055. for(var i = 0; i < sceneResources.length; i++){
  2056. if(sceneResources[i].scene == sceneName){
  2057. resources.push(sceneResources[i]);
  2058. }
  2059. }
  2060. if(resources.length > 0){
  2061. loadResources(resources, callback);
  2062. }else{
  2063. callback();
  2064. }
  2065. },
  2066. resolveTemplate: function(sceneName){
  2067. // summary:
  2068. // Given the name of a scene, returns the path to it's template
  2069. // file. For example, for a scene named 'main', the file
  2070. // returned is 'app/views/main/main-scene.html'
  2071. // This function can be overridden if it is desired to have
  2072. // a different name to file mapping.
  2073. return "app/views/" + sceneName + "/" + sceneName + "-scene.html";
  2074. },
  2075. resolveAssistant: function(sceneName){
  2076. // summary:
  2077. // Given the name of a scene, returns the path to it's assistant
  2078. // file. For example, for a scene named 'main', the file
  2079. // returned is 'app/assistants/main-assistant.js'
  2080. // This function can be overridden if it is desired to have
  2081. // a different name to file mapping.
  2082. return "app/assistants/" + sceneName + "-assistant.js";
  2083. }
  2084. });
  2085. })();
  2086. });
  2087. },
  2088. 'dijit/_base/scroll':function(){
  2089. define("dijit/_base/scroll", [
  2090. "dojo/window", // windowUtils.scrollIntoView
  2091. ".." // export symbol to dijit
  2092. ], function(windowUtils, dijit){
  2093. // module:
  2094. // dijit/_base/scroll
  2095. // summary:
  2096. // Back compatibility module, new code should use windowUtils directly instead of using this module.
  2097. dijit.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
  2098. // summary:
  2099. // Scroll the passed node into view, if it is not already.
  2100. // Deprecated, use `windowUtils.scrollIntoView` instead.
  2101. windowUtils.scrollIntoView(node, pos);
  2102. };
  2103. });
  2104. },
  2105. 'dojo/fx':function(){
  2106. define([
  2107. "./_base/lang",
  2108. "./Evented",
  2109. "./_base/kernel",
  2110. "./_base/array",
  2111. "./_base/connect",
  2112. "./_base/fx",
  2113. "./dom",
  2114. "./dom-style",
  2115. "./dom-geometry",
  2116. "./ready",
  2117. "require" // for context sensitive loading of Toggler
  2118. ], function(lang, Evented, dojo, arrayUtil, connect, baseFx, dom, domStyle, geom, ready, require) {
  2119. // module:
  2120. // dojo/fx
  2121. // summary:
  2122. // TODOC
  2123. /*=====
  2124. dojo.fx = {
  2125. // summary: Effects library on top of Base animations
  2126. };
  2127. var coreFx = dojo.fx;
  2128. =====*/
  2129. // For back-compat, remove in 2.0.
  2130. if(!dojo.isAsync){
  2131. ready(0, function(){
  2132. var requires = ["./fx/Toggler"];
  2133. require(requires); // use indirection so modules not rolled into a build
  2134. });
  2135. }
  2136. var coreFx = dojo.fx = {};
  2137. var _baseObj = {
  2138. _fire: function(evt, args){
  2139. if(this[evt]){
  2140. this[evt].apply(this, args||[]);
  2141. }
  2142. return this;
  2143. }
  2144. };
  2145. var _chain = function(animations){
  2146. this._index = -1;
  2147. this._animations = animations||[];
  2148. this._current = this._onAnimateCtx = this._onEndCtx = null;
  2149. this.duration = 0;
  2150. arrayUtil.forEach(this._animations, function(a){
  2151. this.duration += a.duration;
  2152. if(a.delay){ this.duration += a.delay; }
  2153. }, this);
  2154. };
  2155. _chain.prototype = new Evented();
  2156. lang.extend(_chain, {
  2157. _onAnimate: function(){
  2158. this._fire("onAnimate", arguments);
  2159. },
  2160. _onEnd: function(){
  2161. connect.disconnect(this._onAnimateCtx);
  2162. connect.disconnect(this._onEndCtx);
  2163. this._onAnimateCtx = this._onEndCtx = null;
  2164. if(this._index + 1 == this._animations.length){
  2165. this._fire("onEnd");
  2166. }else{
  2167. // switch animations
  2168. this._current = this._animations[++this._index];
  2169. this._onAnimateCtx = connect.connect(this._current, "onAnimate", this, "_onAnimate");
  2170. this._onEndCtx = connect.connect(this._current, "onEnd", this, "_onEnd");
  2171. this._current.play(0, true);
  2172. }
  2173. },
  2174. play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
  2175. if(!this._current){ this._current = this._animations[this._index = 0]; }
  2176. if(!gotoStart && this._current.status() == "playing"){ return this; }
  2177. var beforeBegin = connect.connect(this._current, "beforeBegin", this, function(){
  2178. this._fire("beforeBegin");
  2179. }),
  2180. onBegin = connect.connect(this._current, "onBegin", this, function(arg){
  2181. this._fire("onBegin", arguments);
  2182. }),
  2183. onPlay = connect.connect(this._current, "onPlay", this, function(arg){
  2184. this._fire("onPlay", arguments);
  2185. connect.disconnect(beforeBegin);
  2186. connect.disconnect(onBegin);
  2187. connect.disconnect(onPlay);
  2188. });
  2189. if(this._onAnimateCtx){
  2190. connect.disconnect(this._onAnimateCtx);
  2191. }
  2192. this._onAnimateCtx = connect.connect(this._current, "onAnimate", this, "_onAnimate");
  2193. if(this._onEndCtx){
  2194. connect.disconnect(this._onEndCtx);
  2195. }
  2196. this._onEndCtx = connect.connect(this._current, "onEnd", this, "_onEnd");
  2197. this._current.play.apply(this._current, arguments);
  2198. return this;
  2199. },
  2200. pause: function(){
  2201. if(this._current){
  2202. var e = connect.connect(this._current, "onPause", this, function(arg){
  2203. this._fire("onPause", arguments);
  2204. connect.disconnect(e);
  2205. });
  2206. this._current.pause();
  2207. }
  2208. return this;
  2209. },
  2210. gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
  2211. this.pause();
  2212. var offset = this.duration * percent;
  2213. this._current = null;
  2214. arrayUtil.some(this._animations, function(a){
  2215. if(a.duration <= offset){
  2216. this._current = a;
  2217. return true;
  2218. }
  2219. offset -= a.duration;
  2220. return false;
  2221. });
  2222. if(this._current){
  2223. this._current.gotoPercent(offset / this._current.duration, andPlay);
  2224. }
  2225. return this;
  2226. },
  2227. stop: function(/*boolean?*/ gotoEnd){
  2228. if(this._current){
  2229. if(gotoEnd){
  2230. for(; this._index + 1 < this._animations.length; ++this._index){
  2231. this._animations[this._index].stop(true);
  2232. }
  2233. this._current = this._animations[this._index];
  2234. }
  2235. var e = connect.connect(this._current, "onStop", this, function(arg){
  2236. this._fire("onStop", arguments);
  2237. connect.disconnect(e);
  2238. });
  2239. this._current.stop();
  2240. }
  2241. return this;
  2242. },
  2243. status: function(){
  2244. return this._current ? this._current.status() : "stopped";
  2245. },
  2246. destroy: function(){
  2247. if(this._onAnimateCtx){ connect.disconnect(this._onAnimateCtx); }
  2248. if(this._onEndCtx){ connect.disconnect(this._onEndCtx); }
  2249. }
  2250. });
  2251. lang.extend(_chain, _baseObj);
  2252. coreFx.chain = /*===== dojo.fx.chain = =====*/ function(/*dojo.Animation[]*/ animations){
  2253. // summary:
  2254. // Chain a list of `dojo.Animation`s to run in sequence
  2255. //
  2256. // description:
  2257. // Return a `dojo.Animation` which will play all passed
  2258. // `dojo.Animation` instances in sequence, firing its own
  2259. // synthesized events simulating a single animation. (eg:
  2260. // onEnd of this animation means the end of the chain,
  2261. // not the individual animations within)
  2262. //
  2263. // example:
  2264. // Once `node` is faded out, fade in `otherNode`
  2265. // | dojo.fx.chain([
  2266. // | dojo.fadeIn({ node:node }),
  2267. // | dojo.fadeOut({ node:otherNode })
  2268. // | ]).play();
  2269. //
  2270. return new _chain(animations); // dojo.Animation
  2271. };
  2272. var _combine = function(animations){
  2273. this._animations = animations||[];
  2274. this._connects = [];
  2275. this._finished = 0;
  2276. this.duration = 0;
  2277. arrayUtil.forEach(animations, function(a){
  2278. var duration = a.duration;
  2279. if(a.delay){ duration += a.delay; }
  2280. if(this.duration < duration){ this.duration = duration; }
  2281. this._connects.push(connect.connect(a, "onEnd", this, "_onEnd"));
  2282. }, this);
  2283. this._pseudoAnimation = new baseFx.Animation({curve: [0, 1], duration: this.duration});
  2284. var self = this;
  2285. arrayUtil.forEach(["beforeBegin", "onBegin", "onPlay", "onAnimate", "onPause", "onStop", "onEnd"],
  2286. function(evt){
  2287. self._connects.push(connect.connect(self._pseudoAnimation, evt,
  2288. function(){ self._fire(evt, arguments); }
  2289. ));
  2290. }
  2291. );
  2292. };
  2293. lang.extend(_combine, {
  2294. _doAction: function(action, args){
  2295. arrayUtil.forEach(this._animations, function(a){
  2296. a[action].apply(a, args);
  2297. });
  2298. return this;
  2299. },
  2300. _onEnd: function(){
  2301. if(++this._finished > this._animations.length){
  2302. this._fire("onEnd");
  2303. }
  2304. },
  2305. _call: function(action, args){
  2306. var t = this._pseudoAnimation;
  2307. t[action].apply(t, args);
  2308. },
  2309. play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
  2310. this._finished = 0;
  2311. this._doAction("play", arguments);
  2312. this._call("play", arguments);
  2313. return this;
  2314. },
  2315. pause: function(){
  2316. this._doAction("pause", arguments);
  2317. this._call("pause", arguments);
  2318. return this;
  2319. },
  2320. gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
  2321. var ms = this.duration * percent;
  2322. arrayUtil.forEach(this._animations, function(a){
  2323. a.gotoPercent(a.duration < ms ? 1 : (ms / a.duration), andPlay);
  2324. });
  2325. this._call("gotoPercent", arguments);
  2326. return this;
  2327. },
  2328. stop: function(/*boolean?*/ gotoEnd){
  2329. this._doAction("stop", arguments);
  2330. this._call("stop", arguments);
  2331. return this;
  2332. },
  2333. status: function(){
  2334. return this._pseudoAnimation.status();
  2335. },
  2336. destroy: function(){
  2337. arrayUtil.forEach(this._connects, connect.disconnect);
  2338. }
  2339. });
  2340. lang.extend(_combine, _baseObj);
  2341. coreFx.combine = /*===== dojo.fx.combine = =====*/ function(/*dojo.Animation[]*/ animations){
  2342. // summary:
  2343. // Combine a list of `dojo.Animation`s to run in parallel
  2344. //
  2345. // description:
  2346. // Combine an array of `dojo.Animation`s to run in parallel,
  2347. // providing a new `dojo.Animation` instance encompasing each
  2348. // animation, firing standard animation events.
  2349. //
  2350. // example:
  2351. // Fade out `node` while fading in `otherNode` simultaneously
  2352. // | dojo.fx.combine([
  2353. // | dojo.fadeIn({ node:node }),
  2354. // | dojo.fadeOut({ node:otherNode })
  2355. // | ]).play();
  2356. //
  2357. // example:
  2358. // When the longest animation ends, execute a function:
  2359. // | var anim = dojo.fx.combine([
  2360. // | dojo.fadeIn({ node: n, duration:700 }),
  2361. // | dojo.fadeOut({ node: otherNode, duration: 300 })
  2362. // | ]);
  2363. // | dojo.connect(anim, "onEnd", function(){
  2364. // | // overall animation is done.
  2365. // | });
  2366. // | anim.play(); // play the animation
  2367. //
  2368. return new _combine(animations); // dojo.Animation
  2369. };
  2370. coreFx.wipeIn = /*===== dojo.fx.wipeIn = =====*/ function(/*Object*/ args){
  2371. // summary:
  2372. // Expand a node to it's natural height.
  2373. //
  2374. // description:
  2375. // Returns an animation that will expand the
  2376. // node defined in 'args' object from it's current height to
  2377. // it's natural height (with no scrollbar).
  2378. // Node must have no margin/border/padding.
  2379. //
  2380. // args: Object
  2381. // A hash-map of standard `dojo.Animation` constructor properties
  2382. // (such as easing: node: duration: and so on)
  2383. //
  2384. // example:
  2385. // | dojo.fx.wipeIn({
  2386. // | node:"someId"
  2387. // | }).play()
  2388. var node = args.node = dom.byId(args.node), s = node.style, o;
  2389. var anim = baseFx.animateProperty(lang.mixin({
  2390. properties: {
  2391. height: {
  2392. // wrapped in functions so we wait till the last second to query (in case value has changed)
  2393. start: function(){
  2394. // start at current [computed] height, but use 1px rather than 0
  2395. // because 0 causes IE to display the whole panel
  2396. o = s.overflow;
  2397. s.overflow = "hidden";
  2398. if(s.visibility == "hidden" || s.display == "none"){
  2399. s.height = "1px";
  2400. s.display = "";
  2401. s.visibility = "";
  2402. return 1;
  2403. }else{
  2404. var height = domStyle.get(node, "height");
  2405. return Math.max(height, 1);
  2406. }
  2407. },
  2408. end: function(){
  2409. return node.scrollHeight;
  2410. }
  2411. }
  2412. }
  2413. }, args));
  2414. var fini = function(){
  2415. s.height = "auto";
  2416. s.overflow = o;
  2417. };
  2418. connect.connect(anim, "onStop", fini);
  2419. connect.connect(anim, "onEnd", fini);
  2420. return anim; // dojo.Animation
  2421. };
  2422. coreFx.wipeOut = /*===== dojo.fx.wipeOut = =====*/ function(/*Object*/ args){
  2423. // summary:
  2424. // Shrink a node to nothing and hide it.
  2425. //
  2426. // description:
  2427. // Returns an animation that will shrink node defined in "args"
  2428. // from it's current height to 1px, and then hide it.
  2429. //
  2430. // args: Object
  2431. // A hash-map of standard `dojo.Animation` constructor properties
  2432. // (such as easing: node: duration: and so on)
  2433. //
  2434. // example:
  2435. // | dojo.fx.wipeOut({ node:"someId" }).play()
  2436. var node = args.node = dom.byId(args.node), s = node.style, o;
  2437. var anim = baseFx.animateProperty(lang.mixin({
  2438. properties: {
  2439. height: {
  2440. end: 1 // 0 causes IE to display the whole panel
  2441. }
  2442. }
  2443. }, args));
  2444. connect.connect(anim, "beforeBegin", function(){
  2445. o = s.overflow;
  2446. s.overflow = "hidden";
  2447. s.display = "";
  2448. });
  2449. var fini = function(){
  2450. s.overflow = o;
  2451. s.height = "auto";
  2452. s.display = "none";
  2453. };
  2454. connect.connect(anim, "onStop", fini);
  2455. connect.connect(anim, "onEnd", fini);
  2456. return anim; // dojo.Animation
  2457. };
  2458. coreFx.slideTo = /*===== dojo.fx.slideTo = =====*/ function(/*Object*/ args){
  2459. // summary:
  2460. // Slide a node to a new top/left position
  2461. //
  2462. // description:
  2463. // Returns an animation that will slide "node"
  2464. // defined in args Object from its current position to
  2465. // the position defined by (args.left, args.top).
  2466. //
  2467. // args: Object
  2468. // A hash-map of standard `dojo.Animation` constructor properties
  2469. // (such as easing: node: duration: and so on). Special args members
  2470. // are `top` and `left`, which indicate the new position to slide to.
  2471. //
  2472. // example:
  2473. // | .slideTo({ node: node, left:"40", top:"50", units:"px" }).play()
  2474. var node = args.node = dom.byId(args.node),
  2475. top = null, left = null;
  2476. var init = (function(n){
  2477. return function(){
  2478. var cs = domStyle.getComputedStyle(n);
  2479. var pos = cs.position;
  2480. top = (pos == 'absolute' ? n.offsetTop : parseInt(cs.top) || 0);
  2481. left = (pos == 'absolute' ? n.offsetLeft : parseInt(cs.left) || 0);
  2482. if(pos != 'absolute' && pos != 'relative'){
  2483. var ret = geom.position(n, true);
  2484. top = ret.y;
  2485. left = ret.x;
  2486. n.style.position="absolute";
  2487. n.style.top=top+"px";
  2488. n.style.left=left+"px";
  2489. }
  2490. };
  2491. })(node);
  2492. init();
  2493. var anim = baseFx.animateProperty(lang.mixin({
  2494. properties: {
  2495. top: args.top || 0,
  2496. left: args.left || 0
  2497. }
  2498. }, args));
  2499. connect.connect(anim, "beforeBegin", anim, init);
  2500. return anim; // dojo.Animation
  2501. };
  2502. return coreFx;
  2503. });
  2504. },
  2505. 'dijit/_base':function(){
  2506. define("dijit/_base", [
  2507. ".",
  2508. "./a11y", // used to be in dijit/_base/manager
  2509. "./WidgetSet", // used to be in dijit/_base/manager
  2510. "./_base/focus",
  2511. "./_base/manager",
  2512. "./_base/place",
  2513. "./_base/popup",
  2514. "./_base/scroll",
  2515. "./_base/sniff",
  2516. "./_base/typematic",
  2517. "./_base/wai",
  2518. "./_base/window"
  2519. ], function(dijit){
  2520. // module:
  2521. // dijit/_base
  2522. // summary:
  2523. // Includes all the modules in dijit/_base
  2524. return dijit._base;
  2525. });
  2526. },
  2527. 'dojox/mobile/sniff':function(){
  2528. define("dojox/mobile/sniff", [
  2529. "dojo/_base/window",
  2530. "dojo/_base/sniff"
  2531. ], function(win, has){
  2532. var ua = navigator.userAgent;
  2533. // BlackBerry (OS 6 or later only)
  2534. has.add("bb", ua.indexOf("BlackBerry") >= 0 && parseFloat(ua.split("Version/")[1]) || undefined, undefined, true);
  2535. // Android
  2536. has.add("android", parseFloat(ua.split("Android ")[1]) || undefined, undefined, true);
  2537. // iPhone, iPod, or iPad
  2538. // If iPod or iPad is detected, in addition to has("ipod") or has("ipad"),
  2539. // has("iphone") will also have iOS version number.
  2540. if(ua.match(/(iPhone|iPod|iPad)/)){
  2541. var p = RegExp.$1.replace(/P/, 'p');
  2542. var v = ua.match(/OS ([\d_]+)/) ? RegExp.$1 : "1";
  2543. var os = parseFloat(v.replace(/_/, '.').replace(/_/g, ''));
  2544. has.add(p, os, undefined, true);
  2545. has.add("iphone", os, undefined, true);
  2546. }
  2547. if(has("webkit")){
  2548. has.add("touch", (typeof win.doc.documentElement.ontouchstart != "undefined" &&
  2549. navigator.appVersion.indexOf("Mobile") != -1) || !!has("android"), undefined, true);
  2550. }
  2551. return has;
  2552. });
  2553. },
  2554. 'dojox/mobile/ProgressIndicator':function(){
  2555. define([
  2556. "dojo/_base/config",
  2557. "dojo/_base/declare",
  2558. "dojo/dom-construct",
  2559. "dojo/dom-style",
  2560. "dojo/has"
  2561. ], function(config, declare, domConstruct, domStyle, has){
  2562. // module:
  2563. // dojox/mobile/ProgressIndicator
  2564. // summary:
  2565. // A progress indication widget.
  2566. var cls = declare("dojox.mobile.ProgressIndicator", null, {
  2567. // summary:
  2568. // A progress indication widget.
  2569. // description:
  2570. // ProgressIndicator is a round spinning graphical representation
  2571. // that indicates the current task is on-going.
  2572. // interval: Number
  2573. // The time interval in milliseconds for updating the spinning
  2574. // indicator.
  2575. interval: 100,
  2576. // colors: Array
  2577. // An array of indicator colors.
  2578. colors: [
  2579. "#C0C0C0", "#C0C0C0", "#C0C0C0", "#C0C0C0",
  2580. "#C0C0C0", "#C0C0C0", "#B8B9B8", "#AEAFAE",
  2581. "#A4A5A4", "#9A9A9A", "#8E8E8E", "#838383"
  2582. ],
  2583. constructor: function(){
  2584. this._bars = [];
  2585. this.domNode = domConstruct.create("DIV");
  2586. this.domNode.className = "mblProgContainer";
  2587. if(config["mblAndroidWorkaround"] !== false && has("android") >= 2.2 && has("android") < 3){
  2588. // workaround to avoid the side effects of the fixes for android screen flicker problem
  2589. domStyle.set(this.domNode, "webkitTransform", "translate3d(0,0,0)");
  2590. }
  2591. this.spinnerNode = domConstruct.create("DIV", null, this.domNode);
  2592. for(var i = 0; i < this.colors.length; i++){
  2593. var div = domConstruct.create("DIV", {className:"mblProg mblProg"+i}, this.spinnerNode);
  2594. this._bars.push(div);
  2595. }
  2596. },
  2597. start: function(){
  2598. // summary:
  2599. // Starts the ProgressIndicator spinning.
  2600. if(this.imageNode){
  2601. var img = this.imageNode;
  2602. var l = Math.round((this.domNode.offsetWidth - img.offsetWidth) / 2);
  2603. var t = Math.round((this.domNode.offsetHeight - img.offsetHeight) / 2);
  2604. img.style.margin = t+"px "+l+"px";
  2605. return;
  2606. }
  2607. var cntr = 0;
  2608. var _this = this;
  2609. var n = this.colors.length;
  2610. this.timer = setInterval(function(){
  2611. cntr--;
  2612. cntr = cntr < 0 ? n - 1 : cntr;
  2613. var c = _this.colors;
  2614. for(var i = 0; i < n; i++){
  2615. var idx = (cntr + i) % n;
  2616. _this._bars[i].style.backgroundColor = c[idx];
  2617. }
  2618. }, this.interval);
  2619. },
  2620. stop: function(){
  2621. // summary:
  2622. // Stops the ProgressIndicator spinning.
  2623. if(this.timer){
  2624. clearInterval(this.timer);
  2625. }
  2626. this.timer = null;
  2627. if(this.domNode.parentNode){
  2628. this.domNode.parentNode.removeChild(this.domNode);
  2629. }
  2630. },
  2631. setImage: function(/*String*/file){
  2632. // summary:
  2633. // Sets an indicator icon image file (typically animated GIF).
  2634. // If null is specified, restores the default spinner.
  2635. if(file){
  2636. this.imageNode = domConstruct.create("IMG", {src:file}, this.domNode);
  2637. this.spinnerNode.style.display = "none";
  2638. }else{
  2639. if(this.imageNode){
  2640. this.domNode.removeChild(this.imageNode);
  2641. this.imageNode = null;
  2642. }
  2643. this.spinnerNode.style.display = "";
  2644. }
  2645. }
  2646. });
  2647. cls._instance = null;
  2648. cls.getInstance = function(){
  2649. if(!cls._instance){
  2650. cls._instance = new cls();
  2651. }
  2652. return cls._instance;
  2653. };
  2654. return cls;
  2655. });
  2656. },
  2657. 'dijit/form/_FormWidgetMixin':function(){
  2658. define("dijit/form/_FormWidgetMixin", [
  2659. "dojo/_base/array", // array.forEach
  2660. "dojo/_base/declare", // declare
  2661. "dojo/dom-attr", // domAttr.set
  2662. "dojo/dom-style", // domStyle.get
  2663. "dojo/_base/lang", // lang.hitch lang.isArray
  2664. "dojo/mouse", // mouse.isLeft
  2665. "dojo/_base/sniff", // has("webkit")
  2666. "dojo/_base/window", // win.body
  2667. "dojo/window", // winUtils.scrollIntoView
  2668. "../a11y" // a11y.hasDefaultTabStop
  2669. ], function(array, declare, domAttr, domStyle, lang, mouse, has, win, winUtils, a11y){
  2670. // module:
  2671. // dijit/form/_FormWidgetMixin
  2672. // summary:
  2673. // Mixin for widgets corresponding to native HTML elements such as <checkbox> or <button>,
  2674. // which can be children of a <form> node or a `dijit.form.Form` widget.
  2675. return declare("dijit.form._FormWidgetMixin", null, {
  2676. // summary:
  2677. // Mixin for widgets corresponding to native HTML elements such as <checkbox> or <button>,
  2678. // which can be children of a <form> node or a `dijit.form.Form` widget.
  2679. //
  2680. // description:
  2681. // Represents a single HTML element.
  2682. // All these widgets should have these attributes just like native HTML input elements.
  2683. // You can set them during widget construction or afterwards, via `dijit._Widget.attr`.
  2684. //
  2685. // They also share some common methods.
  2686. // name: [const] String
  2687. // Name used when submitting form; same as "name" attribute or plain HTML elements
  2688. name: "",
  2689. // alt: String
  2690. // Corresponds to the native HTML <input> element's attribute.
  2691. alt: "",
  2692. // value: String
  2693. // Corresponds to the native HTML <input> element's attribute.
  2694. value: "",
  2695. // type: [const] String
  2696. // Corresponds to the native HTML <input> element's attribute.
  2697. type: "text",
  2698. // tabIndex: Integer
  2699. // Order fields are traversed when user hits the tab key
  2700. tabIndex: "0",
  2701. _setTabIndexAttr: "focusNode", // force copy even when tabIndex default value, needed since Button is <span>
  2702. // disabled: Boolean
  2703. // Should this widget respond to user input?
  2704. // In markup, this is specified as "disabled='disabled'", or just "disabled".
  2705. disabled: false,
  2706. // intermediateChanges: Boolean
  2707. // Fires onChange for each value change or only on demand
  2708. intermediateChanges: false,
  2709. // scrollOnFocus: Boolean
  2710. // On focus, should this widget scroll into view?
  2711. scrollOnFocus: true,
  2712. // Override _WidgetBase mapping id to this.domNode, needs to be on focusNode so <label> etc.
  2713. // works with screen reader
  2714. _setIdAttr: "focusNode",
  2715. _setDisabledAttr: function(/*Boolean*/ value){
  2716. this._set("disabled", value);
  2717. domAttr.set(this.focusNode, 'disabled', value);
  2718. if(this.valueNode){
  2719. domAttr.set(this.valueNode, 'disabled', value);
  2720. }
  2721. this.focusNode.setAttribute("aria-disabled", value ? "true" : "false");
  2722. if(value){
  2723. // reset these, because after the domNode is disabled, we can no longer receive
  2724. // mouse related events, see #4200
  2725. this._set("hovering", false);
  2726. this._set("active", false);
  2727. // clear tab stop(s) on this widget's focusable node(s) (ComboBox has two focusable nodes)
  2728. var attachPointNames = "tabIndex" in this.attributeMap ? this.attributeMap.tabIndex :
  2729. ("_setTabIndexAttr" in this) ? this._setTabIndexAttr : "focusNode";
  2730. array.forEach(lang.isArray(attachPointNames) ? attachPointNames : [attachPointNames], function(attachPointName){
  2731. var node = this[attachPointName];
  2732. // complex code because tabIndex=-1 on a <div> doesn't work on FF
  2733. if(has("webkit") || a11y.hasDefaultTabStop(node)){ // see #11064 about webkit bug
  2734. node.setAttribute('tabIndex', "-1");
  2735. }else{
  2736. node.removeAttribute('tabIndex');
  2737. }
  2738. }, this);
  2739. }else{
  2740. if(this.tabIndex != ""){
  2741. this.set('tabIndex', this.tabIndex);
  2742. }
  2743. }
  2744. },
  2745. _onFocus: function(/*String*/ by){
  2746. // If user clicks on the widget, even if the mouse is released outside of it,
  2747. // this widget's focusNode should get focus (to mimic native browser hehavior).
  2748. // Browsers often need help to make sure the focus via mouse actually gets to the focusNode.
  2749. if(by == "mouse" && this.isFocusable()){
  2750. // IE exhibits strange scrolling behavior when refocusing a node so only do it when !focused.
  2751. var focusConnector = this.connect(this.focusNode, "onfocus", function(){
  2752. this.disconnect(mouseUpConnector);
  2753. this.disconnect(focusConnector);
  2754. });
  2755. // Set a global event to handle mouseup, so it fires properly
  2756. // even if the cursor leaves this.domNode before the mouse up event.
  2757. var mouseUpConnector = this.connect(win.body(), "onmouseup", function(){
  2758. this.disconnect(mouseUpConnector);
  2759. this.disconnect(focusConnector);
  2760. // if here, then the mousedown did not focus the focusNode as the default action
  2761. if(this.focused){
  2762. this.focus();
  2763. }
  2764. });
  2765. }
  2766. if(this.scrollOnFocus){
  2767. this.defer(function(){ winUtils.scrollIntoView(this.domNode); }); // without defer, the input caret position can change on mouse click
  2768. }
  2769. this.inherited(arguments);
  2770. },
  2771. isFocusable: function(){
  2772. // summary:
  2773. // Tells if this widget is focusable or not. Used internally by dijit.
  2774. // tags:
  2775. // protected
  2776. return !this.disabled && this.focusNode && (domStyle.get(this.domNode, "display") != "none");
  2777. },
  2778. focus: function(){
  2779. // summary:
  2780. // Put focus on this widget
  2781. if(!this.disabled && this.focusNode.focus){
  2782. try{ this.focusNode.focus(); }catch(e){}/*squelch errors from hidden nodes*/
  2783. }
  2784. },
  2785. compare: function(/*anything*/ val1, /*anything*/ val2){
  2786. // summary:
  2787. // Compare 2 values (as returned by get('value') for this widget).
  2788. // tags:
  2789. // protected
  2790. if(typeof val1 == "number" && typeof val2 == "number"){
  2791. return (isNaN(val1) && isNaN(val2)) ? 0 : val1 - val2;
  2792. }else if(val1 > val2){
  2793. return 1;
  2794. }else if(val1 < val2){
  2795. return -1;
  2796. }else{
  2797. return 0;
  2798. }
  2799. },
  2800. onChange: function(/*===== newValue =====*/){
  2801. // summary:
  2802. // Callback when this widget's value is changed.
  2803. // tags:
  2804. // callback
  2805. },
  2806. // _onChangeActive: [private] Boolean
  2807. // Indicates that changes to the value should call onChange() callback.
  2808. // This is false during widget initialization, to avoid calling onChange()
  2809. // when the initial value is set.
  2810. _onChangeActive: false,
  2811. _handleOnChange: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
  2812. // summary:
  2813. // Called when the value of the widget is set. Calls onChange() if appropriate
  2814. // newValue:
  2815. // the new value
  2816. // priorityChange:
  2817. // For a slider, for example, dragging the slider is priorityChange==false,
  2818. // but on mouse up, it's priorityChange==true. If intermediateChanges==false,
  2819. // onChange is only called form priorityChange=true events.
  2820. // tags:
  2821. // private
  2822. if(this._lastValueReported == undefined && (priorityChange === null || !this._onChangeActive)){
  2823. // this block executes not for a change, but during initialization,
  2824. // and is used to store away the original value (or for ToggleButton, the original checked state)
  2825. this._resetValue = this._lastValueReported = newValue;
  2826. }
  2827. this._pendingOnChange = this._pendingOnChange
  2828. || (typeof newValue != typeof this._lastValueReported)
  2829. || (this.compare(newValue, this._lastValueReported) != 0);
  2830. if((this.intermediateChanges || priorityChange || priorityChange === undefined) && this._pendingOnChange){
  2831. this._lastValueReported = newValue;
  2832. this._pendingOnChange = false;
  2833. if(this._onChangeActive){
  2834. if(this._onChangeHandle){
  2835. this._onChangeHandle.remove();
  2836. }
  2837. // defer allows hidden value processing to run and
  2838. // also the onChange handler can safely adjust focus, etc
  2839. this._onChangeHandle = this.defer(
  2840. function(){
  2841. this._onChangeHandle = null;
  2842. this.onChange(newValue);
  2843. }); // try to collapse multiple onChange's fired faster than can be processed
  2844. }
  2845. }
  2846. },
  2847. create: function(){
  2848. // Overrides _Widget.create()
  2849. this.inherited(arguments);
  2850. this._onChangeActive = true;
  2851. },
  2852. destroy: function(){
  2853. if(this._onChangeHandle){ // destroy called before last onChange has fired
  2854. this._onChangeHandle.remove();
  2855. this.onChange(this._lastValueReported);
  2856. }
  2857. this.inherited(arguments);
  2858. }
  2859. });
  2860. });
  2861. },
  2862. 'dijit/BackgroundIframe':function(){
  2863. define("dijit/BackgroundIframe", [
  2864. "require", // require.toUrl
  2865. ".", // to export dijit.BackgroundIframe
  2866. "dojo/_base/config",
  2867. "dojo/dom-construct", // domConstruct.create
  2868. "dojo/dom-style", // domStyle.set
  2869. "dojo/_base/lang", // lang.extend lang.hitch
  2870. "dojo/on",
  2871. "dojo/_base/sniff", // has("ie"), has("mozilla"), has("quirks")
  2872. "dojo/_base/window" // win.doc.createElement
  2873. ], function(require, dijit, config, domConstruct, domStyle, lang, on, has, win){
  2874. // module:
  2875. // dijit/BackgroundIFrame
  2876. // Flag for whether to create background iframe behind popups like Menus and Dialog.
  2877. // A background iframe is useful to prevent problems with popups appearing behind applets/pdf files,
  2878. // and is also useful on older versions of IE (IE6 and IE7) to prevent the "bleed through select" problem.
  2879. // TODO: For 2.0, make this false by default. Also, possibly move definition to has.js so that this module can be
  2880. // conditionally required via dojo/has!bgIfame?dijit/BackgroundIframe
  2881. has.add("bgIframe", has("ie") || has("mozilla"));
  2882. // summary:
  2883. // new dijit.BackgroundIframe(node)
  2884. // Makes a background iframe as a child of node, that fills
  2885. // area (and position) of node
  2886. // TODO: remove _frames, it isn't being used much, since popups never release their
  2887. // iframes (see [22236])
  2888. var _frames = new function(){
  2889. // summary:
  2890. // cache of iframes
  2891. var queue = [];
  2892. this.pop = function(){
  2893. var iframe;
  2894. if(queue.length){
  2895. iframe = queue.pop();
  2896. iframe.style.display="";
  2897. }else{
  2898. if(has("ie") < 9){
  2899. var burl = config["dojoBlankHtmlUrl"] || require.toUrl("dojo/resources/blank.html") || "javascript:\"\"";
  2900. var html="<iframe src='" + burl + "' role='presentation'"
  2901. + " style='position: absolute; left: 0px; top: 0px;"
  2902. + "z-index: -1; filter:Alpha(Opacity=\"0\");'>";
  2903. iframe = win.doc.createElement(html);
  2904. }else{
  2905. iframe = domConstruct.create("iframe");
  2906. iframe.src = 'javascript:""';
  2907. iframe.className = "dijitBackgroundIframe";
  2908. iframe.setAttribute("role", "presentation");
  2909. domStyle.set(iframe, "opacity", 0.1);
  2910. }
  2911. iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didn't work.
  2912. }
  2913. return iframe;
  2914. };
  2915. this.push = function(iframe){
  2916. iframe.style.display="none";
  2917. queue.push(iframe);
  2918. }
  2919. }();
  2920. dijit.BackgroundIframe = function(/*DomNode*/ node){
  2921. // summary:
  2922. // For IE/FF z-index schenanigans. id attribute is required.
  2923. //
  2924. // description:
  2925. // new dijit.BackgroundIframe(node)
  2926. // Makes a background iframe as a child of node, that fills
  2927. // area (and position) of node
  2928. if(!node.id){ throw new Error("no id"); }
  2929. if(has("bgIframe")){
  2930. var iframe = (this.iframe = _frames.pop());
  2931. node.appendChild(iframe);
  2932. if(has("ie")<7 || has("quirks")){
  2933. this.resize(node);
  2934. this._conn = on(node, 'resize', lang.hitch(this, function(){
  2935. this.resize(node);
  2936. }));
  2937. }else{
  2938. domStyle.set(iframe, {
  2939. width: '100%',
  2940. height: '100%'
  2941. });
  2942. }
  2943. }
  2944. };
  2945. lang.extend(dijit.BackgroundIframe, {
  2946. resize: function(node){
  2947. // summary:
  2948. // Resize the iframe so it's the same size as node.
  2949. // Needed on IE6 and IE/quirks because height:100% doesn't work right.
  2950. if(this.iframe){
  2951. domStyle.set(this.iframe, {
  2952. width: node.offsetWidth + 'px',
  2953. height: node.offsetHeight + 'px'
  2954. });
  2955. }
  2956. },
  2957. destroy: function(){
  2958. // summary:
  2959. // destroy the iframe
  2960. if(this._conn){
  2961. this._conn.remove();
  2962. this._conn = null;
  2963. }
  2964. if(this.iframe){
  2965. _frames.push(this.iframe);
  2966. delete this.iframe;
  2967. }
  2968. }
  2969. });
  2970. return dijit.BackgroundIframe;
  2971. });
  2972. },
  2973. 'dojox/mobile':function(){
  2974. define([
  2975. ".",
  2976. "dojo/_base/lang",
  2977. "dojox/mobile/_base"
  2978. ], function(dojox, lang, base){
  2979. lang.getObject("mobile", true, dojox);
  2980. return dojox.mobile;
  2981. });
  2982. },
  2983. 'dijit/form/_FormValueMixin':function(){
  2984. define("dijit/form/_FormValueMixin", [
  2985. "dojo/_base/declare", // declare
  2986. "dojo/dom-attr", // domAttr.set
  2987. "dojo/keys", // keys.ESCAPE
  2988. "dojo/_base/sniff", // has("ie"), has("quirks")
  2989. "./_FormWidgetMixin"
  2990. ], function(declare, domAttr, keys, has, _FormWidgetMixin){
  2991. /*=====
  2992. var _FormWidgetMixin = dijit.form._FormWidgetMixin;
  2993. =====*/
  2994. // module:
  2995. // dijit/form/_FormValueMixin
  2996. // summary:
  2997. // Mixin for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values.
  2998. return declare("dijit.form._FormValueMixin", _FormWidgetMixin, {
  2999. // summary:
  3000. // Mixin for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values.
  3001. // description:
  3002. // Each _FormValueMixin represents a single input value, and has a (possibly hidden) <input> element,
  3003. // to which it serializes it's input value, so that form submission (either normal submission or via FormBind?)
  3004. // works as expected.
  3005. // readOnly: Boolean
  3006. // Should this widget respond to user input?
  3007. // In markup, this is specified as "readOnly".
  3008. // Similar to disabled except readOnly form values are submitted.
  3009. readOnly: false,
  3010. _setReadOnlyAttr: function(/*Boolean*/ value){
  3011. domAttr.set(this.focusNode, 'readOnly', value);
  3012. this._set("readOnly", value);
  3013. },
  3014. postCreate: function(){
  3015. this.inherited(arguments);
  3016. if(has("ie")){ // IE won't stop the event with keypress
  3017. this.connect(this.focusNode || this.domNode, "onkeydown", this._onKeyDown);
  3018. }
  3019. // Update our reset value if it hasn't yet been set (because this.set()
  3020. // is only called when there *is* a value)
  3021. if(this._resetValue === undefined){
  3022. this._lastValueReported = this._resetValue = this.value;
  3023. }
  3024. },
  3025. _setValueAttr: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
  3026. // summary:
  3027. // Hook so set('value', value) works.
  3028. // description:
  3029. // Sets the value of the widget.
  3030. // If the value has changed, then fire onChange event, unless priorityChange
  3031. // is specified as null (or false?)
  3032. this._handleOnChange(newValue, priorityChange);
  3033. },
  3034. _handleOnChange: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
  3035. // summary:
  3036. // Called when the value of the widget has changed. Saves the new value in this.value,
  3037. // and calls onChange() if appropriate. See _FormWidget._handleOnChange() for details.
  3038. this._set("value", newValue);
  3039. this.inherited(arguments);
  3040. },
  3041. undo: function(){
  3042. // summary:
  3043. // Restore the value to the last value passed to onChange
  3044. this._setValueAttr(this._lastValueReported, false);
  3045. },
  3046. reset: function(){
  3047. // summary:
  3048. // Reset the widget's value to what it was at initialization time
  3049. this._hasBeenBlurred = false;
  3050. this._setValueAttr(this._resetValue, true);
  3051. },
  3052. _onKeyDown: function(e){
  3053. if(e.keyCode == keys.ESCAPE && !(e.ctrlKey || e.altKey || e.metaKey)){
  3054. var te;
  3055. if(has("ie") < 9 || (has("ie") && has("quirks"))){
  3056. e.preventDefault(); // default behavior needs to be stopped here since keypress is too late
  3057. te = document.createEventObject();
  3058. te.keyCode = keys.ESCAPE;
  3059. te.shiftKey = e.shiftKey;
  3060. e.srcElement.fireEvent('onkeypress', te);
  3061. }
  3062. }
  3063. }
  3064. });
  3065. });
  3066. },
  3067. 'dojox/mobile/common':function(){
  3068. define("dojox/mobile/common", [
  3069. "dojo/_base/kernel", // to test dojo.hash
  3070. "dojo/_base/array",
  3071. "dojo/_base/config",
  3072. "dojo/_base/connect",
  3073. "dojo/_base/lang",
  3074. "dojo/_base/window",
  3075. "dojo/dom-class",
  3076. "dojo/dom-construct",
  3077. "dojo/dom-style",
  3078. // "dojo/hash", // optionally prereq'ed
  3079. "dojo/ready",
  3080. "dijit/registry", // registry.toArray
  3081. "./sniff",
  3082. "./uacss"
  3083. ], function(dojo, array, config, connect, lang, win, domClass, domConstruct, domStyle, ready, registry, has, uacss){
  3084. var dm = lang.getObject("dojox.mobile", true);
  3085. /*=====
  3086. var dm = dojox.mobile;
  3087. =====*/
  3088. // module:
  3089. // dojox/mobile/common
  3090. // summary:
  3091. // A common module for dojox.mobile.
  3092. // description:
  3093. // This module includes common utility functions that are used by
  3094. // dojox.mobile widgets. Also, it provides functions that are commonly
  3095. // necessary for mobile web applications, such as the hide address bar
  3096. // function.
  3097. dm.getScreenSize = function(){
  3098. // summary:
  3099. // Returns the dimensions of the browser window.
  3100. return {
  3101. h: win.global.innerHeight || win.doc.documentElement.clientHeight,
  3102. w: win.global.innerWidth || win.doc.documentElement.clientWidth
  3103. };
  3104. };
  3105. dm.updateOrient = function(){
  3106. // summary:
  3107. // Updates the orientation specific css classes, 'dj_portrait' and
  3108. // 'dj_landscape'.
  3109. var dim = dm.getScreenSize();
  3110. domClass.replace(win.doc.documentElement,
  3111. dim.h > dim.w ? "dj_portrait" : "dj_landscape",
  3112. dim.h > dim.w ? "dj_landscape" : "dj_portrait");
  3113. };
  3114. dm.updateOrient();
  3115. dm.tabletSize = 500;
  3116. dm.detectScreenSize = function(/*Boolean?*/force){
  3117. // summary:
  3118. // Detects the screen size and determines if the screen is like
  3119. // phone or like tablet. If the result is changed,
  3120. // it sets either of the following css class to <html>
  3121. // - 'dj_phone'
  3122. // - 'dj_tablet'
  3123. // and it publishes either of the following events.
  3124. // - '/dojox/mobile/screenSize/phone'
  3125. // - '/dojox/mobile/screenSize/tablet'
  3126. var dim = dm.getScreenSize();
  3127. var sz = Math.min(dim.w, dim.h);
  3128. var from, to;
  3129. if(sz >= dm.tabletSize && (force || (!this._sz || this._sz < dm.tabletSize))){
  3130. from = "phone";
  3131. to = "tablet";
  3132. }else if(sz < dm.tabletSize && (force || (!this._sz || this._sz >= dm.tabletSize))){
  3133. from = "tablet";
  3134. to = "phone";
  3135. }
  3136. if(to){
  3137. domClass.replace(win.doc.documentElement, "dj_"+to, "dj_"+from);
  3138. connect.publish("/dojox/mobile/screenSize/"+to, [dim]);
  3139. }
  3140. this._sz = sz;
  3141. };
  3142. dm.detectScreenSize();
  3143. dm.setupIcon = function(/*DomNode*/iconNode, /*String*/iconPos){
  3144. // summary:
  3145. // Sets up CSS sprite for a foreground image.
  3146. if(iconNode && iconPos){
  3147. var arr = array.map(iconPos.split(/[ ,]/),function(item){return item-0});
  3148. var t = arr[0]; // top
  3149. var r = arr[1] + arr[2]; // right
  3150. var b = arr[0] + arr[3]; // bottom
  3151. var l = arr[1]; // left
  3152. domStyle.set(iconNode, {
  3153. clip: "rect("+t+"px "+r+"px "+b+"px "+l+"px)",
  3154. top: (iconNode.parentNode ? domStyle.get(iconNode, "top") : 0) - t + "px",
  3155. left: -l + "px"
  3156. });
  3157. }
  3158. };
  3159. // dojox.mobile.hideAddressBarWait: Number
  3160. // The time in milliseconds to wait before the fail-safe hiding address
  3161. // bar runs. The value must be larger than 800.
  3162. dm.hideAddressBarWait = typeof(config["mblHideAddressBarWait"]) === "number" ?
  3163. config["mblHideAddressBarWait"] : 1500;
  3164. dm.hide_1 = function(force){
  3165. // summary:
  3166. // Internal function to hide the address bar.
  3167. scrollTo(0, 1);
  3168. var h = dm.getScreenSize().h + "px";
  3169. if(has("android")){
  3170. if(force){
  3171. win.body().style.minHeight = h;
  3172. }
  3173. dm.resizeAll();
  3174. }else{
  3175. if(force || dm._h === h && h !== win.body().style.minHeight){
  3176. win.body().style.minHeight = h;
  3177. dm.resizeAll();
  3178. }
  3179. }
  3180. dm._h = h;
  3181. };
  3182. dm.hide_fs = function(){
  3183. // summary:
  3184. // Internal function to hide the address bar for fail-safe.
  3185. // description:
  3186. // Resets the height of the body, performs hiding the address
  3187. // bar, and calls resizeAll().
  3188. // This is for fail-safe, in case of failure to complete the
  3189. // address bar hiding in time.
  3190. var t = win.body().style.minHeight;
  3191. win.body().style.minHeight = (dm.getScreenSize().h * 2) + "px"; // to ensure enough height for scrollTo to work
  3192. scrollTo(0, 1);
  3193. setTimeout(function(){
  3194. dm.hide_1(1);
  3195. dm._hiding = false;
  3196. }, 1000);
  3197. };
  3198. dm.hideAddressBar = function(/*Event?*/evt){
  3199. // summary:
  3200. // Hides the address bar.
  3201. // description:
  3202. // Tries hiding of the address bar a couple of times to do it as
  3203. // quick as possible while ensuring resize is done after the hiding
  3204. // finishes.
  3205. if(dm.disableHideAddressBar || dm._hiding){ return; }
  3206. dm._hiding = true;
  3207. dm._h = 0;
  3208. win.body().style.minHeight = (dm.getScreenSize().h * 2) + "px"; // to ensure enough height for scrollTo to work
  3209. setTimeout(dm.hide_1, 0);
  3210. setTimeout(dm.hide_1, 200);
  3211. setTimeout(dm.hide_1, 800);
  3212. setTimeout(dm.hide_fs, dm.hideAddressBarWait);
  3213. };
  3214. dm.resizeAll = function(/*Event?*/evt, /*Widget?*/root){
  3215. // summary:
  3216. // Call the resize() method of all the top level resizable widgets.
  3217. // description:
  3218. // Find all widgets that do not have a parent or the parent does not
  3219. // have the resize() method, and call resize() for them.
  3220. // If a widget has a parent that has resize(), call of the widget's
  3221. // resize() is its parent's responsibility.
  3222. // evt:
  3223. // Native event object
  3224. // root:
  3225. // If specified, search the specified widget recursively for top level
  3226. // resizable widgets.
  3227. // root.resize() is always called regardless of whether root is a
  3228. // top level widget or not.
  3229. // If omitted, search the entire page.
  3230. if(dm.disableResizeAll){ return; }
  3231. connect.publish("/dojox/mobile/resizeAll", [evt, root]);
  3232. dm.updateOrient();
  3233. dm.detectScreenSize();
  3234. var isTopLevel = function(w){
  3235. var parent = w.getParent && w.getParent();
  3236. return !!((!parent || !parent.resize) && w.resize);
  3237. };
  3238. var resizeRecursively = function(w){
  3239. array.forEach(w.getChildren(), function(child){
  3240. if(isTopLevel(child)){ child.resize(); }
  3241. resizeRecursively(child);
  3242. });
  3243. };
  3244. if(root){
  3245. if(root.resize){ root.resize(); }
  3246. resizeRecursively(root);
  3247. }else{
  3248. array.forEach(array.filter(registry.toArray(), isTopLevel),
  3249. function(w){ w.resize(); });
  3250. }
  3251. };
  3252. dm.openWindow = function(url, target){
  3253. // summary:
  3254. // Opens a new browser window with the given url.
  3255. win.global.open(url, target || "_blank");
  3256. };
  3257. dm.createDomButton = function(/*DomNode*/refNode, /*Object?*/style, /*DomNode?*/toNode){
  3258. // summary:
  3259. // Creates a DOM button.
  3260. // description:
  3261. // DOM button is a simple graphical object that consists of one or
  3262. // more nested DIV elements with some CSS styling. It can be used
  3263. // in place of an icon image on ListItem, IconItem, and so on.
  3264. // The kind of DOM button to create is given as a class name of
  3265. // refNode. The number of DIVs to create is searched from the style
  3266. // sheets in the page. However, if the class name has a suffix that
  3267. // starts with an underscore, like mblDomButtonGoldStar_5, then the
  3268. // suffixed number is used instead. A class name for DOM button
  3269. // must starts with 'mblDomButton'.
  3270. // refNode:
  3271. // A node that has a DOM button class name.
  3272. // style:
  3273. // A hash object to set styles to the node.
  3274. // toNode:
  3275. // A root node to create a DOM button. If omitted, refNode is used.
  3276. if(!dm._domButtons){
  3277. if(has("webkit")){
  3278. var findDomButtons = function(sheet, dic){
  3279. // summary:
  3280. // Searches the style sheets for DOM buttons.
  3281. // description:
  3282. // Returns a key-value pair object whose keys are DOM
  3283. // button class names and values are the number of DOM
  3284. // elements they need.
  3285. var i, j;
  3286. if(!sheet){
  3287. var dic = {};
  3288. var ss = dojo.doc.styleSheets;
  3289. for (i = 0; i < ss.length; i++){
  3290. ss[i] && findDomButtons(ss[i], dic);
  3291. }
  3292. return dic;
  3293. }
  3294. var rules = sheet.cssRules || [];
  3295. for (i = 0; i < rules.length; i++){
  3296. var rule = rules[i];
  3297. if(rule.href && rule.styleSheet){
  3298. findDomButtons(rule.styleSheet, dic);
  3299. }else if(rule.selectorText){
  3300. var sels = rule.selectorText.split(/,/);
  3301. for (j = 0; j < sels.length; j++){
  3302. var sel = sels[j];
  3303. var n = sel.split(/>/).length - 1;
  3304. if(sel.match(/(mblDomButton\w+)/)){
  3305. var cls = RegExp.$1;
  3306. if(!dic[cls] || n > dic[cls]){
  3307. dic[cls] = n;
  3308. }
  3309. }
  3310. }
  3311. }
  3312. }
  3313. }
  3314. dm._domButtons = findDomButtons();
  3315. }else{
  3316. dm._domButtons = {};
  3317. }
  3318. }
  3319. var s = refNode.className;
  3320. var node = toNode || refNode;
  3321. if(s.match(/(mblDomButton\w+)/) && s.indexOf("/") === -1){
  3322. var btnClass = RegExp.$1;
  3323. var nDiv = 4;
  3324. if(s.match(/(mblDomButton\w+_(\d+))/)){
  3325. nDiv = RegExp.$2 - 0;
  3326. }else if(dm._domButtons[btnClass] !== undefined){
  3327. nDiv = dm._domButtons[btnClass];
  3328. }
  3329. var props = null;
  3330. if(has("bb") && config["mblBBBoxShadowWorkaround"] !== false){
  3331. // Removes box-shadow because BlackBerry incorrectly renders it.
  3332. props = {style:"-webkit-box-shadow:none"};
  3333. }
  3334. for(var i = 0, p = node; i < nDiv; i++){
  3335. p = p.firstChild || domConstruct.create("DIV", props, p);
  3336. }
  3337. if(toNode){
  3338. setTimeout(function(){
  3339. domClass.remove(refNode, btnClass);
  3340. }, 0);
  3341. domClass.add(toNode, btnClass);
  3342. }
  3343. }else if(s.indexOf(".") !== -1){ // file name
  3344. domConstruct.create("IMG", {src:s}, node);
  3345. }else{
  3346. return null;
  3347. }
  3348. domClass.add(node, "mblDomButton");
  3349. if(config["mblAndroidWorkaround"] !== false && has("android") >= 2.2){
  3350. // Android workaround for the issue that domButtons' -webkit-transform styles sometimes invalidated
  3351. // by applying -webkit-transform:translated3d(x,y,z) style programmatically to non-ancestor elements,
  3352. // which results in breaking domButtons.
  3353. domStyle.set(node, "webkitTransform", "translate3d(0,0,0)");
  3354. }
  3355. !!style && domStyle.set(node, style);
  3356. return node;
  3357. };
  3358. dm.createIcon = function(/*String*/icon, /*String*/iconPos, /*DomNode*/node, /*String?*/title, /*DomNode?*/parent){
  3359. // summary:
  3360. // Creates or updates an icon node
  3361. // description:
  3362. // If node exists, updates the existing node. Otherwise, creates a new one.
  3363. // icon:
  3364. // Path for an image, or DOM button class name.
  3365. if(icon && icon.indexOf("mblDomButton") === 0){
  3366. // DOM button
  3367. if(node && node.className.match(/(mblDomButton\w+)/)){
  3368. domClass.remove(node, RegExp.$1);
  3369. }else{
  3370. node = domConstruct.create("DIV");
  3371. }
  3372. node.title = title;
  3373. domClass.add(node, icon);
  3374. dm.createDomButton(node);
  3375. }else if(icon && icon !== "none"){
  3376. // Image
  3377. if(!node || node.nodeName !== "IMG"){
  3378. node = domConstruct.create("IMG", {
  3379. alt: title
  3380. });
  3381. }
  3382. node.src = (icon || "").replace("${theme}", dm.currentTheme);
  3383. dm.setupIcon(node, iconPos);
  3384. if(parent && iconPos){
  3385. var arr = iconPos.split(/[ ,]/);
  3386. domStyle.set(parent, {
  3387. width: arr[2] + "px",
  3388. height: arr[3] + "px"
  3389. });
  3390. }
  3391. }
  3392. if(parent){
  3393. parent.appendChild(node);
  3394. }
  3395. return node;
  3396. };
  3397. // flag for iphone flicker workaround
  3398. dm._iw = config["mblIosWorkaround"] !== false && has("iphone");
  3399. if(dm._iw){
  3400. dm._iwBgCover = domConstruct.create("div"); // Cover to hide flicker in the background
  3401. }
  3402. if(config.parseOnLoad){
  3403. ready(90, function(){
  3404. // avoid use of query
  3405. /*
  3406. var list = query('[lazy=true] [dojoType]', null);
  3407. list.forEach(function(node, index, nodeList){
  3408. node.setAttribute("__dojoType", node.getAttribute("dojoType"));
  3409. node.removeAttribute("dojoType");
  3410. });
  3411. */
  3412. var nodes = win.body().getElementsByTagName("*");
  3413. var i, len, s;
  3414. len = nodes.length;
  3415. for(i = 0; i < len; i++){
  3416. s = nodes[i].getAttribute("dojoType");
  3417. if(s){
  3418. if(nodes[i].parentNode.getAttribute("lazy") == "true"){
  3419. nodes[i].setAttribute("__dojoType", s);
  3420. nodes[i].removeAttribute("dojoType");
  3421. }
  3422. }
  3423. }
  3424. });
  3425. }
  3426. ready(function(){
  3427. dm.detectScreenSize(true);
  3428. if(config["mblApplyPageStyles"] !== false){
  3429. domClass.add(win.doc.documentElement, "mobile");
  3430. }
  3431. if(has("chrome")){
  3432. // dojox.mobile does not load uacss (only _compat does), but we need dj_chrome.
  3433. domClass.add(win.doc.documentElement, "dj_chrome");
  3434. }
  3435. if(config["mblAndroidWorkaround"] !== false && has("android") >= 2.2){ // workaround for android screen flicker problem
  3436. if(config["mblAndroidWorkaroundButtonStyle"] !== false){
  3437. // workaround to avoid buttons disappear due to the side-effect of the webkitTransform workaroud below
  3438. domConstruct.create("style", {innerHTML:"BUTTON,INPUT[type='button'],INPUT[type='submit'],INPUT[type='reset'],INPUT[type='file']::-webkit-file-upload-button{-webkit-appearance:none;}"}, win.doc.head, "first");
  3439. }
  3440. if(has("android") < 3){ // for Android 2.2.x and 2.3.x
  3441. domStyle.set(win.doc.documentElement, "webkitTransform", "translate3d(0,0,0)");
  3442. // workaround for auto-scroll issue when focusing input fields
  3443. connect.connect(null, "onfocus", null, function(e){
  3444. domStyle.set(win.doc.documentElement, "webkitTransform", "");
  3445. });
  3446. connect.connect(null, "onblur", null, function(e){
  3447. domStyle.set(win.doc.documentElement, "webkitTransform", "translate3d(0,0,0)");
  3448. });
  3449. }else{ // for Android 3.x
  3450. if(config["mblAndroid3Workaround"] !== false){
  3451. domStyle.set(win.doc.documentElement, {
  3452. webkitBackfaceVisibility: "hidden",
  3453. webkitPerspective: 8000
  3454. });
  3455. }
  3456. }
  3457. }
  3458. // You can disable hiding the address bar with the following djConfig.
  3459. // var djConfig = { mblHideAddressBar: false };
  3460. var f = dm.resizeAll;
  3461. if(config["mblHideAddressBar"] !== false &&
  3462. navigator.appVersion.indexOf("Mobile") != -1 ||
  3463. config["mblForceHideAddressBar"] === true){
  3464. dm.hideAddressBar();
  3465. if(config["mblAlwaysHideAddressBar"] === true){
  3466. f = dm.hideAddressBar;
  3467. }
  3468. }
  3469. connect.connect(null, (win.global.onorientationchange !== undefined && !has("android"))
  3470. ? "onorientationchange" : "onresize", null, f);
  3471. // avoid use of query
  3472. /*
  3473. var list = query('[__dojoType]', null);
  3474. list.forEach(function(node, index, nodeList){
  3475. node.setAttribute("dojoType", node.getAttribute("__dojoType"));
  3476. node.removeAttribute("__dojoType");
  3477. });
  3478. */
  3479. var nodes = win.body().getElementsByTagName("*");
  3480. var i, len = nodes.length, s;
  3481. for(i = 0; i < len; i++){
  3482. s = nodes[i].getAttribute("__dojoType");
  3483. if(s){
  3484. nodes[i].setAttribute("dojoType", s);
  3485. nodes[i].removeAttribute("__dojoType");
  3486. }
  3487. }
  3488. if(dojo.hash){
  3489. // find widgets under root recursively
  3490. var findWidgets = function(root){
  3491. if(!root){ return []; }
  3492. var arr = registry.findWidgets(root);
  3493. var widgets = arr;
  3494. for(var i = 0; i < widgets.length; i++){
  3495. arr = arr.concat(findWidgets(widgets[i].containerNode));
  3496. }
  3497. return arr;
  3498. };
  3499. connect.subscribe("/dojo/hashchange", null, function(value){
  3500. var view = dm.currentView;
  3501. if(!view){ return; }
  3502. var params = dm._params;
  3503. if(!params){ // browser back/forward button was pressed
  3504. var moveTo = value ? value : dm._defaultView.id;
  3505. var widgets = findWidgets(view.domNode);
  3506. var dir = 1, transition = "slide";
  3507. for(i = 0; i < widgets.length; i++){
  3508. var w = widgets[i];
  3509. if("#"+moveTo == w.moveTo){
  3510. // found a widget that has the given moveTo
  3511. transition = w.transition;
  3512. dir = (w instanceof dm.Heading) ? -1 : 1;
  3513. break;
  3514. }
  3515. }
  3516. params = [ moveTo, dir, transition ];
  3517. }
  3518. view.performTransition.apply(view, params);
  3519. dm._params = null;
  3520. });
  3521. }
  3522. win.body().style.visibility = "visible";
  3523. });
  3524. // To search _parentNode first. TODO:1.8 reconsider this redefinition.
  3525. registry.getEnclosingWidget = function(node){
  3526. while(node){
  3527. var id = node.getAttribute && node.getAttribute("widgetId");
  3528. if(id){
  3529. return registry.byId(id);
  3530. }
  3531. node = node._parentNode || node.parentNode;
  3532. }
  3533. return null;
  3534. };
  3535. return dm;
  3536. });
  3537. },
  3538. 'dojox/mobile/Heading':function(){
  3539. define([
  3540. "dojo/_base/array",
  3541. "dojo/_base/connect",
  3542. "dojo/_base/declare",
  3543. "dojo/_base/lang",
  3544. "dojo/_base/window",
  3545. "dojo/dom-class",
  3546. "dojo/dom-construct",
  3547. "dojo/dom-style",
  3548. "dijit/registry", // registry.byId
  3549. "dijit/_Contained",
  3550. "dijit/_Container",
  3551. "dijit/_WidgetBase",
  3552. "./View"
  3553. ], function(array, connect, declare, lang, win, domClass, domConstruct, domStyle, registry, Contained, Container, WidgetBase, View){
  3554. var dm = lang.getObject("dojox.mobile", true);
  3555. /*=====
  3556. var Contained = dijit._Contained;
  3557. var Container = dijit._Container;
  3558. var WidgetBase = dijit._WidgetBase;
  3559. =====*/
  3560. // module:
  3561. // dojox/mobile/Heading
  3562. // summary:
  3563. // A widget that represents a navigation bar.
  3564. return declare("dojox.mobile.Heading", [WidgetBase, Container, Contained],{
  3565. // summary:
  3566. // A widget that represents a navigation bar.
  3567. // description:
  3568. // Heading is a widget that represents a navigation bar, which
  3569. // usually appears at the top of an application. It usually
  3570. // displays the title of the current view and can contain a
  3571. // navigational control. If you use it with
  3572. // dojox.mobile.ScrollableView, it can also be used as a fixed
  3573. // header bar or a fixed footer bar. In such cases, specify the
  3574. // fixed="top" attribute to be a fixed header bar or the
  3575. // fixed="bottom" attribute to be a fixed footer bar. Heading can
  3576. // have one or more ToolBarButton widgets as its children.
  3577. // back: String
  3578. // A label for the navigational control to return to the previous
  3579. // View.
  3580. back: "",
  3581. // href: String
  3582. // A URL to open when the navigational control is pressed.
  3583. href: "",
  3584. // moveTo: String
  3585. // The id of the transition destination view which resides in the
  3586. // current page.
  3587. //
  3588. // If the value has a hash sign ('#') before the id (e.g. #view1)
  3589. // and the dojo.hash module is loaded by the user application, the
  3590. // view transition updates the hash in the browser URL so that the
  3591. // user can bookmark the destination view. In this case, the user
  3592. // can also use the browser's back/forward button to navigate
  3593. // through the views in the browser history.
  3594. //
  3595. // If null, transitions to a blank view.
  3596. // If '#', returns immediately without transition.
  3597. moveTo: "",
  3598. // transition: String
  3599. // A type of animated transition effect. You can choose from the
  3600. // standard transition types, "slide", "fade", "flip", or from the
  3601. // extended transition types, "cover", "coverv", "dissolve",
  3602. // "reveal", "revealv", "scaleIn", "scaleOut", "slidev",
  3603. // "swirl", "zoomIn", "zoomOut". If "none" is specified, transition
  3604. // occurs immediately without animation.
  3605. transition: "slide",
  3606. // label: String
  3607. // A title text of the heading. If the label is not specified, the
  3608. // innerHTML of the node is used as a label.
  3609. label: "",
  3610. // iconBase: String
  3611. // The default icon path for child items.
  3612. iconBase: "",
  3613. // backProp: Object
  3614. // Properties for the back button.
  3615. backProp: {className: "mblArrowButton"},
  3616. // tag: String
  3617. // A name of html tag to create as domNode.
  3618. tag: "H1",
  3619. buildRendering: function(){
  3620. this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement(this.tag);
  3621. this.domNode.className = "mblHeading";
  3622. if(!this.label){
  3623. array.forEach(this.domNode.childNodes, function(n){
  3624. if(n.nodeType == 3){
  3625. var v = lang.trim(n.nodeValue);
  3626. if(v){
  3627. this.label = v;
  3628. this.labelNode = domConstruct.create("SPAN", {innerHTML:v}, n, "replace");
  3629. }
  3630. }
  3631. }, this);
  3632. }
  3633. if(!this.labelNode){
  3634. this.labelNode = domConstruct.create("SPAN", null, this.domNode);
  3635. }
  3636. this.labelNode.className = "mblHeadingSpanTitle";
  3637. this.labelDivNode = domConstruct.create("DIV", {
  3638. className: "mblHeadingDivTitle",
  3639. innerHTML: this.labelNode.innerHTML
  3640. }, this.domNode);
  3641. },
  3642. startup: function(){
  3643. if(this._started){ return; }
  3644. var parent = this.getParent && this.getParent();
  3645. if(!parent || !parent.resize){ // top level widget
  3646. var _this = this;
  3647. setTimeout(function(){ // necessary to render correctly
  3648. _this.resize();
  3649. }, 0);
  3650. }
  3651. this.inherited(arguments);
  3652. },
  3653. resize: function(){
  3654. if(this._btn){
  3655. this._btn.style.width = this._body.offsetWidth + this._head.offsetWidth + "px";
  3656. }
  3657. if(this.labelNode){
  3658. // find the rightmost left button (B), and leftmost right button (C)
  3659. // +-----------------------------+
  3660. // | |A| |B| |C| |D| |
  3661. // +-----------------------------+
  3662. var leftBtn, rightBtn;
  3663. var children = this.containerNode.childNodes;
  3664. for(var i = children.length - 1; i >= 0; i--){
  3665. var c = children[i];
  3666. if(c.nodeType === 1){
  3667. if(!rightBtn && domClass.contains(c, "mblToolBarButton") && domStyle.get(c, "float") === "right"){
  3668. rightBtn = c;
  3669. }
  3670. if(!leftBtn && (domClass.contains(c, "mblToolBarButton") && domStyle.get(c, "float") === "left" || c === this._btn)){
  3671. leftBtn = c;
  3672. }
  3673. }
  3674. }
  3675. if(!this.labelNodeLen && this.label){
  3676. this.labelNode.style.display = "inline";
  3677. this.labelNodeLen = this.labelNode.offsetWidth;
  3678. this.labelNode.style.display = "";
  3679. }
  3680. var bw = this.domNode.offsetWidth; // bar width
  3681. var rw = rightBtn ? bw - rightBtn.offsetLeft + 5 : 0; // rightBtn width
  3682. var lw = leftBtn ? leftBtn.offsetLeft + leftBtn.offsetWidth + 5 : 0; // leftBtn width
  3683. var tw = this.labelNodeLen || 0; // title width
  3684. domClass[bw - Math.max(rw,lw)*2 > tw ? "add" : "remove"](this.domNode, "mblHeadingCenterTitle");
  3685. }
  3686. array.forEach(this.getChildren(), function(child){
  3687. if(child.resize){ child.resize(); }
  3688. });
  3689. },
  3690. _setBackAttr: function(/*String*/back){
  3691. if (!back){
  3692. domConstruct.destroy(this._btn);
  3693. this._btn = null;
  3694. this.back = "";
  3695. }else{
  3696. if(!this._btn){
  3697. var btn = domConstruct.create("DIV", this.backProp, this.domNode, "first");
  3698. var head = domConstruct.create("DIV", {className:"mblArrowButtonHead"}, btn);
  3699. var body = domConstruct.create("DIV", {className:"mblArrowButtonBody mblArrowButtonText"}, btn);
  3700. this._body = body;
  3701. this._head = head;
  3702. this._btn = btn;
  3703. this.backBtnNode = btn;
  3704. this.connect(body, "onclick", "onClick");
  3705. }
  3706. this.back = back;
  3707. this._body.innerHTML = this._cv ? this._cv(this.back) : this.back;
  3708. }
  3709. this.resize();
  3710. },
  3711. _setLabelAttr: function(/*String*/label){
  3712. this.label = label;
  3713. this.labelNode.innerHTML = this.labelDivNode.innerHTML = this._cv ? this._cv(label) : label;
  3714. },
  3715. findCurrentView: function(){
  3716. // summary:
  3717. // Search for the view widget that contains this widget.
  3718. var w = this;
  3719. while(true){
  3720. w = w.getParent();
  3721. if(!w){ return null; }
  3722. if(w instanceof View){ break; }
  3723. }
  3724. return w;
  3725. },
  3726. onClick: function(e){
  3727. var h1 = this.domNode;
  3728. domClass.add(h1, "mblArrowButtonSelected");
  3729. setTimeout(function(){
  3730. domClass.remove(h1, "mblArrowButtonSelected");
  3731. }, 1000);
  3732. if(this.back && !this.moveTo && !this.href && history){
  3733. history.back();
  3734. return;
  3735. }
  3736. // keep the clicked position for transition animations
  3737. var view = this.findCurrentView();
  3738. if(view){
  3739. view.clickedPosX = e.clientX;
  3740. view.clickedPosY = e.clientY;
  3741. }
  3742. this.goTo(this.moveTo, this.href);
  3743. },
  3744. goTo: function(moveTo, href){
  3745. // summary:
  3746. // Given the destination, makes a view transition.
  3747. var view = this.findCurrentView();
  3748. if(!view){ return; }
  3749. if(href){
  3750. view.performTransition(null, -1, this.transition, this, function(){location.href = href;});
  3751. }else{
  3752. if(dm.app && dm.app.STAGE_CONTROLLER_ACTIVE){
  3753. // If in a full mobile app, then use its mechanisms to move back a scene
  3754. connect.publish("/dojox/mobile/app/goback");
  3755. }else{
  3756. // Basically transition should be performed between two
  3757. // siblings that share the same parent.
  3758. // However, when views are nested and transition occurs from
  3759. // an inner view, search for an ancestor view that is a sibling
  3760. // of the target view, and use it as a source view.
  3761. var node = registry.byId(view.convertToId(moveTo));
  3762. if(node){
  3763. var parent = node.getParent();
  3764. while(view){
  3765. var myParent = view.getParent();
  3766. if(parent === myParent){
  3767. break;
  3768. }
  3769. view = myParent;
  3770. }
  3771. }
  3772. if(view){
  3773. view.performTransition(moveTo, -1, this.transition);
  3774. }
  3775. }
  3776. }
  3777. }
  3778. });
  3779. });
  3780. },
  3781. 'dojox/main':function(){
  3782. define("dojox/main", ["dojo/_base/kernel"], function(dojo) {
  3783. // module:
  3784. // dojox/main
  3785. // summary:
  3786. // The dojox package main module; dojox package is somewhat unusual in that the main module currently just provides an empty object.
  3787. return dojo.dojox;
  3788. });
  3789. },
  3790. 'dojox/mobile/RoundRectList':function(){
  3791. define("dojox/mobile/RoundRectList", [
  3792. "dojo/_base/array",
  3793. "dojo/_base/declare",
  3794. "dojo/_base/window",
  3795. "dijit/_Contained",
  3796. "dijit/_Container",
  3797. "dijit/_WidgetBase"
  3798. ], function(array, declare, win, Contained, Container, WidgetBase){
  3799. /*=====
  3800. var Contained = dijit._Contained;
  3801. var Container = dijit._Container;
  3802. var WidgetBase = dijit._WidgetBase;
  3803. =====*/
  3804. // module:
  3805. // dojox/mobile/RoundRectList
  3806. // summary:
  3807. // A rounded rectangle list.
  3808. return declare("dojox.mobile.RoundRectList", [WidgetBase, Container, Contained], {
  3809. // summary:
  3810. // A rounded rectangle list.
  3811. // description:
  3812. // RoundRectList is a rounded rectangle list, which can be used to
  3813. // display a group of items. Each item must be
  3814. // dojox.mobile.ListItem.
  3815. // transition: String
  3816. // The default animated transition effect for child items.
  3817. transition: "slide",
  3818. // iconBase: String
  3819. // The default icon path for child items.
  3820. iconBase: "",
  3821. // iconPos: String
  3822. // The default icon position for child items.
  3823. iconPos: "",
  3824. // select: String
  3825. // Selection mode of the list. The check mark is shown for the
  3826. // selected list item(s). The value can be "single", "multiple", or
  3827. // "". If "single", there can be only one selected item at a time.
  3828. // If "multiple", there can be multiple selected items at a time.
  3829. select: "",
  3830. // stateful: String
  3831. // If true, the last selected item remains highlighted.
  3832. stateful: false,
  3833. buildRendering: function(){
  3834. this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement("UL");
  3835. this.domNode.className = "mblRoundRectList";
  3836. },
  3837. resize: function(){
  3838. // summary:
  3839. // Calls resize() of each child widget.
  3840. array.forEach(this.getChildren(), function(child){
  3841. if(child.resize){ child.resize(); }
  3842. });
  3843. },
  3844. onCheckStateChanged: function(/*Widget*/listItem, /*String*/newState){
  3845. // summary:
  3846. // Stub function to connect to from your application.
  3847. // description:
  3848. // Called when the check state has been changed.
  3849. },
  3850. _setStatefulAttr: function(stateful){
  3851. this.stateful = stateful;
  3852. array.forEach(this.getChildren(), function(child){
  3853. child.setArrow && child.setArrow();
  3854. });
  3855. },
  3856. deselectItem: function(/*ListItem*/item){
  3857. // summary:
  3858. // Deselects the given item.
  3859. item.deselect();
  3860. },
  3861. deselectAll: function(){
  3862. // summary:
  3863. // Deselects all the items.
  3864. array.forEach(this.getChildren(), function(child){
  3865. child.deselect && child.deselect();
  3866. });
  3867. },
  3868. selectItem: function(/*ListItem*/item){
  3869. // summary:
  3870. // Selects the given item.
  3871. item.select();
  3872. }
  3873. });
  3874. });
  3875. },
  3876. 'dojo/Stateful':function(){
  3877. define(["./_base/declare", "./_base/lang", "./_base/array"], function(declare, lang, array) {
  3878. // module:
  3879. // dojo/Stateful
  3880. // summary:
  3881. // TODOC
  3882. return declare("dojo.Stateful", null, {
  3883. // summary:
  3884. // Base class for objects that provide named properties with optional getter/setter
  3885. // control and the ability to watch for property changes
  3886. // example:
  3887. // | var obj = new dojo.Stateful();
  3888. // | obj.watch("foo", function(){
  3889. // | console.log("foo changed to " + this.get("foo"));
  3890. // | });
  3891. // | obj.set("foo","bar");
  3892. postscript: function(mixin){
  3893. if(mixin){
  3894. lang.mixin(this, mixin);
  3895. }
  3896. },
  3897. get: function(/*String*/name){
  3898. // summary:
  3899. // Get a property on a Stateful instance.
  3900. // name:
  3901. // The property to get.
  3902. // returns:
  3903. // The property value on this Stateful instance.
  3904. // description:
  3905. // Get a named property on a Stateful object. The property may
  3906. // potentially be retrieved via a getter method in subclasses. In the base class
  3907. // this just retrieves the object's property.
  3908. // For example:
  3909. // | stateful = new dojo.Stateful({foo: 3});
  3910. // | stateful.get("foo") // returns 3
  3911. // | stateful.foo // returns 3
  3912. return this[name]; //Any
  3913. },
  3914. set: function(/*String*/name, /*Object*/value){
  3915. // summary:
  3916. // Set a property on a Stateful instance
  3917. // name:
  3918. // The property to set.
  3919. // value:
  3920. // The value to set in the property.
  3921. // returns:
  3922. // The function returns this dojo.Stateful instance.
  3923. // description:
  3924. // Sets named properties on a stateful object and notifies any watchers of
  3925. // the property. A programmatic setter may be defined in subclasses.
  3926. // For example:
  3927. // | stateful = new dojo.Stateful();
  3928. // | stateful.watch(function(name, oldValue, value){
  3929. // | // this will be called on the set below
  3930. // | }
  3931. // | stateful.set(foo, 5);
  3932. //
  3933. // set() may also be called with a hash of name/value pairs, ex:
  3934. // | myObj.set({
  3935. // | foo: "Howdy",
  3936. // | bar: 3
  3937. // | })
  3938. // This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
  3939. if(typeof name === "object"){
  3940. for(var x in name){
  3941. if(name.hasOwnProperty(x) && x !="_watchCallbacks"){
  3942. this.set(x, name[x]);
  3943. }
  3944. }
  3945. return this;
  3946. }
  3947. var oldValue = this[name];
  3948. this[name] = value;
  3949. if(this._watchCallbacks){
  3950. this._watchCallbacks(name, oldValue, value);
  3951. }
  3952. return this; //dojo.Stateful
  3953. },
  3954. watch: function(/*String?*/name, /*Function*/callback){
  3955. // summary:
  3956. // Watches a property for changes
  3957. // name:
  3958. // Indicates the property to watch. This is optional (the callback may be the
  3959. // only parameter), and if omitted, all the properties will be watched
  3960. // returns:
  3961. // An object handle for the watch. The unwatch method of this object
  3962. // can be used to discontinue watching this property:
  3963. // | var watchHandle = obj.watch("foo", callback);
  3964. // | watchHandle.unwatch(); // callback won't be called now
  3965. // callback:
  3966. // The function to execute when the property changes. This will be called after
  3967. // the property has been changed. The callback will be called with the |this|
  3968. // set to the instance, the first argument as the name of the property, the
  3969. // second argument as the old value and the third argument as the new value.
  3970. var callbacks = this._watchCallbacks;
  3971. if(!callbacks){
  3972. var self = this;
  3973. callbacks = this._watchCallbacks = function(name, oldValue, value, ignoreCatchall){
  3974. var notify = function(propertyCallbacks){
  3975. if(propertyCallbacks){
  3976. propertyCallbacks = propertyCallbacks.slice();
  3977. for(var i = 0, l = propertyCallbacks.length; i < l; i++){
  3978. propertyCallbacks[i].call(self, name, oldValue, value);
  3979. }
  3980. }
  3981. };
  3982. notify(callbacks['_' + name]);
  3983. if(!ignoreCatchall){
  3984. notify(callbacks["*"]); // the catch-all
  3985. }
  3986. }; // we use a function instead of an object so it will be ignored by JSON conversion
  3987. }
  3988. if(!callback && typeof name === "function"){
  3989. callback = name;
  3990. name = "*";
  3991. }else{
  3992. // prepend with dash to prevent name conflicts with function (like "name" property)
  3993. name = '_' + name;
  3994. }
  3995. var propertyCallbacks = callbacks[name];
  3996. if(typeof propertyCallbacks !== "object"){
  3997. propertyCallbacks = callbacks[name] = [];
  3998. }
  3999. propertyCallbacks.push(callback);
  4000. return {
  4001. unwatch: function(){
  4002. propertyCallbacks.splice(array.indexOf(propertyCallbacks, callback), 1);
  4003. }
  4004. }; //Object
  4005. }
  4006. });
  4007. });
  4008. },
  4009. 'dojox/mobile/app/List':function(){
  4010. // wrapped by build app
  4011. define(["dijit","dojo","dojox","dojo/require!dojo/string,dijit/_WidgetBase"], function(dijit,dojo,dojox){
  4012. dojo.provide("dojox.mobile.app.List");
  4013. dojo.experimental("dojox.mobile.app.List");
  4014. dojo.require("dojo.string");
  4015. dojo.require("dijit._WidgetBase");
  4016. (function(){
  4017. var templateCache = {};
  4018. dojo.declare("dojox.mobile.app.List", dijit._WidgetBase, {
  4019. // summary:
  4020. // A templated list widget. Given a simple array of data objects
  4021. // and a HTML template, it renders a list of elements, with
  4022. // support for a swipe delete action. An optional template
  4023. // can be provided for when the list is empty.
  4024. // items: Array
  4025. // The array of data items that will be rendered.
  4026. items: null,
  4027. // itemTemplate: String
  4028. // The URL to the HTML file containing the markup for each individual
  4029. // data item.
  4030. itemTemplate: "",
  4031. // emptyTemplate: String
  4032. // The URL to the HTML file containing the HTML to display if there
  4033. // are no data items. This is optional.
  4034. emptyTemplate: "",
  4035. // dividerTemplate: String
  4036. // The URL to the HTML file containing the markup for the dividers
  4037. // between groups of list items
  4038. dividerTemplate: "",
  4039. // dividerFunction: Function
  4040. // Function to create divider elements. This should return a divider
  4041. // value for each item in the list
  4042. dividerFunction: null,
  4043. // labelDelete: String
  4044. // The label to display for the Delete button
  4045. labelDelete: "Delete",
  4046. // labelCancel: String
  4047. // The label to display for the Cancel button
  4048. labelCancel: "Cancel",
  4049. // controller: Object
  4050. //
  4051. controller: null,
  4052. // autoDelete: Boolean
  4053. autoDelete: true,
  4054. // enableDelete: Boolean
  4055. enableDelete: true,
  4056. // enableHold: Boolean
  4057. enableHold: true,
  4058. // formatters: Object
  4059. // A name/value map of functions used to format data for display
  4060. formatters: null,
  4061. // _templateLoadCount: Number
  4062. // The number of templates remaining to load before the list renders.
  4063. _templateLoadCount: 0,
  4064. // _mouseDownPos: Object
  4065. // The coordinates of where a mouseDown event was detected
  4066. _mouseDownPos: null,
  4067. baseClass: "list",
  4068. constructor: function(){
  4069. this._checkLoadComplete = dojo.hitch(this, this._checkLoadComplete);
  4070. this._replaceToken = dojo.hitch(this, this._replaceToken);
  4071. this._postDeleteAnim = dojo.hitch(this, this._postDeleteAnim);
  4072. },
  4073. postCreate: function(){
  4074. var _this = this;
  4075. if(this.emptyTemplate){
  4076. this._templateLoadCount++;
  4077. }
  4078. if(this.itemTemplate){
  4079. this._templateLoadCount++;
  4080. }
  4081. if(this.dividerTemplate){
  4082. this._templateLoadCount++;
  4083. }
  4084. this.connect(this.domNode, "onmousedown", function(event){
  4085. var touch = event;
  4086. if(event.targetTouches && event.targetTouches.length > 0){
  4087. touch = event.targetTouches[0];
  4088. }
  4089. // Find the node that was tapped/clicked
  4090. var rowNode = _this._getRowNode(event.target);
  4091. if(rowNode){
  4092. // Add the rows data to the event so it can be picked up
  4093. // by any listeners
  4094. _this._setDataInfo(rowNode, event);
  4095. // Select and highlight the row
  4096. _this._selectRow(rowNode);
  4097. // Record the position that was tapped
  4098. _this._mouseDownPos = {
  4099. x: touch.pageX,
  4100. y: touch.pageY
  4101. };
  4102. _this._dragThreshold = null;
  4103. }
  4104. });
  4105. this.connect(this.domNode, "onmouseup", function(event){
  4106. // When the mouse/finger comes off the list,
  4107. // call the onSelect function and deselect the row.
  4108. if(event.targetTouches && event.targetTouches.length > 0){
  4109. event = event.targetTouches[0];
  4110. }
  4111. var rowNode = _this._getRowNode(event.target);
  4112. if(rowNode){
  4113. _this._setDataInfo(rowNode, event);
  4114. if(_this._selectedRow){
  4115. _this.onSelect(rowNode._data, rowNode._idx, rowNode);
  4116. }
  4117. this._deselectRow();
  4118. }
  4119. });
  4120. // If swipe-to-delete is enabled, listen for the mouse moving
  4121. if(this.enableDelete){
  4122. this.connect(this.domNode, "mousemove", function(event){
  4123. dojo.stopEvent(event);
  4124. if(!_this._selectedRow){
  4125. return;
  4126. }
  4127. var rowNode = _this._getRowNode(event.target);
  4128. // Still check for enableDelete in case it's changed after
  4129. // this listener is added.
  4130. if(_this.enableDelete && rowNode && !_this._deleting){
  4131. _this.handleDrag(event);
  4132. }
  4133. });
  4134. }
  4135. // Put the data and index onto each onclick event.
  4136. this.connect(this.domNode, "onclick", function(event){
  4137. if(event.touches && event.touches.length > 0){
  4138. event = event.touches[0];
  4139. }
  4140. var rowNode = _this._getRowNode(event.target, true);
  4141. if(rowNode){
  4142. _this._setDataInfo(rowNode, event);
  4143. }
  4144. });
  4145. // If the mouse or finger moves off the selected row,
  4146. // deselect it.
  4147. this.connect(this.domNode, "mouseout", function(event){
  4148. if(event.touches && event.touches.length > 0){
  4149. event = event.touches[0];
  4150. }
  4151. if(event.target == _this._selectedRow){
  4152. _this._deselectRow();
  4153. }
  4154. });
  4155. // If no item template has been provided, it is an error.
  4156. if(!this.itemTemplate){
  4157. throw Error("An item template must be provided to " + this.declaredClass);
  4158. }
  4159. // Load the item template
  4160. this._loadTemplate(this.itemTemplate, "itemTemplate", this._checkLoadComplete);
  4161. if(this.emptyTemplate){
  4162. // If the optional empty template has been provided, load it.
  4163. this._loadTemplate(this.emptyTemplate, "emptyTemplate", this._checkLoadComplete);
  4164. }
  4165. if(this.dividerTemplate){
  4166. this._loadTemplate(this.dividerTemplate, "dividerTemplate", this._checkLoadComplete);
  4167. }
  4168. },
  4169. handleDrag: function(event){
  4170. // summary:
  4171. // Handles rows being swiped for deletion.
  4172. var touch = event;
  4173. if(event.targetTouches && event.targetTouches.length > 0){
  4174. touch = event.targetTouches[0];
  4175. }
  4176. // Get the distance that the mouse or finger has moved since
  4177. // beginning the swipe action.
  4178. var diff = touch.pageX - this._mouseDownPos.x;
  4179. var absDiff = Math.abs(diff);
  4180. if(absDiff > 10 && !this._dragThreshold){
  4181. // Make the user drag the row 60% of the width to remove it
  4182. this._dragThreshold = dojo.marginBox(this._selectedRow).w * 0.6;
  4183. if(!this.autoDelete){
  4184. this.createDeleteButtons(this._selectedRow);
  4185. }
  4186. }
  4187. this._selectedRow.style.left = (absDiff > 10 ? diff : 0) + "px";
  4188. // If the user has dragged the row more than the threshold, slide
  4189. // it off the screen in preparation for deletion.
  4190. if(this._dragThreshold && this._dragThreshold < absDiff){
  4191. this.preDelete(diff);
  4192. }
  4193. },
  4194. handleDragCancel: function(){
  4195. // summary:
  4196. // Handle a drag action being cancelled, for whatever reason.
  4197. // Reset handles, remove CSS classes etc.
  4198. if(this._deleting){
  4199. return;
  4200. }
  4201. dojo.removeClass(this._selectedRow, "hold");
  4202. this._selectedRow.style.left = 0;
  4203. this._mouseDownPos = null;
  4204. this._dragThreshold = null;
  4205. this._deleteBtns && dojo.style(this._deleteBtns, "display", "none");
  4206. },
  4207. preDelete: function(currentLeftPos){
  4208. // summary:
  4209. // Slides the row offscreen before it is deleted
  4210. // TODO: do this with CSS3!
  4211. var self = this;
  4212. this._deleting = true;
  4213. dojo.animateProperty({
  4214. node: this._selectedRow,
  4215. duration: 400,
  4216. properties: {
  4217. left: {
  4218. end: currentLeftPos +
  4219. ((currentLeftPos > 0 ? 1 : -1) * this._dragThreshold * 0.8)
  4220. }
  4221. },
  4222. onEnd: dojo.hitch(this, function(){
  4223. if(this.autoDelete){
  4224. this.deleteRow(this._selectedRow);
  4225. }
  4226. })
  4227. }).play();
  4228. },
  4229. deleteRow: function(row){
  4230. // First make the row invisible
  4231. // Put it back where it came from
  4232. dojo.style(row, {
  4233. visibility: "hidden",
  4234. minHeight: "0px"
  4235. });
  4236. dojo.removeClass(row, "hold");
  4237. this._deleteAnimConn =
  4238. this.connect(row, "webkitAnimationEnd", this._postDeleteAnim);
  4239. dojo.addClass(row, "collapsed");
  4240. },
  4241. _postDeleteAnim: function(event){
  4242. // summary:
  4243. // Completes the deletion of a row.
  4244. if(this._deleteAnimConn){
  4245. this.disconnect(this._deleteAnimConn);
  4246. this._deleteAnimConn = null;
  4247. }
  4248. var row = this._selectedRow;
  4249. var sibling = row.nextSibling;
  4250. var prevSibling = row.previousSibling;
  4251. // If the previous node is a divider and either this is
  4252. // the last element in the list, or the next node is
  4253. // also a divider, remove the divider for the deleted section.
  4254. if(prevSibling && prevSibling._isDivider){
  4255. if(!sibling || sibling._isDivider){
  4256. prevSibling.parentNode.removeChild(prevSibling);
  4257. }
  4258. }
  4259. row.parentNode.removeChild(row);
  4260. this.onDelete(row._data, row._idx, this.items);
  4261. // Decrement the index of each following row
  4262. while(sibling){
  4263. if(sibling._idx){
  4264. sibling._idx--;
  4265. }
  4266. sibling = sibling.nextSibling;
  4267. }
  4268. dojo.destroy(row);
  4269. // Fix up the 'first' and 'last' CSS classes on the rows
  4270. dojo.query("> *:not(.buttons)", this.domNode).forEach(this.applyClass);
  4271. this._deleting = false;
  4272. this._deselectRow();
  4273. },
  4274. createDeleteButtons: function(aroundNode){
  4275. // summary:
  4276. // Creates the two buttons displayed when confirmation is
  4277. // required before deletion of a row.
  4278. // aroundNode:
  4279. // The DOM node of the row about to be deleted.
  4280. var mb = dojo.marginBox(aroundNode);
  4281. var pos = dojo._abs(aroundNode, true);
  4282. if(!this._deleteBtns){
  4283. // Create the delete buttons.
  4284. this._deleteBtns = dojo.create("div",{
  4285. "class": "buttons"
  4286. }, this.domNode);
  4287. this.buttons = [];
  4288. this.buttons.push(new dojox.mobile.Button({
  4289. btnClass: "mblRedButton",
  4290. label: this.labelDelete
  4291. }));
  4292. this.buttons.push(new dojox.mobile.Button({
  4293. btnClass: "mblBlueButton",
  4294. label: this.labelCancel
  4295. }));
  4296. dojo.place(this.buttons[0].domNode, this._deleteBtns);
  4297. dojo.place(this.buttons[1].domNode, this._deleteBtns);
  4298. dojo.addClass(this.buttons[0].domNode, "deleteBtn");
  4299. dojo.addClass(this.buttons[1].domNode, "cancelBtn");
  4300. this._handleButtonClick = dojo.hitch(this._handleButtonClick);
  4301. this.connect(this._deleteBtns, "onclick", this._handleButtonClick);
  4302. }
  4303. dojo.removeClass(this._deleteBtns, "fade out fast");
  4304. dojo.style(this._deleteBtns, {
  4305. display: "",
  4306. width: mb.w + "px",
  4307. height: mb.h + "px",
  4308. top: (aroundNode.offsetTop) + "px",
  4309. left: "0px"
  4310. });
  4311. },
  4312. onDelete: function(data, index, array){
  4313. // summary:
  4314. // Called when a row is deleted
  4315. // data:
  4316. // The data related to the row being deleted
  4317. // index:
  4318. // The index of the data in the total array
  4319. // array:
  4320. // The array of data used.
  4321. array.splice(index, 1);
  4322. // If the data is empty, rerender in case an emptyTemplate has
  4323. // been provided
  4324. if(array.length < 1){
  4325. this.render();
  4326. }
  4327. },
  4328. cancelDelete: function(){
  4329. // summary:
  4330. // Cancels the deletion of a row.
  4331. this._deleting = false;
  4332. this.handleDragCancel();
  4333. },
  4334. _handleButtonClick: function(event){
  4335. // summary:
  4336. // Handles the click of one of the deletion buttons, either to
  4337. // delete the row or to cancel the deletion.
  4338. if(event.touches && event.touches.length > 0){
  4339. event = event.touches[0];
  4340. }
  4341. var node = event.target;
  4342. if(dojo.hasClass(node, "deleteBtn")){
  4343. this.deleteRow(this._selectedRow);
  4344. }else if(dojo.hasClass(node, "cancelBtn")){
  4345. this.cancelDelete();
  4346. }else{
  4347. return;
  4348. }
  4349. dojo.addClass(this._deleteBtns, "fade out");
  4350. },
  4351. applyClass: function(node, idx, array){
  4352. // summary:
  4353. // Applies the 'first' and 'last' CSS classes to the relevant
  4354. // rows.
  4355. dojo.removeClass(node, "first last");
  4356. if(idx == 0){
  4357. dojo.addClass(node, "first");
  4358. }
  4359. if(idx == array.length - 1){
  4360. dojo.addClass(node, "last");
  4361. }
  4362. },
  4363. _setDataInfo: function(rowNode, event){
  4364. // summary:
  4365. // Attaches the data item and index for each row to any event
  4366. // that occurs on that row.
  4367. event.item = rowNode._data;
  4368. event.index = rowNode._idx;
  4369. },
  4370. onSelect: function(data, index, rowNode){
  4371. // summary:
  4372. // Dummy function that is called when a row is tapped
  4373. },
  4374. _selectRow: function(row){
  4375. // summary:
  4376. // Selects a row, applies the relevant CSS classes.
  4377. if(this._deleting && this._selectedRow && row != this._selectedRow){
  4378. this.cancelDelete();
  4379. }
  4380. if(!dojo.hasClass(row, "row")){
  4381. return;
  4382. }
  4383. if(this.enableHold || this.enableDelete){
  4384. dojo.addClass(row, "hold");
  4385. }
  4386. this._selectedRow = row;
  4387. },
  4388. _deselectRow: function(){
  4389. // summary:
  4390. // Deselects a row, and cancels any drag actions that were
  4391. // occurring.
  4392. if(!this._selectedRow || this._deleting){
  4393. return;
  4394. }
  4395. this.handleDragCancel();
  4396. dojo.removeClass(this._selectedRow, "hold");
  4397. this._selectedRow = null;
  4398. },
  4399. _getRowNode: function(fromNode, ignoreNoClick){
  4400. // summary:
  4401. // Gets the DOM node of the row that is equal to or the parent
  4402. // of the node passed to this function.
  4403. while(fromNode && !fromNode._data && fromNode != this.domNode){
  4404. if(!ignoreNoClick && dojo.hasClass(fromNode, "noclick")){
  4405. return null;
  4406. }
  4407. fromNode = fromNode.parentNode;
  4408. }
  4409. return fromNode == this.domNode ? null : fromNode;
  4410. },
  4411. applyTemplate: function(template, data){
  4412. return dojo._toDom(dojo.string.substitute(
  4413. template, data, this._replaceToken, this.formatters || this));
  4414. },
  4415. render: function(){
  4416. // summary:
  4417. // Renders the list.
  4418. // Delete all existing nodes, except the deletion buttons.
  4419. dojo.query("> *:not(.buttons)", this.domNode).forEach(dojo.destroy);
  4420. // If there is no data, and an empty template has been provided,
  4421. // render it.
  4422. if(this.items.length < 1 && this.emptyTemplate){
  4423. dojo.place(dojo._toDom(this.emptyTemplate), this.domNode, "first");
  4424. }else{
  4425. this.domNode.appendChild(this._renderRange(0, this.items.length));
  4426. }
  4427. if(dojo.hasClass(this.domNode.parentNode, "mblRoundRect")){
  4428. dojo.addClass(this.domNode.parentNode, "mblRoundRectList")
  4429. }
  4430. var divs = dojo.query("> .row", this.domNode);
  4431. if(divs.length > 0){
  4432. dojo.addClass(divs[0], "first");
  4433. dojo.addClass(divs[divs.length - 1], "last");
  4434. }
  4435. },
  4436. _renderRange: function(startIdx, endIdx){
  4437. var rows = [];
  4438. var row, i;
  4439. var frag = document.createDocumentFragment();
  4440. startIdx = Math.max(0, startIdx);
  4441. endIdx = Math.min(endIdx, this.items.length);
  4442. for(i = startIdx; i < endIdx; i++){
  4443. // Create a document fragment containing the templated row
  4444. row = this.applyTemplate(this.itemTemplate, this.items[i]);
  4445. dojo.addClass(row, 'row');
  4446. row._data = this.items[i];
  4447. row._idx = i;
  4448. rows.push(row);
  4449. }
  4450. if(!this.dividerFunction || !this.dividerTemplate){
  4451. for(i = startIdx; i < endIdx; i++){
  4452. rows[i]._data = this.items[i];
  4453. rows[i]._idx = i;
  4454. frag.appendChild(rows[i]);
  4455. }
  4456. }else{
  4457. var prevDividerValue = null;
  4458. var dividerValue;
  4459. var divider;
  4460. for(i = startIdx; i < endIdx; i++){
  4461. rows[i]._data = this.items[i];
  4462. rows[i]._idx = i;
  4463. dividerValue = this.dividerFunction(this.items[i]);
  4464. if(dividerValue && dividerValue != prevDividerValue){
  4465. divider = this.applyTemplate(this.dividerTemplate, {
  4466. label: dividerValue,
  4467. item: this.items[i]
  4468. });
  4469. divider._isDivider = true;
  4470. frag.appendChild(divider);
  4471. prevDividerValue = dividerValue;
  4472. }
  4473. frag.appendChild(rows[i]);
  4474. }
  4475. }
  4476. return frag;
  4477. },
  4478. _replaceToken: function(value, key){
  4479. if(key.charAt(0) == '!'){ value = dojo.getObject(key.substr(1), false, _this); }
  4480. if(typeof value == "undefined"){ return ""; } // a debugging aide
  4481. if(value == null){ return ""; }
  4482. // Substitution keys beginning with ! will skip the transform step,
  4483. // in case a user wishes to insert unescaped markup, e.g. ${!foo}
  4484. return key.charAt(0) == "!" ? value :
  4485. // Safer substitution, see heading "Attribute values" in
  4486. // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
  4487. value.toString().replace(/"/g,"&quot;"); //TODO: add &amp? use encodeXML method?
  4488. },
  4489. _checkLoadComplete: function(){
  4490. // summary:
  4491. // Checks if all templates have loaded
  4492. this._templateLoadCount--;
  4493. if(this._templateLoadCount < 1 && this.get("items")){
  4494. this.render();
  4495. }
  4496. },
  4497. _loadTemplate: function(url, thisAttr, callback){
  4498. // summary:
  4499. // Loads a template
  4500. if(!url){
  4501. callback();
  4502. return;
  4503. }
  4504. if(templateCache[url]){
  4505. this.set(thisAttr, templateCache[url]);
  4506. callback();
  4507. }else{
  4508. var _this = this;
  4509. dojo.xhrGet({
  4510. url: url,
  4511. sync: false,
  4512. handleAs: "text",
  4513. load: function(text){
  4514. templateCache[url] = dojo.trim(text);
  4515. _this.set(thisAttr, templateCache[url]);
  4516. callback();
  4517. }
  4518. });
  4519. }
  4520. },
  4521. _setFormattersAttr: function(formatters){
  4522. // summary:
  4523. // Sets the data items, and causes a rerender of the list
  4524. this.formatters = formatters;
  4525. },
  4526. _setItemsAttr: function(items){
  4527. // summary:
  4528. // Sets the data items, and causes a rerender of the list
  4529. this.items = items || [];
  4530. if(this._templateLoadCount < 1 && items){
  4531. this.render();
  4532. }
  4533. },
  4534. destroy: function(){
  4535. if(this.buttons){
  4536. dojo.forEach(this.buttons, function(button){
  4537. button.destroy();
  4538. });
  4539. this.buttons = null;
  4540. }
  4541. this.inherited(arguments);
  4542. }
  4543. });
  4544. })();
  4545. });
  4546. },
  4547. 'dojox/mobile/app/ListSelector':function(){
  4548. // wrapped by build app
  4549. define("dojox/mobile/app/ListSelector", ["dijit","dojo","dojox","dojo/require!dojox/mobile/app/_Widget,dojo/fx"], function(dijit,dojo,dojox){
  4550. dojo.provide("dojox.mobile.app.ListSelector");
  4551. dojo.experimental("dojox.mobile.app.ListSelector");
  4552. dojo.require("dojox.mobile.app._Widget");
  4553. dojo.require("dojo.fx");
  4554. dojo.declare("dojox.mobile.app.ListSelector", dojox.mobile.app._Widget, {
  4555. // data: Array
  4556. // The array of items to display. Each element in the array
  4557. // should have both a label and value attribute, e.g.
  4558. // [{label: "Open", value: 1} , {label: "Delete", value: 2}]
  4559. data: null,
  4560. // controller: Object
  4561. // The current SceneController widget.
  4562. controller: null,
  4563. // onChoose: Function
  4564. // The callback function for when an item is selected
  4565. onChoose: null,
  4566. destroyOnHide: false,
  4567. _setDataAttr: function(data){
  4568. this.data = data;
  4569. if(this.data){
  4570. this.render();
  4571. }
  4572. },
  4573. postCreate: function(){
  4574. dojo.addClass(this.domNode, "listSelector");
  4575. var _this = this;
  4576. this.connect(this.domNode, "onclick", function(event){
  4577. if(!dojo.hasClass(event.target, "listSelectorRow")){
  4578. return;
  4579. }
  4580. if(_this.onChoose){
  4581. _this.onChoose(_this.data[event.target._idx].value);
  4582. }
  4583. _this.hide();
  4584. });
  4585. this.connect(this.domNode, "onmousedown", function(event){
  4586. if(!dojo.hasClass(event.target, "listSelectorRow")){
  4587. return;
  4588. }
  4589. dojo.addClass(event.target, "listSelectorRow-selected");
  4590. });
  4591. this.connect(this.domNode, "onmouseup", function(event){
  4592. if(!dojo.hasClass(event.target, "listSelectorRow")){
  4593. return;
  4594. }
  4595. dojo.removeClass(event.target, "listSelectorRow-selected");
  4596. });
  4597. this.connect(this.domNode, "onmouseout", function(event){
  4598. if(!dojo.hasClass(event.target, "listSelectorRow")){
  4599. return;
  4600. }
  4601. dojo.removeClass(event.target, "listSelectorRow-selected");
  4602. });
  4603. var viewportSize = this.controller.getWindowSize();
  4604. this.mask = dojo.create("div", {"class": "dialogUnderlayWrapper",
  4605. innerHTML: "<div class=\"dialogUnderlay\"></div>"
  4606. }, this.controller.assistant.domNode);
  4607. this.connect(this.mask, "onclick", function(){
  4608. _this.onChoose && _this.onChoose();
  4609. _this.hide();
  4610. });
  4611. },
  4612. show: function(fromNode){
  4613. // Using dojo.fx here. Must figure out how to do this with CSS animations!!
  4614. var startPos;
  4615. var windowSize = this.controller.getWindowSize();
  4616. var fromNodePos;
  4617. if(fromNode){
  4618. fromNodePos = dojo._abs(fromNode);
  4619. startPos = fromNodePos;
  4620. }else{
  4621. startPos.x = windowSize.w / 2;
  4622. startPos.y = 200;
  4623. }
  4624. console.log("startPos = ", startPos);
  4625. dojo.style(this.domNode, {
  4626. opacity: 0,
  4627. display: "",
  4628. width: Math.floor(windowSize.w * 0.8) + "px"
  4629. });
  4630. var maxWidth = 0;
  4631. dojo.query(">", this.domNode).forEach(function(node){
  4632. dojo.style(node, {
  4633. "float": "left"
  4634. });
  4635. maxWidth = Math.max(maxWidth, dojo.marginBox(node).w);
  4636. dojo.style(node, {
  4637. "float": "none"
  4638. });
  4639. });
  4640. maxWidth = Math.min(maxWidth, Math.round(windowSize.w * 0.8))
  4641. + dojo.style(this.domNode, "paddingLeft")
  4642. + dojo.style(this.domNode, "paddingRight")
  4643. + 1;
  4644. dojo.style(this.domNode, "width", maxWidth + "px");
  4645. var targetHeight = dojo.marginBox(this.domNode).h;
  4646. var _this = this;
  4647. var targetY = fromNodePos ?
  4648. Math.max(30, fromNodePos.y - targetHeight - 10) :
  4649. this.getScroll().y + 30;
  4650. console.log("fromNodePos = ", fromNodePos, " targetHeight = ", targetHeight,
  4651. " targetY = " + targetY, " startPos ", startPos);
  4652. var anim1 = dojo.animateProperty({
  4653. node: this.domNode,
  4654. duration: 400,
  4655. properties: {
  4656. width: {start: 1, end: maxWidth},
  4657. height: {start: 1, end: targetHeight},
  4658. top: {start: startPos.y, end: targetY},
  4659. left: {start: startPos.x, end: (windowSize.w/2 - maxWidth/2)},
  4660. opacity: {start: 0, end: 1},
  4661. fontSize: {start: 1}
  4662. },
  4663. onEnd: function(){
  4664. dojo.style(_this.domNode, "width", "inherit");
  4665. }
  4666. });
  4667. var anim2 = dojo.fadeIn({
  4668. node: this.mask,
  4669. duration: 400
  4670. });
  4671. dojo.fx.combine([anim1, anim2]).play();
  4672. },
  4673. hide: function(){
  4674. // Using dojo.fx here. Must figure out how to do this with CSS animations!!
  4675. var _this = this;
  4676. var anim1 = dojo.animateProperty({
  4677. node: this.domNode,
  4678. duration: 500,
  4679. properties: {
  4680. width: {end: 1},
  4681. height: {end: 1},
  4682. opacity: {end: 0},
  4683. fontSize: {end: 1}
  4684. },
  4685. onEnd: function(){
  4686. if(_this.get("destroyOnHide")){
  4687. _this.destroy();
  4688. }
  4689. }
  4690. });
  4691. var anim2 = dojo.fadeOut({
  4692. node: this.mask,
  4693. duration: 400
  4694. });
  4695. dojo.fx.combine([anim1, anim2]).play();
  4696. },
  4697. render: function(){
  4698. // summary:
  4699. // Renders
  4700. dojo.empty(this.domNode);
  4701. dojo.style(this.domNode, "opacity", 0);
  4702. var row;
  4703. for(var i = 0; i < this.data.length; i++){
  4704. // Create each row and add any custom classes. Also set the _idx property.
  4705. row = dojo.create("div", {
  4706. "class": "listSelectorRow " + (this.data[i].className || ""),
  4707. innerHTML: this.data[i].label
  4708. }, this.domNode);
  4709. row._idx = i;
  4710. if(i == 0){
  4711. dojo.addClass(row, "first");
  4712. }
  4713. if(i == this.data.length - 1){
  4714. dojo.addClass(row, "last");
  4715. }
  4716. }
  4717. },
  4718. destroy: function(){
  4719. this.inherited(arguments);
  4720. dojo.destroy(this.mask);
  4721. }
  4722. });
  4723. });
  4724. },
  4725. 'dojox/mobile/EdgeToEdgeCategory':function(){
  4726. define("dojox/mobile/EdgeToEdgeCategory", [
  4727. "dojo/_base/declare",
  4728. "./RoundRectCategory"
  4729. ], function(declare, RoundRectCategory){
  4730. /*=====
  4731. var RoundRectCategory = dojox.mobile.RoundRectCategory;
  4732. =====*/
  4733. // module:
  4734. // dojox/mobile/EdgeToEdgeCategory
  4735. // summary:
  4736. // A category header for an edge-to-edge list.
  4737. return declare("dojox.mobile.EdgeToEdgeCategory", RoundRectCategory, {
  4738. // summary:
  4739. // A category header for an edge-to-edge list.
  4740. buildRendering: function(){
  4741. this.inherited(arguments);
  4742. this.domNode.className = "mblEdgeToEdgeCategory";
  4743. }
  4744. });
  4745. });
  4746. },
  4747. 'dojo/string':function(){
  4748. define(["./_base/kernel", "./_base/lang"], function(dojo, lang) {
  4749. // module:
  4750. // dojo/string
  4751. // summary:
  4752. // TODOC
  4753. lang.getObject("string", true, dojo);
  4754. /*=====
  4755. dojo.string = {
  4756. // summary: String utilities for Dojo
  4757. };
  4758. =====*/
  4759. dojo.string.rep = function(/*String*/str, /*Integer*/num){
  4760. // summary:
  4761. // Efficiently replicate a string `n` times.
  4762. // str:
  4763. // the string to replicate
  4764. // num:
  4765. // number of times to replicate the string
  4766. if(num <= 0 || !str){ return ""; }
  4767. var buf = [];
  4768. for(;;){
  4769. if(num & 1){
  4770. buf.push(str);
  4771. }
  4772. if(!(num >>= 1)){ break; }
  4773. str += str;
  4774. }
  4775. return buf.join(""); // String
  4776. };
  4777. dojo.string.pad = function(/*String*/text, /*Integer*/size, /*String?*/ch, /*Boolean?*/end){
  4778. // summary:
  4779. // Pad a string to guarantee that it is at least `size` length by
  4780. // filling with the character `ch` at either the start or end of the
  4781. // string. Pads at the start, by default.
  4782. // text:
  4783. // the string to pad
  4784. // size:
  4785. // length to provide padding
  4786. // ch:
  4787. // character to pad, defaults to '0'
  4788. // end:
  4789. // adds padding at the end if true, otherwise pads at start
  4790. // example:
  4791. // | // Fill the string to length 10 with "+" characters on the right. Yields "Dojo++++++".
  4792. // | dojo.string.pad("Dojo", 10, "+", true);
  4793. if(!ch){
  4794. ch = '0';
  4795. }
  4796. var out = String(text),
  4797. pad = dojo.string.rep(ch, Math.ceil((size - out.length) / ch.length));
  4798. return end ? out + pad : pad + out; // String
  4799. };
  4800. dojo.string.substitute = function( /*String*/ template,
  4801. /*Object|Array*/map,
  4802. /*Function?*/ transform,
  4803. /*Object?*/ thisObject){
  4804. // summary:
  4805. // Performs parameterized substitutions on a string. Throws an
  4806. // exception if any parameter is unmatched.
  4807. // template:
  4808. // a string with expressions in the form `${key}` to be replaced or
  4809. // `${key:format}` which specifies a format function. keys are case-sensitive.
  4810. // map:
  4811. // hash to search for substitutions
  4812. // transform:
  4813. // a function to process all parameters before substitution takes
  4814. // place, e.g. mylib.encodeXML
  4815. // thisObject:
  4816. // where to look for optional format function; default to the global
  4817. // namespace
  4818. // example:
  4819. // Substitutes two expressions in a string from an Array or Object
  4820. // | // returns "File 'foo.html' is not found in directory '/temp'."
  4821. // | // by providing substitution data in an Array
  4822. // | dojo.string.substitute(
  4823. // | "File '${0}' is not found in directory '${1}'.",
  4824. // | ["foo.html","/temp"]
  4825. // | );
  4826. // |
  4827. // | // also returns "File 'foo.html' is not found in directory '/temp'."
  4828. // | // but provides substitution data in an Object structure. Dotted
  4829. // | // notation may be used to traverse the structure.
  4830. // | dojo.string.substitute(
  4831. // | "File '${name}' is not found in directory '${info.dir}'.",
  4832. // | { name: "foo.html", info: { dir: "/temp" } }
  4833. // | );
  4834. // example:
  4835. // Use a transform function to modify the values:
  4836. // | // returns "file 'foo.html' is not found in directory '/temp'."
  4837. // | dojo.string.substitute(
  4838. // | "${0} is not found in ${1}.",
  4839. // | ["foo.html","/temp"],
  4840. // | function(str){
  4841. // | // try to figure out the type
  4842. // | var prefix = (str.charAt(0) == "/") ? "directory": "file";
  4843. // | return prefix + " '" + str + "'";
  4844. // | }
  4845. // | );
  4846. // example:
  4847. // Use a formatter
  4848. // | // returns "thinger -- howdy"
  4849. // | dojo.string.substitute(
  4850. // | "${0:postfix}", ["thinger"], null, {
  4851. // | postfix: function(value, key){
  4852. // | return value + " -- howdy";
  4853. // | }
  4854. // | }
  4855. // | );
  4856. thisObject = thisObject || dojo.global;
  4857. transform = transform ?
  4858. lang.hitch(thisObject, transform) : function(v){ return v; };
  4859. return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g,
  4860. function(match, key, format){
  4861. var value = lang.getObject(key, false, map);
  4862. if(format){
  4863. value = lang.getObject(format, false, thisObject).call(thisObject, value, key);
  4864. }
  4865. return transform(value, key).toString();
  4866. }); // String
  4867. };
  4868. /*=====
  4869. dojo.string.trim = function(str){
  4870. // summary:
  4871. // Trims whitespace from both sides of the string
  4872. // str: String
  4873. // String to be trimmed
  4874. // returns: String
  4875. // Returns the trimmed string
  4876. // description:
  4877. // This version of trim() was taken from [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript).
  4878. // The short yet performant version of this function is dojo.trim(),
  4879. // which is part of Dojo base. Uses String.prototype.trim instead, if available.
  4880. return ""; // String
  4881. }
  4882. =====*/
  4883. dojo.string.trim = String.prototype.trim ?
  4884. lang.trim : // aliasing to the native function
  4885. function(str){
  4886. str = str.replace(/^\s+/, '');
  4887. for(var i = str.length - 1; i >= 0; i--){
  4888. if(/\S/.test(str.charAt(i))){
  4889. str = str.substring(0, i + 1);
  4890. break;
  4891. }
  4892. }
  4893. return str;
  4894. };
  4895. return dojo.string;
  4896. });
  4897. },
  4898. 'dojox/mobile/TextBox':function(){
  4899. define([
  4900. "dojo/_base/declare",
  4901. "dojo/dom-construct",
  4902. "dijit/_WidgetBase",
  4903. "dijit/form/_FormValueMixin",
  4904. "dijit/form/_TextBoxMixin"
  4905. ], function(declare, domConstruct, WidgetBase, FormValueMixin, TextBoxMixin){
  4906. /*=====
  4907. WidgetBase = dijit._WidgetBase;
  4908. FormValueMixin = dijit.form._FormValueMixin;
  4909. TextBoxMixin = dijit.form._TextBoxMixin;
  4910. =====*/
  4911. return declare("dojox.mobile.TextBox",[WidgetBase, FormValueMixin, TextBoxMixin],{
  4912. // summary:
  4913. // A non-templated base class for textbox form inputs
  4914. baseClass: "mblTextBox",
  4915. // Override automatic assigning type --> node, it causes exception on IE8.
  4916. // Instead, type must be specified as this.type when the node is created, as part of the original DOM
  4917. _setTypeAttr: null,
  4918. // Map widget attributes to DOMNode attributes.
  4919. _setPlaceHolderAttr: "textbox",
  4920. buildRendering: function(){
  4921. if(!this.srcNodeRef){
  4922. this.srcNodeRef = domConstruct.create("input", {"type":this.type});
  4923. }
  4924. this.inherited(arguments);
  4925. this.textbox = this.focusNode = this.domNode;
  4926. },
  4927. postCreate: function(){
  4928. this.inherited(arguments);
  4929. this.connect(this.textbox, "onfocus", "_onFocus");
  4930. this.connect(this.textbox, "onblur", "_onBlur");
  4931. }
  4932. });
  4933. });
  4934. },
  4935. 'dijit/registry':function(){
  4936. define("dijit/registry", [
  4937. "dojo/_base/array", // array.forEach array.map
  4938. "dojo/_base/sniff", // has("ie")
  4939. "dojo/_base/unload", // unload.addOnWindowUnload
  4940. "dojo/_base/window", // win.body
  4941. "." // dijit._scopeName
  4942. ], function(array, has, unload, win, dijit){
  4943. // module:
  4944. // dijit/registry
  4945. // summary:
  4946. // Registry of existing widget on page, plus some utility methods.
  4947. // Must be accessed through AMD api, ex:
  4948. // require(["dijit/registry"], function(registry){ registry.byId("foo"); })
  4949. var _widgetTypeCtr = {}, hash = {};
  4950. var registry = {
  4951. // summary:
  4952. // A set of widgets indexed by id
  4953. length: 0,
  4954. add: function(/*dijit._Widget*/ widget){
  4955. // summary:
  4956. // Add a widget to the registry. If a duplicate ID is detected, a error is thrown.
  4957. //
  4958. // widget: dijit._Widget
  4959. // Any dijit._Widget subclass.
  4960. if(hash[widget.id]){
  4961. throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
  4962. }
  4963. hash[widget.id] = widget;
  4964. this.length++;
  4965. },
  4966. remove: function(/*String*/ id){
  4967. // summary:
  4968. // Remove a widget from the registry. Does not destroy the widget; simply
  4969. // removes the reference.
  4970. if(hash[id]){
  4971. delete hash[id];
  4972. this.length--;
  4973. }
  4974. },
  4975. byId: function(/*String|Widget*/ id){
  4976. // summary:
  4977. // Find a widget by it's id.
  4978. // If passed a widget then just returns the widget.
  4979. return typeof id == "string" ? hash[id] : id; // dijit._Widget
  4980. },
  4981. byNode: function(/*DOMNode*/ node){
  4982. // summary:
  4983. // Returns the widget corresponding to the given DOMNode
  4984. return hash[node.getAttribute("widgetId")]; // dijit._Widget
  4985. },
  4986. toArray: function(){
  4987. // summary:
  4988. // Convert registry into a true Array
  4989. //
  4990. // example:
  4991. // Work with the widget .domNodes in a real Array
  4992. // | array.map(dijit.registry.toArray(), function(w){ return w.domNode; });
  4993. var ar = [];
  4994. for(var id in hash){
  4995. ar.push(hash[id]);
  4996. }
  4997. return ar; // dijit._Widget[]
  4998. },
  4999. getUniqueId: function(/*String*/widgetType){
  5000. // summary:
  5001. // Generates a unique id for a given widgetType
  5002. var id;
  5003. do{
  5004. id = widgetType + "_" +
  5005. (widgetType in _widgetTypeCtr ?
  5006. ++_widgetTypeCtr[widgetType] : _widgetTypeCtr[widgetType] = 0);
  5007. }while(hash[id]);
  5008. return dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String
  5009. },
  5010. findWidgets: function(/*DomNode*/ root){
  5011. // summary:
  5012. // Search subtree under root returning widgets found.
  5013. // Doesn't search for nested widgets (ie, widgets inside other widgets).
  5014. var outAry = [];
  5015. function getChildrenHelper(root){
  5016. for(var node = root.firstChild; node; node = node.nextSibling){
  5017. if(node.nodeType == 1){
  5018. var widgetId = node.getAttribute("widgetId");
  5019. if(widgetId){
  5020. var widget = hash[widgetId];
  5021. if(widget){ // may be null on page w/multiple dojo's loaded
  5022. outAry.push(widget);
  5023. }
  5024. }else{
  5025. getChildrenHelper(node);
  5026. }
  5027. }
  5028. }
  5029. }
  5030. getChildrenHelper(root);
  5031. return outAry;
  5032. },
  5033. _destroyAll: function(){
  5034. // summary:
  5035. // Code to destroy all widgets and do other cleanup on page unload
  5036. // Clean up focus manager lingering references to widgets and nodes
  5037. dijit._curFocus = null;
  5038. dijit._prevFocus = null;
  5039. dijit._activeStack = [];
  5040. // Destroy all the widgets, top down
  5041. array.forEach(registry.findWidgets(win.body()), function(widget){
  5042. // Avoid double destroy of widgets like Menu that are attached to <body>
  5043. // even though they are logically children of other widgets.
  5044. if(!widget._destroyed){
  5045. if(widget.destroyRecursive){
  5046. widget.destroyRecursive();
  5047. }else if(widget.destroy){
  5048. widget.destroy();
  5049. }
  5050. }
  5051. });
  5052. },
  5053. getEnclosingWidget: function(/*DOMNode*/ node){
  5054. // summary:
  5055. // Returns the widget whose DOM tree contains the specified DOMNode, or null if
  5056. // the node is not contained within the DOM tree of any widget
  5057. while(node){
  5058. var id = node.getAttribute && node.getAttribute("widgetId");
  5059. if(id){
  5060. return hash[id];
  5061. }
  5062. node = node.parentNode;
  5063. }
  5064. return null;
  5065. },
  5066. // In case someone needs to access hash.
  5067. // Actually, this is accessed from WidgetSet back-compatibility code
  5068. _hash: hash
  5069. };
  5070. /*=====
  5071. dijit.registry = {
  5072. // summary:
  5073. // A list of widgets on a page.
  5074. };
  5075. =====*/
  5076. dijit.registry = registry;
  5077. return registry;
  5078. });
  5079. },
  5080. 'dijit/_base/manager':function(){
  5081. define("dijit/_base/manager", [
  5082. "dojo/_base/array",
  5083. "dojo/_base/config", // defaultDuration
  5084. "../registry",
  5085. ".." // for setting exports to dijit namespace
  5086. ], function(array, config, registry, dijit){
  5087. // module:
  5088. // dijit/_base/manager
  5089. // summary:
  5090. // Shim to methods on registry, plus a few other declarations.
  5091. // New code should access dijit/registry directly when possible.
  5092. /*=====
  5093. dijit.byId = function(id){
  5094. // summary:
  5095. // Returns a widget by it's id, or if passed a widget, no-op (like dom.byId())
  5096. // id: String|dijit._Widget
  5097. return registry.byId(id); // dijit._Widget
  5098. };
  5099. dijit.getUniqueId = function(widgetType){
  5100. // summary:
  5101. // Generates a unique id for a given widgetType
  5102. // widgetType: String
  5103. return registry.getUniqueId(widgetType); // String
  5104. };
  5105. dijit.findWidgets = function(root){
  5106. // summary:
  5107. // Search subtree under root returning widgets found.
  5108. // Doesn't search for nested widgets (ie, widgets inside other widgets).
  5109. // root: DOMNode
  5110. return registry.findWidgets(root);
  5111. };
  5112. dijit._destroyAll = function(){
  5113. // summary:
  5114. // Code to destroy all widgets and do other cleanup on page unload
  5115. return registry._destroyAll();
  5116. };
  5117. dijit.byNode = function(node){
  5118. // summary:
  5119. // Returns the widget corresponding to the given DOMNode
  5120. // node: DOMNode
  5121. return registry.byNode(node); // dijit._Widget
  5122. };
  5123. dijit.getEnclosingWidget = function(node){
  5124. // summary:
  5125. // Returns the widget whose DOM tree contains the specified DOMNode, or null if
  5126. // the node is not contained within the DOM tree of any widget
  5127. // node: DOMNode
  5128. return registry.getEnclosingWidget(node);
  5129. };
  5130. =====*/
  5131. array.forEach(["byId", "getUniqueId", "findWidgets", "_destroyAll", "byNode", "getEnclosingWidget"], function(name){
  5132. dijit[name] = registry[name];
  5133. });
  5134. /*=====
  5135. dojo.mixin(dijit, {
  5136. // defaultDuration: Integer
  5137. // The default fx.animation speed (in ms) to use for all Dijit
  5138. // transitional fx.animations, unless otherwise specified
  5139. // on a per-instance basis. Defaults to 200, overrided by
  5140. // `djConfig.defaultDuration`
  5141. defaultDuration: 200
  5142. });
  5143. =====*/
  5144. dijit.defaultDuration = config["defaultDuration"] || 200;
  5145. return dijit;
  5146. });
  5147. },
  5148. 'dijit/_base/place':function(){
  5149. define("dijit/_base/place", [
  5150. "dojo/_base/array", // array.forEach
  5151. "dojo/_base/lang", // lang.isArray
  5152. "dojo/window", // windowUtils.getBox
  5153. "../place",
  5154. ".." // export to dijit namespace
  5155. ], function(array, lang, windowUtils, place, dijit){
  5156. // module:
  5157. // dijit/_base/place
  5158. // summary:
  5159. // Back compatibility module, new code should use dijit/place directly instead of using this module.
  5160. dijit.getViewport = function(){
  5161. // summary:
  5162. // Deprecated method to return the dimensions and scroll position of the viewable area of a browser window.
  5163. // New code should use windowUtils.getBox()
  5164. return windowUtils.getBox();
  5165. };
  5166. /*=====
  5167. dijit.placeOnScreen = function(node, pos, corners, padding){
  5168. // summary:
  5169. // Positions one of the node's corners at specified position
  5170. // such that node is fully visible in viewport.
  5171. // Deprecated, new code should use dijit.place.at() instead.
  5172. };
  5173. =====*/
  5174. dijit.placeOnScreen = place.at;
  5175. /*=====
  5176. dijit.placeOnScreenAroundElement = function(node, aroundElement, aroundCorners, layoutNode){
  5177. // summary:
  5178. // Like dijit.placeOnScreenAroundNode(), except it accepts an arbitrary object
  5179. // for the "around" argument and finds a proper processor to place a node.
  5180. // Deprecated, new code should use dijit.place.around() instead.
  5181. };
  5182. ====*/
  5183. dijit.placeOnScreenAroundElement = function(node, aroundNode, aroundCorners, layoutNode){
  5184. // Convert old style {"BL": "TL", "BR": "TR"} type argument
  5185. // to style needed by dijit.place code:
  5186. // [
  5187. // {aroundCorner: "BL", corner: "TL" },
  5188. // {aroundCorner: "BR", corner: "TR" }
  5189. // ]
  5190. var positions;
  5191. if(lang.isArray(aroundCorners)){
  5192. positions = aroundCorners;
  5193. }else{
  5194. positions = [];
  5195. for(var key in aroundCorners){
  5196. positions.push({aroundCorner: key, corner: aroundCorners[key]});
  5197. }
  5198. }
  5199. return place.around(node, aroundNode, positions, true, layoutNode);
  5200. };
  5201. /*=====
  5202. dijit.placeOnScreenAroundNode = function(node, aroundNode, aroundCorners, layoutNode){
  5203. // summary:
  5204. // Position node adjacent or kitty-corner to aroundNode
  5205. // such that it's fully visible in viewport.
  5206. // Deprecated, new code should use dijit.place.around() instead.
  5207. };
  5208. =====*/
  5209. dijit.placeOnScreenAroundNode = dijit.placeOnScreenAroundElement;
  5210. /*=====
  5211. dijit.placeOnScreenAroundRectangle = function(node, aroundRect, aroundCorners, layoutNode){
  5212. // summary:
  5213. // Like dijit.placeOnScreenAroundNode(), except that the "around"
  5214. // parameter is an arbitrary rectangle on the screen (x, y, width, height)
  5215. // instead of a dom node.
  5216. // Deprecated, new code should use dijit.place.around() instead.
  5217. };
  5218. =====*/
  5219. dijit.placeOnScreenAroundRectangle = dijit.placeOnScreenAroundElement;
  5220. dijit.getPopupAroundAlignment = function(/*Array*/ position, /*Boolean*/ leftToRight){
  5221. // summary:
  5222. // Deprecated method, unneeded when using dijit/place directly.
  5223. // Transforms the passed array of preferred positions into a format suitable for
  5224. // passing as the aroundCorners argument to dijit.placeOnScreenAroundElement.
  5225. //
  5226. // position: String[]
  5227. // This variable controls the position of the drop down.
  5228. // It's an array of strings with the following values:
  5229. //
  5230. // * before: places drop down to the left of the target node/widget, or to the right in
  5231. // the case of RTL scripts like Hebrew and Arabic
  5232. // * after: places drop down to the right of the target node/widget, or to the left in
  5233. // the case of RTL scripts like Hebrew and Arabic
  5234. // * above: drop down goes above target node
  5235. // * below: drop down goes below target node
  5236. //
  5237. // The list is positions is tried, in order, until a position is found where the drop down fits
  5238. // within the viewport.
  5239. //
  5240. // leftToRight: Boolean
  5241. // Whether the popup will be displaying in leftToRight mode.
  5242. //
  5243. var align = {};
  5244. array.forEach(position, function(pos){
  5245. var ltr = leftToRight;
  5246. switch(pos){
  5247. case "after":
  5248. align[leftToRight ? "BR" : "BL"] = leftToRight ? "BL" : "BR";
  5249. break;
  5250. case "before":
  5251. align[leftToRight ? "BL" : "BR"] = leftToRight ? "BR" : "BL";
  5252. break;
  5253. case "below-alt":
  5254. ltr = !ltr;
  5255. // fall through
  5256. case "below":
  5257. // first try to align left borders, next try to align right borders (or reverse for RTL mode)
  5258. align[ltr ? "BL" : "BR"] = ltr ? "TL" : "TR";
  5259. align[ltr ? "BR" : "BL"] = ltr ? "TR" : "TL";
  5260. break;
  5261. case "above-alt":
  5262. ltr = !ltr;
  5263. // fall through
  5264. case "above":
  5265. default:
  5266. // first try to align left borders, next try to align right borders (or reverse for RTL mode)
  5267. align[ltr ? "TL" : "TR"] = ltr ? "BL" : "BR";
  5268. align[ltr ? "TR" : "TL"] = ltr ? "BR" : "BL";
  5269. break;
  5270. }
  5271. });
  5272. return align;
  5273. };
  5274. return dijit;
  5275. });
  5276. },
  5277. 'dojox/mobile/View':function(){
  5278. define([
  5279. "dojo/_base/kernel", // to test dojo.hash
  5280. "dojo/_base/array",
  5281. "dojo/_base/config",
  5282. "dojo/_base/connect",
  5283. "dojo/_base/declare",
  5284. "dojo/_base/lang",
  5285. "dojo/_base/sniff",
  5286. "dojo/_base/window",
  5287. "dojo/_base/Deferred",
  5288. "dojo/dom",
  5289. "dojo/dom-class",
  5290. "dojo/dom-geometry",
  5291. "dojo/dom-style",
  5292. // "dojo/hash", // optionally prereq'ed
  5293. "dijit/registry", // registry.byNode
  5294. "dijit/_Contained",
  5295. "dijit/_Container",
  5296. "dijit/_WidgetBase",
  5297. "./ViewController", // to load ViewController for you (no direct references)
  5298. "./transition"
  5299. ], function(dojo, array, config, connect, declare, lang, has, win, Deferred, dom, domClass, domGeometry, domStyle, registry, Contained, Container, WidgetBase, ViewController, transitDeferred){
  5300. /*=====
  5301. var Contained = dijit._Contained;
  5302. var Container = dijit._Container;
  5303. var WidgetBase = dijit._WidgetBase;
  5304. var ViewController = dojox.mobile.ViewController;
  5305. =====*/
  5306. // module:
  5307. // dojox/mobile/View
  5308. // summary:
  5309. // A widget that represents a view that occupies the full screen
  5310. var dm = lang.getObject("dojox.mobile", true);
  5311. return declare("dojox.mobile.View", [WidgetBase, Container, Contained], {
  5312. // summary:
  5313. // A widget that represents a view that occupies the full screen
  5314. // description:
  5315. // View acts as a container for any HTML and/or widgets. An entire
  5316. // HTML page can have multiple View widgets and the user can
  5317. // navigate through the views back and forth without page
  5318. // transitions.
  5319. // selected: Boolean
  5320. // If true, the view is displayed at startup time.
  5321. selected: false,
  5322. // keepScrollPos: Boolean
  5323. // If true, the scroll position is kept between views.
  5324. keepScrollPos: true,
  5325. constructor: function(params, node){
  5326. if(node){
  5327. dom.byId(node).style.visibility = "hidden";
  5328. }
  5329. this._aw = has("android") >= 2.2 && has("android") < 3; // flag for android animation workaround
  5330. },
  5331. buildRendering: function(){
  5332. this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement("DIV");
  5333. this.domNode.className = "mblView";
  5334. this.connect(this.domNode, "webkitAnimationEnd", "onAnimationEnd");
  5335. this.connect(this.domNode, "webkitAnimationStart", "onAnimationStart");
  5336. if(!config['mblCSS3Transition']){
  5337. this.connect(this.domNode, "webkitTransitionEnd", "onAnimationEnd");
  5338. }
  5339. var id = location.href.match(/#(\w+)([^\w=]|$)/) ? RegExp.$1 : null;
  5340. this._visible = this.selected && !id || this.id == id;
  5341. if(this.selected){
  5342. dm._defaultView = this;
  5343. }
  5344. },
  5345. startup: function(){
  5346. if(this._started){ return; }
  5347. var siblings = [];
  5348. var children = this.domNode.parentNode.childNodes;
  5349. var visible = false;
  5350. // check if a visible view exists
  5351. for(var i = 0; i < children.length; i++){
  5352. var c = children[i];
  5353. if(c.nodeType === 1 && domClass.contains(c, "mblView")){
  5354. siblings.push(c);
  5355. visible = visible || registry.byNode(c)._visible;
  5356. }
  5357. }
  5358. var _visible = this._visible;
  5359. // if no visible view exists, make the first view visible
  5360. if(siblings.length === 1 || (!visible && siblings[0] === this.domNode)){
  5361. _visible = true;
  5362. }
  5363. var _this = this;
  5364. setTimeout(function(){ // necessary to render the view correctly
  5365. if(!_visible){
  5366. _this.domNode.style.display = "none";
  5367. }else{
  5368. dm.currentView = _this; //TODO:1.8 reconsider this. currentView may not have a currently showing view when views are nested.
  5369. _this.onStartView();
  5370. connect.publish("/dojox/mobile/startView", [_this]);
  5371. }
  5372. if(_this.domNode.style.visibility != "visible"){ // this check is to avoid screen flickers
  5373. _this.domNode.style.visibility = "visible";
  5374. }
  5375. var parent = _this.getParent && _this.getParent();
  5376. if(!parent || !parent.resize){ // top level widget
  5377. _this.resize();
  5378. }
  5379. }, has("ie") ? 100 : 0); // give IE a little time to complete drawing
  5380. this.inherited(arguments);
  5381. },
  5382. resize: function(){
  5383. // summary:
  5384. // Calls resize() of each child widget.
  5385. array.forEach(this.getChildren(), function(child){
  5386. if(child.resize){ child.resize(); }
  5387. });
  5388. },
  5389. onStartView: function(){
  5390. // summary:
  5391. // Stub function to connect to from your application.
  5392. // description:
  5393. // Called only when this view is shown at startup time.
  5394. },
  5395. onBeforeTransitionIn: function(moveTo, dir, transition, context, method){
  5396. // summary:
  5397. // Stub function to connect to from your application.
  5398. // description:
  5399. // Called before the arriving transition occurs.
  5400. },
  5401. onAfterTransitionIn: function(moveTo, dir, transition, context, method){
  5402. // summary:
  5403. // Stub function to connect to from your application.
  5404. // description:
  5405. // Called after the arriving transition occurs.
  5406. },
  5407. onBeforeTransitionOut: function(moveTo, dir, transition, context, method){
  5408. // summary:
  5409. // Stub function to connect to from your application.
  5410. // description:
  5411. // Called before the leaving transition occurs.
  5412. },
  5413. onAfterTransitionOut: function(moveTo, dir, transition, context, method){
  5414. // summary:
  5415. // Stub function to connect to from your application.
  5416. // description:
  5417. // Called after the leaving transition occurs.
  5418. },
  5419. _saveState: function(moveTo, dir, transition, context, method){
  5420. this._context = context;
  5421. this._method = method;
  5422. if(transition == "none"){
  5423. transition = null;
  5424. }
  5425. this._moveTo = moveTo;
  5426. this._dir = dir;
  5427. this._transition = transition;
  5428. this._arguments = lang._toArray(arguments);
  5429. this._args = [];
  5430. if(context || method){
  5431. for(var i = 5; i < arguments.length; i++){
  5432. this._args.push(arguments[i]);
  5433. }
  5434. }
  5435. },
  5436. _fixViewState: function(/*DomNode*/toNode){
  5437. // summary:
  5438. // Sanity check for view transition states.
  5439. // description:
  5440. // Sometimes uninitialization of Views fails after making view transition,
  5441. // and that results in failure of subsequent view transitions.
  5442. // This function does the uninitialization for all the sibling views.
  5443. var nodes = this.domNode.parentNode.childNodes;
  5444. for(var i = 0; i < nodes.length; i++){
  5445. var n = nodes[i];
  5446. if(n.nodeType === 1 && domClass.contains(n, "mblView")){
  5447. n.className = "mblView"; //TODO: Should remove classes one by one. This would clear user defined classes or even mblScrollableView.
  5448. }
  5449. }
  5450. toNode.className = "mblView"; // just in case toNode is a sibling of an ancestor.
  5451. },
  5452. convertToId: function(moveTo){
  5453. if(typeof(moveTo) == "string"){
  5454. // removes a leading hash mark (#) and params if exists
  5455. // ex. "#bar&myParam=0003" -> "bar"
  5456. moveTo.match(/^#?([^&?]+)/);
  5457. return RegExp.$1;
  5458. }
  5459. return moveTo;
  5460. },
  5461. performTransition: function(/*String*/moveTo, /*Number*/dir, /*String*/transition,
  5462. /*Object|null*/context, /*String|Function*/method /*optional args*/){
  5463. // summary:
  5464. // Function to perform the various types of view transitions, such as fade, slide, and flip.
  5465. // moveTo: String
  5466. // The id of the transition destination view which resides in
  5467. // the current page.
  5468. // If the value has a hash sign ('#') before the id
  5469. // (e.g. #view1) and the dojo.hash module is loaded by the user
  5470. // application, the view transition updates the hash in the
  5471. // browser URL so that the user can bookmark the destination
  5472. // view. In this case, the user can also use the browser's
  5473. // back/forward button to navigate through the views in the
  5474. // browser history.
  5475. // If null, transitions to a blank view.
  5476. // If '#', returns immediately without transition.
  5477. // dir: Number
  5478. // The transition direction. If 1, transition forward. If -1, transition backward.
  5479. // For example, the slide transition slides the view from right to left when dir == 1,
  5480. // and from left to right when dir == -1.
  5481. // transition: String
  5482. // A type of animated transition effect. You can choose from
  5483. // the standard transition types, "slide", "fade", "flip", or
  5484. // from the extended transition types, "cover", "coverv",
  5485. // "dissolve", "reveal", "revealv", "scaleIn",
  5486. // "scaleOut", "slidev", "swirl", "zoomIn", "zoomOut". If
  5487. // "none" is specified, transition occurs immediately without
  5488. // animation.
  5489. // context: Object
  5490. // The object that the callback function will receive as "this".
  5491. // method: String|Function
  5492. // A callback function that is called when the transition has been finished.
  5493. // A function reference, or name of a function in context.
  5494. // tags:
  5495. // public
  5496. //
  5497. // example:
  5498. // Transition backward to a view whose id is "foo" with the slide animation.
  5499. // | performTransition("foo", -1, "slide");
  5500. //
  5501. // example:
  5502. // Transition forward to a blank view, and then open another page.
  5503. // | performTransition(null, 1, "slide", null, function(){location.href = href;});
  5504. if(moveTo === "#"){ return; }
  5505. if(dojo.hash){
  5506. if(typeof(moveTo) == "string" && moveTo.charAt(0) == '#' && !dm._params){
  5507. dm._params = [];
  5508. for(var i = 0; i < arguments.length; i++){
  5509. dm._params.push(arguments[i]);
  5510. }
  5511. dojo.hash(moveTo);
  5512. return;
  5513. }
  5514. }
  5515. this._saveState.apply(this, arguments);
  5516. var toNode;
  5517. if(moveTo){
  5518. toNode = this.convertToId(moveTo);
  5519. }else{
  5520. if(!this._dummyNode){
  5521. this._dummyNode = win.doc.createElement("DIV");
  5522. win.body().appendChild(this._dummyNode);
  5523. }
  5524. toNode = this._dummyNode;
  5525. }
  5526. var fromNode = this.domNode;
  5527. var fromTop = fromNode.offsetTop;
  5528. toNode = this.toNode = dom.byId(toNode);
  5529. if(!toNode){ console.log("dojox.mobile.View#performTransition: destination view not found: "+moveTo); return; }
  5530. toNode.style.visibility = this._aw ? "visible" : "hidden";
  5531. toNode.style.display = "";
  5532. this._fixViewState(toNode);
  5533. var toWidget = registry.byNode(toNode);
  5534. if(toWidget){
  5535. // Now that the target view became visible, it's time to run resize()
  5536. if(config["mblAlwaysResizeOnTransition"] || !toWidget._resized){
  5537. dm.resizeAll(null, toWidget);
  5538. toWidget._resized = true;
  5539. }
  5540. if(transition && transition != "none"){
  5541. // Temporarily add padding to align with the fromNode while transition
  5542. toWidget.containerNode.style.paddingTop = fromTop + "px";
  5543. }
  5544. toWidget.movedFrom = fromNode.id;
  5545. }
  5546. this.onBeforeTransitionOut.apply(this, arguments);
  5547. connect.publish("/dojox/mobile/beforeTransitionOut", [this].concat(lang._toArray(arguments)));
  5548. if(toWidget){
  5549. // perform view transition keeping the scroll position
  5550. if(this.keepScrollPos && !this.getParent()){
  5551. var scrollTop = win.body().scrollTop || win.doc.documentElement.scrollTop || win.global.pageYOffset || 0;
  5552. fromNode._scrollTop = scrollTop;
  5553. var toTop = (dir == 1) ? 0 : (toNode._scrollTop || 0);
  5554. toNode.style.top = "0px";
  5555. if(scrollTop > 1 || toTop !== 0){
  5556. fromNode.style.top = toTop - scrollTop + "px";
  5557. if(config["mblHideAddressBar"] !== false){
  5558. setTimeout(function(){ // iPhone needs setTimeout
  5559. win.global.scrollTo(0, (toTop || 1));
  5560. }, 0);
  5561. }
  5562. }
  5563. }else{
  5564. toNode.style.top = "0px";
  5565. }
  5566. toWidget.onBeforeTransitionIn.apply(toWidget, arguments);
  5567. connect.publish("/dojox/mobile/beforeTransitionIn", [toWidget].concat(lang._toArray(arguments)));
  5568. }
  5569. if(!this._aw){
  5570. toNode.style.display = "none";
  5571. toNode.style.visibility = "visible";
  5572. }
  5573. if(dm._iw && dm.scrollable){ // Workaround for iPhone flicker issue (only when scrollable.js is loaded)
  5574. var ss = dm.getScreenSize();
  5575. // Show cover behind the view.
  5576. // cover's z-index is set to -10000, lower than z-index value specified in transition css.
  5577. win.body().appendChild(dm._iwBgCover);
  5578. domStyle.set(dm._iwBgCover, {
  5579. position: "absolute",
  5580. top: "0px",
  5581. left: "0px",
  5582. height: (ss.h + 1) + "px", // "+1" means the height of scrollTo(0,1)
  5583. width: ss.w + "px",
  5584. backgroundColor: domStyle.get(win.body(), "background-color"),
  5585. zIndex: -10000,
  5586. display: ""
  5587. });
  5588. // Show toNode behind the cover.
  5589. domStyle.set(toNode, {
  5590. position: "absolute",
  5591. zIndex: -10001,
  5592. visibility: "visible",
  5593. display: ""
  5594. });
  5595. // setTimeout seems to be necessary to avoid flicker.
  5596. // Also the duration of setTimeout should be long enough to avoid flicker.
  5597. // 0 is not effective. 50 sometimes causes flicker.
  5598. setTimeout(lang.hitch(this, function(){
  5599. this._doTransition(fromNode, toNode, transition, dir);
  5600. }), 80);
  5601. }else{
  5602. this._doTransition(fromNode, toNode, transition, dir);
  5603. }
  5604. },
  5605. _toCls: function(s){
  5606. // convert from transition name to corresponding class name
  5607. // ex. "slide" -> "mblSlide"
  5608. return "mbl"+s.charAt(0).toUpperCase() + s.substring(1);
  5609. },
  5610. _doTransition: function(fromNode, toNode, transition, dir){
  5611. var rev = (dir == -1) ? " mblReverse" : "";
  5612. if(dm._iw && dm.scrollable){ // Workaround for iPhone flicker issue (only when scrollable.js is loaded)
  5613. // Show toNode after flicker ends
  5614. domStyle.set(toNode, {
  5615. position: "",
  5616. zIndex: ""
  5617. });
  5618. // Remove cover
  5619. win.body().removeChild(dm._iwBgCover);
  5620. }else if(!this._aw){
  5621. toNode.style.display = "";
  5622. }
  5623. if(!transition || transition == "none"){
  5624. this.domNode.style.display = "none";
  5625. this.invokeCallback();
  5626. }else if(config['mblCSS3Transition']){
  5627. //get dojox/css3/transit first
  5628. Deferred.when(transitDeferred, lang.hitch(this, function(transit){
  5629. //follow the style of .mblView.mblIn in View.css
  5630. //need to set the toNode to absolute position
  5631. var toPosition = domStyle.get(toNode, "position");
  5632. domStyle.set(toNode, "position", "absolute");
  5633. Deferred.when(transit(fromNode, toNode, {transition: transition, reverse: (dir===-1)?true:false}),lang.hitch(this,function(){
  5634. domStyle.set(toNode, "position", toPosition);
  5635. this.invokeCallback();
  5636. }));
  5637. }));
  5638. }else{
  5639. var s = this._toCls(transition);
  5640. domClass.add(fromNode, s + " mblOut" + rev);
  5641. domClass.add(toNode, s + " mblIn" + rev);
  5642. setTimeout(function(){
  5643. domClass.add(fromNode, "mblTransition");
  5644. domClass.add(toNode, "mblTransition");
  5645. }, 100);
  5646. // set transform origin
  5647. var fromOrigin = "50% 50%";
  5648. var toOrigin = "50% 50%";
  5649. var scrollTop, posX, posY;
  5650. if(transition.indexOf("swirl") != -1 || transition.indexOf("zoom") != -1){
  5651. if(this.keepScrollPos && !this.getParent()){
  5652. scrollTop = win.body().scrollTop || win.doc.documentElement.scrollTop || win.global.pageYOffset || 0;
  5653. }else{
  5654. scrollTop = -domGeometry.position(fromNode, true).y;
  5655. }
  5656. posY = win.global.innerHeight / 2 + scrollTop;
  5657. fromOrigin = "50% " + posY + "px";
  5658. toOrigin = "50% " + posY + "px";
  5659. }else if(transition.indexOf("scale") != -1){
  5660. var viewPos = domGeometry.position(fromNode, true);
  5661. posX = ((this.clickedPosX !== undefined) ? this.clickedPosX : win.global.innerWidth / 2) - viewPos.x;
  5662. if(this.keepScrollPos && !this.getParent()){
  5663. scrollTop = win.body().scrollTop || win.doc.documentElement.scrollTop || win.global.pageYOffset || 0;
  5664. }else{
  5665. scrollTop = -viewPos.y;
  5666. }
  5667. posY = ((this.clickedPosY !== undefined) ? this.clickedPosY : win.global.innerHeight / 2) + scrollTop;
  5668. fromOrigin = posX + "px " + posY + "px";
  5669. toOrigin = posX + "px " + posY + "px";
  5670. }
  5671. domStyle.set(fromNode, {webkitTransformOrigin:fromOrigin});
  5672. domStyle.set(toNode, {webkitTransformOrigin:toOrigin});
  5673. }
  5674. dm.currentView = registry.byNode(toNode);
  5675. },
  5676. onAnimationStart: function(e){
  5677. },
  5678. onAnimationEnd: function(e){
  5679. var name = e.animationName || e.target.className;
  5680. if(name.indexOf("Out") === -1 &&
  5681. name.indexOf("In") === -1 &&
  5682. name.indexOf("Shrink") === -1){ return; }
  5683. var isOut = false;
  5684. if(domClass.contains(this.domNode, "mblOut")){
  5685. isOut = true;
  5686. this.domNode.style.display = "none";
  5687. domClass.remove(this.domNode, [this._toCls(this._transition), "mblIn", "mblOut", "mblReverse"]);
  5688. }else{
  5689. // Reset the temporary padding
  5690. this.containerNode.style.paddingTop = "";
  5691. }
  5692. domStyle.set(this.domNode, {webkitTransformOrigin:""});
  5693. if(name.indexOf("Shrink") !== -1){
  5694. var li = e.target;
  5695. li.style.display = "none";
  5696. domClass.remove(li, "mblCloseContent");
  5697. }
  5698. if(isOut){
  5699. this.invokeCallback();
  5700. }
  5701. // this.domNode may be destroyed as a result of invoking the callback,
  5702. // so check for that before accessing it.
  5703. this.domNode && (this.domNode.className = "mblView");
  5704. // clear the clicked position
  5705. this.clickedPosX = this.clickedPosY = undefined;
  5706. },
  5707. invokeCallback: function(){
  5708. this.onAfterTransitionOut.apply(this, this._arguments);
  5709. connect.publish("/dojox/mobile/afterTransitionOut", [this].concat(this._arguments));
  5710. var toWidget = registry.byNode(this.toNode);
  5711. if(toWidget){
  5712. toWidget.onAfterTransitionIn.apply(toWidget, this._arguments);
  5713. connect.publish("/dojox/mobile/afterTransitionIn", [toWidget].concat(this._arguments));
  5714. toWidget.movedFrom = undefined;
  5715. }
  5716. var c = this._context, m = this._method;
  5717. if(!c && !m){ return; }
  5718. if(!m){
  5719. m = c;
  5720. c = null;
  5721. }
  5722. c = c || win.global;
  5723. if(typeof(m) == "string"){
  5724. c[m].apply(c, this._args);
  5725. }else{
  5726. m.apply(c, this._args);
  5727. }
  5728. },
  5729. getShowingView: function(){
  5730. // summary:
  5731. // Find the currently showing view from my sibling views.
  5732. // description:
  5733. // Note that dojox.mobile.currentView is the last shown view.
  5734. // If the page consists of a splitter, there are multiple showing views.
  5735. var nodes = this.domNode.parentNode.childNodes;
  5736. for(var i = 0; i < nodes.length; i++){
  5737. var n = nodes[i];
  5738. if(n.nodeType === 1 && domClass.contains(n, "mblView") && domStyle.get(n, "display") !== "none"){
  5739. return registry.byNode(n);
  5740. }
  5741. }
  5742. return null;
  5743. },
  5744. show: function(){
  5745. // summary:
  5746. // Shows this view without a transition animation.
  5747. var view = this.getShowingView();
  5748. if(view){
  5749. view.domNode.style.display = "none"; // from-style
  5750. }
  5751. this.domNode.style.display = ""; // to-style
  5752. dm.currentView = this;
  5753. }
  5754. });
  5755. });
  5756. },
  5757. 'dijit/WidgetSet':function(){
  5758. define("dijit/WidgetSet", [
  5759. "dojo/_base/array", // array.forEach array.map
  5760. "dojo/_base/declare", // declare
  5761. "dojo/_base/window", // win.global
  5762. "./registry" // to add functions to dijit.registry
  5763. ], function(array, declare, win, registry){
  5764. // module:
  5765. // dijit/WidgetSet
  5766. // summary:
  5767. // Legacy registry code. New modules should just use registry.
  5768. // Will be removed in 2.0.
  5769. var WidgetSet = declare("dijit.WidgetSet", null, {
  5770. // summary:
  5771. // A set of widgets indexed by id. A default instance of this class is
  5772. // available as `dijit.registry`
  5773. //
  5774. // example:
  5775. // Create a small list of widgets:
  5776. // | var ws = new dijit.WidgetSet();
  5777. // | ws.add(dijit.byId("one"));
  5778. // | ws.add(dijit.byId("two"));
  5779. // | // destroy both:
  5780. // | ws.forEach(function(w){ w.destroy(); });
  5781. //
  5782. // example:
  5783. // Using dijit.registry:
  5784. // | dijit.registry.forEach(function(w){ /* do something */ });
  5785. constructor: function(){
  5786. this._hash = {};
  5787. this.length = 0;
  5788. },
  5789. add: function(/*dijit._Widget*/ widget){
  5790. // summary:
  5791. // Add a widget to this list. If a duplicate ID is detected, a error is thrown.
  5792. //
  5793. // widget: dijit._Widget
  5794. // Any dijit._Widget subclass.
  5795. if(this._hash[widget.id]){
  5796. throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
  5797. }
  5798. this._hash[widget.id] = widget;
  5799. this.length++;
  5800. },
  5801. remove: function(/*String*/ id){
  5802. // summary:
  5803. // Remove a widget from this WidgetSet. Does not destroy the widget; simply
  5804. // removes the reference.
  5805. if(this._hash[id]){
  5806. delete this._hash[id];
  5807. this.length--;
  5808. }
  5809. },
  5810. forEach: function(/*Function*/ func, /* Object? */thisObj){
  5811. // summary:
  5812. // Call specified function for each widget in this set.
  5813. //
  5814. // func:
  5815. // A callback function to run for each item. Is passed the widget, the index
  5816. // in the iteration, and the full hash, similar to `array.forEach`.
  5817. //
  5818. // thisObj:
  5819. // An optional scope parameter
  5820. //
  5821. // example:
  5822. // Using the default `dijit.registry` instance:
  5823. // | dijit.registry.forEach(function(widget){
  5824. // | console.log(widget.declaredClass);
  5825. // | });
  5826. //
  5827. // returns:
  5828. // Returns self, in order to allow for further chaining.
  5829. thisObj = thisObj || win.global;
  5830. var i = 0, id;
  5831. for(id in this._hash){
  5832. func.call(thisObj, this._hash[id], i++, this._hash);
  5833. }
  5834. return this; // dijit.WidgetSet
  5835. },
  5836. filter: function(/*Function*/ filter, /* Object? */thisObj){
  5837. // summary:
  5838. // Filter down this WidgetSet to a smaller new WidgetSet
  5839. // Works the same as `array.filter` and `NodeList.filter`
  5840. //
  5841. // filter:
  5842. // Callback function to test truthiness. Is passed the widget
  5843. // reference and the pseudo-index in the object.
  5844. //
  5845. // thisObj: Object?
  5846. // Option scope to use for the filter function.
  5847. //
  5848. // example:
  5849. // Arbitrary: select the odd widgets in this list
  5850. // | dijit.registry.filter(function(w, i){
  5851. // | return i % 2 == 0;
  5852. // | }).forEach(function(w){ /* odd ones */ });
  5853. thisObj = thisObj || win.global;
  5854. var res = new WidgetSet(), i = 0, id;
  5855. for(id in this._hash){
  5856. var w = this._hash[id];
  5857. if(filter.call(thisObj, w, i++, this._hash)){
  5858. res.add(w);
  5859. }
  5860. }
  5861. return res; // dijit.WidgetSet
  5862. },
  5863. byId: function(/*String*/ id){
  5864. // summary:
  5865. // Find a widget in this list by it's id.
  5866. // example:
  5867. // Test if an id is in a particular WidgetSet
  5868. // | var ws = new dijit.WidgetSet();
  5869. // | ws.add(dijit.byId("bar"));
  5870. // | var t = ws.byId("bar") // returns a widget
  5871. // | var x = ws.byId("foo"); // returns undefined
  5872. return this._hash[id]; // dijit._Widget
  5873. },
  5874. byClass: function(/*String*/ cls){
  5875. // summary:
  5876. // Reduce this widgetset to a new WidgetSet of a particular `declaredClass`
  5877. //
  5878. // cls: String
  5879. // The Class to scan for. Full dot-notated string.
  5880. //
  5881. // example:
  5882. // Find all `dijit.TitlePane`s in a page:
  5883. // | dijit.registry.byClass("dijit.TitlePane").forEach(function(tp){ tp.close(); });
  5884. var res = new WidgetSet(), id, widget;
  5885. for(id in this._hash){
  5886. widget = this._hash[id];
  5887. if(widget.declaredClass == cls){
  5888. res.add(widget);
  5889. }
  5890. }
  5891. return res; // dijit.WidgetSet
  5892. },
  5893. toArray: function(){
  5894. // summary:
  5895. // Convert this WidgetSet into a true Array
  5896. //
  5897. // example:
  5898. // Work with the widget .domNodes in a real Array
  5899. // | array.map(dijit.registry.toArray(), function(w){ return w.domNode; });
  5900. var ar = [];
  5901. for(var id in this._hash){
  5902. ar.push(this._hash[id]);
  5903. }
  5904. return ar; // dijit._Widget[]
  5905. },
  5906. map: function(/* Function */func, /* Object? */thisObj){
  5907. // summary:
  5908. // Create a new Array from this WidgetSet, following the same rules as `array.map`
  5909. // example:
  5910. // | var nodes = dijit.registry.map(function(w){ return w.domNode; });
  5911. //
  5912. // returns:
  5913. // A new array of the returned values.
  5914. return array.map(this.toArray(), func, thisObj); // Array
  5915. },
  5916. every: function(func, thisObj){
  5917. // summary:
  5918. // A synthetic clone of `array.every` acting explicitly on this WidgetSet
  5919. //
  5920. // func: Function
  5921. // A callback function run for every widget in this list. Exits loop
  5922. // when the first false return is encountered.
  5923. //
  5924. // thisObj: Object?
  5925. // Optional scope parameter to use for the callback
  5926. thisObj = thisObj || win.global;
  5927. var x = 0, i;
  5928. for(i in this._hash){
  5929. if(!func.call(thisObj, this._hash[i], x++, this._hash)){
  5930. return false; // Boolean
  5931. }
  5932. }
  5933. return true; // Boolean
  5934. },
  5935. some: function(func, thisObj){
  5936. // summary:
  5937. // A synthetic clone of `array.some` acting explicitly on this WidgetSet
  5938. //
  5939. // func: Function
  5940. // A callback function run for every widget in this list. Exits loop
  5941. // when the first true return is encountered.
  5942. //
  5943. // thisObj: Object?
  5944. // Optional scope parameter to use for the callback
  5945. thisObj = thisObj || win.global;
  5946. var x = 0, i;
  5947. for(i in this._hash){
  5948. if(func.call(thisObj, this._hash[i], x++, this._hash)){
  5949. return true; // Boolean
  5950. }
  5951. }
  5952. return false; // Boolean
  5953. }
  5954. });
  5955. // Add in 1.x compatibility methods to dijit.registry.
  5956. // These functions won't show up in the API doc but since they are deprecated anyway,
  5957. // that's probably for the best.
  5958. array.forEach(["forEach", "filter", "byClass", "map", "every", "some"], function(func){
  5959. registry[func] = WidgetSet.prototype[func];
  5960. });
  5961. return WidgetSet;
  5962. });
  5963. },
  5964. 'dojo/fx/easing':function(){
  5965. define(["../_base/lang"], function(lang) {
  5966. // module:
  5967. // dojo/fx/easing
  5968. // summary:
  5969. // This module defines standard easing functions that are useful for animations.
  5970. var easingFuncs = /*===== dojo.fx.easing= =====*/ {
  5971. // summary:
  5972. // Collection of easing functions to use beyond the default
  5973. // `dojo._defaultEasing` function.
  5974. //
  5975. // description:
  5976. //
  5977. // Easing functions are used to manipulate the iteration through
  5978. // an `dojo.Animation`s _Line. _Line being the properties of an Animation,
  5979. // and the easing function progresses through that Line determing
  5980. // how quickly (or slowly) it should go. Or more accurately: modify
  5981. // the value of the _Line based on the percentage of animation completed.
  5982. //
  5983. // All functions follow a simple naming convention of "ease type" + "when".
  5984. // If the name of the function ends in Out, the easing described appears
  5985. // towards the end of the animation. "In" means during the beginning,
  5986. // and InOut means both ranges of the Animation will applied, both
  5987. // beginning and end.
  5988. //
  5989. // One does not call the easing function directly, it must be passed to
  5990. // the `easing` property of an animation.
  5991. //
  5992. // example:
  5993. // | dojo.require("dojo.fx.easing");
  5994. // | var anim = dojo.fadeOut({
  5995. // | node: 'node',
  5996. // | duration: 2000,
  5997. // | // note there is no ()
  5998. // | easing: dojo.fx.easing.quadIn
  5999. // | }).play();
  6000. //
  6001. linear: function(/* Decimal? */n){
  6002. // summary: A linear easing function
  6003. return n;
  6004. },
  6005. quadIn: function(/* Decimal? */n){
  6006. return Math.pow(n, 2);
  6007. },
  6008. quadOut: function(/* Decimal? */n){
  6009. return n * (n - 2) * -1;
  6010. },
  6011. quadInOut: function(/* Decimal? */n){
  6012. n = n * 2;
  6013. if(n < 1){ return Math.pow(n, 2) / 2; }
  6014. return -1 * ((--n) * (n - 2) - 1) / 2;
  6015. },
  6016. cubicIn: function(/* Decimal? */n){
  6017. return Math.pow(n, 3);
  6018. },
  6019. cubicOut: function(/* Decimal? */n){
  6020. return Math.pow(n - 1, 3) + 1;
  6021. },
  6022. cubicInOut: function(/* Decimal? */n){
  6023. n = n * 2;
  6024. if(n < 1){ return Math.pow(n, 3) / 2; }
  6025. n -= 2;
  6026. return (Math.pow(n, 3) + 2) / 2;
  6027. },
  6028. quartIn: function(/* Decimal? */n){
  6029. return Math.pow(n, 4);
  6030. },
  6031. quartOut: function(/* Decimal? */n){
  6032. return -1 * (Math.pow(n - 1, 4) - 1);
  6033. },
  6034. quartInOut: function(/* Decimal? */n){
  6035. n = n * 2;
  6036. if(n < 1){ return Math.pow(n, 4) / 2; }
  6037. n -= 2;
  6038. return -1 / 2 * (Math.pow(n, 4) - 2);
  6039. },
  6040. quintIn: function(/* Decimal? */n){
  6041. return Math.pow(n, 5);
  6042. },
  6043. quintOut: function(/* Decimal? */n){
  6044. return Math.pow(n - 1, 5) + 1;
  6045. },
  6046. quintInOut: function(/* Decimal? */n){
  6047. n = n * 2;
  6048. if(n < 1){ return Math.pow(n, 5) / 2; }
  6049. n -= 2;
  6050. return (Math.pow(n, 5) + 2) / 2;
  6051. },
  6052. sineIn: function(/* Decimal? */n){
  6053. return -1 * Math.cos(n * (Math.PI / 2)) + 1;
  6054. },
  6055. sineOut: function(/* Decimal? */n){
  6056. return Math.sin(n * (Math.PI / 2));
  6057. },
  6058. sineInOut: function(/* Decimal? */n){
  6059. return -1 * (Math.cos(Math.PI * n) - 1) / 2;
  6060. },
  6061. expoIn: function(/* Decimal? */n){
  6062. return (n == 0) ? 0 : Math.pow(2, 10 * (n - 1));
  6063. },
  6064. expoOut: function(/* Decimal? */n){
  6065. return (n == 1) ? 1 : (-1 * Math.pow(2, -10 * n) + 1);
  6066. },
  6067. expoInOut: function(/* Decimal? */n){
  6068. if(n == 0){ return 0; }
  6069. if(n == 1){ return 1; }
  6070. n = n * 2;
  6071. if(n < 1){ return Math.pow(2, 10 * (n - 1)) / 2; }
  6072. --n;
  6073. return (-1 * Math.pow(2, -10 * n) + 2) / 2;
  6074. },
  6075. circIn: function(/* Decimal? */n){
  6076. return -1 * (Math.sqrt(1 - Math.pow(n, 2)) - 1);
  6077. },
  6078. circOut: function(/* Decimal? */n){
  6079. n = n - 1;
  6080. return Math.sqrt(1 - Math.pow(n, 2));
  6081. },
  6082. circInOut: function(/* Decimal? */n){
  6083. n = n * 2;
  6084. if(n < 1){ return -1 / 2 * (Math.sqrt(1 - Math.pow(n, 2)) - 1); }
  6085. n -= 2;
  6086. return 1 / 2 * (Math.sqrt(1 - Math.pow(n, 2)) + 1);
  6087. },
  6088. backIn: function(/* Decimal? */n){
  6089. // summary:
  6090. // An easing function that starts away from the target,
  6091. // and quickly accelerates towards the end value.
  6092. //
  6093. // Use caution when the easing will cause values to become
  6094. // negative as some properties cannot be set to negative values.
  6095. var s = 1.70158;
  6096. return Math.pow(n, 2) * ((s + 1) * n - s);
  6097. },
  6098. backOut: function(/* Decimal? */n){
  6099. // summary:
  6100. // An easing function that pops past the range briefly, and slowly comes back.
  6101. //
  6102. // description:
  6103. // An easing function that pops past the range briefly, and slowly comes back.
  6104. //
  6105. // Use caution when the easing will cause values to become negative as some
  6106. // properties cannot be set to negative values.
  6107. n = n - 1;
  6108. var s = 1.70158;
  6109. return Math.pow(n, 2) * ((s + 1) * n + s) + 1;
  6110. },
  6111. backInOut: function(/* Decimal? */n){
  6112. // summary:
  6113. // An easing function combining the effects of `backIn` and `backOut`
  6114. //
  6115. // description:
  6116. // An easing function combining the effects of `backIn` and `backOut`.
  6117. // Use caution when the easing will cause values to become negative
  6118. // as some properties cannot be set to negative values.
  6119. var s = 1.70158 * 1.525;
  6120. n = n * 2;
  6121. if(n < 1){ return (Math.pow(n, 2) * ((s + 1) * n - s)) / 2; }
  6122. n-=2;
  6123. return (Math.pow(n, 2) * ((s + 1) * n + s) + 2) / 2;
  6124. },
  6125. elasticIn: function(/* Decimal? */n){
  6126. // summary:
  6127. // An easing function the elastically snaps from the start value
  6128. //
  6129. // description:
  6130. // An easing function the elastically snaps from the start value
  6131. //
  6132. // Use caution when the elasticity will cause values to become negative
  6133. // as some properties cannot be set to negative values.
  6134. if(n == 0 || n == 1){ return n; }
  6135. var p = .3;
  6136. var s = p / 4;
  6137. n = n - 1;
  6138. return -1 * Math.pow(2, 10 * n) * Math.sin((n - s) * (2 * Math.PI) / p);
  6139. },
  6140. elasticOut: function(/* Decimal? */n){
  6141. // summary:
  6142. // An easing function that elasticly snaps around the target value,
  6143. // near the end of the Animation
  6144. //
  6145. // description:
  6146. // An easing function that elasticly snaps around the target value,
  6147. // near the end of the Animation
  6148. //
  6149. // Use caution when the elasticity will cause values to become
  6150. // negative as some properties cannot be set to negative values.
  6151. if(n==0 || n == 1){ return n; }
  6152. var p = .3;
  6153. var s = p / 4;
  6154. return Math.pow(2, -10 * n) * Math.sin((n - s) * (2 * Math.PI) / p) + 1;
  6155. },
  6156. elasticInOut: function(/* Decimal? */n){
  6157. // summary:
  6158. // An easing function that elasticly snaps around the value, near
  6159. // the beginning and end of the Animation.
  6160. //
  6161. // description:
  6162. // An easing function that elasticly snaps around the value, near
  6163. // the beginning and end of the Animation.
  6164. //
  6165. // Use caution when the elasticity will cause values to become
  6166. // negative as some properties cannot be set to negative values.
  6167. if(n == 0) return 0;
  6168. n = n * 2;
  6169. if(n == 2) return 1;
  6170. var p = .3 * 1.5;
  6171. var s = p / 4;
  6172. if(n < 1){
  6173. n -= 1;
  6174. return -.5 * (Math.pow(2, 10 * n) * Math.sin((n - s) * (2 * Math.PI) / p));
  6175. }
  6176. n -= 1;
  6177. return .5 * (Math.pow(2, -10 * n) * Math.sin((n - s) * (2 * Math.PI) / p)) + 1;
  6178. },
  6179. bounceIn: function(/* Decimal? */n){
  6180. // summary:
  6181. // An easing function that 'bounces' near the beginning of an Animation
  6182. return (1 - easingFuncs.bounceOut(1 - n)); // Decimal
  6183. },
  6184. bounceOut: function(/* Decimal? */n){
  6185. // summary:
  6186. // An easing function that 'bounces' near the end of an Animation
  6187. var s = 7.5625;
  6188. var p = 2.75;
  6189. var l;
  6190. if(n < (1 / p)){
  6191. l = s * Math.pow(n, 2);
  6192. }else if(n < (2 / p)){
  6193. n -= (1.5 / p);
  6194. l = s * Math.pow(n, 2) + .75;
  6195. }else if(n < (2.5 / p)){
  6196. n -= (2.25 / p);
  6197. l = s * Math.pow(n, 2) + .9375;
  6198. }else{
  6199. n -= (2.625 / p);
  6200. l = s * Math.pow(n, 2) + .984375;
  6201. }
  6202. return l;
  6203. },
  6204. bounceInOut: function(/* Decimal? */n){
  6205. // summary:
  6206. // An easing function that 'bounces' at the beginning and end of the Animation
  6207. if(n < 0.5){ return easingFuncs.bounceIn(n * 2) / 2; }
  6208. return (easingFuncs.bounceOut(n * 2 - 1) / 2) + 0.5; // Decimal
  6209. }
  6210. };
  6211. lang.setObject("dojo.fx.easing", easingFuncs);
  6212. return easingFuncs;
  6213. });
  6214. },
  6215. 'dijit/a11y':function(){
  6216. define("dijit/a11y", [
  6217. "dojo/_base/array", // array.forEach array.map
  6218. "dojo/dom", // dom.byId
  6219. "dojo/dom-attr", // domAttr.attr domAttr.has
  6220. "dojo/dom-style", // domStyle.style
  6221. "dojo/_base/lang", // lang.mixin()
  6222. "dojo/_base/sniff", // has("ie") 1
  6223. "./main" // for exporting methods to dijit namespace
  6224. ], function(array, dom, domAttr, domStyle, lang, has, dijit){
  6225. // module:
  6226. // dijit/a11y
  6227. var undefined;
  6228. var a11y = {
  6229. // summary:
  6230. // Accessibility utility functions (keyboard, tab stops, etc.)
  6231. _isElementShown: function(/*Element*/ elem){
  6232. var s = domStyle.get(elem);
  6233. return (s.visibility != "hidden")
  6234. && (s.visibility != "collapsed")
  6235. && (s.display != "none")
  6236. && (domAttr.get(elem, "type") != "hidden");
  6237. },
  6238. hasDefaultTabStop: function(/*Element*/ elem){
  6239. // summary:
  6240. // Tests if element is tab-navigable even without an explicit tabIndex setting
  6241. // No explicit tabIndex setting, need to investigate node type
  6242. switch(elem.nodeName.toLowerCase()){
  6243. case "a":
  6244. // An <a> w/out a tabindex is only navigable if it has an href
  6245. return domAttr.has(elem, "href");
  6246. case "area":
  6247. case "button":
  6248. case "input":
  6249. case "object":
  6250. case "select":
  6251. case "textarea":
  6252. // These are navigable by default
  6253. return true;
  6254. case "iframe":
  6255. // If it's an editor <iframe> then it's tab navigable.
  6256. var body;
  6257. try{
  6258. // non-IE
  6259. var contentDocument = elem.contentDocument;
  6260. if("designMode" in contentDocument && contentDocument.designMode == "on"){
  6261. return true;
  6262. }
  6263. body = contentDocument.body;
  6264. }catch(e1){
  6265. // contentWindow.document isn't accessible within IE7/8
  6266. // if the iframe.src points to a foreign url and this
  6267. // page contains an element, that could get focus
  6268. try{
  6269. body = elem.contentWindow.document.body;
  6270. }catch(e2){
  6271. return false;
  6272. }
  6273. }
  6274. return body && (body.contentEditable == 'true' ||
  6275. (body.firstChild && body.firstChild.contentEditable == 'true'));
  6276. default:
  6277. return elem.contentEditable == 'true';
  6278. }
  6279. },
  6280. effectiveTabIndex: function(/*Element*/ elem){
  6281. // summary:
  6282. // Returns effective tabIndex of an element, either a number, or undefined if element isn't focusable.
  6283. if(domAttr.get(elem, "disabled")){
  6284. return undefined;
  6285. }else if(domAttr.has(elem, "tabIndex")){
  6286. // Explicit tab index setting
  6287. return +domAttr.get(elem, "tabIndex");// + to convert string --> number
  6288. }else{
  6289. // No explicit tabIndex setting, so depends on node type
  6290. return a11y.hasDefaultTabStop(elem) ? 0 : undefined;
  6291. }
  6292. },
  6293. isTabNavigable: function(/*Element*/ elem){
  6294. // summary:
  6295. // Tests if an element is tab-navigable
  6296. return a11y.effectiveTabIndex(elem) >= 0;
  6297. },
  6298. isFocusable: function(/*Element*/ elem){
  6299. // summary:
  6300. // Tests if an element is focusable by tabbing to it, or clicking it with the mouse.
  6301. return a11y.effectiveTabIndex(elem) >= -1;
  6302. },
  6303. _getTabNavigable: function(/*DOMNode*/ root){
  6304. // summary:
  6305. // Finds descendants of the specified root node.
  6306. // description:
  6307. // Finds the following descendants of the specified root node:
  6308. //
  6309. // - the first tab-navigable element in document order
  6310. // without a tabIndex or with tabIndex="0"
  6311. // - the last tab-navigable element in document order
  6312. // without a tabIndex or with tabIndex="0"
  6313. // - the first element in document order with the lowest
  6314. // positive tabIndex value
  6315. // - the last element in document order with the highest
  6316. // positive tabIndex value
  6317. var first, last, lowest, lowestTabindex, highest, highestTabindex, radioSelected = {};
  6318. function radioName(node){
  6319. // If this element is part of a radio button group, return the name for that group.
  6320. return node && node.tagName.toLowerCase() == "input" &&
  6321. node.type && node.type.toLowerCase() == "radio" &&
  6322. node.name && node.name.toLowerCase();
  6323. }
  6324. var shown = a11y._isElementShown, effectiveTabIndex = a11y.effectiveTabIndex;
  6325. var walkTree = function(/*DOMNode*/ parent){
  6326. for(var child = parent.firstChild; child; child = child.nextSibling){
  6327. // Skip text elements, hidden elements, and also non-HTML elements (those in custom namespaces) in IE,
  6328. // since show() invokes getAttribute("type"), which crash on VML nodes in IE.
  6329. if(child.nodeType != 1 || (has("ie") <= 9 && child.scopeName !== "HTML") || !shown(child)){
  6330. continue;
  6331. }
  6332. var tabindex = effectiveTabIndex(child);
  6333. if(tabindex >= 0){
  6334. if(tabindex == 0){
  6335. if(!first){
  6336. first = child;
  6337. }
  6338. last = child;
  6339. }else if(tabindex > 0){
  6340. if(!lowest || tabindex < lowestTabindex){
  6341. lowestTabindex = tabindex;
  6342. lowest = child;
  6343. }
  6344. if(!highest || tabindex >= highestTabindex){
  6345. highestTabindex = tabindex;
  6346. highest = child;
  6347. }
  6348. }
  6349. var rn = radioName(child);
  6350. if(domAttr.get(child, "checked") && rn){
  6351. radioSelected[rn] = child;
  6352. }
  6353. }
  6354. if(child.nodeName.toUpperCase() != 'SELECT'){
  6355. walkTree(child);
  6356. }
  6357. }
  6358. };
  6359. if(shown(root)){
  6360. walkTree(root);
  6361. }
  6362. function rs(node){
  6363. // substitute checked radio button for unchecked one, if there is a checked one with the same name.
  6364. return radioSelected[radioName(node)] || node;
  6365. }
  6366. return { first: rs(first), last: rs(last), lowest: rs(lowest), highest: rs(highest) };
  6367. },
  6368. getFirstInTabbingOrder: function(/*String|DOMNode*/ root, /*Document?*/ doc){
  6369. // summary:
  6370. // Finds the descendant of the specified root node
  6371. // that is first in the tabbing order
  6372. var elems = a11y._getTabNavigable(dom.byId(root, doc));
  6373. return elems.lowest ? elems.lowest : elems.first; // DomNode
  6374. },
  6375. getLastInTabbingOrder: function(/*String|DOMNode*/ root, /*Document?*/ doc){
  6376. // summary:
  6377. // Finds the descendant of the specified root node
  6378. // that is last in the tabbing order
  6379. var elems = a11y._getTabNavigable(dom.byId(root, doc));
  6380. return elems.last ? elems.last : elems.highest; // DomNode
  6381. }
  6382. };
  6383. 1 && lang.mixin(dijit, a11y);
  6384. return a11y;
  6385. });
  6386. },
  6387. 'dijit/typematic':function(){
  6388. define("dijit/typematic", [
  6389. "dojo/_base/array", // array.forEach
  6390. "dojo/_base/connect", // connect.connect
  6391. "dojo/_base/event", // event.stop
  6392. "dojo/_base/kernel", // kernel.deprecated
  6393. "dojo/_base/lang", // lang.mixin, lang.hitch
  6394. "dojo/on",
  6395. "dojo/_base/sniff", // has("ie")
  6396. "." // setting dijit.typematic global
  6397. ], function(array, connect, event, kernel, lang, on, has, dijit){
  6398. // module:
  6399. // dijit/typematic
  6400. // summary:
  6401. // These functions are used to repetitively call a user specified callback
  6402. // method when a specific key or mouse click over a specific DOM node is
  6403. // held down for a specific amount of time.
  6404. // Only 1 such event is allowed to occur on the browser page at 1 time.
  6405. var typematic = (dijit.typematic = {
  6406. // summary:
  6407. // These functions are used to repetitively call a user specified callback
  6408. // method when a specific key or mouse click over a specific DOM node is
  6409. // held down for a specific amount of time.
  6410. // Only 1 such event is allowed to occur on the browser page at 1 time.
  6411. _fireEventAndReload: function(){
  6412. this._timer = null;
  6413. this._callback(++this._count, this._node, this._evt);
  6414. // Schedule next event, timer is at most minDelay (default 10ms) to avoid
  6415. // browser overload (particularly avoiding starving DOH robot so it never gets to send a mouseup)
  6416. this._currentTimeout = Math.max(
  6417. this._currentTimeout < 0 ? this._initialDelay :
  6418. (this._subsequentDelay > 1 ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay)),
  6419. this._minDelay);
  6420. this._timer = setTimeout(lang.hitch(this, "_fireEventAndReload"), this._currentTimeout);
  6421. },
  6422. trigger: function(/*Event*/ evt, /*Object*/ _this, /*DOMNode*/ node, /*Function*/ callback, /*Object*/ obj, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
  6423. // summary:
  6424. // Start a timed, repeating callback sequence.
  6425. // If already started, the function call is ignored.
  6426. // This method is not normally called by the user but can be
  6427. // when the normal listener code is insufficient.
  6428. // evt:
  6429. // key or mouse event object to pass to the user callback
  6430. // _this:
  6431. // pointer to the user's widget space.
  6432. // node:
  6433. // the DOM node object to pass the the callback function
  6434. // callback:
  6435. // function to call until the sequence is stopped called with 3 parameters:
  6436. // count:
  6437. // integer representing number of repeated calls (0..n) with -1 indicating the iteration has stopped
  6438. // node:
  6439. // the DOM node object passed in
  6440. // evt:
  6441. // key or mouse event object
  6442. // obj:
  6443. // user space object used to uniquely identify each typematic sequence
  6444. // subsequentDelay (optional):
  6445. // if > 1, the number of milliseconds until the 3->n events occur
  6446. // or else the fractional time multiplier for the next event's delay, default=0.9
  6447. // initialDelay (optional):
  6448. // the number of milliseconds until the 2nd event occurs, default=500ms
  6449. // minDelay (optional):
  6450. // the maximum delay in milliseconds for event to fire, default=10ms
  6451. if(obj != this._obj){
  6452. this.stop();
  6453. this._initialDelay = initialDelay || 500;
  6454. this._subsequentDelay = subsequentDelay || 0.90;
  6455. this._minDelay = minDelay || 10;
  6456. this._obj = obj;
  6457. this._evt = evt;
  6458. this._node = node;
  6459. this._currentTimeout = -1;
  6460. this._count = -1;
  6461. this._callback = lang.hitch(_this, callback);
  6462. this._fireEventAndReload();
  6463. this._evt = lang.mixin({faux: true}, evt);
  6464. }
  6465. },
  6466. stop: function(){
  6467. // summary:
  6468. // Stop an ongoing timed, repeating callback sequence.
  6469. if(this._timer){
  6470. clearTimeout(this._timer);
  6471. this._timer = null;
  6472. }
  6473. if(this._obj){
  6474. this._callback(-1, this._node, this._evt);
  6475. this._obj = null;
  6476. }
  6477. },
  6478. addKeyListener: function(/*DOMNode*/ node, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
  6479. // summary:
  6480. // Start listening for a specific typematic key.
  6481. // See also the trigger method for other parameters.
  6482. // keyObject:
  6483. // an object defining the key to listen for:
  6484. // charOrCode:
  6485. // the printable character (string) or keyCode (number) to listen for.
  6486. // keyCode:
  6487. // (deprecated - use charOrCode) the keyCode (number) to listen for (implies charCode = 0).
  6488. // charCode:
  6489. // (deprecated - use charOrCode) the charCode (number) to listen for.
  6490. // ctrlKey:
  6491. // desired ctrl key state to initiate the callback sequence:
  6492. // - pressed (true)
  6493. // - released (false)
  6494. // - either (unspecified)
  6495. // altKey:
  6496. // same as ctrlKey but for the alt key
  6497. // shiftKey:
  6498. // same as ctrlKey but for the shift key
  6499. // returns:
  6500. // a connection handle
  6501. if(keyObject.keyCode){
  6502. keyObject.charOrCode = keyObject.keyCode;
  6503. kernel.deprecated("keyCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0");
  6504. }else if(keyObject.charCode){
  6505. keyObject.charOrCode = String.fromCharCode(keyObject.charCode);
  6506. kernel.deprecated("charCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0");
  6507. }
  6508. var handles = [
  6509. on(node, connect._keypress, lang.hitch(this, function(evt){
  6510. if(evt.charOrCode == keyObject.charOrCode &&
  6511. (keyObject.ctrlKey === undefined || keyObject.ctrlKey == evt.ctrlKey) &&
  6512. (keyObject.altKey === undefined || keyObject.altKey == evt.altKey) &&
  6513. (keyObject.metaKey === undefined || keyObject.metaKey == (evt.metaKey || false)) && // IE doesn't even set metaKey
  6514. (keyObject.shiftKey === undefined || keyObject.shiftKey == evt.shiftKey)){
  6515. event.stop(evt);
  6516. typematic.trigger(evt, _this, node, callback, keyObject, subsequentDelay, initialDelay, minDelay);
  6517. }else if(typematic._obj == keyObject){
  6518. typematic.stop();
  6519. }
  6520. })),
  6521. on(node, "keyup", lang.hitch(this, function(){
  6522. if(typematic._obj == keyObject){
  6523. typematic.stop();
  6524. }
  6525. }))
  6526. ];
  6527. return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } };
  6528. },
  6529. addMouseListener: function(/*DOMNode*/ node, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
  6530. // summary:
  6531. // Start listening for a typematic mouse click.
  6532. // See the trigger method for other parameters.
  6533. // returns:
  6534. // a connection handle
  6535. var handles = [
  6536. on(node, "mousedown", lang.hitch(this, function(evt){
  6537. event.stop(evt);
  6538. typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay);
  6539. })),
  6540. on(node, "mouseup", lang.hitch(this, function(evt){
  6541. if(this._obj){
  6542. event.stop(evt);
  6543. }
  6544. typematic.stop();
  6545. })),
  6546. on(node, "mouseout", lang.hitch(this, function(evt){
  6547. event.stop(evt);
  6548. typematic.stop();
  6549. })),
  6550. on(node, "mousemove", lang.hitch(this, function(evt){
  6551. evt.preventDefault();
  6552. })),
  6553. on(node, "dblclick", lang.hitch(this, function(evt){
  6554. event.stop(evt);
  6555. if(has("ie") < 9){
  6556. typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay);
  6557. setTimeout(lang.hitch(this, typematic.stop), 50);
  6558. }
  6559. }))
  6560. ];
  6561. return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } };
  6562. },
  6563. addListener: function(/*Node*/ mouseNode, /*Node*/ keyNode, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
  6564. // summary:
  6565. // Start listening for a specific typematic key and mouseclick.
  6566. // This is a thin wrapper to addKeyListener and addMouseListener.
  6567. // See the addMouseListener and addKeyListener methods for other parameters.
  6568. // mouseNode:
  6569. // the DOM node object to listen on for mouse events.
  6570. // keyNode:
  6571. // the DOM node object to listen on for key events.
  6572. // returns:
  6573. // a connection handle
  6574. var handles = [
  6575. this.addKeyListener(keyNode, keyObject, _this, callback, subsequentDelay, initialDelay, minDelay),
  6576. this.addMouseListener(mouseNode, _this, callback, subsequentDelay, initialDelay, minDelay)
  6577. ];
  6578. return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } };
  6579. }
  6580. });
  6581. return typematic;
  6582. });
  6583. },
  6584. 'dojox/mobile/app/ImageView':function(){
  6585. // wrapped by build app
  6586. define("dojox/mobile/app/ImageView", ["dijit","dojo","dojox","dojo/require!dojox/mobile/app/_Widget,dojo/fx/easing"], function(dijit,dojo,dojox){
  6587. dojo.provide("dojox.mobile.app.ImageView");
  6588. dojo.experimental("dojox.mobile.app.ImageView");
  6589. dojo.require("dojox.mobile.app._Widget");
  6590. dojo.require("dojo.fx.easing");
  6591. dojo.declare("dojox.mobile.app.ImageView", dojox.mobile.app._Widget, {
  6592. // zoom: Number
  6593. // The current level of zoom. This should not be set manually.
  6594. zoom: 1,
  6595. // zoomCenterX: Number
  6596. // The X coordinate in the image where the zoom is focused
  6597. zoomCenterX: 0,
  6598. // zoomCenterY: Number
  6599. // The Y coordinate in the image where the zoom is focused
  6600. zoomCenterY: 0,
  6601. // maxZoom: Number
  6602. // The highest degree to which an image can be zoomed. For example,
  6603. // a maxZoom of 5 means that the image will be 5 times larger than normal
  6604. maxZoom: 5,
  6605. // autoZoomLevel: Number
  6606. // The degree to which the image is zoomed when auto zoom is invoked.
  6607. // The higher the number, the more the image is zoomed in.
  6608. autoZoomLevel: 3,
  6609. // disableAutoZoom: Boolean
  6610. // Disables auto zoom
  6611. disableAutoZoom: false,
  6612. // disableSwipe: Boolean
  6613. // Disables the users ability to swipe from one image to the next.
  6614. disableSwipe: false,
  6615. // autoZoomEvent: String
  6616. // Overrides the default event listened to which invokes auto zoom
  6617. autoZoomEvent: null,
  6618. // _leftImg: Node
  6619. // The full sized image to the left
  6620. _leftImg: null,
  6621. // _centerImg: Node
  6622. // The full sized image in the center
  6623. _centerImg: null,
  6624. // _rightImg: Node
  6625. // The full sized image to the right
  6626. _rightImg: null,
  6627. // _leftImg: Node
  6628. // The small sized image to the left
  6629. _leftSmallImg: null,
  6630. // _centerImg: Node
  6631. // The small sized image in the center
  6632. _centerSmallImg: null,
  6633. // _rightImg: Node
  6634. // The small sized image to the right
  6635. _rightSmallImg: null,
  6636. constructor: function(){
  6637. this.panX = 0;
  6638. this.panY = 0;
  6639. this.handleLoad = dojo.hitch(this, this.handleLoad);
  6640. this._updateAnimatedZoom = dojo.hitch(this, this._updateAnimatedZoom);
  6641. this._updateAnimatedPan = dojo.hitch(this, this._updateAnimatedPan);
  6642. this._onAnimPanEnd = dojo.hitch(this, this._onAnimPanEnd);
  6643. },
  6644. buildRendering: function(){
  6645. this.inherited(arguments);
  6646. this.canvas = dojo.create("canvas", {}, this.domNode);
  6647. dojo.addClass(this.domNode, "mblImageView");
  6648. },
  6649. postCreate: function(){
  6650. this.inherited(arguments);
  6651. this.size = dojo.marginBox(this.domNode);
  6652. dojo.style(this.canvas, {
  6653. width: this.size.w + "px",
  6654. height: this.size.h + "px"
  6655. });
  6656. this.canvas.height = this.size.h;
  6657. this.canvas.width = this.size.w;
  6658. var _this = this;
  6659. // Listen to the mousedown/touchstart event. Record the position
  6660. // so we can use it to pan the image.
  6661. this.connect(this.domNode, "onmousedown", function(event){
  6662. if(_this.isAnimating()){
  6663. return;
  6664. }
  6665. if(_this.panX){
  6666. _this.handleDragEnd();
  6667. }
  6668. _this.downX = event.targetTouches ? event.targetTouches[0].clientX : event.clientX;
  6669. _this.downY = event.targetTouches ? event.targetTouches[0].clientY : event.clientY;
  6670. });
  6671. // record the movement of the mouse.
  6672. this.connect(this.domNode, "onmousemove", function(event){
  6673. if(_this.isAnimating()){
  6674. return;
  6675. }
  6676. if((!_this.downX && _this.downX !== 0) || (!_this.downY && _this.downY !== 0)){
  6677. // If the touch didn't begin on this widget, ignore the movement
  6678. return;
  6679. }
  6680. if((!_this.disableSwipe && _this.zoom == 1)
  6681. || (!_this.disableAutoZoom && _this.zoom != 1)){
  6682. var x = event.targetTouches ?
  6683. event.targetTouches[0].clientX : event.pageX;
  6684. var y = event.targetTouches ?
  6685. event.targetTouches[0].clientY : event.pageY;
  6686. _this.panX = x - _this.downX;
  6687. _this.panY = y - _this.downY;
  6688. if(_this.zoom == 1){
  6689. // If not zoomed in, then try to move to the next or prev image
  6690. // but only if the mouse has moved more than 10 pixels
  6691. // in the X direction
  6692. if(Math.abs(_this.panX) > 10){
  6693. _this.render();
  6694. }
  6695. }else{
  6696. // If zoomed in, pan the image if the mouse has moved more
  6697. // than 10 pixels in either direction.
  6698. if(Math.abs(_this.panX) > 10 || Math.abs(_this.panY) > 10){
  6699. _this.render();
  6700. }
  6701. }
  6702. }
  6703. });
  6704. this.connect(this.domNode, "onmouseout", function(event){
  6705. if(!_this.isAnimating() && _this.panX){
  6706. _this.handleDragEnd();
  6707. }
  6708. });
  6709. this.connect(this.domNode, "onmouseover", function(event){
  6710. _this.downX = _this.downY = null;
  6711. });
  6712. // Set up AutoZoom, which zooms in a fixed amount when the user taps
  6713. // a part of the canvas
  6714. this.connect(this.domNode, "onclick", function(event){
  6715. if(_this.isAnimating()){
  6716. return;
  6717. }
  6718. if(_this.downX == null || _this.downY == null){
  6719. return;
  6720. }
  6721. var x = (event.targetTouches ?
  6722. event.targetTouches[0].clientX : event.pageX);
  6723. var y = (event.targetTouches ?
  6724. event.targetTouches[0].clientY : event.pageY);
  6725. // If the mouse/finger has moved more than 14 pixels from where it
  6726. // started, do not treat it as a click. It is a drag.
  6727. if(Math.abs(_this.panX) > 14 || Math.abs(_this.panY) > 14){
  6728. _this.downX = _this.downY = null;
  6729. _this.handleDragEnd();
  6730. return;
  6731. }
  6732. _this.downX = _this.downY = null;
  6733. if(!_this.disableAutoZoom){
  6734. if(!_this._centerImg || !_this._centerImg._loaded){
  6735. // Do nothing until the image is loaded
  6736. return;
  6737. }
  6738. if(_this.zoom != 1){
  6739. _this.set("animatedZoom", 1);
  6740. return;
  6741. }
  6742. var pos = dojo._abs(_this.domNode);
  6743. // Translate the clicked point to a point on the source image
  6744. var xRatio = _this.size.w / _this._centerImg.width;
  6745. var yRatio = _this.size.h / _this._centerImg.height;
  6746. // Do an animated zoom to the point which was clicked.
  6747. _this.zoomTo(
  6748. ((x - pos.x) / xRatio) - _this.panX,
  6749. ((y - pos.y) / yRatio) - _this.panY,
  6750. _this.autoZoomLevel);
  6751. }
  6752. });
  6753. // Listen for Flick events
  6754. dojo.connect(this.domNode, "flick", this, "handleFlick");
  6755. },
  6756. isAnimating: function(){
  6757. // summary:
  6758. // Returns true if an animation is in progress, false otherwise.
  6759. return this._anim && this._anim.status() == "playing";
  6760. },
  6761. handleDragEnd: function(){
  6762. // summary:
  6763. // Handles the end of a dragging event. If not zoomed in, it
  6764. // determines if the next or previous image should be transitioned
  6765. // to.
  6766. this.downX = this.downY = null;
  6767. console.log("handleDragEnd");
  6768. if(this.zoom == 1){
  6769. if(!this.panX){
  6770. return;
  6771. }
  6772. var leftLoaded = (this._leftImg && this._leftImg._loaded)
  6773. || (this._leftSmallImg && this._leftSmallImg._loaded);
  6774. var rightLoaded = (this._rightImg && this._rightImg._loaded)
  6775. || (this._rightSmallImg && this._rightSmallImg._loaded);
  6776. // Check if the drag has moved the image more than half its length.
  6777. // If so, move to either the previous or next image.
  6778. var doMove =
  6779. !(Math.abs(this.panX) < this._centerImg._baseWidth / 2) &&
  6780. (
  6781. (this.panX > 0 && leftLoaded ? 1 : 0) ||
  6782. (this.panX < 0 && rightLoaded ? 1 : 0)
  6783. );
  6784. if(!doMove){
  6785. // If not moving to another image, animate the sliding of the
  6786. // image back into place.
  6787. this._animPanTo(0, dojo.fx.easing.expoOut, 700);
  6788. }else{
  6789. // Move to another image.
  6790. this.moveTo(this.panX);
  6791. }
  6792. }else{
  6793. if(!this.panX && !this.panY){
  6794. return;
  6795. }
  6796. // Recenter the zoomed image based on where it was panned to
  6797. // previously
  6798. this.zoomCenterX -= (this.panX / this.zoom);
  6799. this.zoomCenterY -= (this.panY / this.zoom);
  6800. this.panX = this.panY = 0;
  6801. }
  6802. },
  6803. handleFlick: function(event){
  6804. // summary:
  6805. // Handle a flick event.
  6806. if(this.zoom == 1 && event.duration < 500){
  6807. // Only handle quick flicks here, less than 0.5 seconds
  6808. // If not zoomed in, then check if we should move to the next photo
  6809. // or not
  6810. if(event.direction == "ltr"){
  6811. this.moveTo(1);
  6812. }else if(event.direction == "rtl"){
  6813. this.moveTo(-1);
  6814. }
  6815. // If an up or down flick occurs, it means nothing so ignore it
  6816. this.downX = this.downY = null;
  6817. }
  6818. },
  6819. moveTo: function(direction){
  6820. direction = direction > 0 ? 1 : -1;
  6821. var toImg;
  6822. if(direction < 1){
  6823. if(this._rightImg && this._rightImg._loaded){
  6824. toImg = this._rightImg;
  6825. }else if(this._rightSmallImg && this._rightSmallImg._loaded){
  6826. toImg = this._rightSmallImg;
  6827. }
  6828. }else{
  6829. if(this._leftImg && this._leftImg._loaded){
  6830. toImg = this._leftImg;
  6831. }else if(this._leftSmallImg && this._leftSmallImg._loaded){
  6832. toImg = this._leftSmallImg;
  6833. }
  6834. }
  6835. this._moveDir = direction;
  6836. var _this = this;
  6837. if(toImg && toImg._loaded){
  6838. // If the image is loaded, make a linear animation to show it
  6839. this._animPanTo(this.size.w * direction, null, 500, function(){
  6840. _this.panX = 0;
  6841. _this.panY = 0;
  6842. if(direction < 0){
  6843. // Moving to show the right image
  6844. _this._switchImage("left", "right");
  6845. }else{
  6846. // Moving to show the left image
  6847. _this._switchImage("right", "left");
  6848. }
  6849. _this.render();
  6850. _this.onChange(direction * -1);
  6851. });
  6852. }else{
  6853. // If the next image is not loaded, make an animation to
  6854. // move the center image to half the width of the widget and back
  6855. // again
  6856. console.log("moveTo image not loaded!", toImg);
  6857. this._animPanTo(0, dojo.fx.easing.expoOut, 700);
  6858. }
  6859. },
  6860. _switchImage: function(toImg, fromImg){
  6861. var toSmallImgName = "_" + toImg + "SmallImg";
  6862. var toImgName = "_" + toImg + "Img";
  6863. var fromSmallImgName = "_" + fromImg + "SmallImg";
  6864. var fromImgName = "_" + fromImg + "Img";
  6865. this[toImgName] = this._centerImg;
  6866. this[toSmallImgName] = this._centerSmallImg;
  6867. this[toImgName]._type = toImg;
  6868. if(this[toSmallImgName]){
  6869. this[toSmallImgName]._type = toImg;
  6870. }
  6871. this._centerImg = this[fromImgName];
  6872. this._centerSmallImg = this[fromSmallImgName];
  6873. this._centerImg._type = "center";
  6874. if(this._centerSmallImg){
  6875. this._centerSmallImg._type = "center";
  6876. }
  6877. this[fromImgName] = this[fromSmallImgName] = null;
  6878. },
  6879. _animPanTo: function(to, easing, duration, callback){
  6880. this._animCallback = callback;
  6881. this._anim = new dojo.Animation({
  6882. curve: [this.panX, to],
  6883. onAnimate: this._updateAnimatedPan,
  6884. duration: duration || 500,
  6885. easing: easing,
  6886. onEnd: this._onAnimPanEnd
  6887. });
  6888. this._anim.play();
  6889. return this._anim;
  6890. },
  6891. onChange: function(direction){
  6892. // summary:
  6893. // Stub function that can be listened to in order to provide
  6894. // new images when the displayed image changes
  6895. },
  6896. _updateAnimatedPan: function(amount){
  6897. this.panX = amount;
  6898. this.render();
  6899. },
  6900. _onAnimPanEnd: function(){
  6901. this.panX = this.panY = 0;
  6902. if(this._animCallback){
  6903. this._animCallback();
  6904. }
  6905. },
  6906. zoomTo: function(centerX, centerY, zoom){
  6907. this.set("zoomCenterX", centerX);
  6908. this.set("zoomCenterY", centerY);
  6909. this.set("animatedZoom", zoom);
  6910. },
  6911. render: function(){
  6912. var cxt = this.canvas.getContext('2d');
  6913. cxt.clearRect(0, 0, this.canvas.width, this.canvas.height);
  6914. // Render the center image
  6915. this._renderImg(
  6916. this._centerSmallImg,
  6917. this._centerImg,
  6918. this.zoom == 1 ? (this.panX < 0 ? 1 : this.panX > 0 ? -1 : 0) : 0);
  6919. if(this.zoom == 1 && this.panX != 0){
  6920. if(this.panX > 0){
  6921. // Render the left image, showing the right side of it
  6922. this._renderImg(this._leftSmallImg, this._leftImg, 1);
  6923. }else{
  6924. // Render the right image, showing the left side of it
  6925. this._renderImg(this._rightSmallImg, this._rightImg, -1);
  6926. }
  6927. }
  6928. },
  6929. _renderImg: function(smallImg, largeImg, panDir){
  6930. // summary:
  6931. // Renders a single image
  6932. // If zoomed, we just display the center img
  6933. var img = (largeImg && largeImg._loaded) ? largeImg : smallImg;
  6934. if(!img || !img._loaded){
  6935. // If neither the large or small image is loaded, display nothing
  6936. return;
  6937. }
  6938. var cxt = this.canvas.getContext('2d');
  6939. var baseWidth = img._baseWidth;
  6940. var baseHeight = img._baseHeight;
  6941. // Calculate the size the image would be if there were no bounds
  6942. var desiredWidth = baseWidth * this.zoom;
  6943. var desiredHeight = baseHeight * this.zoom;
  6944. // Calculate the actual size of the viewable image
  6945. var destWidth = Math.min(this.size.w, desiredWidth);
  6946. var destHeight = Math.min(this.size.h, desiredHeight);
  6947. // Calculate the size of the window on the original image to use
  6948. var sourceWidth = this.dispWidth = img.width * (destWidth / desiredWidth);
  6949. var sourceHeight = this.dispHeight = img.height * (destHeight / desiredHeight);
  6950. var zoomCenterX = this.zoomCenterX - (this.panX / this.zoom);
  6951. var zoomCenterY = this.zoomCenterY - (this.panY / this.zoom);
  6952. // Calculate where the center of the view should be
  6953. var centerX = Math.floor(Math.max(sourceWidth / 2,
  6954. Math.min(img.width - sourceWidth / 2, zoomCenterX)));
  6955. var centerY = Math.floor(Math.max(sourceHeight / 2,
  6956. Math.min(img.height - sourceHeight / 2, zoomCenterY)));
  6957. var sourceX = Math.max(0,
  6958. Math.round((img.width - sourceWidth)/2 + (centerX - img._centerX)) );
  6959. var sourceY = Math.max(0,
  6960. Math.round((img.height - sourceHeight) / 2 + (centerY - img._centerY))
  6961. );
  6962. var destX = Math.round(Math.max(0, this.canvas.width - destWidth)/2);
  6963. var destY = Math.round(Math.max(0, this.canvas.height - destHeight)/2);
  6964. var oldDestWidth = destWidth;
  6965. var oldSourceWidth = sourceWidth;
  6966. if(this.zoom == 1 && panDir && this.panX){
  6967. if(this.panX < 0){
  6968. if(panDir > 0){
  6969. // If the touch is moving left, and the right side of the
  6970. // image should be shown, then reduce the destination width
  6971. // by the absolute value of panX
  6972. destWidth -= Math.abs(this.panX);
  6973. destX = 0;
  6974. }else if(panDir < 0){
  6975. // If the touch is moving left, and the left side of the
  6976. // image should be shown, then set the displayed width
  6977. // to the absolute value of panX, less some pixels for
  6978. // a padding between images
  6979. destWidth = Math.max(1, Math.abs(this.panX) - 5);
  6980. destX = this.size.w - destWidth;
  6981. }
  6982. }else{
  6983. if(panDir > 0){
  6984. // If the touch is moving right, and the right side of the
  6985. // image should be shown, then set the destination width
  6986. // to the absolute value of the pan, less some pixels for
  6987. // padding
  6988. destWidth = Math.max(1, Math.abs(this.panX) - 5);
  6989. destX = 0;
  6990. }else if(panDir < 0){
  6991. // If the touch is moving right, and the left side of the
  6992. // image should be shown, then reduce the destination width
  6993. // by the widget width minus the absolute value of panX
  6994. destWidth -= Math.abs(this.panX);
  6995. destX = this.size.w - destWidth;
  6996. }
  6997. }
  6998. sourceWidth = Math.max(1,
  6999. Math.floor(sourceWidth * (destWidth / oldDestWidth)));
  7000. if(panDir > 0){
  7001. // If the right side of the image should be displayed, move
  7002. // the sourceX to be the width of the image minus the difference
  7003. // between the original sourceWidth and the new sourceWidth
  7004. sourceX = (sourceX + oldSourceWidth) - (sourceWidth);
  7005. }
  7006. sourceX = Math.floor(sourceX);
  7007. }
  7008. try{
  7009. // See https://developer.mozilla.org/en/Canvas_tutorial/Using_images
  7010. cxt.drawImage(
  7011. img,
  7012. Math.max(0, sourceX),
  7013. sourceY,
  7014. Math.min(oldSourceWidth, sourceWidth),
  7015. sourceHeight,
  7016. destX, // Xpos
  7017. destY, // Ypos
  7018. Math.min(oldDestWidth, destWidth),
  7019. destHeight
  7020. );
  7021. }catch(e){
  7022. console.log("Caught Error",e,
  7023. "type=", img._type,
  7024. "oldDestWidth = ", oldDestWidth,
  7025. "destWidth", destWidth,
  7026. "destX", destX
  7027. , "oldSourceWidth=",oldSourceWidth,
  7028. "sourceWidth=", sourceWidth,
  7029. "sourceX = " + sourceX
  7030. );
  7031. }
  7032. },
  7033. _setZoomAttr: function(amount){
  7034. this.zoom = Math.min(this.maxZoom, Math.max(1, amount));
  7035. if(this.zoom == 1
  7036. && this._centerImg
  7037. && this._centerImg._loaded){
  7038. if(!this.isAnimating()){
  7039. this.zoomCenterX = this._centerImg.width / 2;
  7040. this.zoomCenterY = this._centerImg.height / 2;
  7041. }
  7042. this.panX = this.panY = 0;
  7043. }
  7044. this.render();
  7045. },
  7046. _setZoomCenterXAttr: function(value){
  7047. if(value != this.zoomCenterX){
  7048. if(this._centerImg && this._centerImg._loaded){
  7049. value = Math.min(this._centerImg.width, value);
  7050. }
  7051. this.zoomCenterX = Math.max(0, Math.round(value));
  7052. }
  7053. },
  7054. _setZoomCenterYAttr: function(value){
  7055. if(value != this.zoomCenterY){
  7056. if(this._centerImg && this._centerImg._loaded){
  7057. value = Math.min(this._centerImg.height, value);
  7058. }
  7059. this.zoomCenterY = Math.max(0, Math.round(value));
  7060. }
  7061. },
  7062. _setZoomCenterAttr: function(value){
  7063. if(value.x != this.zoomCenterX || value.y != this.zoomCenterY){
  7064. this.set("zoomCenterX", value.x);
  7065. this.set("zoomCenterY", value.y);
  7066. this.render();
  7067. }
  7068. },
  7069. _setAnimatedZoomAttr: function(amount){
  7070. if(this._anim && this._anim.status() == "playing"){
  7071. return;
  7072. }
  7073. this._anim = new dojo.Animation({
  7074. curve: [this.zoom, amount],
  7075. onAnimate: this._updateAnimatedZoom,
  7076. onEnd: this._onAnimEnd
  7077. });
  7078. this._anim.play();
  7079. },
  7080. _updateAnimatedZoom: function(amount){
  7081. this._setZoomAttr(amount);
  7082. },
  7083. _setCenterUrlAttr: function(urlOrObj){
  7084. this._setImage("center", urlOrObj);
  7085. },
  7086. _setLeftUrlAttr: function(urlOrObj){
  7087. this._setImage("left", urlOrObj);
  7088. },
  7089. _setRightUrlAttr: function(urlOrObj){
  7090. this._setImage("right", urlOrObj);
  7091. },
  7092. _setImage: function(name, urlOrObj){
  7093. var smallUrl = null;
  7094. var largeUrl = null;
  7095. if(dojo.isString(urlOrObj)){
  7096. // If the argument is a string, then just load the large url
  7097. largeUrl = urlOrObj;
  7098. }else{
  7099. largeUrl = urlOrObj.large;
  7100. smallUrl = urlOrObj.small;
  7101. }
  7102. if(this["_" + name + "Img"] && this["_" + name + "Img"]._src == largeUrl){
  7103. // Identical URL, ignore it
  7104. return;
  7105. }
  7106. // Just do the large image for now
  7107. var largeImg = this["_" + name + "Img"] = new Image();
  7108. largeImg._type = name;
  7109. largeImg._loaded = false;
  7110. largeImg._src = largeUrl;
  7111. largeImg._conn = dojo.connect(largeImg, "onload", this.handleLoad);
  7112. if(smallUrl){
  7113. // If a url to a small version of the image has been provided,
  7114. // load that image first.
  7115. var smallImg = this["_" + name + "SmallImg"] = new Image();
  7116. smallImg._type = name;
  7117. smallImg._loaded = false;
  7118. smallImg._conn = dojo.connect(smallImg, "onload", this.handleLoad);
  7119. smallImg._isSmall = true;
  7120. smallImg._src = smallUrl;
  7121. smallImg.src = smallUrl;
  7122. }
  7123. // It's important that the large url's src is set after the small image
  7124. // to ensure it's loaded second.
  7125. largeImg.src = largeUrl;
  7126. },
  7127. handleLoad: function(evt){
  7128. // summary:
  7129. // Handles the loading of an image, both the large and small
  7130. // versions. A render is triggered as a result of each image load.
  7131. var img = evt.target;
  7132. img._loaded = true;
  7133. dojo.disconnect(img._conn);
  7134. var type = img._type;
  7135. switch(type){
  7136. case "center":
  7137. this.zoomCenterX = img.width / 2;
  7138. this.zoomCenterY = img.height / 2;
  7139. break;
  7140. }
  7141. var height = img.height;
  7142. var width = img.width;
  7143. if(width / this.size.w < height / this.size.h){
  7144. // Fit the height to the height of the canvas
  7145. img._baseHeight = this.canvas.height;
  7146. img._baseWidth = width / (height / this.size.h);
  7147. }else{
  7148. // Fix the width to the width of the canvas
  7149. img._baseWidth = this.canvas.width;
  7150. img._baseHeight = height / (width / this.size.w);
  7151. }
  7152. img._centerX = width / 2;
  7153. img._centerY = height / 2;
  7154. this.render();
  7155. this.onLoad(img._type, img._src, img._isSmall);
  7156. },
  7157. onLoad: function(type, url, isSmall){
  7158. // summary:
  7159. // Dummy function that is called whenever an image loads.
  7160. // type: String
  7161. // The position of the image that has loaded, either
  7162. // "center", "left" or "right"
  7163. // url: String
  7164. // The src of the image
  7165. // isSmall: Boolean
  7166. // True if it is a small version of the image that has loaded,
  7167. // false otherwise.
  7168. }
  7169. });
  7170. });
  7171. },
  7172. 'dijit/_base/focus':function(){
  7173. define("dijit/_base/focus", [
  7174. "dojo/_base/array", // array.forEach
  7175. "dojo/dom", // dom.isDescendant
  7176. "dojo/_base/lang", // lang.isArray
  7177. "dojo/topic", // publish
  7178. "dojo/_base/window", // win.doc win.doc.selection win.global win.global.getSelection win.withGlobal
  7179. "../focus",
  7180. ".." // for exporting symbols to dijit
  7181. ], function(array, dom, lang, topic, win, focus, dijit){
  7182. // module:
  7183. // dijit/_base/focus
  7184. // summary:
  7185. // Deprecated module to monitor currently focused node and stack of currently focused widgets.
  7186. // New code should access dijit/focus directly.
  7187. lang.mixin(dijit, {
  7188. // _curFocus: DomNode
  7189. // Currently focused item on screen
  7190. _curFocus: null,
  7191. // _prevFocus: DomNode
  7192. // Previously focused item on screen
  7193. _prevFocus: null,
  7194. isCollapsed: function(){
  7195. // summary:
  7196. // Returns true if there is no text selected
  7197. return dijit.getBookmark().isCollapsed;
  7198. },
  7199. getBookmark: function(){
  7200. // summary:
  7201. // Retrieves a bookmark that can be used with moveToBookmark to return to the same range
  7202. var bm, rg, tg, sel = win.doc.selection, cf = focus.curNode;
  7203. if(win.global.getSelection){
  7204. //W3C Range API for selections.
  7205. sel = win.global.getSelection();
  7206. if(sel){
  7207. if(sel.isCollapsed){
  7208. tg = cf? cf.tagName : "";
  7209. if(tg){
  7210. //Create a fake rangelike item to restore selections.
  7211. tg = tg.toLowerCase();
  7212. if(tg == "textarea" ||
  7213. (tg == "input" && (!cf.type || cf.type.toLowerCase() == "text"))){
  7214. sel = {
  7215. start: cf.selectionStart,
  7216. end: cf.selectionEnd,
  7217. node: cf,
  7218. pRange: true
  7219. };
  7220. return {isCollapsed: (sel.end <= sel.start), mark: sel}; //Object.
  7221. }
  7222. }
  7223. bm = {isCollapsed:true};
  7224. if(sel.rangeCount){
  7225. bm.mark = sel.getRangeAt(0).cloneRange();
  7226. }
  7227. }else{
  7228. rg = sel.getRangeAt(0);
  7229. bm = {isCollapsed: false, mark: rg.cloneRange()};
  7230. }
  7231. }
  7232. }else if(sel){
  7233. // If the current focus was a input of some sort and no selection, don't bother saving
  7234. // a native bookmark. This is because it causes issues with dialog/page selection restore.
  7235. // So, we need to create psuedo bookmarks to work with.
  7236. tg = cf ? cf.tagName : "";
  7237. tg = tg.toLowerCase();
  7238. if(cf && tg && (tg == "button" || tg == "textarea" || tg == "input")){
  7239. if(sel.type && sel.type.toLowerCase() == "none"){
  7240. return {
  7241. isCollapsed: true,
  7242. mark: null
  7243. }
  7244. }else{
  7245. rg = sel.createRange();
  7246. return {
  7247. isCollapsed: rg.text && rg.text.length?false:true,
  7248. mark: {
  7249. range: rg,
  7250. pRange: true
  7251. }
  7252. };
  7253. }
  7254. }
  7255. bm = {};
  7256. //'IE' way for selections.
  7257. try{
  7258. // createRange() throws exception when dojo in iframe
  7259. //and nothing selected, see #9632
  7260. rg = sel.createRange();
  7261. bm.isCollapsed = !(sel.type == 'Text' ? rg.htmlText.length : rg.length);
  7262. }catch(e){
  7263. bm.isCollapsed = true;
  7264. return bm;
  7265. }
  7266. if(sel.type.toUpperCase() == 'CONTROL'){
  7267. if(rg.length){
  7268. bm.mark=[];
  7269. var i=0,len=rg.length;
  7270. while(i<len){
  7271. bm.mark.push(rg.item(i++));
  7272. }
  7273. }else{
  7274. bm.isCollapsed = true;
  7275. bm.mark = null;
  7276. }
  7277. }else{
  7278. bm.mark = rg.getBookmark();
  7279. }
  7280. }else{
  7281. console.warn("No idea how to store the current selection for this browser!");
  7282. }
  7283. return bm; // Object
  7284. },
  7285. moveToBookmark: function(/*Object*/ bookmark){
  7286. // summary:
  7287. // Moves current selection to a bookmark
  7288. // bookmark:
  7289. // This should be a returned object from dijit.getBookmark()
  7290. var _doc = win.doc,
  7291. mark = bookmark.mark;
  7292. if(mark){
  7293. if(win.global.getSelection){
  7294. //W3C Rangi API (FF, WebKit, Opera, etc)
  7295. var sel = win.global.getSelection();
  7296. if(sel && sel.removeAllRanges){
  7297. if(mark.pRange){
  7298. var n = mark.node;
  7299. n.selectionStart = mark.start;
  7300. n.selectionEnd = mark.end;
  7301. }else{
  7302. sel.removeAllRanges();
  7303. sel.addRange(mark);
  7304. }
  7305. }else{
  7306. console.warn("No idea how to restore selection for this browser!");
  7307. }
  7308. }else if(_doc.selection && mark){
  7309. //'IE' way.
  7310. var rg;
  7311. if(mark.pRange){
  7312. rg = mark.range;
  7313. }else if(lang.isArray(mark)){
  7314. rg = _doc.body.createControlRange();
  7315. //rg.addElement does not have call/apply method, so can not call it directly
  7316. //rg is not available in "range.addElement(item)", so can't use that either
  7317. array.forEach(mark, function(n){
  7318. rg.addElement(n);
  7319. });
  7320. }else{
  7321. rg = _doc.body.createTextRange();
  7322. rg.moveToBookmark(mark);
  7323. }
  7324. rg.select();
  7325. }
  7326. }
  7327. },
  7328. getFocus: function(/*Widget?*/ menu, /*Window?*/ openedForWindow){
  7329. // summary:
  7330. // Called as getFocus(), this returns an Object showing the current focus
  7331. // and selected text.
  7332. //
  7333. // Called as getFocus(widget), where widget is a (widget representing) a button
  7334. // that was just pressed, it returns where focus was before that button
  7335. // was pressed. (Pressing the button may have either shifted focus to the button,
  7336. // or removed focus altogether.) In this case the selected text is not returned,
  7337. // since it can't be accurately determined.
  7338. //
  7339. // menu: dijit._Widget or {domNode: DomNode} structure
  7340. // The button that was just pressed. If focus has disappeared or moved
  7341. // to this button, returns the previous focus. In this case the bookmark
  7342. // information is already lost, and null is returned.
  7343. //
  7344. // openedForWindow:
  7345. // iframe in which menu was opened
  7346. //
  7347. // returns:
  7348. // A handle to restore focus/selection, to be passed to `dijit.focus`
  7349. var node = !focus.curNode || (menu && dom.isDescendant(focus.curNode, menu.domNode)) ? dijit._prevFocus : focus.curNode;
  7350. return {
  7351. node: node,
  7352. bookmark: node && (node == focus.curNode) && win.withGlobal(openedForWindow || win.global, dijit.getBookmark),
  7353. openedForWindow: openedForWindow
  7354. }; // Object
  7355. },
  7356. // _activeStack: dijit._Widget[]
  7357. // List of currently active widgets (focused widget and it's ancestors)
  7358. _activeStack: [],
  7359. registerIframe: function(/*DomNode*/ iframe){
  7360. // summary:
  7361. // Registers listeners on the specified iframe so that any click
  7362. // or focus event on that iframe (or anything in it) is reported
  7363. // as a focus/click event on the <iframe> itself.
  7364. // description:
  7365. // Currently only used by editor.
  7366. // returns:
  7367. // Handle to pass to unregisterIframe()
  7368. return focus.registerIframe(iframe);
  7369. },
  7370. unregisterIframe: function(/*Object*/ handle){
  7371. // summary:
  7372. // Unregisters listeners on the specified iframe created by registerIframe.
  7373. // After calling be sure to delete or null out the handle itself.
  7374. // handle:
  7375. // Handle returned by registerIframe()
  7376. handle && handle.remove();
  7377. },
  7378. registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){
  7379. // summary:
  7380. // Registers listeners on the specified window (either the main
  7381. // window or an iframe's window) to detect when the user has clicked somewhere
  7382. // or focused somewhere.
  7383. // description:
  7384. // Users should call registerIframe() instead of this method.
  7385. // targetWindow:
  7386. // If specified this is the window associated with the iframe,
  7387. // i.e. iframe.contentWindow.
  7388. // effectiveNode:
  7389. // If specified, report any focus events inside targetWindow as
  7390. // an event on effectiveNode, rather than on evt.target.
  7391. // returns:
  7392. // Handle to pass to unregisterWin()
  7393. return focus.registerWin(targetWindow, effectiveNode);
  7394. },
  7395. unregisterWin: function(/*Handle*/ handle){
  7396. // summary:
  7397. // Unregisters listeners on the specified window (either the main
  7398. // window or an iframe's window) according to handle returned from registerWin().
  7399. // After calling be sure to delete or null out the handle itself.
  7400. handle && handle.remove();
  7401. }
  7402. });
  7403. // Override focus singleton's focus function so that dijit.focus()
  7404. // has backwards compatible behavior of restoring selection (although
  7405. // probably no one is using that).
  7406. focus.focus = function(/*Object || DomNode */ handle){
  7407. // summary:
  7408. // Sets the focused node and the selection according to argument.
  7409. // To set focus to an iframe's content, pass in the iframe itself.
  7410. // handle:
  7411. // object returned by get(), or a DomNode
  7412. if(!handle){ return; }
  7413. var node = "node" in handle ? handle.node : handle, // because handle is either DomNode or a composite object
  7414. bookmark = handle.bookmark,
  7415. openedForWindow = handle.openedForWindow,
  7416. collapsed = bookmark ? bookmark.isCollapsed : false;
  7417. // Set the focus
  7418. // Note that for iframe's we need to use the <iframe> to follow the parentNode chain,
  7419. // but we need to set focus to iframe.contentWindow
  7420. if(node){
  7421. var focusNode = (node.tagName.toLowerCase() == "iframe") ? node.contentWindow : node;
  7422. if(focusNode && focusNode.focus){
  7423. try{
  7424. // Gecko throws sometimes if setting focus is impossible,
  7425. // node not displayed or something like that
  7426. focusNode.focus();
  7427. }catch(e){/*quiet*/}
  7428. }
  7429. focus._onFocusNode(node);
  7430. }
  7431. // set the selection
  7432. // do not need to restore if current selection is not empty
  7433. // (use keyboard to select a menu item) or if previous selection was collapsed
  7434. // as it may cause focus shift (Esp in IE).
  7435. if(bookmark && win.withGlobal(openedForWindow || win.global, dijit.isCollapsed) && !collapsed){
  7436. if(openedForWindow){
  7437. openedForWindow.focus();
  7438. }
  7439. try{
  7440. win.withGlobal(openedForWindow || win.global, dijit.moveToBookmark, null, [bookmark]);
  7441. }catch(e2){
  7442. /*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
  7443. }
  7444. }
  7445. };
  7446. // For back compatibility, monitor changes to focused node and active widget stack,
  7447. // publishing events and copying changes from focus manager variables into dijit (top level) variables
  7448. focus.watch("curNode", function(name, oldVal, newVal){
  7449. dijit._curFocus = newVal;
  7450. dijit._prevFocus = oldVal;
  7451. if(newVal){
  7452. topic.publish("focusNode", newVal); // publish
  7453. }
  7454. });
  7455. focus.watch("activeStack", function(name, oldVal, newVal){
  7456. dijit._activeStack = newVal;
  7457. });
  7458. focus.on("widget-blur", function(widget, by){
  7459. topic.publish("widgetBlur", widget, by); // publish
  7460. });
  7461. focus.on("widget-focus", function(widget, by){
  7462. topic.publish("widgetFocus", widget, by); // publish
  7463. });
  7464. return dijit;
  7465. });
  7466. },
  7467. 'dojox/mobile/ListItem':function(){
  7468. define("dojox/mobile/ListItem", [
  7469. "dojo/_base/array",
  7470. "dojo/_base/connect",
  7471. "dojo/_base/declare",
  7472. "dojo/_base/lang",
  7473. "dojo/dom-class",
  7474. "dojo/dom-construct",
  7475. "dojo/has",
  7476. "./common",
  7477. "./_ItemBase",
  7478. "./TransitionEvent"
  7479. ], function(array, connect, declare, lang, domClass, domConstruct, has, common, ItemBase, TransitionEvent){
  7480. /*=====
  7481. var ItemBase = dojox.mobile._ItemBase;
  7482. =====*/
  7483. // module:
  7484. // dojox/mobile/ListItem
  7485. // summary:
  7486. // An item of either RoundRectList or EdgeToEdgeList.
  7487. return declare("dojox.mobile.ListItem", ItemBase, {
  7488. // summary:
  7489. // An item of either RoundRectList or EdgeToEdgeList.
  7490. // description:
  7491. // ListItem represents an item of either RoundRectList or
  7492. // EdgeToEdgeList. There are three ways to move to a different
  7493. // view, moveTo, href, and url. You can choose only one of them.
  7494. // rightText: String
  7495. // A right-aligned text to display on the item.
  7496. rightText: "",
  7497. // rightIcon: String
  7498. // An icon to display at the right hand side of the item. The value
  7499. // can be either a path for an image file or a class name of a DOM
  7500. // button.
  7501. rightIcon: "",
  7502. // rightIcon2: String
  7503. // An icon to display at the left of the rightIcon. The value can
  7504. // be either a path for an image file or a class name of a DOM
  7505. // button.
  7506. rightIcon2: "",
  7507. // anchorLabel: Boolean
  7508. // If true, the label text becomes a clickable anchor text. When
  7509. // the user clicks on the text, the onAnchorLabelClicked handler is
  7510. // called. You can override or connect to the handler and implement
  7511. // any action. The handler has no default action.
  7512. anchorLabel: false,
  7513. // noArrow: Boolean
  7514. // If true, the right hand side arrow is not displayed.
  7515. noArrow: false,
  7516. // selected: Boolean
  7517. // If true, the item is highlighted to indicate it is selected.
  7518. selected: false,
  7519. // checked: Boolean
  7520. // If true, a check mark is displayed at the right of the item.
  7521. checked: false,
  7522. // arrowClass: String
  7523. // An icon to display as an arrow. The value can be either a path
  7524. // for an image file or a class name of a DOM button.
  7525. arrowClass: "mblDomButtonArrow",
  7526. // checkClass: String
  7527. // An icon to display as a check mark. The value can be either a
  7528. // path for an image file or a class name of a DOM button.
  7529. checkClass: "mblDomButtonCheck",
  7530. // variableHeight: Boolean
  7531. // If true, the height of the item varies according to its
  7532. // content. In dojo 1.6 or older, the "mblVariableHeight" class was
  7533. // used for this purpose. In dojo 1.7, adding the mblVariableHeight
  7534. // class still works for backward compatibility.
  7535. variableHeight: false,
  7536. // rightIconTitle: String
  7537. // An alt text for the right icon.
  7538. rightIconTitle: "",
  7539. // rightIcon2Title: String
  7540. // An alt text for the right icon2.
  7541. rightIcon2Title: "",
  7542. // btnClass: String
  7543. // Deprecated. For backward compatibility.
  7544. btnClass: "",
  7545. // btnClass2: String
  7546. // Deprecated. For backward compatibility.
  7547. btnClass2: "",
  7548. // tag: String
  7549. // A name of html tag to create as domNode.
  7550. tag: "li",
  7551. postMixInProperties: function(){
  7552. // for backward compatibility
  7553. if(this.btnClass){
  7554. this.rightIcon = this.btnClass;
  7555. }
  7556. this._setBtnClassAttr = this._setRightIconAttr;
  7557. this._setBtnClass2Attr = this._setRightIcon2Attr;
  7558. },
  7559. buildRendering: function(){
  7560. this.domNode = this.srcNodeRef || domConstruct.create(this.tag);
  7561. this.inherited(arguments);
  7562. this.domNode.className = "mblListItem" + (this.selected ? " mblItemSelected" : "");
  7563. // label
  7564. var box = this.box = domConstruct.create("DIV");
  7565. box.className = "mblListItemTextBox";
  7566. if(this.anchorLabel){
  7567. box.style.cursor = "pointer";
  7568. }
  7569. var r = this.srcNodeRef;
  7570. if(r && !this.label){
  7571. this.label = "";
  7572. for(var i = 0, len = r.childNodes.length; i < len; i++){
  7573. var n = r.firstChild;
  7574. if(n.nodeType === 3 && lang.trim(n.nodeValue) !== ""){
  7575. n.nodeValue = this._cv ? this._cv(n.nodeValue) : n.nodeValue;
  7576. this.labelNode = domConstruct.create("SPAN", {className:"mblListItemLabel"});
  7577. this.labelNode.appendChild(n);
  7578. n = this.labelNode;
  7579. }
  7580. box.appendChild(n);
  7581. }
  7582. }
  7583. if(!this.labelNode){
  7584. this.labelNode = domConstruct.create("SPAN", {className:"mblListItemLabel"}, box);
  7585. }
  7586. if(this.anchorLabel){
  7587. box.style.display = "inline"; // to narrow the text region
  7588. }
  7589. var a = this.anchorNode = domConstruct.create("A");
  7590. a.className = "mblListItemAnchor";
  7591. this.domNode.appendChild(a);
  7592. a.appendChild(box);
  7593. },
  7594. startup: function(){
  7595. if(this._started){ return; }
  7596. this.inheritParams();
  7597. var parent = this.getParent();
  7598. if(this.moveTo || this.href || this.url || this.clickable || (parent && parent.select)){
  7599. this._onClickHandle = this.connect(this.anchorNode, "onclick", "onClick");
  7600. }
  7601. this.setArrow();
  7602. if(domClass.contains(this.domNode, "mblVariableHeight")){
  7603. this.variableHeight = true;
  7604. }
  7605. if(this.variableHeight){
  7606. domClass.add(this.domNode, "mblVariableHeight");
  7607. setTimeout(lang.hitch(this, "layoutVariableHeight"));
  7608. }
  7609. this.set("icon", this.icon); // _setIconAttr may be called twice but this is necessary for offline instantiation
  7610. if(!this.checked && this.checkClass.indexOf(',') !== -1){
  7611. this.set("checked", this.checked);
  7612. }
  7613. this.inherited(arguments);
  7614. },
  7615. resize: function(){
  7616. if(this.variableHeight){
  7617. this.layoutVariableHeight();
  7618. }
  7619. },
  7620. onClick: function(e){
  7621. var a = e.currentTarget;
  7622. var li = a.parentNode;
  7623. if(domClass.contains(li, "mblItemSelected")){ return; } // already selected
  7624. if(this.anchorLabel){
  7625. for(var p = e.target; p.tagName !== this.tag.toUpperCase(); p = p.parentNode){
  7626. if(p.className == "mblListItemTextBox"){
  7627. domClass.add(p, "mblListItemTextBoxSelected");
  7628. setTimeout(function(){
  7629. domClass.remove(p, "mblListItemTextBoxSelected");
  7630. }, has("android") ? 300 : 1000);
  7631. this.onAnchorLabelClicked(e);
  7632. return;
  7633. }
  7634. }
  7635. }
  7636. var parent = this.getParent();
  7637. if(parent.select){
  7638. if(parent.select === "single"){
  7639. if(!this.checked){
  7640. this.set("checked", true);
  7641. }
  7642. }else if(parent.select === "multiple"){
  7643. this.set("checked", !this.checked);
  7644. }
  7645. }
  7646. this.select();
  7647. if (this.href && this.hrefTarget) {
  7648. common.openWindow(this.href, this.hrefTarget);
  7649. return;
  7650. }
  7651. var transOpts;
  7652. if(this.moveTo || this.href || this.url || this.scene){
  7653. transOpts = {moveTo: this.moveTo, href: this.href, url: this.url, scene: this.scene, transition: this.transition, transitionDir: this.transitionDir};
  7654. }else if(this.transitionOptions){
  7655. transOpts = this.transitionOptions;
  7656. }
  7657. if(transOpts){
  7658. this.setTransitionPos(e);
  7659. return new TransitionEvent(this.domNode,transOpts,e).dispatch();
  7660. }
  7661. },
  7662. select: function(){
  7663. // summary:
  7664. // Makes this widget in the selected state.
  7665. var parent = this.getParent();
  7666. if(parent.stateful){
  7667. parent.deselectAll();
  7668. }else{
  7669. var _this = this;
  7670. setTimeout(function(){
  7671. _this.deselect();
  7672. }, has("android") ? 300 : 1000);
  7673. }
  7674. domClass.add(this.domNode, "mblItemSelected");
  7675. },
  7676. deselect: function(){
  7677. // summary:
  7678. // Makes this widget in the deselected state.
  7679. domClass.remove(this.domNode, "mblItemSelected");
  7680. },
  7681. onAnchorLabelClicked: function(e){
  7682. // summary:
  7683. // Stub function to connect to from your application.
  7684. },
  7685. layoutVariableHeight: function(){
  7686. var h = this.anchorNode.offsetHeight;
  7687. if(h === this.anchorNodeHeight){ return; }
  7688. this.anchorNodeHeight = h;
  7689. array.forEach([
  7690. this.rightTextNode,
  7691. this.rightIcon2Node,
  7692. this.rightIconNode,
  7693. this.iconNode
  7694. ], function(n){
  7695. if(n){
  7696. var t = Math.round((h - n.offsetHeight) / 2);
  7697. n.style.marginTop = t + "px";
  7698. }
  7699. });
  7700. },
  7701. setArrow: function(){
  7702. // summary:
  7703. // Sets the arrow icon if necessary.
  7704. if(this.checked){ return; }
  7705. var c = "";
  7706. var parent = this.getParent();
  7707. if(this.moveTo || this.href || this.url || this.clickable){
  7708. if(!this.noArrow && !(parent && parent.stateful)){
  7709. c = this.arrowClass;
  7710. }
  7711. }
  7712. if(c){
  7713. this._setRightIconAttr(c);
  7714. }
  7715. },
  7716. _setIconAttr: function(icon){
  7717. if(!this.getParent()){ return; } // icon may be invalid because inheritParams is not called yet
  7718. this.icon = icon;
  7719. var a = this.anchorNode;
  7720. if(!this.iconNode){
  7721. if(icon){
  7722. var ref = this.rightIconNode || this.rightIcon2Node || this.rightTextNode || this.box;
  7723. this.iconNode = domConstruct.create("DIV", {className:"mblListItemIcon"}, ref, "before");
  7724. }
  7725. }else{
  7726. domConstruct.empty(this.iconNode);
  7727. }
  7728. if(icon && icon !== "none"){
  7729. common.createIcon(icon, this.iconPos, null, this.alt, this.iconNode);
  7730. if(this.iconPos){
  7731. domClass.add(this.iconNode.firstChild, "mblListItemSpriteIcon");
  7732. }
  7733. domClass.remove(a, "mblListItemAnchorNoIcon");
  7734. }else{
  7735. domClass.add(a, "mblListItemAnchorNoIcon");
  7736. }
  7737. },
  7738. _setCheckedAttr: function(/*Boolean*/checked){
  7739. var parent = this.getParent();
  7740. if(parent && parent.select === "single" && checked){
  7741. array.forEach(parent.getChildren(), function(child){
  7742. child.set("checked", false);
  7743. });
  7744. }
  7745. this._setRightIconAttr(this.checkClass);
  7746. var icons = this.rightIconNode.childNodes;
  7747. if(icons.length === 1){
  7748. this.rightIconNode.style.display = checked ? "" : "none";
  7749. }else{
  7750. icons[0].style.display = checked ? "" : "none";
  7751. icons[1].style.display = !checked ? "" : "none";
  7752. }
  7753. domClass.toggle(this.domNode, "mblListItemChecked", checked);
  7754. if(parent && this.checked !== checked){
  7755. parent.onCheckStateChanged(this, checked);
  7756. }
  7757. this.checked = checked;
  7758. },
  7759. _setRightTextAttr: function(/*String*/text){
  7760. if(!this.rightTextNode){
  7761. this.rightTextNode = domConstruct.create("DIV", {className:"mblListItemRightText"}, this.box, "before");
  7762. }
  7763. this.rightText = text;
  7764. this.rightTextNode.innerHTML = this._cv ? this._cv(text) : text;
  7765. },
  7766. _setRightIconAttr: function(/*String*/icon){
  7767. if(!this.rightIconNode){
  7768. var ref = this.rightIcon2Node || this.rightTextNode || this.box;
  7769. this.rightIconNode = domConstruct.create("DIV", {className:"mblListItemRightIcon"}, ref, "before");
  7770. }else{
  7771. domConstruct.empty(this.rightIconNode);
  7772. }
  7773. this.rightIcon = icon;
  7774. var arr = (icon || "").split(/,/);
  7775. if(arr.length === 1){
  7776. common.createIcon(icon, null, null, this.rightIconTitle, this.rightIconNode);
  7777. }else{
  7778. common.createIcon(arr[0], null, null, this.rightIconTitle, this.rightIconNode);
  7779. common.createIcon(arr[1], null, null, this.rightIconTitle, this.rightIconNode);
  7780. }
  7781. },
  7782. _setRightIcon2Attr: function(/*String*/icon){
  7783. if(!this.rightIcon2Node){
  7784. var ref = this.rightTextNode || this.box;
  7785. this.rightIcon2Node = domConstruct.create("DIV", {className:"mblListItemRightIcon2"}, ref, "before");
  7786. }else{
  7787. domConstruct.empty(this.rightIcon2Node);
  7788. }
  7789. this.rightIcon2 = icon;
  7790. common.createIcon(icon, null, null, this.rightIcon2Title, this.rightIcon2Node);
  7791. },
  7792. _setLabelAttr: function(/*String*/text){
  7793. this.label = text;
  7794. this.labelNode.innerHTML = this._cv ? this._cv(text) : text;
  7795. }
  7796. });
  7797. });
  7798. },
  7799. 'dojox/mobile/app/StageController':function(){
  7800. // wrapped by build app
  7801. define(["dijit","dojo","dojox","dojo/require!dojox/mobile/app/SceneController"], function(dijit,dojo,dojox){
  7802. dojo.provide("dojox.mobile.app.StageController");
  7803. dojo.experimental("dojox.mobile.app.StageController");
  7804. dojo.require("dojox.mobile.app.SceneController");
  7805. dojo.declare("dojox.mobile.app.StageController", null,{
  7806. // scenes: Array
  7807. // The list of scenes currently in existance in the app.
  7808. scenes: null,
  7809. effect: "fade",
  7810. constructor: function(node){
  7811. this.domNode = node;
  7812. this.scenes = [];
  7813. if(dojo.config.mobileAnim){
  7814. this.effect = dojo.config.mobileAnim;
  7815. }
  7816. },
  7817. getActiveSceneController: function(){
  7818. return this.scenes[this.scenes.length - 1];
  7819. },
  7820. pushScene: function(sceneName, params){
  7821. if(this._opInProgress){
  7822. return;
  7823. }
  7824. this._opInProgress = true;
  7825. // Push new scenes as the first element on the page.
  7826. var node = dojo.create("div", {
  7827. "class": "scene-wrapper",
  7828. style: {
  7829. visibility: "hidden"
  7830. }
  7831. }, this.domNode);
  7832. var controller = new dojox.mobile.app.SceneController({}, node);
  7833. if(this.scenes.length > 0){
  7834. this.scenes[this.scenes.length -1].assistant.deactivate();
  7835. }
  7836. this.scenes.push(controller);
  7837. var _this = this;
  7838. dojo.forEach(this.scenes, this.setZIndex);
  7839. controller.stageController = this;
  7840. controller.init(sceneName, params).addCallback(function(){
  7841. if(_this.scenes.length == 1){
  7842. controller.domNode.style.visibility = "visible";
  7843. _this.scenes[_this.scenes.length - 1].assistant.activate(params);
  7844. _this._opInProgress = false;
  7845. }else{
  7846. _this.scenes[_this.scenes.length - 2]
  7847. .performTransition(
  7848. _this.scenes[_this.scenes.length - 1].domNode,
  7849. 1,
  7850. _this.effect,
  7851. null,
  7852. function(){
  7853. // When the scene is ready, activate it.
  7854. _this.scenes[_this.scenes.length - 1].assistant.activate(params);
  7855. _this._opInProgress = false;
  7856. });
  7857. }
  7858. });
  7859. },
  7860. setZIndex: function(controller, idx){
  7861. dojo.style(controller.domNode, "zIndex", idx + 1);
  7862. },
  7863. popScene: function(data){
  7864. // performTransition: function(/*String*/moveTo, /*Number*/dir, /*String*/transition,
  7865. // /*Object|null*/context, /*String|Function*/method /*optional args*/){
  7866. if(this._opInProgress){
  7867. return;
  7868. }
  7869. var _this = this;
  7870. if(this.scenes.length > 1){
  7871. this._opInProgress = true;
  7872. this.scenes[_this.scenes.length - 2].assistant.activate(data);
  7873. this.scenes[_this.scenes.length - 1]
  7874. .performTransition(
  7875. _this.scenes[this.scenes.length - 2].domNode,
  7876. -1,
  7877. this.effect,
  7878. null,
  7879. function(){
  7880. // When the scene is no longer visible, destroy it
  7881. _this._destroyScene(_this.scenes[_this.scenes.length - 1]);
  7882. _this.scenes.splice(_this.scenes.length - 1, 1);
  7883. _this._opInProgress = false;
  7884. });
  7885. }else{
  7886. console.log("cannot pop the scene if there is just one");
  7887. }
  7888. },
  7889. popScenesTo: function(sceneName, data){
  7890. if(this._opInProgress){
  7891. return;
  7892. }
  7893. while(this.scenes.length > 2 &&
  7894. this.scenes[this.scenes.length - 2].sceneName != sceneName){
  7895. this._destroyScene(this.scenes[this.scenes.length - 2]);
  7896. this.scenes.splice(this.scenes.length - 2, 1);
  7897. }
  7898. this.popScene(data);
  7899. },
  7900. _destroyScene: function(scene){
  7901. scene.assistant.deactivate();
  7902. scene.assistant.destroy();
  7903. scene.destroyRecursive();
  7904. }
  7905. });
  7906. });
  7907. },
  7908. 'dijit/place':function(){
  7909. define("dijit/place", [
  7910. "dojo/_base/array", // array.forEach array.map array.some
  7911. "dojo/dom-geometry", // domGeometry.position
  7912. "dojo/dom-style", // domStyle.getComputedStyle
  7913. "dojo/_base/kernel", // kernel.deprecated
  7914. "dojo/_base/window", // win.body
  7915. "./Viewport", // getEffectiveBox
  7916. "." // dijit (defining dijit.place to match API doc)
  7917. ], function(array, domGeometry, domStyle, kernel, win, Viewport, dijit){
  7918. // module:
  7919. // dijit/place
  7920. // summary:
  7921. // Code to place a popup relative to another node
  7922. function _place(/*DomNode*/ node, choices, layoutNode, aroundNodeCoords){
  7923. // summary:
  7924. // Given a list of spots to put node, put it at the first spot where it fits,
  7925. // of if it doesn't fit anywhere then the place with the least overflow
  7926. // choices: Array
  7927. // Array of elements like: {corner: 'TL', pos: {x: 10, y: 20} }
  7928. // Above example says to put the top-left corner of the node at (10,20)
  7929. // layoutNode: Function(node, aroundNodeCorner, nodeCorner, size)
  7930. // for things like tooltip, they are displayed differently (and have different dimensions)
  7931. // based on their orientation relative to the parent. This adjusts the popup based on orientation.
  7932. // It also passes in the available size for the popup, which is useful for tooltips to
  7933. // tell them that their width is limited to a certain amount. layoutNode() may return a value expressing
  7934. // how much the popup had to be modified to fit into the available space. This is used to determine
  7935. // what the best placement is.
  7936. // aroundNodeCoords: Object
  7937. // Size of aroundNode, ex: {w: 200, h: 50}
  7938. // get {x: 10, y: 10, w: 100, h:100} type obj representing position of
  7939. // viewport over document
  7940. var view = Viewport.getEffectiveBox(node.ownerDocument);
  7941. // This won't work if the node is inside a <div style="position: relative">,
  7942. // so reattach it to win.doc.body. (Otherwise, the positioning will be wrong
  7943. // and also it might get cutoff)
  7944. if(!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body"){
  7945. win.body().appendChild(node);
  7946. }
  7947. var best = null;
  7948. array.some(choices, function(choice){
  7949. var corner = choice.corner;
  7950. var pos = choice.pos;
  7951. var overflow = 0;
  7952. // calculate amount of space available given specified position of node
  7953. var spaceAvailable = {
  7954. w: {
  7955. 'L': view.l + view.w - pos.x,
  7956. 'R': pos.x - view.l,
  7957. 'M': view.w
  7958. }[corner.charAt(1)],
  7959. h: {
  7960. 'T': view.t + view.h - pos.y,
  7961. 'B': pos.y - view.t,
  7962. 'M': view.h
  7963. }[corner.charAt(0)]
  7964. };
  7965. // Clear left/right position settings set earlier so they don't interfere with calculations,
  7966. // specifically when layoutNode() (a.k.a. Tooltip.orient()) measures natural width of Tooltip
  7967. var s = node.style;
  7968. s.left = s.right = "auto";
  7969. // configure node to be displayed in given position relative to button
  7970. // (need to do this in order to get an accurate size for the node, because
  7971. // a tooltip's size changes based on position, due to triangle)
  7972. if(layoutNode){
  7973. var res = layoutNode(node, choice.aroundCorner, corner, spaceAvailable, aroundNodeCoords);
  7974. overflow = typeof res == "undefined" ? 0 : res;
  7975. }
  7976. // get node's size
  7977. var style = node.style;
  7978. var oldDisplay = style.display;
  7979. var oldVis = style.visibility;
  7980. if(style.display == "none"){
  7981. style.visibility = "hidden";
  7982. style.display = "";
  7983. }
  7984. var bb = domGeometry.position(node);
  7985. style.display = oldDisplay;
  7986. style.visibility = oldVis;
  7987. // coordinates and size of node with specified corner placed at pos,
  7988. // and clipped by viewport
  7989. var
  7990. startXpos = {
  7991. 'L': pos.x,
  7992. 'R': pos.x - bb.w,
  7993. 'M': Math.max(view.l, Math.min(view.l + view.w, pos.x + (bb.w >> 1)) - bb.w) // M orientation is more flexible
  7994. }[corner.charAt(1)],
  7995. startYpos = {
  7996. 'T': pos.y,
  7997. 'B': pos.y - bb.h,
  7998. 'M': Math.max(view.t, Math.min(view.t + view.h, pos.y + (bb.h >> 1)) - bb.h)
  7999. }[corner.charAt(0)],
  8000. startX = Math.max(view.l, startXpos),
  8001. startY = Math.max(view.t, startYpos),
  8002. endX = Math.min(view.l + view.w, startXpos + bb.w),
  8003. endY = Math.min(view.t + view.h, startYpos + bb.h),
  8004. width = endX - startX,
  8005. height = endY - startY;
  8006. overflow += (bb.w - width) + (bb.h - height);
  8007. if(best == null || overflow < best.overflow){
  8008. best = {
  8009. corner: corner,
  8010. aroundCorner: choice.aroundCorner,
  8011. x: startX,
  8012. y: startY,
  8013. w: width,
  8014. h: height,
  8015. overflow: overflow,
  8016. spaceAvailable: spaceAvailable
  8017. };
  8018. }
  8019. return !overflow;
  8020. });
  8021. // In case the best position is not the last one we checked, need to call
  8022. // layoutNode() again.
  8023. if(best.overflow && layoutNode){
  8024. layoutNode(node, best.aroundCorner, best.corner, best.spaceAvailable, aroundNodeCoords);
  8025. }
  8026. // And then position the node. Do this last, after the layoutNode() above
  8027. // has sized the node, due to browser quirks when the viewport is scrolled
  8028. // (specifically that a Tooltip will shrink to fit as though the window was
  8029. // scrolled to the left).
  8030. var s = node.style;
  8031. s.top = best.y + "px";
  8032. s.left = best.x + "px";
  8033. s.right = "auto"; // needed for FF or else tooltip goes to far left
  8034. return best;
  8035. }
  8036. /*=====
  8037. dijit.place.__Position = function(){
  8038. // x: Integer
  8039. // horizontal coordinate in pixels, relative to document body
  8040. // y: Integer
  8041. // vertical coordinate in pixels, relative to document body
  8042. this.x = x;
  8043. this.y = y;
  8044. };
  8045. =====*/
  8046. /*=====
  8047. dijit.place.__Rectangle = function(){
  8048. // x: Integer
  8049. // horizontal offset in pixels, relative to document body
  8050. // y: Integer
  8051. // vertical offset in pixels, relative to document body
  8052. // w: Integer
  8053. // width in pixels. Can also be specified as "width" for backwards-compatibility.
  8054. // h: Integer
  8055. // height in pixels. Can also be specified as "height" from backwards-compatibility.
  8056. this.x = x;
  8057. this.y = y;
  8058. this.w = w;
  8059. this.h = h;
  8060. };
  8061. =====*/
  8062. return (dijit.place = {
  8063. // summary:
  8064. // Code to place a DOMNode relative to another DOMNode.
  8065. // Load using require(["dijit/place"], function(place){ ... }).
  8066. at: function(node, pos, corners, padding){
  8067. // summary:
  8068. // Positions one of the node's corners at specified position
  8069. // such that node is fully visible in viewport.
  8070. // description:
  8071. // NOTE: node is assumed to be absolutely or relatively positioned.
  8072. // node: DOMNode
  8073. // The node to position
  8074. // pos: dijit.place.__Position
  8075. // Object like {x: 10, y: 20}
  8076. // corners: String[]
  8077. // Array of Strings representing order to try corners in, like ["TR", "BL"].
  8078. // Possible values are:
  8079. // * "BL" - bottom left
  8080. // * "BR" - bottom right
  8081. // * "TL" - top left
  8082. // * "TR" - top right
  8083. // padding: dijit.place.__Position?
  8084. // optional param to set padding, to put some buffer around the element you want to position.
  8085. // example:
  8086. // Try to place node's top right corner at (10,20).
  8087. // If that makes node go (partially) off screen, then try placing
  8088. // bottom left corner at (10,20).
  8089. // | place(node, {x: 10, y: 20}, ["TR", "BL"])
  8090. var choices = array.map(corners, function(corner){
  8091. var c = { corner: corner, pos: {x:pos.x,y:pos.y} };
  8092. if(padding){
  8093. c.pos.x += corner.charAt(1) == 'L' ? padding.x : -padding.x;
  8094. c.pos.y += corner.charAt(0) == 'T' ? padding.y : -padding.y;
  8095. }
  8096. return c;
  8097. });
  8098. return _place(node, choices);
  8099. },
  8100. around: function(
  8101. /*DomNode*/ node,
  8102. /*DomNode || dijit.place.__Rectangle*/ anchor,
  8103. /*String[]*/ positions,
  8104. /*Boolean*/ leftToRight,
  8105. /*Function?*/ layoutNode){
  8106. // summary:
  8107. // Position node adjacent or kitty-corner to anchor
  8108. // such that it's fully visible in viewport.
  8109. //
  8110. // description:
  8111. // Place node such that corner of node touches a corner of
  8112. // aroundNode, and that node is fully visible.
  8113. //
  8114. // anchor:
  8115. // Either a DOMNode or a __Rectangle (object with x, y, width, height).
  8116. //
  8117. // positions:
  8118. // Ordered list of positions to try matching up.
  8119. // * before: places drop down to the left of the anchor node/widget, or to the right in the case
  8120. // of RTL scripts like Hebrew and Arabic; aligns either the top of the drop down
  8121. // with the top of the anchor, or the bottom of the drop down with bottom of the anchor.
  8122. // * after: places drop down to the right of the anchor node/widget, or to the left in the case
  8123. // of RTL scripts like Hebrew and Arabic; aligns either the top of the drop down
  8124. // with the top of the anchor, or the bottom of the drop down with bottom of the anchor.
  8125. // * before-centered: centers drop down to the left of the anchor node/widget, or to the right
  8126. // in the case of RTL scripts like Hebrew and Arabic
  8127. // * after-centered: centers drop down to the right of the anchor node/widget, or to the left
  8128. // in the case of RTL scripts like Hebrew and Arabic
  8129. // * above-centered: drop down is centered above anchor node
  8130. // * above: drop down goes above anchor node, left sides aligned
  8131. // * above-alt: drop down goes above anchor node, right sides aligned
  8132. // * below-centered: drop down is centered above anchor node
  8133. // * below: drop down goes below anchor node
  8134. // * below-alt: drop down goes below anchor node, right sides aligned
  8135. //
  8136. // layoutNode: Function(node, aroundNodeCorner, nodeCorner)
  8137. // For things like tooltip, they are displayed differently (and have different dimensions)
  8138. // based on their orientation relative to the parent. This adjusts the popup based on orientation.
  8139. //
  8140. // leftToRight:
  8141. // True if widget is LTR, false if widget is RTL. Affects the behavior of "above" and "below"
  8142. // positions slightly.
  8143. //
  8144. // example:
  8145. // | placeAroundNode(node, aroundNode, {'BL':'TL', 'TR':'BR'});
  8146. // This will try to position node such that node's top-left corner is at the same position
  8147. // as the bottom left corner of the aroundNode (ie, put node below
  8148. // aroundNode, with left edges aligned). If that fails it will try to put
  8149. // the bottom-right corner of node where the top right corner of aroundNode is
  8150. // (ie, put node above aroundNode, with right edges aligned)
  8151. //
  8152. // if around is a DOMNode (or DOMNode id), convert to coordinates
  8153. var aroundNodePos = (typeof anchor == "string" || "offsetWidth" in anchor)
  8154. ? domGeometry.position(anchor, true)
  8155. : anchor;
  8156. // Compute position and size of visible part of anchor (it may be partially hidden by ancestor nodes w/scrollbars)
  8157. if(anchor.parentNode){
  8158. // ignore nodes between position:relative and position:absolute
  8159. var sawPosAbsolute = domStyle.getComputedStyle(anchor).position == "absolute";
  8160. var parent = anchor.parentNode;
  8161. while(parent && parent.nodeType == 1 && parent.nodeName != "BODY"){ //ignoring the body will help performance
  8162. var parentPos = domGeometry.position(parent, true),
  8163. pcs = domStyle.getComputedStyle(parent);
  8164. if(/relative|absolute/.test(pcs.position)){
  8165. sawPosAbsolute = false;
  8166. }
  8167. if(!sawPosAbsolute && /hidden|auto|scroll/.test(pcs.overflow)){
  8168. var bottomYCoord = Math.min(aroundNodePos.y + aroundNodePos.h, parentPos.y + parentPos.h);
  8169. var rightXCoord = Math.min(aroundNodePos.x + aroundNodePos.w, parentPos.x + parentPos.w);
  8170. aroundNodePos.x = Math.max(aroundNodePos.x, parentPos.x);
  8171. aroundNodePos.y = Math.max(aroundNodePos.y, parentPos.y);
  8172. aroundNodePos.h = bottomYCoord - aroundNodePos.y;
  8173. aroundNodePos.w = rightXCoord - aroundNodePos.x;
  8174. }
  8175. if(pcs.position == "absolute"){
  8176. sawPosAbsolute = true;
  8177. }
  8178. parent = parent.parentNode;
  8179. }
  8180. }
  8181. var x = aroundNodePos.x,
  8182. y = aroundNodePos.y,
  8183. width = "w" in aroundNodePos ? aroundNodePos.w : (aroundNodePos.w = aroundNodePos.width),
  8184. height = "h" in aroundNodePos ? aroundNodePos.h : (kernel.deprecated("place.around: dijit.place.__Rectangle: { x:"+x+", y:"+y+", height:"+aroundNodePos.height+", width:"+width+" } has been deprecated. Please use { x:"+x+", y:"+y+", h:"+aroundNodePos.height+", w:"+width+" }", "", "2.0"), aroundNodePos.h = aroundNodePos.height);
  8185. // Convert positions arguments into choices argument for _place()
  8186. var choices = [];
  8187. function push(aroundCorner, corner){
  8188. choices.push({
  8189. aroundCorner: aroundCorner,
  8190. corner: corner,
  8191. pos: {
  8192. x: {
  8193. 'L': x,
  8194. 'R': x + width,
  8195. 'M': x + (width >> 1)
  8196. }[aroundCorner.charAt(1)],
  8197. y: {
  8198. 'T': y,
  8199. 'B': y + height,
  8200. 'M': y + (height >> 1)
  8201. }[aroundCorner.charAt(0)]
  8202. }
  8203. })
  8204. }
  8205. array.forEach(positions, function(pos){
  8206. var ltr = leftToRight;
  8207. switch(pos){
  8208. case "above-centered":
  8209. push("TM", "BM");
  8210. break;
  8211. case "below-centered":
  8212. push("BM", "TM");
  8213. break;
  8214. case "after-centered":
  8215. ltr = !ltr;
  8216. // fall through
  8217. case "before-centered":
  8218. push(ltr ? "ML" : "MR", ltr ? "MR" : "ML");
  8219. break;
  8220. case "after":
  8221. ltr = !ltr;
  8222. // fall through
  8223. case "before":
  8224. push(ltr ? "TL" : "TR", ltr ? "TR" : "TL");
  8225. push(ltr ? "BL" : "BR", ltr ? "BR" : "BL");
  8226. break;
  8227. case "below-alt":
  8228. ltr = !ltr;
  8229. // fall through
  8230. case "below":
  8231. // first try to align left borders, next try to align right borders (or reverse for RTL mode)
  8232. push(ltr ? "BL" : "BR", ltr ? "TL" : "TR");
  8233. push(ltr ? "BR" : "BL", ltr ? "TR" : "TL");
  8234. break;
  8235. case "above-alt":
  8236. ltr = !ltr;
  8237. // fall through
  8238. case "above":
  8239. // first try to align left borders, next try to align right borders (or reverse for RTL mode)
  8240. push(ltr ? "TL" : "TR", ltr ? "BL" : "BR");
  8241. push(ltr ? "TR" : "TL", ltr ? "BR" : "BL");
  8242. break;
  8243. default:
  8244. // To assist dijit/_base/place, accept arguments of type {aroundCorner: "BL", corner: "TL"}.
  8245. // Not meant to be used directly.
  8246. push(pos.aroundCorner, pos.corner);
  8247. }
  8248. });
  8249. var position = _place(node, choices, layoutNode, {w: width, h: height});
  8250. position.aroundNodePos = aroundNodePos;
  8251. return position;
  8252. }
  8253. });
  8254. });
  8255. },
  8256. 'dojox/mobile/app/_event':function(){
  8257. // wrapped by build app
  8258. define("dojox/mobile/app/_event", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
  8259. dojo.provide("dojox.mobile.app._event");
  8260. dojo.experimental("dojox.mobile.app._event.js");
  8261. dojo.mixin(dojox.mobile.app, {
  8262. eventMap: {},
  8263. connectFlick: function(target, context, method){
  8264. // summary:
  8265. // Listens for a flick event on a DOM node. If the mouse/touch
  8266. // moves more than 15 pixels in any given direction it is a flick.
  8267. // The synthetic event fired specifies the direction as
  8268. // <ul>
  8269. // <li><b>'ltr'</b> Left To Right</li>
  8270. // <li><b>'rtl'</b> Right To Left</li>
  8271. // <li><b>'ttb'</b> Top To Bottom</li>
  8272. // <li><b>'btt'</b> Bottom To Top</li>
  8273. // </ul>
  8274. // target: Node
  8275. // The DOM node to connect to
  8276. var startX;
  8277. var startY;
  8278. var isFlick = false;
  8279. var currentX;
  8280. var currentY;
  8281. var connMove;
  8282. var connUp;
  8283. var direction;
  8284. var time;
  8285. // Listen to to the mousedown/touchstart event
  8286. var connDown = dojo.connect("onmousedown", target, function(event){
  8287. isFlick = false;
  8288. startX = event.targetTouches ? event.targetTouches[0].clientX : event.clientX;
  8289. startY = event.targetTouches ? event.targetTouches[0].clientY : event.clientY;
  8290. time = (new Date()).getTime();
  8291. connMove = dojo.connect(target, "onmousemove", onMove);
  8292. connUp = dojo.connect(target, "onmouseup", onUp);
  8293. });
  8294. // The function that handles the mousemove/touchmove event
  8295. var onMove = function(event){
  8296. dojo.stopEvent(event);
  8297. currentX = event.targetTouches ? event.targetTouches[0].clientX : event.clientX;
  8298. currentY = event.targetTouches ? event.targetTouches[0].clientY : event.clientY;
  8299. if(Math.abs(Math.abs(currentX) - Math.abs(startX)) > 15){
  8300. isFlick = true;
  8301. direction = (currentX > startX) ? "ltr" : "rtl";
  8302. }else if(Math.abs(Math.abs(currentY) - Math.abs(startY)) > 15){
  8303. isFlick = true;
  8304. direction = (currentY > startY) ? "ttb" : "btt";
  8305. }
  8306. };
  8307. var onUp = function(event){
  8308. dojo.stopEvent(event);
  8309. connMove && dojo.disconnect(connMove);
  8310. connUp && dojo.disconnect(connUp);
  8311. if(isFlick){
  8312. var flickEvt = {
  8313. target: target,
  8314. direction: direction,
  8315. duration: (new Date()).getTime() - time
  8316. };
  8317. if(context && method){
  8318. context[method](flickEvt);
  8319. }else{
  8320. method(flickEvt);
  8321. }
  8322. }
  8323. };
  8324. }
  8325. });
  8326. dojox.mobile.app.isIPhone = (dojo.isSafari
  8327. && (navigator.userAgent.indexOf("iPhone") > -1 ||
  8328. navigator.userAgent.indexOf("iPod") > -1
  8329. ));
  8330. dojox.mobile.app.isWebOS = (navigator.userAgent.indexOf("webOS") > -1);
  8331. dojox.mobile.app.isAndroid = (navigator.userAgent.toLowerCase().indexOf("android") > -1);
  8332. if(dojox.mobile.app.isIPhone || dojox.mobile.app.isAndroid){
  8333. // We are touchable.
  8334. // Override the dojo._connect function to replace mouse events with touch events
  8335. dojox.mobile.app.eventMap = {
  8336. onmousedown: "ontouchstart",
  8337. mousedown: "ontouchstart",
  8338. onmouseup: "ontouchend",
  8339. mouseup: "ontouchend",
  8340. onmousemove: "ontouchmove",
  8341. mousemove: "ontouchmove"
  8342. };
  8343. }
  8344. dojo._oldConnect = dojo._connect;
  8345. dojo._connect = function(obj, event, context, method, dontFix){
  8346. event = dojox.mobile.app.eventMap[event] || event;
  8347. if(event == "flick" || event == "onflick"){
  8348. if(dojo.global["Mojo"]){
  8349. event = Mojo.Event.flick;
  8350. } else{
  8351. return dojox.mobile.app.connectFlick(obj, context, method);
  8352. }
  8353. }
  8354. return dojo._oldConnect(obj, event, context, method, dontFix);
  8355. };
  8356. });
  8357. },
  8358. 'dojox/mobile/_base':function(){
  8359. define("dojox/mobile/_base", [
  8360. "./common",
  8361. "./View",
  8362. "./Heading",
  8363. "./RoundRect",
  8364. "./RoundRectCategory",
  8365. "./EdgeToEdgeCategory",
  8366. "./RoundRectList",
  8367. "./EdgeToEdgeList",
  8368. "./ListItem",
  8369. "./Switch",
  8370. "./ToolBarButton",
  8371. "./ProgressIndicator"
  8372. ], function(common, View, Heading, RoundRect, RoundRectCategory, EdgeToEdgeCategory, RoundRectList, EdgeToEdgeList, ListItem, Switch, ToolBarButton, ProgressIndicator){
  8373. // module:
  8374. // dojox/mobile/_base
  8375. // summary:
  8376. // Includes the basic dojox.mobile modules
  8377. return common;
  8378. });
  8379. },
  8380. 'dojox/mobile/Button':function(){
  8381. define("dojox/mobile/Button", [
  8382. "dojo/_base/array",
  8383. "dojo/_base/declare",
  8384. "dojo/dom-class",
  8385. "dojo/dom-construct",
  8386. "dijit/_WidgetBase",
  8387. "dijit/form/_ButtonMixin",
  8388. "dijit/form/_FormWidgetMixin"
  8389. ],
  8390. function(array, declare, domClass, domConstruct, WidgetBase, ButtonMixin, FormWidgetMixin){
  8391. /*=====
  8392. WidgetBase = dijit._WidgetBase;
  8393. FormWidgetMixin = dijit.form._FormWidgetMixin;
  8394. ButtonMixin = dijit.form._ButtonMixin;
  8395. =====*/
  8396. return declare("dojox.mobile.Button", [WidgetBase, FormWidgetMixin, ButtonMixin], {
  8397. // summary:
  8398. // Non-templated BUTTON widget with a thin API wrapper for click events and setting the label
  8399. //
  8400. // description:
  8401. // Buttons can display a label, an icon, or both.
  8402. // A label should always be specified (through innerHTML) or the label
  8403. // attribute. It can be hidden via showLabel=false.
  8404. // example:
  8405. // | <button dojoType="dijit.form.Button" onClick="...">Hello world</button>
  8406. baseClass: "mblButton",
  8407. // Override automatic assigning type --> node, it causes exception on IE.
  8408. // Instead, type must be specified as this.type when the node is created, as part of the original DOM
  8409. _setTypeAttr: null,
  8410. // duration: Number
  8411. // duration of selection, milliseconds or -1 for no post-click CSS styling
  8412. duration: 1000,
  8413. _onClick: function(e){
  8414. var ret = this.inherited(arguments);
  8415. if(ret && this.duration >= 0){ // if its not a button with a state, then emulate press styles
  8416. var button = this.focusNode || this.domNode;
  8417. var newStateClasses = (this.baseClass+' '+this["class"]).split(" ");
  8418. newStateClasses = array.map(newStateClasses, function(c){ return c+"Selected"; });
  8419. domClass.add(button, newStateClasses);
  8420. setTimeout(function(){
  8421. domClass.remove(button, newStateClasses);
  8422. }, this.duration);
  8423. }
  8424. return ret;
  8425. },
  8426. isFocusable: function(){ return false; },
  8427. buildRendering: function(){
  8428. if(!this.srcNodeRef){
  8429. this.srcNodeRef = domConstruct.create("button", {"type": this.type});
  8430. }else if(this._cv){
  8431. var n = this.srcNodeRef.firstChild;
  8432. if(n && n.nodeType === 3){
  8433. n.nodeValue = this._cv(n.nodeValue);
  8434. }
  8435. }
  8436. this.inherited(arguments);
  8437. this.focusNode = this.domNode;
  8438. },
  8439. postCreate: function(){
  8440. this.inherited(arguments);
  8441. this.connect(this.domNode, "onclick", "_onClick");
  8442. },
  8443. _setLabelAttr: function(/*String*/ content){
  8444. this.inherited(arguments, [this._cv ? this._cv(content) : content]);
  8445. }
  8446. });
  8447. });
  8448. },
  8449. 'dojox/mobile/Switch':function(){
  8450. define("dojox/mobile/Switch", [
  8451. "dojo/_base/array",
  8452. "dojo/_base/connect",
  8453. "dojo/_base/declare",
  8454. "dojo/_base/event",
  8455. "dojo/_base/window",
  8456. "dojo/dom-class",
  8457. "dijit/_Contained",
  8458. "dijit/_WidgetBase",
  8459. "./sniff"
  8460. ], function(array, connect, declare, event, win, domClass, Contained, WidgetBase, has){
  8461. /*=====
  8462. Contained = dijit._Contained;
  8463. WidgetBase = dijit._WidgetBase;
  8464. =====*/
  8465. // module:
  8466. // dojox/mobile/Switch
  8467. // summary:
  8468. // A toggle switch with a sliding knob.
  8469. return declare("dojox.mobile.Switch", [WidgetBase, Contained],{
  8470. // summary:
  8471. // A toggle switch with a sliding knob.
  8472. // description:
  8473. // Switch is a toggle switch with a sliding knob. You can either
  8474. // tap or slide the knob to toggle the switch. The onStateChanged
  8475. // handler is called when the switch is manipulated.
  8476. // value: String
  8477. // The initial state of the switch. "on" or "off". The default
  8478. // value is "on".
  8479. value: "on",
  8480. // name: String
  8481. // A name for a hidden input field, which holds the current value.
  8482. name: "",
  8483. // leftLabel: String
  8484. // The left-side label of the switch.
  8485. leftLabel: "ON",
  8486. // rightLabel: String
  8487. // The right-side label of the switch.
  8488. rightLabel: "OFF",
  8489. /* internal properties */
  8490. _width: 53,
  8491. buildRendering: function(){
  8492. this.domNode = win.doc.createElement("DIV");
  8493. var c = (this.srcNodeRef && this.srcNodeRef.className) || this.className || this["class"];
  8494. this._swClass = (c || "").replace(/ .*/,"");
  8495. this.domNode.className = "mblSwitch";
  8496. var nameAttr = this.name ? " name=\"" + this.name + "\"" : "";
  8497. this.domNode.innerHTML =
  8498. '<div class="mblSwitchInner">'
  8499. + '<div class="mblSwitchBg mblSwitchBgLeft">'
  8500. + '<div class="mblSwitchText mblSwitchTextLeft"></div>'
  8501. + '</div>'
  8502. + '<div class="mblSwitchBg mblSwitchBgRight">'
  8503. + '<div class="mblSwitchText mblSwitchTextRight"></div>'
  8504. + '</div>'
  8505. + '<div class="mblSwitchKnob"></div>'
  8506. + '<input type="hidden"'+nameAttr+'></div>'
  8507. + '</div>';
  8508. var n = this.inner = this.domNode.firstChild;
  8509. this.left = n.childNodes[0];
  8510. this.right = n.childNodes[1];
  8511. this.knob = n.childNodes[2];
  8512. this.input = n.childNodes[3];
  8513. },
  8514. postCreate: function(){
  8515. this.connect(this.domNode, "onclick", "onClick");
  8516. this.connect(this.domNode, has("touch") ? "touchstart" : "onmousedown", "onTouchStart");
  8517. this._initialValue = this.value; // for reset()
  8518. },
  8519. _changeState: function(/*String*/state, /*Boolean*/anim){
  8520. var on = (state === "on");
  8521. this.left.style.display = "";
  8522. this.right.style.display = "";
  8523. this.inner.style.left = "";
  8524. if(anim){
  8525. domClass.add(this.domNode, "mblSwitchAnimation");
  8526. }
  8527. domClass.remove(this.domNode, on ? "mblSwitchOff" : "mblSwitchOn");
  8528. domClass.add(this.domNode, on ? "mblSwitchOn" : "mblSwitchOff");
  8529. var _this = this;
  8530. setTimeout(function(){
  8531. _this.left.style.display = on ? "" : "none";
  8532. _this.right.style.display = !on ? "" : "none";
  8533. domClass.remove(_this.domNode, "mblSwitchAnimation");
  8534. }, anim ? 300 : 0);
  8535. },
  8536. startup: function(){
  8537. if(this._swClass.indexOf("Round") != -1){
  8538. var r = Math.round(this.domNode.offsetHeight / 2);
  8539. this.createRoundMask(this._swClass, r, this.domNode.offsetWidth);
  8540. }
  8541. },
  8542. createRoundMask: function(className, r, w){
  8543. if(!has("webkit") || !className){ return; }
  8544. if(!this._createdMasks){ this._createdMasks = []; }
  8545. if(this._createdMasks[className]){ return; }
  8546. this._createdMasks[className] = 1;
  8547. var ctx = win.doc.getCSSCanvasContext("2d", className+"Mask", w, 100);
  8548. ctx.fillStyle = "#000000";
  8549. ctx.beginPath();
  8550. ctx.moveTo(r, 0);
  8551. ctx.arcTo(0, 0, 0, 2*r, r);
  8552. ctx.arcTo(0, 2*r, r, 2*r, r);
  8553. ctx.lineTo(w - r, 2*r);
  8554. ctx.arcTo(w, 2*r, w, r, r);
  8555. ctx.arcTo(w, 0, w - r, 0, r);
  8556. ctx.closePath();
  8557. ctx.fill();
  8558. },
  8559. onClick: function(e){
  8560. if(this._moved){ return; }
  8561. this.value = this.input.value = (this.value == "on") ? "off" : "on";
  8562. this._changeState(this.value, true);
  8563. this.onStateChanged(this.value);
  8564. },
  8565. onTouchStart: function(e){
  8566. // summary:
  8567. // Internal function to handle touchStart events.
  8568. this._moved = false;
  8569. this.innerStartX = this.inner.offsetLeft;
  8570. if(!this._conn){
  8571. this._conn = [];
  8572. this._conn.push(connect.connect(this.inner, has("touch") ? "touchmove" : "onmousemove", this, "onTouchMove"));
  8573. this._conn.push(connect.connect(this.inner, has("touch") ? "touchend" : "onmouseup", this, "onTouchEnd"));
  8574. }
  8575. this.touchStartX = e.touches ? e.touches[0].pageX : e.clientX;
  8576. this.left.style.display = "";
  8577. this.right.style.display = "";
  8578. event.stop(e);
  8579. },
  8580. onTouchMove: function(e){
  8581. // summary:
  8582. // Internal function to handle touchMove events.
  8583. e.preventDefault();
  8584. var dx;
  8585. if(e.targetTouches){
  8586. if(e.targetTouches.length != 1){ return false; }
  8587. dx = e.targetTouches[0].clientX - this.touchStartX;
  8588. }else{
  8589. dx = e.clientX - this.touchStartX;
  8590. }
  8591. var pos = this.innerStartX + dx;
  8592. var d = 10;
  8593. if(pos <= -(this._width-d)){ pos = -this._width; }
  8594. if(pos >= -d){ pos = 0; }
  8595. this.inner.style.left = pos + "px";
  8596. if(Math.abs(dx) > d){
  8597. this._moved = true;
  8598. }
  8599. },
  8600. onTouchEnd: function(e){
  8601. // summary:
  8602. // Internal function to handle touchEnd events.
  8603. array.forEach(this._conn, connect.disconnect);
  8604. this._conn = null;
  8605. if(this.innerStartX == this.inner.offsetLeft){
  8606. if(has("touch")){
  8607. var ev = win.doc.createEvent("MouseEvents");
  8608. ev.initEvent("click", true, true);
  8609. this.inner.dispatchEvent(ev);
  8610. }
  8611. return;
  8612. }
  8613. var newState = (this.inner.offsetLeft < -(this._width/2)) ? "off" : "on";
  8614. this._changeState(newState, true);
  8615. if(newState != this.value){
  8616. this.value = this.input.value = newState;
  8617. this.onStateChanged(newState);
  8618. }
  8619. },
  8620. onStateChanged: function(/*String*/newState){
  8621. // summary:
  8622. // Stub function to connect to from your application.
  8623. // description:
  8624. // Called when the state has been changed.
  8625. },
  8626. _setValueAttr: function(/*String*/value){
  8627. this._changeState(value, false);
  8628. if(this.value != value){
  8629. this.onStateChanged(value);
  8630. }
  8631. this.value = this.input.value = value;
  8632. },
  8633. _setLeftLabelAttr: function(/*String*/label){
  8634. this.leftLabel = label;
  8635. this.left.firstChild.innerHTML = this._cv ? this._cv(label) : label;
  8636. },
  8637. _setRightLabelAttr: function(/*String*/label){
  8638. this.rightLabel = label;
  8639. this.right.firstChild.innerHTML = this._cv ? this._cv(label) : label;
  8640. },
  8641. reset: function(){
  8642. // summary:
  8643. // Reset the widget's value to what it was at initialization time
  8644. this.set("value", this._initialValue);
  8645. }
  8646. });
  8647. });
  8648. },
  8649. 'dijit/focus':function(){
  8650. define("dijit/focus", [
  8651. "dojo/aspect",
  8652. "dojo/_base/declare", // declare
  8653. "dojo/dom", // domAttr.get dom.isDescendant
  8654. "dojo/dom-attr", // domAttr.get dom.isDescendant
  8655. "dojo/dom-construct", // connect to domConstruct.empty, domConstruct.destroy
  8656. "dojo/Evented",
  8657. "dojo/_base/lang", // lang.hitch
  8658. "dojo/on",
  8659. "dojo/domReady",
  8660. "dojo/_base/sniff", // has("ie")
  8661. "dojo/Stateful",
  8662. "dojo/_base/window", // win.body
  8663. "dojo/window", // winUtils.get
  8664. "./a11y", // a11y.isTabNavigable
  8665. "./registry", // registry.byId
  8666. "./main" // to set dijit.focus
  8667. ], function(aspect, declare, dom, domAttr, domConstruct, Evented, lang, on, domReady, has, Stateful, win, winUtils,
  8668. a11y, registry, dijit){
  8669. // module:
  8670. // dijit/focus
  8671. var FocusManager = declare([Stateful, Evented], {
  8672. // summary:
  8673. // Tracks the currently focused node, and which widgets are currently "active".
  8674. // Access via require(["dijit/focus"], function(focus){ ... }).
  8675. //
  8676. // A widget is considered active if it or a descendant widget has focus,
  8677. // or if a non-focusable node of this widget or a descendant was recently clicked.
  8678. //
  8679. // Call focus.watch("curNode", callback) to track the current focused DOMNode,
  8680. // or focus.watch("activeStack", callback) to track the currently focused stack of widgets.
  8681. //
  8682. // Call focus.on("widget-blur", func) or focus.on("widget-focus", ...) to monitor when
  8683. // when widgets become active/inactive
  8684. //
  8685. // Finally, focus(node) will focus a node, suppressing errors if the node doesn't exist.
  8686. // curNode: DomNode
  8687. // Currently focused item on screen
  8688. curNode: null,
  8689. // activeStack: dijit/_WidgetBase[]
  8690. // List of currently active widgets (focused widget and it's ancestors)
  8691. activeStack: [],
  8692. constructor: function(){
  8693. // Don't leave curNode/prevNode pointing to bogus elements
  8694. var check = lang.hitch(this, function(node){
  8695. if(dom.isDescendant(this.curNode, node)){
  8696. this.set("curNode", null);
  8697. }
  8698. if(dom.isDescendant(this.prevNode, node)){
  8699. this.set("prevNode", null);
  8700. }
  8701. });
  8702. aspect.before(domConstruct, "empty", check);
  8703. aspect.before(domConstruct, "destroy", check);
  8704. },
  8705. registerIframe: function(/*DomNode*/ iframe){
  8706. // summary:
  8707. // Registers listeners on the specified iframe so that any click
  8708. // or focus event on that iframe (or anything in it) is reported
  8709. // as a focus/click event on the `<iframe>` itself.
  8710. // description:
  8711. // Currently only used by editor.
  8712. // returns:
  8713. // Handle with remove() method to deregister.
  8714. return this.registerWin(iframe.contentWindow, iframe);
  8715. },
  8716. registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){
  8717. // summary:
  8718. // Registers listeners on the specified window (either the main
  8719. // window or an iframe's window) to detect when the user has clicked somewhere
  8720. // or focused somewhere.
  8721. // description:
  8722. // Users should call registerIframe() instead of this method.
  8723. // targetWindow:
  8724. // If specified this is the window associated with the iframe,
  8725. // i.e. iframe.contentWindow.
  8726. // effectiveNode:
  8727. // If specified, report any focus events inside targetWindow as
  8728. // an event on effectiveNode, rather than on evt.target.
  8729. // returns:
  8730. // Handle with remove() method to deregister.
  8731. // TODO: make this function private in 2.0; Editor/users should call registerIframe(),
  8732. // Listen for blur and focus events on targetWindow's document.
  8733. var _this = this,
  8734. body = targetWindow.document && targetWindow.document.body;
  8735. if(body){
  8736. var mdh = on(body, 'mousedown', function(evt){
  8737. _this._justMouseDowned = true;
  8738. // Use a 13 ms timeout to work-around Chrome resolving too fast and focusout
  8739. // events not seeing that a mousedown just happened when a popup closes.
  8740. // See https://bugs.dojotoolkit.org/ticket/17668
  8741. setTimeout(function(){ _this._justMouseDowned = false; }, 13);
  8742. // workaround weird IE bug where the click is on an orphaned node
  8743. // (first time clicking a Select/DropDownButton inside a TooltipDialog).
  8744. // actually, strangely this is happening on latest chrome too.
  8745. if(evt && evt.target && evt.target.parentNode == null){
  8746. return;
  8747. }
  8748. _this._onTouchNode(effectiveNode || evt.target, "mouse");
  8749. });
  8750. var fih = on(body, 'focusin', function(evt){
  8751. // When you refocus the browser window, IE gives an event with an empty srcElement
  8752. if(!evt.target.tagName) { return; }
  8753. // IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1,
  8754. // ignore those events
  8755. var tag = evt.target.tagName.toLowerCase();
  8756. if(tag == "#document" || tag == "body"){ return; }
  8757. if(a11y.isTabNavigable(evt.target)){
  8758. // If condition doesn't seem quite right, but it is correctly preventing focus events for
  8759. // clicks on disabled buttons.
  8760. _this._onFocusNode(effectiveNode || evt.target);
  8761. }else{
  8762. // Previous code called _onTouchNode() for any activate event on a non-focusable node. Can
  8763. // probably just ignore such an event as it will be handled by onmousedown handler above, but
  8764. // leaving the code for now.
  8765. _this._onTouchNode(effectiveNode || evt.target);
  8766. }
  8767. });
  8768. var foh = on(body, 'focusout', function(evt){
  8769. _this._onBlurNode(effectiveNode || evt.target);
  8770. });
  8771. return {
  8772. remove: function(){
  8773. mdh.remove();
  8774. fih.remove();
  8775. foh.remove();
  8776. mdh = fih = foh = null;
  8777. body = null; // prevent memory leak (apparent circular reference via closure)
  8778. }
  8779. };
  8780. }
  8781. },
  8782. _onBlurNode: function(/*DomNode*/ node){
  8783. // summary:
  8784. // Called when focus leaves a node.
  8785. // Usually ignored, _unless_ it *isn't* followed by touching another node,
  8786. // which indicates that we tabbed off the last field on the page,
  8787. // in which case every widget is marked inactive
  8788. // If the blur event isn't followed by a focus event, it means the user clicked on something unfocusable,
  8789. // so clear focus.
  8790. if(this._clearFocusTimer){
  8791. clearTimeout(this._clearFocusTimer);
  8792. }
  8793. this._clearFocusTimer = setTimeout(lang.hitch(this, function(){
  8794. this.set("prevNode", this.curNode);
  8795. this.set("curNode", null);
  8796. }), 0);
  8797. if(this._justMouseDowned){
  8798. // the mouse down caused a new widget to be marked as active; this blur event
  8799. // is coming late, so ignore it.
  8800. return;
  8801. }
  8802. // If the blur event isn't followed by a focus or touch event then mark all widgets as inactive.
  8803. if(this._clearActiveWidgetsTimer){
  8804. clearTimeout(this._clearActiveWidgetsTimer);
  8805. }
  8806. this._clearActiveWidgetsTimer = setTimeout(lang.hitch(this, function(){
  8807. delete this._clearActiveWidgetsTimer;
  8808. this._setStack([]);
  8809. }), 100);
  8810. },
  8811. _onTouchNode: function(/*DomNode*/ node, /*String*/ by){
  8812. // summary:
  8813. // Callback when node is focused or mouse-downed
  8814. // node:
  8815. // The node that was touched.
  8816. // by:
  8817. // "mouse" if the focus/touch was caused by a mouse down event
  8818. // ignore the recent blurNode event
  8819. if(this._clearActiveWidgetsTimer){
  8820. clearTimeout(this._clearActiveWidgetsTimer);
  8821. delete this._clearActiveWidgetsTimer;
  8822. }
  8823. // compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem)
  8824. var newStack=[];
  8825. try{
  8826. while(node){
  8827. var popupParent = domAttr.get(node, "dijitPopupParent");
  8828. if(popupParent){
  8829. node=registry.byId(popupParent).domNode;
  8830. }else if(node.tagName && node.tagName.toLowerCase() == "body"){
  8831. // is this the root of the document or just the root of an iframe?
  8832. if(node === win.body()){
  8833. // node is the root of the main document
  8834. break;
  8835. }
  8836. // otherwise, find the iframe this node refers to (can't access it via parentNode,
  8837. // need to do this trick instead). window.frameElement is supported in IE/FF/Webkit
  8838. node=winUtils.get(node.ownerDocument).frameElement;
  8839. }else{
  8840. // if this node is the root node of a widget, then add widget id to stack,
  8841. // except ignore clicks on disabled widgets (actually focusing a disabled widget still works,
  8842. // to support MenuItem)
  8843. var id = node.getAttribute && node.getAttribute("widgetId"),
  8844. widget = id && registry.byId(id);
  8845. if(widget && !(by == "mouse" && widget.get("disabled"))){
  8846. newStack.unshift(id);
  8847. }
  8848. node=node.parentNode;
  8849. }
  8850. }
  8851. }catch(e){ /* squelch */ }
  8852. this._setStack(newStack, by);
  8853. },
  8854. _onFocusNode: function(/*DomNode*/ node){
  8855. // summary:
  8856. // Callback when node is focused
  8857. if(!node){
  8858. return;
  8859. }
  8860. if(node.nodeType == 9){
  8861. // Ignore focus events on the document itself. This is here so that
  8862. // (for example) clicking the up/down arrows of a spinner
  8863. // (which don't get focus) won't cause that widget to blur. (FF issue)
  8864. return;
  8865. }
  8866. // There was probably a blur event right before this event, but since we have a new focus, don't
  8867. // do anything with the blur
  8868. if(this._clearFocusTimer){
  8869. clearTimeout(this._clearFocusTimer);
  8870. delete this._clearFocusTimer;
  8871. }
  8872. this._onTouchNode(node);
  8873. if(node == this.curNode){ return; }
  8874. this.set("prevNode", this.curNode);
  8875. this.set("curNode", node);
  8876. },
  8877. _setStack: function(/*String[]*/ newStack, /*String*/ by){
  8878. // summary:
  8879. // The stack of active widgets has changed. Send out appropriate events and records new stack.
  8880. // newStack:
  8881. // array of widget id's, starting from the top (outermost) widget
  8882. // by:
  8883. // "mouse" if the focus/touch was caused by a mouse down event
  8884. var oldStack = this.activeStack, lastOldIdx = oldStack.length - 1, lastNewIdx = newStack.length - 1;
  8885. if(newStack[lastNewIdx] == oldStack[lastOldIdx]){
  8886. // no changes, return now to avoid spurious notifications about changes to activeStack
  8887. return;
  8888. }
  8889. this.set("activeStack", newStack);
  8890. var widget, i;
  8891. // for all elements that have gone out of focus, set focused=false
  8892. for(i = lastOldIdx; i >= 0 && oldStack[i] != newStack[i]; i--){
  8893. widget = registry.byId(oldStack[i]);
  8894. if(widget){
  8895. widget._hasBeenBlurred = true; // TODO: used by form widgets, should be moved there
  8896. widget.set("focused", false);
  8897. if(widget._focusManager == this){
  8898. widget._onBlur(by);
  8899. }
  8900. this.emit("widget-blur", widget, by);
  8901. }
  8902. }
  8903. // for all element that have come into focus, set focused=true
  8904. for(i++; i <= lastNewIdx; i++){
  8905. widget = registry.byId(newStack[i]);
  8906. if(widget){
  8907. widget.set("focused", true);
  8908. if(widget._focusManager == this){
  8909. widget._onFocus(by);
  8910. }
  8911. this.emit("widget-focus", widget, by);
  8912. }
  8913. }
  8914. },
  8915. focus: function(node){
  8916. // summary:
  8917. // Focus the specified node, suppressing errors if they occur
  8918. if(node){
  8919. try{ node.focus(); }catch(e){/*quiet*/}
  8920. }
  8921. }
  8922. });
  8923. var singleton = new FocusManager();
  8924. // register top window and all the iframes it contains
  8925. domReady(function(){
  8926. var handle = singleton.registerWin(winUtils.get(document));
  8927. if(has("ie")){
  8928. on(window, "unload", function(){
  8929. if(handle){ // because this gets called twice when doh.robot is running
  8930. handle.remove();
  8931. handle = null;
  8932. }
  8933. });
  8934. }
  8935. });
  8936. // Setup dijit.focus as a pointer to the singleton but also (for backwards compatibility)
  8937. // as a function to set focus. Remove for 2.0.
  8938. dijit.focus = function(node){
  8939. singleton.focus(node); // indirection here allows dijit/_base/focus.js to override behavior
  8940. };
  8941. for(var attr in singleton){
  8942. if(!/^_/.test(attr)){
  8943. dijit.focus[attr] = typeof singleton[attr] == "function" ? lang.hitch(singleton, attr) : singleton[attr];
  8944. }
  8945. }
  8946. singleton.watch(function(attr, oldVal, newVal){
  8947. dijit.focus[attr] = newVal;
  8948. });
  8949. return singleton;
  8950. });
  8951. },
  8952. 'dijit/_base/sniff':function(){
  8953. define("dijit/_base/sniff", [ "dojo/uacss" ], function(){
  8954. // module:
  8955. // dijit/_base/sniff
  8956. // summary:
  8957. // Back compatibility module, new code should require dojo/uacss directly instead of this module.
  8958. });
  8959. },
  8960. 'dijit/main':function(){
  8961. define("dijit/main", [
  8962. "dojo/_base/kernel"
  8963. ], function(dojo){
  8964. // module:
  8965. // dijit
  8966. // summary:
  8967. // The dijit package main module
  8968. return dojo.dijit;
  8969. });
  8970. },
  8971. 'dojox/mobile/RoundRect':function(){
  8972. define([
  8973. "dojo/_base/array",
  8974. "dojo/_base/declare",
  8975. "dojo/_base/window",
  8976. "dijit/_Contained",
  8977. "dijit/_Container",
  8978. "dijit/_WidgetBase"
  8979. ], function(array, declare, win, Contained, Container, WidgetBase){
  8980. /*=====
  8981. var Contained = dijit._Contained;
  8982. var Container = dijit._Container;
  8983. var WidgetBase = dijit._WidgetBase;
  8984. =====*/
  8985. // module:
  8986. // dojox/mobile/RoundRect
  8987. // summary:
  8988. // A simple round rectangle container.
  8989. return declare("dojox.mobile.RoundRect", [WidgetBase, Container, Contained], {
  8990. // summary:
  8991. // A simple round rectangle container.
  8992. // description:
  8993. // RoundRect is a simple round rectangle container for any HTML
  8994. // and/or widgets. You can achieve the same appearance by just
  8995. // applying the -webkit-border-radius style to a div tag. However,
  8996. // if you use RoundRect, you can get a round rectangle even on
  8997. // non-CSS3 browsers such as (older) IE.
  8998. // shadow: Boolean
  8999. // If true, adds a shadow effect to the container element.
  9000. shadow: false,
  9001. buildRendering: function(){
  9002. this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement("DIV");
  9003. this.domNode.className = this.shadow ? "mblRoundRect mblShadow" : "mblRoundRect";
  9004. },
  9005. resize: function(){
  9006. // summary:
  9007. // Calls resize() of each child widget.
  9008. array.forEach(this.getChildren(), function(child){
  9009. if(child.resize){ child.resize(); }
  9010. });
  9011. }
  9012. });
  9013. });
  9014. },
  9015. 'dijit/form/_ButtonMixin':function(){
  9016. define("dijit/form/_ButtonMixin", [
  9017. "dojo/_base/declare", // declare
  9018. "dojo/dom", // dom.setSelectable
  9019. "dojo/_base/event", // event.stop
  9020. "../registry" // registry.byNode
  9021. ], function(declare, dom, event, registry){
  9022. // module:
  9023. // dijit/form/_ButtonMixin
  9024. // summary:
  9025. // A mixin to add a thin standard API wrapper to a normal HTML button
  9026. return declare("dijit.form._ButtonMixin", null, {
  9027. // summary:
  9028. // A mixin to add a thin standard API wrapper to a normal HTML button
  9029. // description:
  9030. // A label should always be specified (through innerHTML) or the label attribute.
  9031. // Attach points:
  9032. // focusNode (required): this node receives focus
  9033. // valueNode (optional): this node's value gets submitted with FORM elements
  9034. // containerNode (optional): this node gets the innerHTML assignment for label
  9035. // example:
  9036. // | <button data-dojo-type="dijit.form.Button" onClick="...">Hello world</button>
  9037. //
  9038. // example:
  9039. // | var button1 = new dijit.form.Button({label: "hello world", onClick: foo});
  9040. // | dojo.body().appendChild(button1.domNode);
  9041. // label: HTML String
  9042. // Content to display in button.
  9043. label: "",
  9044. // type: [const] String
  9045. // Type of button (submit, reset, button, checkbox, radio)
  9046. type: "button",
  9047. _onClick: function(/*Event*/ e){
  9048. // summary:
  9049. // Internal function to handle click actions
  9050. if(this.disabled){
  9051. event.stop(e);
  9052. return false;
  9053. }
  9054. var preventDefault = this.onClick(e) === false; // user click actions
  9055. if(!preventDefault && this.type == "submit" && !(this.valueNode||this.focusNode).form){ // see if a non-form widget needs to be signalled
  9056. for(var node=this.domNode; node.parentNode; node=node.parentNode){
  9057. var widget=registry.byNode(node);
  9058. if(widget && typeof widget._onSubmit == "function"){
  9059. widget._onSubmit(e);
  9060. preventDefault = true;
  9061. break;
  9062. }
  9063. }
  9064. }
  9065. if(preventDefault){
  9066. e.preventDefault();
  9067. }
  9068. return !preventDefault;
  9069. },
  9070. postCreate: function(){
  9071. this.inherited(arguments);
  9072. dom.setSelectable(this.focusNode, false);
  9073. },
  9074. onClick: function(/*Event*/ /*===== e =====*/){
  9075. // summary:
  9076. // Callback for when button is clicked.
  9077. // If type="submit", return true to perform submit, or false to cancel it.
  9078. // type:
  9079. // callback
  9080. return true; // Boolean
  9081. },
  9082. _setLabelAttr: function(/*String*/ content){
  9083. // summary:
  9084. // Hook for set('label', ...) to work.
  9085. // description:
  9086. // Set the label (text) of the button; takes an HTML string.
  9087. this._set("label", content);
  9088. (this.containerNode||this.focusNode).innerHTML = content;
  9089. }
  9090. });
  9091. });
  9092. },
  9093. 'dijit/_base/typematic':function(){
  9094. define("dijit/_base/typematic", ["../typematic"], function(){
  9095. // for back-compat, just loads top level module
  9096. });
  9097. },
  9098. 'dojox/mobile/RoundRectCategory':function(){
  9099. define([
  9100. "dojo/_base/declare",
  9101. "dojo/_base/window",
  9102. "dijit/_Contained",
  9103. "dijit/_WidgetBase"
  9104. ], function(declare, win, Contained, WidgetBase){
  9105. /*=====
  9106. var Contained = dijit._Contained;
  9107. var WidgetBase = dijit._WidgetBase;
  9108. =====*/
  9109. // module:
  9110. // dojox/mobile/RoundRectCategory
  9111. // summary:
  9112. // A category header for a rounded rectangle list.
  9113. return declare("dojox.mobile.RoundRectCategory", [WidgetBase, Contained],{
  9114. // summary:
  9115. // A category header for a rounded rectangle list.
  9116. // label: String
  9117. // A label text for the widget.
  9118. label: "",
  9119. buildRendering: function(){
  9120. this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement("H2");
  9121. this.domNode.className = "mblRoundRectCategory";
  9122. if(!this.label){
  9123. this.label = this.domNode.innerHTML;
  9124. }
  9125. },
  9126. _setLabelAttr: function(/*String*/label){
  9127. this.label = label;
  9128. this.domNode.innerHTML = this._cv ? this._cv(label) : label;
  9129. }
  9130. });
  9131. });
  9132. },
  9133. 'dojox/mobile/app/TextBox':function(){
  9134. // wrapped by build app
  9135. define("dojox/mobile/app/TextBox", ["dijit","dojo","dojox","dojo/require!dojox/mobile/TextBox"], function(dijit,dojo,dojox){
  9136. dojo.provide("dojox.mobile.app.TextBox");
  9137. dojo.deprecated("dojox.mobile.app.TextBox is deprecated", "dojox.mobile.app.TextBox moved to dojox.mobile.TextBox", 1.8);
  9138. dojo.require("dojox.mobile.TextBox");
  9139. dojox.mobile.app.TextBox = dojox.mobile.TextBox;
  9140. });
  9141. },
  9142. 'dojox/mobile/app/SceneAssistant':function(){
  9143. // wrapped by build app
  9144. define("dojox/mobile/app/SceneAssistant", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
  9145. dojo.provide("dojox.mobile.app.SceneAssistant");
  9146. dojo.experimental("dojox.mobile.app.SceneAssistant");
  9147. dojo.declare("dojox.mobile.app.SceneAssistant", null, {
  9148. // summary:
  9149. // The base class for all scene assistants.
  9150. constructor: function(){
  9151. },
  9152. setup: function(){
  9153. // summary:
  9154. // Called to set up the widget. The UI is not visible at this time
  9155. },
  9156. activate: function(params){
  9157. // summary:
  9158. // Called each time the scene becomes visible. This can be as a result
  9159. // of a new scene being created, or a subsequent scene being destroyed
  9160. // and control transferring back to this scene assistant.
  9161. // params:
  9162. // Optional paramters, only passed when a subsequent scene pops itself
  9163. // off the stack and passes back data.
  9164. },
  9165. deactivate: function(){
  9166. // summary:
  9167. // Called each time the scene becomes invisible. This can be as a result
  9168. // of it being popped off the stack and destroyed,
  9169. // or another scene being created and pushed on top of it on the stack
  9170. },
  9171. destroy: function(){
  9172. var children =
  9173. dojo.query("> [widgetId]", this.containerNode).map(dijit.byNode);
  9174. dojo.forEach(children, function(child){ child.destroyRecursive(); });
  9175. this.disconnect();
  9176. },
  9177. connect: function(obj, method, callback){
  9178. if(!this._connects){
  9179. this._connects = [];
  9180. }
  9181. this._connects.push(dojo.connect(obj, method, callback));
  9182. },
  9183. disconnect: function(){
  9184. dojo.forEach(this._connects, dojo.disconnect);
  9185. this._connects = [];
  9186. }
  9187. });
  9188. });
  9189. },
  9190. 'dijit/_base/popup':function(){
  9191. define("dijit/_base/popup", [
  9192. "dojo/dom-class", // domClass.contains
  9193. "../popup",
  9194. "../BackgroundIframe" // just loading for back-compat, in case client code is referencing it
  9195. ], function(domClass, popup){
  9196. // module:
  9197. // dijit/_base/popup
  9198. // summary:
  9199. // Old module for popups, new code should use dijit/popup directly
  9200. // Hack support for old API passing in node instead of a widget (to various methods)
  9201. var origCreateWrapper = popup._createWrapper;
  9202. popup._createWrapper = function(widget){
  9203. if(!widget.declaredClass){
  9204. // make fake widget to pass to new API
  9205. widget = {
  9206. _popupWrapper: (widget.parentNode && domClass.contains(widget.parentNode, "dijitPopup")) ?
  9207. widget.parentNode : null,
  9208. domNode: widget,
  9209. destroy: function(){}
  9210. };
  9211. }
  9212. return origCreateWrapper.call(this, widget);
  9213. };
  9214. // Support old format of orient parameter
  9215. var origOpen = popup.open;
  9216. popup.open = function(/*dijit.popup.__OpenArgs*/ args){
  9217. // Convert old hash structure (ex: {"BL": "TL", ...}) of orient to format compatible w/new popup.open() API.
  9218. // Don't do conversion for:
  9219. // - null parameter (that means to use the default positioning)
  9220. // - "R" or "L" strings used to indicate positioning for context menus (when there is no around node)
  9221. // - new format, ex: ["below", "above"]
  9222. // - return value from deprecated dijit.getPopupAroundAlignment() method,
  9223. // ex: ["below", "above"]
  9224. if(args.orient && typeof args.orient != "string" && !("length" in args.orient)){
  9225. var ary = [];
  9226. for(var key in args.orient){
  9227. ary.push({aroundCorner: key, corner: args.orient[key]});
  9228. }
  9229. args.orient = ary;
  9230. }
  9231. return origOpen.call(this, args);
  9232. };
  9233. return popup;
  9234. });
  9235. },
  9236. 'dojox/mobile/transition':function(){
  9237. define("dojox/mobile/transition", [
  9238. "dojo/_base/Deferred",
  9239. "dojo/_base/config"
  9240. ], function(Deferred, config){
  9241. /* summary: this is the wrapper module which load
  9242. * dojox/css3/transit conditionally. If mblCSS3Transition
  9243. * is set to 'dojox/css3/transit', it will be loaded as
  9244. * the module to conduct the view transition.
  9245. */
  9246. if(config['mblCSS3Transition']){
  9247. //require dojox/css3/transit and resolve it as the result of transitDeferred.
  9248. var transitDeferred = new Deferred();
  9249. require([config['mblCSS3Transition']], function(transit){
  9250. transitDeferred.resolve(transit);
  9251. });
  9252. return transitDeferred;
  9253. }
  9254. return null;
  9255. });
  9256. },
  9257. 'dijit/_base/wai':function(){
  9258. define("dijit/_base/wai", [
  9259. "dojo/dom-attr", // domAttr.attr
  9260. "dojo/_base/lang", // lang.mixin
  9261. "..", // export symbols to dijit
  9262. "../hccss" // not using this module directly, but loading it sets CSS flag on <html>
  9263. ], function(domAttr, lang, dijit){
  9264. // module:
  9265. // dijit/_base/wai
  9266. // summary:
  9267. // Deprecated methods for setting/getting wai roles and states.
  9268. // New code should call setAttribute()/getAttribute() directly.
  9269. //
  9270. // Also loads hccss to apply dijit_a11y class to root node if machine is in high-contrast mode.
  9271. lang.mixin(dijit, {
  9272. hasWaiRole: function(/*Element*/ elem, /*String?*/ role){
  9273. // summary:
  9274. // Determines if an element has a particular role.
  9275. // returns:
  9276. // True if elem has the specific role attribute and false if not.
  9277. // For backwards compatibility if role parameter not provided,
  9278. // returns true if has a role
  9279. var waiRole = this.getWaiRole(elem);
  9280. return role ? (waiRole.indexOf(role) > -1) : (waiRole.length > 0);
  9281. },
  9282. getWaiRole: function(/*Element*/ elem){
  9283. // summary:
  9284. // Gets the role for an element (which should be a wai role).
  9285. // returns:
  9286. // The role of elem or an empty string if elem
  9287. // does not have a role.
  9288. return lang.trim((domAttr.get(elem, "role") || "").replace("wairole:",""));
  9289. },
  9290. setWaiRole: function(/*Element*/ elem, /*String*/ role){
  9291. // summary:
  9292. // Sets the role on an element.
  9293. // description:
  9294. // Replace existing role attribute with new role.
  9295. domAttr.set(elem, "role", role);
  9296. },
  9297. removeWaiRole: function(/*Element*/ elem, /*String*/ role){
  9298. // summary:
  9299. // Removes the specified role from an element.
  9300. // Removes role attribute if no specific role provided (for backwards compat.)
  9301. var roleValue = domAttr.get(elem, "role");
  9302. if(!roleValue){ return; }
  9303. if(role){
  9304. var t = lang.trim((" " + roleValue + " ").replace(" " + role + " ", " "));
  9305. domAttr.set(elem, "role", t);
  9306. }else{
  9307. elem.removeAttribute("role");
  9308. }
  9309. },
  9310. hasWaiState: function(/*Element*/ elem, /*String*/ state){
  9311. // summary:
  9312. // Determines if an element has a given state.
  9313. // description:
  9314. // Checks for an attribute called "aria-"+state.
  9315. // returns:
  9316. // true if elem has a value for the given state and
  9317. // false if it does not.
  9318. return elem.hasAttribute ? elem.hasAttribute("aria-"+state) : !!elem.getAttribute("aria-"+state);
  9319. },
  9320. getWaiState: function(/*Element*/ elem, /*String*/ state){
  9321. // summary:
  9322. // Gets the value of a state on an element.
  9323. // description:
  9324. // Checks for an attribute called "aria-"+state.
  9325. // returns:
  9326. // The value of the requested state on elem
  9327. // or an empty string if elem has no value for state.
  9328. return elem.getAttribute("aria-"+state) || "";
  9329. },
  9330. setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){
  9331. // summary:
  9332. // Sets a state on an element.
  9333. // description:
  9334. // Sets an attribute called "aria-"+state.
  9335. elem.setAttribute("aria-"+state, value);
  9336. },
  9337. removeWaiState: function(/*Element*/ elem, /*String*/ state){
  9338. // summary:
  9339. // Removes a state from an element.
  9340. // description:
  9341. // Sets an attribute called "aria-"+state.
  9342. elem.removeAttribute("aria-"+state);
  9343. }
  9344. });
  9345. return dijit;
  9346. });
  9347. },
  9348. 'dojo/window':function(){
  9349. define(["./_base/lang", "./_base/sniff", "./_base/window", "./dom", "./dom-geometry", "./dom-style", "./dom-construct"],
  9350. function(lang, has, baseWindow, dom, geom, style, domConstruct) {
  9351. // feature detection
  9352. /* not needed but included here for future reference
  9353. has.add("rtl-innerVerticalScrollBar-on-left", function(win, doc){
  9354. var body = baseWindow.body(doc),
  9355. scrollable = domConstruct.create('div', {
  9356. style: {overflow:'scroll', overflowX:'hidden', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', width:'64px', height:'64px'}
  9357. }, body, "last"),
  9358. center = domConstruct.create('center', {
  9359. style: {overflow:'hidden', direction:'ltr'}
  9360. }, scrollable, "last"),
  9361. inner = domConstruct.create('div', {
  9362. style: {overflow:'visible', display:'inline' }
  9363. }, center, "last");
  9364. inner.innerHTML="&nbsp;";
  9365. var midPoint = Math.max(inner.offsetLeft, geom.position(inner).x);
  9366. var ret = midPoint >= 32;
  9367. center.removeChild(inner);
  9368. scrollable.removeChild(center);
  9369. body.removeChild(scrollable);
  9370. return ret;
  9371. });
  9372. */
  9373. has.add("rtl-adjust-position-for-verticalScrollBar", function(win, doc){
  9374. var body = baseWindow.body(doc),
  9375. scrollable = domConstruct.create('div', {
  9376. style: {overflow:'scroll', overflowX:'visible', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', top:'0', width:'64px', height:'64px'}
  9377. }, body, "last"),
  9378. div = domConstruct.create('div', {
  9379. style: {overflow:'hidden', direction:'ltr'}
  9380. }, scrollable, "last"),
  9381. ret = geom.position(div).x != 0;
  9382. scrollable.removeChild(div);
  9383. body.removeChild(scrollable);
  9384. return ret;
  9385. });
  9386. has.add("position-fixed-support", function(win, doc){
  9387. // IE6, IE7+quirks, and some older mobile browsers don't support position:fixed
  9388. var body = baseWindow.body(doc),
  9389. outer = domConstruct.create('span', {
  9390. style: {visibility:'hidden', position:'fixed', left:'1px', top:'1px'}
  9391. }, body, "last"),
  9392. inner = domConstruct.create('span', {
  9393. style: {position:'fixed', left:'0', top:'0'}
  9394. }, outer, "last"),
  9395. ret = geom.position(inner).x != geom.position(outer).x;
  9396. outer.removeChild(inner);
  9397. body.removeChild(outer);
  9398. return ret;
  9399. });
  9400. // module:
  9401. // dojo/window
  9402. // summary:
  9403. // TODOC
  9404. var window = lang.getObject("dojo.window", true);
  9405. /*=====
  9406. dojo.window = {
  9407. // summary:
  9408. // TODO
  9409. };
  9410. window = dojo.window;
  9411. =====*/
  9412. window.getBox = function(){
  9413. // summary:
  9414. // Returns the dimensions and scroll position of the viewable area of a browser window
  9415. var
  9416. scrollRoot = (baseWindow.doc.compatMode == 'BackCompat') ? baseWindow.body() : baseWindow.doc.documentElement,
  9417. // get scroll position
  9418. scroll = geom.docScroll(), // scrollRoot.scrollTop/Left should work
  9419. w, h;
  9420. if(has("touch")){ // if(scrollbars not supported)
  9421. var uiWindow = baseWindow.doc.parentWindow || baseWindow.doc.defaultView; // use UI window, not dojo.global window. baseWindow.doc.parentWindow probably not needed since it's not defined for webkit
  9422. // on mobile, scrollRoot.clientHeight <= uiWindow.innerHeight <= scrollRoot.offsetHeight, return uiWindow.innerHeight
  9423. w = uiWindow.innerWidth || scrollRoot.clientWidth; // || scrollRoot.clientXXX probably never evaluated
  9424. h = uiWindow.innerHeight || scrollRoot.clientHeight;
  9425. }else{
  9426. // on desktops, scrollRoot.clientHeight <= scrollRoot.offsetHeight <= uiWindow.innerHeight, return scrollRoot.clientHeight
  9427. // uiWindow.innerWidth/Height includes the scrollbar and cannot be used
  9428. w = scrollRoot.clientWidth;
  9429. h = scrollRoot.clientHeight;
  9430. }
  9431. return {
  9432. l: scroll.x,
  9433. t: scroll.y,
  9434. w: w,
  9435. h: h
  9436. };
  9437. };
  9438. window.get = function(doc){
  9439. // summary:
  9440. // Get window object associated with document doc
  9441. // In some IE versions (at least 6.0), document.parentWindow does not return a
  9442. // reference to the real window object (maybe a copy), so we must fix it as well
  9443. // We use IE specific execScript to attach the real window reference to
  9444. // document._parentWindow for later use
  9445. if(has("ie") < 9 && window !== document.parentWindow){
  9446. /*
  9447. In IE 6, only the variable "window" can be used to connect events (others
  9448. may be only copies).
  9449. */
  9450. doc.parentWindow.execScript("document._parentWindow = window;", "Javascript");
  9451. //to prevent memory leak, unset it after use
  9452. //another possibility is to add an onUnload handler which seems overkill to me (liucougar)
  9453. var win = doc._parentWindow;
  9454. doc._parentWindow = null;
  9455. return win; // Window
  9456. }
  9457. return doc.parentWindow || doc.defaultView; // Window
  9458. };
  9459. window.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
  9460. // summary:
  9461. // Scroll the passed node into view using minimal movement, if it is not already.
  9462. // Don't rely on node.scrollIntoView working just because the function is there since
  9463. // it forces the node to the page's bottom or top (and left or right in IE) without consideration for the minimal movement.
  9464. // WebKit's node.scrollIntoViewIfNeeded doesn't work either for inner scrollbars in right-to-left mode
  9465. // and when there's a fixed position scrollable element
  9466. try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method
  9467. node = dom.byId(node);
  9468. var doc = node.ownerDocument || baseWindow.doc, // TODO: why baseWindow.doc? Isn't node.ownerDocument always defined?
  9469. body = baseWindow.body(doc),
  9470. html = doc.documentElement || body.parentNode,
  9471. isIE = has("ie"),
  9472. isWK = has("webkit");
  9473. // if an untested browser, then use the native method
  9474. if(node == body || node == html){ return; }
  9475. if(!(has("mozilla") || isIE || isWK || has("opera") || has("trident")) && ("scrollIntoView" in node)){
  9476. node.scrollIntoView(false); // short-circuit to native if possible
  9477. return;
  9478. }
  9479. var backCompat = doc.compatMode == 'BackCompat',
  9480. rootWidth = Math.min(body.clientWidth || html.clientWidth, html.clientWidth || body.clientWidth),
  9481. rootHeight = Math.min(body.clientHeight || html.clientHeight, html.clientHeight || body.clientHeight),
  9482. scrollRoot = (isWK || backCompat) ? body : html,
  9483. nodePos = pos || geom.position(node),
  9484. el = node.parentNode,
  9485. isFixed = function(el){
  9486. return (isIE <= 6 || (isIE == 7 && backCompat))
  9487. ? false
  9488. : (has("position-fixed-support") && (style.get(el, 'position').toLowerCase() == "fixed"));
  9489. },
  9490. self = this,
  9491. scrollElementBy = function(el, x, y){
  9492. if(el.tagName == "BODY" || el.tagName == "HTML"){
  9493. self.get(el.ownerDocument).scrollBy(x, y);
  9494. }else{
  9495. x && (el.scrollLeft += x);
  9496. y && (el.scrollTop += y);
  9497. }
  9498. };
  9499. if(isFixed(node)){ return; } // nothing to do
  9500. while(el){
  9501. if(el == body){ el = scrollRoot; }
  9502. var elPos = geom.position(el),
  9503. fixedPos = isFixed(el),
  9504. rtl = style.getComputedStyle(el).direction.toLowerCase() == "rtl";
  9505. if(el == scrollRoot){
  9506. elPos.w = rootWidth; elPos.h = rootHeight;
  9507. if(scrollRoot == html && (isIE || has("trident")) && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x
  9508. if(elPos.x < 0 || !isIE || isIE >= 9 || has("trident")){ elPos.x = 0; } // older IE can have values > 0
  9509. if(elPos.y < 0 || !isIE || isIE >= 9 || has("trident")){ elPos.y = 0; }
  9510. }else{
  9511. var pb = geom.getPadBorderExtents(el);
  9512. elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t;
  9513. var clientSize = el.clientWidth,
  9514. scrollBarSize = elPos.w - clientSize;
  9515. if(clientSize > 0 && scrollBarSize > 0){
  9516. if(rtl && has("rtl-adjust-position-for-verticalScrollBar")){
  9517. elPos.x += scrollBarSize;
  9518. }
  9519. elPos.w = clientSize;
  9520. }
  9521. clientSize = el.clientHeight;
  9522. scrollBarSize = elPos.h - clientSize;
  9523. if(clientSize > 0 && scrollBarSize > 0){
  9524. elPos.h = clientSize;
  9525. }
  9526. }
  9527. if(fixedPos){ // bounded by viewport, not parents
  9528. if(elPos.y < 0){
  9529. elPos.h += elPos.y; elPos.y = 0;
  9530. }
  9531. if(elPos.x < 0){
  9532. elPos.w += elPos.x; elPos.x = 0;
  9533. }
  9534. if(elPos.y + elPos.h > rootHeight){
  9535. elPos.h = rootHeight - elPos.y;
  9536. }
  9537. if(elPos.x + elPos.w > rootWidth){
  9538. elPos.w = rootWidth - elPos.x;
  9539. }
  9540. }
  9541. // calculate overflow in all 4 directions
  9542. var l = nodePos.x - elPos.x, // beyond left: < 0
  9543. // t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0
  9544. t = nodePos.y - elPos.y, // beyond top: < 0
  9545. r = l + nodePos.w - elPos.w, // beyond right: > 0
  9546. bot = t + nodePos.h - elPos.h; // beyond bottom: > 0
  9547. var s, old;
  9548. if(r * l > 0 && (!!el.scrollLeft || el == scrollRoot || el.scrollWidth > el.offsetHeight)){
  9549. s = Math[l < 0? "max" : "min"](l, r);
  9550. if(rtl && ((isIE == 8 && !backCompat) || isIE >= 9 || has("trident"))){ s = -s; }
  9551. old = el.scrollLeft;
  9552. scrollElementBy(el, s, 0);
  9553. s = el.scrollLeft - old;
  9554. nodePos.x -= s;
  9555. }
  9556. if(bot * t > 0 && (!!el.scrollTop || el == scrollRoot || el.scrollHeight > el.offsetHeight)){
  9557. s = Math.ceil(Math[t < 0? "max" : "min"](t, bot));
  9558. old = el.scrollTop;
  9559. scrollElementBy(el, 0, s);
  9560. s = el.scrollTop - old;
  9561. nodePos.y -= s;
  9562. }
  9563. el = (el != scrollRoot) && !fixedPos && el.parentNode;
  9564. }
  9565. }catch(error){
  9566. console.error('scrollIntoView: ' + error);
  9567. node.scrollIntoView(false);
  9568. }
  9569. };
  9570. return window;
  9571. });
  9572. },
  9573. 'dojox/mobile/EdgeToEdgeList':function(){
  9574. define("dojox/mobile/EdgeToEdgeList", [
  9575. "dojo/_base/declare",
  9576. "./RoundRectList"
  9577. ], function(declare, RoundRectList){
  9578. /*=====
  9579. var RoundRectList = dojox.mobile.RoundRectList;
  9580. =====*/
  9581. // module:
  9582. // dojox/mobile/EdgeToEdgeCategory
  9583. // summary:
  9584. // An edge-to-edge layout list.
  9585. return declare("dojox.mobile.EdgeToEdgeList", RoundRectList, {
  9586. // summary:
  9587. // An edge-to-edge layout list.
  9588. // description:
  9589. // EdgeToEdgeList is an edge-to-edge layout list, which displays
  9590. // all items in equally sized rows. Each item must be
  9591. // dojox.mobile.ListItem.
  9592. buildRendering: function(){
  9593. this.inherited(arguments);
  9594. this.domNode.className = "mblEdgeToEdgeList";
  9595. }
  9596. });
  9597. });
  9598. },
  9599. 'dijit/popup':function(){
  9600. define("dijit/popup", [
  9601. "dojo/_base/array", // array.forEach array.some
  9602. "dojo/aspect",
  9603. "dojo/_base/connect", // connect._keypress
  9604. "dojo/_base/declare", // declare
  9605. "dojo/dom", // dom.isDescendant
  9606. "dojo/dom-attr", // domAttr.set
  9607. "dojo/dom-construct", // domConstruct.create domConstruct.destroy
  9608. "dojo/dom-geometry", // domGeometry.isBodyLtr
  9609. "dojo/dom-style", // domStyle.set
  9610. "dojo/_base/event", // event.stop
  9611. "dojo/has",
  9612. "dojo/keys",
  9613. "dojo/_base/lang", // lang.hitch
  9614. "dojo/on",
  9615. "dojo/_base/window", // win.body
  9616. "./place",
  9617. "./BackgroundIframe",
  9618. "." // dijit (defining dijit.popup to match API doc)
  9619. ], function(array, aspect, connect, declare, dom, domAttr, domConstruct, domGeometry, domStyle, event, has, keys, lang, on, win,
  9620. place, BackgroundIframe, dijit){
  9621. // module:
  9622. // dijit/popup
  9623. // summary:
  9624. // Used to show drop downs (ex: the select list of a ComboBox)
  9625. // or popups (ex: right-click context menus)
  9626. /*=====
  9627. dijit.popup.__OpenArgs = function(){
  9628. // popup: Widget
  9629. // widget to display
  9630. // parent: Widget
  9631. // the button etc. that is displaying this popup
  9632. // around: DomNode
  9633. // DOM node (typically a button); place popup relative to this node. (Specify this *or* "x" and "y" parameters.)
  9634. // x: Integer
  9635. // Absolute horizontal position (in pixels) to place node at. (Specify this *or* "around" parameter.)
  9636. // y: Integer
  9637. // Absolute vertical position (in pixels) to place node at. (Specify this *or* "around" parameter.)
  9638. // orient: Object|String
  9639. // When the around parameter is specified, orient should be a list of positions to try, ex:
  9640. // | [ "below", "above" ]
  9641. // For backwards compatibility it can also be an (ordered) hash of tuples of the form
  9642. // (around-node-corner, popup-node-corner), ex:
  9643. // | { "BL": "TL", "TL": "BL" }
  9644. // where BL means "bottom left" and "TL" means "top left", etc.
  9645. //
  9646. // dijit.popup.open() tries to position the popup according to each specified position, in order,
  9647. // until the popup appears fully within the viewport.
  9648. //
  9649. // The default value is ["below", "above"]
  9650. //
  9651. // When an (x,y) position is specified rather than an around node, orient is either
  9652. // "R" or "L". R (for right) means that it tries to put the popup to the right of the mouse,
  9653. // specifically positioning the popup's top-right corner at the mouse position, and if that doesn't
  9654. // fit in the viewport, then it tries, in order, the bottom-right corner, the top left corner,
  9655. // and the top-right corner.
  9656. // onCancel: Function
  9657. // callback when user has canceled the popup by
  9658. // 1. hitting ESC or
  9659. // 2. by using the popup widget's proprietary cancel mechanism (like a cancel button in a dialog);
  9660. // i.e. whenever popupWidget.onCancel() is called, args.onCancel is called
  9661. // onClose: Function
  9662. // callback whenever this popup is closed
  9663. // onExecute: Function
  9664. // callback when user "executed" on the popup/sub-popup by selecting a menu choice, etc. (top menu only)
  9665. // padding: dijit.__Position
  9666. // adding a buffer around the opening position. This is only useful when around is not set.
  9667. this.popup = popup;
  9668. this.parent = parent;
  9669. this.around = around;
  9670. this.x = x;
  9671. this.y = y;
  9672. this.orient = orient;
  9673. this.onCancel = onCancel;
  9674. this.onClose = onClose;
  9675. this.onExecute = onExecute;
  9676. this.padding = padding;
  9677. }
  9678. =====*/
  9679. /*=====
  9680. dijit.popup = {
  9681. // summary:
  9682. // Used to show drop downs (ex: the select list of a ComboBox)
  9683. // or popups (ex: right-click context menus).
  9684. //
  9685. // Access via require(["dijit/popup"], function(popup){ ... }).
  9686. moveOffScreen: function(widget){
  9687. // summary:
  9688. // Moves the popup widget off-screen.
  9689. // Do not use this method to hide popups when not in use, because
  9690. // that will create an accessibility issue: the offscreen popup is
  9691. // still in the tabbing order.
  9692. // widget: dijit._WidgetBase
  9693. // The widget
  9694. },
  9695. hide: function(widget){
  9696. // summary:
  9697. // Hide this popup widget (until it is ready to be shown).
  9698. // Initialization for widgets that will be used as popups
  9699. //
  9700. // Also puts widget inside a wrapper DIV (if not already in one)
  9701. //
  9702. // If popup widget needs to layout it should
  9703. // do so when it is made visible, and popup._onShow() is called.
  9704. // widget: dijit._WidgetBase
  9705. // The widget
  9706. },
  9707. open: function(args){
  9708. // summary:
  9709. // Popup the widget at the specified position
  9710. // example:
  9711. // opening at the mouse position
  9712. // | popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
  9713. // example:
  9714. // opening the widget as a dropdown
  9715. // | popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...}});
  9716. //
  9717. // Note that whatever widget called dijit.popup.open() should also listen to its own _onBlur callback
  9718. // (fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
  9719. // args: dijit.popup.__OpenArgs
  9720. // Parameters
  9721. return {}; // Object specifying which position was chosen
  9722. },
  9723. close: function(popup){
  9724. // summary:
  9725. // Close specified popup and any popups that it parented.
  9726. // If no popup is specified, closes all popups.
  9727. // widget: dijit._WidgetBase?
  9728. // The widget, optional
  9729. }
  9730. };
  9731. =====*/
  9732. function destroyWrapper(){
  9733. // summary:
  9734. // Function to destroy wrapper when popup widget is destroyed.
  9735. // Left in this scope to avoid memory leak on IE8 on refresh page, see #15206.
  9736. if(this._popupWrapper){
  9737. domConstruct.destroy(this._popupWrapper);
  9738. delete this._popupWrapper;
  9739. }
  9740. }
  9741. var PopupManager = declare(null, {
  9742. // _stack: dijit._Widget[]
  9743. // Stack of currently popped up widgets.
  9744. // (someone opened _stack[0], and then it opened _stack[1], etc.)
  9745. _stack: [],
  9746. // _beginZIndex: Number
  9747. // Z-index of the first popup. (If first popup opens other
  9748. // popups they get a higher z-index.)
  9749. _beginZIndex: 1000,
  9750. _idGen: 1,
  9751. _createWrapper: function(/*Widget*/ widget){
  9752. // summary:
  9753. // Initialization for widgets that will be used as popups.
  9754. // Puts widget inside a wrapper DIV (if not already in one),
  9755. // and returns pointer to that wrapper DIV.
  9756. var wrapper = widget._popupWrapper,
  9757. node = widget.domNode;
  9758. if(!wrapper){
  9759. // Create wrapper <div> for when this widget [in the future] will be used as a popup.
  9760. // This is done early because of IE bugs where creating/moving DOM nodes causes focus
  9761. // to go wonky, see tests/robot/Toolbar.html to reproduce
  9762. wrapper = domConstruct.create("div", {
  9763. "class":"dijitPopup",
  9764. style:{ display: "none"},
  9765. role: "presentation"
  9766. }, win.body());
  9767. wrapper.appendChild(node);
  9768. var s = node.style;
  9769. s.display = "";
  9770. s.visibility = "";
  9771. s.position = "";
  9772. s.top = "0px";
  9773. widget._popupWrapper = wrapper;
  9774. aspect.after(widget, "destroy", destroyWrapper, true);
  9775. }
  9776. return wrapper;
  9777. },
  9778. moveOffScreen: function(/*Widget*/ widget){
  9779. // summary:
  9780. // Moves the popup widget off-screen.
  9781. // Do not use this method to hide popups when not in use, because
  9782. // that will create an accessibility issue: the offscreen popup is
  9783. // still in the tabbing order.
  9784. // Create wrapper if not already there
  9785. var wrapper = this._createWrapper(widget);
  9786. domStyle.set(wrapper, {
  9787. visibility: "hidden",
  9788. top: "-9999px", // prevent transient scrollbar causing misalign (#5776), and initial flash in upper left (#10111)
  9789. display: ""
  9790. });
  9791. },
  9792. hide: function(/*Widget*/ widget){
  9793. // summary:
  9794. // Hide this popup widget (until it is ready to be shown).
  9795. // Initialization for widgets that will be used as popups
  9796. //
  9797. // Also puts widget inside a wrapper DIV (if not already in one)
  9798. //
  9799. // If popup widget needs to layout it should
  9800. // do so when it is made visible, and popup._onShow() is called.
  9801. // Create wrapper if not already there
  9802. var wrapper = this._createWrapper(widget);
  9803. domStyle.set(wrapper, "display", "none");
  9804. },
  9805. getTopPopup: function(){
  9806. // summary:
  9807. // Compute the closest ancestor popup that's *not* a child of another popup.
  9808. // Ex: For a TooltipDialog with a button that spawns a tree of menus, find the popup of the button.
  9809. var stack = this._stack;
  9810. for(var pi=stack.length-1; pi > 0 && stack[pi].parent === stack[pi-1].widget; pi--){
  9811. /* do nothing, just trying to get right value for pi */
  9812. }
  9813. return stack[pi];
  9814. },
  9815. open: function(/*dijit.popup.__OpenArgs*/ args){
  9816. // summary:
  9817. // Popup the widget at the specified position
  9818. //
  9819. // example:
  9820. // opening at the mouse position
  9821. // | popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
  9822. //
  9823. // example:
  9824. // opening the widget as a dropdown
  9825. // | popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...}});
  9826. //
  9827. // Note that whatever widget called dijit.popup.open() should also listen to its own _onBlur callback
  9828. // (fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
  9829. var stack = this._stack,
  9830. widget = args.popup,
  9831. orient = args.orient || ["below", "below-alt", "above", "above-alt"],
  9832. ltr = args.parent ? args.parent.isLeftToRight() : domGeometry.isBodyLtr(),
  9833. around = args.around,
  9834. id = (args.around && args.around.id) ? (args.around.id+"_dropdown") : ("popup_"+this._idGen++);
  9835. // If we are opening a new popup that isn't a child of a currently opened popup, then
  9836. // close currently opened popup(s). This should happen automatically when the old popups
  9837. // gets the _onBlur() event, except that the _onBlur() event isn't reliable on IE, see [22198].
  9838. while(stack.length && (!args.parent || !dom.isDescendant(args.parent.domNode, stack[stack.length-1].widget.domNode))){
  9839. this.close(stack[stack.length-1].widget);
  9840. }
  9841. // Get pointer to popup wrapper, and create wrapper if it doesn't exist
  9842. var wrapper = this._createWrapper(widget);
  9843. domAttr.set(wrapper, {
  9844. id: id,
  9845. style: {
  9846. zIndex: this._beginZIndex + stack.length
  9847. },
  9848. "class": "dijitPopup " + (widget.baseClass || widget["class"] || "").split(" ")[0] +"Popup",
  9849. dijitPopupParent: args.parent ? args.parent.id : ""
  9850. });
  9851. if(has("bgIframe") && !widget.bgIframe){
  9852. // setting widget.bgIframe triggers cleanup in _Widget.destroy()
  9853. widget.bgIframe = new BackgroundIframe(wrapper);
  9854. }
  9855. // position the wrapper node and make it visible
  9856. var best = around ?
  9857. place.around(wrapper, around, orient, ltr, widget.orient ? lang.hitch(widget, "orient") : null) :
  9858. place.at(wrapper, args, orient == 'R' ? ['TR','BR','TL','BL'] : ['TL','BL','TR','BR'], args.padding);
  9859. wrapper.style.display = "";
  9860. wrapper.style.visibility = "visible";
  9861. widget.domNode.style.visibility = "visible"; // counteract effects from _HasDropDown
  9862. var handlers = [];
  9863. // provide default escape and tab key handling
  9864. // (this will work for any widget, not just menu)
  9865. handlers.push(on(wrapper, connect._keypress, lang.hitch(this, function(evt){
  9866. if(evt.charOrCode == keys.ESCAPE && args.onCancel){
  9867. event.stop(evt);
  9868. args.onCancel();
  9869. }else if(evt.charOrCode === keys.TAB){
  9870. event.stop(evt);
  9871. var topPopup = this.getTopPopup();
  9872. if(topPopup && topPopup.onCancel){
  9873. topPopup.onCancel();
  9874. }
  9875. }
  9876. })));
  9877. // watch for cancel/execute events on the popup and notify the caller
  9878. // (for a menu, "execute" means clicking an item)
  9879. if(widget.onCancel && args.onCancel){
  9880. handlers.push(widget.on("cancel", args.onCancel));
  9881. }
  9882. handlers.push(widget.on(widget.onExecute ? "execute" : "change", lang.hitch(this, function(){
  9883. var topPopup = this.getTopPopup();
  9884. if(topPopup && topPopup.onExecute){
  9885. topPopup.onExecute();
  9886. }
  9887. })));
  9888. stack.push({
  9889. widget: widget,
  9890. parent: args.parent,
  9891. onExecute: args.onExecute,
  9892. onCancel: args.onCancel,
  9893. onClose: args.onClose,
  9894. handlers: handlers
  9895. });
  9896. if(widget.onOpen){
  9897. // TODO: in 2.0 standardize onShow() (used by StackContainer) and onOpen() (used here)
  9898. widget.onOpen(best);
  9899. }
  9900. return best;
  9901. },
  9902. close: function(/*Widget?*/ popup){
  9903. // summary:
  9904. // Close specified popup and any popups that it parented.
  9905. // If no popup is specified, closes all popups.
  9906. var stack = this._stack;
  9907. // Basically work backwards from the top of the stack closing popups
  9908. // until we hit the specified popup, but IIRC there was some issue where closing
  9909. // a popup would cause others to close too. Thus if we are trying to close B in [A,B,C]
  9910. // closing C might close B indirectly and then the while() condition will run where stack==[A]...
  9911. // so the while condition is constructed defensively.
  9912. while((popup && array.some(stack, function(elem){return elem.widget == popup;})) ||
  9913. (!popup && stack.length)){
  9914. var top = stack.pop(),
  9915. widget = top.widget,
  9916. onClose = top.onClose;
  9917. if(widget.onClose){
  9918. // TODO: in 2.0 standardize onHide() (used by StackContainer) and onClose() (used here)
  9919. widget.onClose();
  9920. }
  9921. var h;
  9922. while(h = top.handlers.pop()){ h.remove(); }
  9923. // Hide the widget and it's wrapper unless it has already been destroyed in above onClose() etc.
  9924. if(widget && widget.domNode){
  9925. this.hide(widget);
  9926. }
  9927. if(onClose){
  9928. onClose();
  9929. }
  9930. }
  9931. }
  9932. });
  9933. return (dijit.popup = new PopupManager());
  9934. });
  9935. },
  9936. 'dojox/mobile/uacss':function(){
  9937. define("dojox/mobile/uacss", [
  9938. "dojo/_base/kernel",
  9939. "dojo/_base/lang",
  9940. "dojo/_base/window",
  9941. "dojox/mobile/sniff"
  9942. ], function(dojo, lang, win, has){
  9943. win.doc.documentElement.className += lang.trim([
  9944. has("bb") ? "dj_bb" : "",
  9945. has("android") ? "dj_android" : "",
  9946. has("iphone") ? "dj_iphone" : "",
  9947. has("ipod") ? "dj_ipod" : "",
  9948. has("ipad") ? "dj_ipad" : ""
  9949. ].join(" ").replace(/ +/g," "));
  9950. return dojo;
  9951. });
  9952. },
  9953. 'dijit/_base/window':function(){
  9954. define("dijit/_base/window", [
  9955. "dojo/window", // windowUtils.get
  9956. ".." // export symbol to dijit
  9957. ], function(windowUtils, dijit){
  9958. // module:
  9959. // dijit/_base/window
  9960. // summary:
  9961. // Back compatibility module, new code should use windowUtils directly instead of using this module.
  9962. dijit.getDocumentWindow = function(doc){
  9963. return windowUtils.get(doc);
  9964. };
  9965. });
  9966. },
  9967. 'dijit/_WidgetBase':function(){
  9968. define("dijit/_WidgetBase", [
  9969. "require", // require.toUrl
  9970. "dojo/_base/array", // array.forEach array.map
  9971. "dojo/aspect",
  9972. "dojo/_base/config", // config.blankGif
  9973. "dojo/_base/connect", // connect.connect
  9974. "dojo/_base/declare", // declare
  9975. "dojo/dom", // dom.byId
  9976. "dojo/dom-attr", // domAttr.set domAttr.remove
  9977. "dojo/dom-class", // domClass.add domClass.replace
  9978. "dojo/dom-construct", // domConstruct.create domConstruct.destroy domConstruct.place
  9979. "dojo/dom-geometry", // isBodyLtr
  9980. "dojo/dom-style", // domStyle.set, domStyle.get
  9981. "dojo/_base/kernel",
  9982. "dojo/_base/lang", // mixin(), isArray(), etc.
  9983. "dojo/on",
  9984. "dojo/ready",
  9985. "dojo/Stateful", // Stateful
  9986. "dojo/topic",
  9987. "dojo/_base/window", // win.doc.createTextNode
  9988. "./registry" // registry.getUniqueId(), registry.findWidgets()
  9989. ], function(require, array, aspect, config, connect, declare,
  9990. dom, domAttr, domClass, domConstruct, domGeometry, domStyle, kernel,
  9991. lang, on, ready, Stateful, topic, win, registry){
  9992. /*=====
  9993. var Stateful = dojo.Stateful;
  9994. =====*/
  9995. // module:
  9996. // dijit/_WidgetBase
  9997. // summary:
  9998. // Future base class for all Dijit widgets.
  9999. // For back-compat, remove in 2.0.
  10000. if(!kernel.isAsync){
  10001. ready(0, function(){
  10002. var requires = ["dijit/_base/manager"];
  10003. require(requires); // use indirection so modules not rolled into a build
  10004. });
  10005. }
  10006. // Nested hash listing attributes for each tag, all strings in lowercase.
  10007. // ex: {"div": {"style": true, "tabindex" true}, "form": { ...
  10008. var tagAttrs = {};
  10009. function getAttrs(obj){
  10010. var ret = {};
  10011. for(var attr in obj){
  10012. ret[attr.toLowerCase()] = true;
  10013. }
  10014. return ret;
  10015. }
  10016. function nonEmptyAttrToDom(attr){
  10017. // summary:
  10018. // Returns a setter function that copies the attribute to this.domNode,
  10019. // or removes the attribute from this.domNode, depending on whether the
  10020. // value is defined or not.
  10021. return function(val){
  10022. domAttr[val ? "set" : "remove"](this.domNode, attr, val);
  10023. this._set(attr, val);
  10024. };
  10025. }
  10026. function isEqual(a, b){
  10027. // summary:
  10028. // Function that determines whether two values are identical,
  10029. // taking into account that NaN is not normally equal to itself
  10030. // in JS.
  10031. return a === b || (/* a is NaN */ a !== a && /* b is NaN */ b !== b);
  10032. }
  10033. return declare("dijit._WidgetBase", Stateful, {
  10034. // summary:
  10035. // Future base class for all Dijit widgets.
  10036. // description:
  10037. // Future base class for all Dijit widgets.
  10038. // _Widget extends this class adding support for various features needed by desktop.
  10039. //
  10040. // Provides stubs for widget lifecycle methods for subclasses to extend, like postMixInProperties(), buildRendering(),
  10041. // postCreate(), startup(), and destroy(), and also public API methods like set(), get(), and watch().
  10042. //
  10043. // Widgets can provide custom setters/getters for widget attributes, which are called automatically by set(name, value).
  10044. // For an attribute XXX, define methods _setXXXAttr() and/or _getXXXAttr().
  10045. //
  10046. // _setXXXAttr can also be a string/hash/array mapping from a widget attribute XXX to the widget's DOMNodes:
  10047. //
  10048. // - DOM node attribute
  10049. // | _setFocusAttr: {node: "focusNode", type: "attribute"}
  10050. // | _setFocusAttr: "focusNode" (shorthand)
  10051. // | _setFocusAttr: "" (shorthand, maps to this.domNode)
  10052. // Maps this.focus to this.focusNode.focus, or (last example) this.domNode.focus
  10053. //
  10054. // - DOM node innerHTML
  10055. // | _setTitleAttr: { node: "titleNode", type: "innerHTML" }
  10056. // Maps this.title to this.titleNode.innerHTML
  10057. //
  10058. // - DOM node innerText
  10059. // | _setTitleAttr: { node: "titleNode", type: "innerText" }
  10060. // Maps this.title to this.titleNode.innerText
  10061. //
  10062. // - DOM node CSS class
  10063. // | _setMyClassAttr: { node: "domNode", type: "class" }
  10064. // Maps this.myClass to this.domNode.className
  10065. //
  10066. // If the value of _setXXXAttr is an array, then each element in the array matches one of the
  10067. // formats of the above list.
  10068. //
  10069. // If the custom setter is null, no action is performed other than saving the new value
  10070. // in the widget (in this).
  10071. //
  10072. // If no custom setter is defined for an attribute, then it will be copied
  10073. // to this.focusNode (if the widget defines a focusNode), or this.domNode otherwise.
  10074. // That's only done though for attributes that match DOMNode attributes (title,
  10075. // alt, aria-labelledby, etc.)
  10076. // id: [const] String
  10077. // A unique, opaque ID string that can be assigned by users or by the
  10078. // system. If the developer passes an ID which is known not to be
  10079. // unique, the specified ID is ignored and the system-generated ID is
  10080. // used instead.
  10081. id: "",
  10082. _setIdAttr: "domNode", // to copy to this.domNode even for auto-generated id's
  10083. // lang: [const] String
  10084. // Rarely used. Overrides the default Dojo locale used to render this widget,
  10085. // as defined by the [HTML LANG](http://www.w3.org/TR/html401/struct/dirlang.html#adef-lang) attribute.
  10086. // Value must be among the list of locales specified during by the Dojo bootstrap,
  10087. // formatted according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt) (like en-us).
  10088. lang: "",
  10089. // set on domNode even when there's a focus node. but don't set lang="", since that's invalid.
  10090. _setLangAttr: nonEmptyAttrToDom("lang"),
  10091. // dir: [const] String
  10092. // Bi-directional support, as defined by the [HTML DIR](http://www.w3.org/TR/html401/struct/dirlang.html#adef-dir)
  10093. // attribute. Either left-to-right "ltr" or right-to-left "rtl". If undefined, widgets renders in page's
  10094. // default direction.
  10095. dir: "",
  10096. // set on domNode even when there's a focus node. but don't set dir="", since that's invalid.
  10097. _setDirAttr: nonEmptyAttrToDom("dir"), // to set on domNode even when there's a focus node
  10098. // textDir: String
  10099. // Bi-directional support, the main variable which is responsible for the direction of the text.
  10100. // The text direction can be different than the GUI direction by using this parameter in creation
  10101. // of a widget.
  10102. // Allowed values:
  10103. // 1. "ltr"
  10104. // 2. "rtl"
  10105. // 3. "auto" - contextual the direction of a text defined by first strong letter.
  10106. // By default is as the page direction.
  10107. textDir: "",
  10108. // class: String
  10109. // HTML class attribute
  10110. "class": "",
  10111. _setClassAttr: { node: "domNode", type: "class" },
  10112. // style: String||Object
  10113. // HTML style attributes as cssText string or name/value hash
  10114. style: "",
  10115. // title: String
  10116. // HTML title attribute.
  10117. //
  10118. // For form widgets this specifies a tooltip to display when hovering over
  10119. // the widget (just like the native HTML title attribute).
  10120. //
  10121. // For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer,
  10122. // etc., it's used to specify the tab label, accordion pane title, etc.
  10123. title: "",
  10124. // tooltip: String
  10125. // When this widget's title attribute is used to for a tab label, accordion pane title, etc.,
  10126. // this specifies the tooltip to appear when the mouse is hovered over that text.
  10127. tooltip: "",
  10128. // baseClass: [protected] String
  10129. // Root CSS class of the widget (ex: dijitTextBox), used to construct CSS classes to indicate
  10130. // widget state.
  10131. baseClass: "",
  10132. // srcNodeRef: [readonly] DomNode
  10133. // pointer to original DOM node
  10134. srcNodeRef: null,
  10135. // domNode: [readonly] DomNode
  10136. // This is our visible representation of the widget! Other DOM
  10137. // Nodes may by assigned to other properties, usually through the
  10138. // template system's data-dojo-attach-point syntax, but the domNode
  10139. // property is the canonical "top level" node in widget UI.
  10140. domNode: null,
  10141. // containerNode: [readonly] DomNode
  10142. // Designates where children of the source DOM node will be placed.
  10143. // "Children" in this case refers to both DOM nodes and widgets.
  10144. // For example, for myWidget:
  10145. //
  10146. // | <div data-dojo-type=myWidget>
  10147. // | <b> here's a plain DOM node
  10148. // | <span data-dojo-type=subWidget>and a widget</span>
  10149. // | <i> and another plain DOM node </i>
  10150. // | </div>
  10151. //
  10152. // containerNode would point to:
  10153. //
  10154. // | <b> here's a plain DOM node
  10155. // | <span data-dojo-type=subWidget>and a widget</span>
  10156. // | <i> and another plain DOM node </i>
  10157. //
  10158. // In templated widgets, "containerNode" is set via a
  10159. // data-dojo-attach-point assignment.
  10160. //
  10161. // containerNode must be defined for any widget that accepts innerHTML
  10162. // (like ContentPane or BorderContainer or even Button), and conversely
  10163. // is null for widgets that don't, like TextBox.
  10164. containerNode: null,
  10165. /*=====
  10166. // _started: Boolean
  10167. // startup() has completed.
  10168. _started: false,
  10169. =====*/
  10170. // attributeMap: [protected] Object
  10171. // Deprecated. Instead of attributeMap, widget should have a _setXXXAttr attribute
  10172. // for each XXX attribute to be mapped to the DOM.
  10173. //
  10174. // attributeMap sets up a "binding" between attributes (aka properties)
  10175. // of the widget and the widget's DOM.
  10176. // Changes to widget attributes listed in attributeMap will be
  10177. // reflected into the DOM.
  10178. //
  10179. // For example, calling set('title', 'hello')
  10180. // on a TitlePane will automatically cause the TitlePane's DOM to update
  10181. // with the new title.
  10182. //
  10183. // attributeMap is a hash where the key is an attribute of the widget,
  10184. // and the value reflects a binding to a:
  10185. //
  10186. // - DOM node attribute
  10187. // | focus: {node: "focusNode", type: "attribute"}
  10188. // Maps this.focus to this.focusNode.focus
  10189. //
  10190. // - DOM node innerHTML
  10191. // | title: { node: "titleNode", type: "innerHTML" }
  10192. // Maps this.title to this.titleNode.innerHTML
  10193. //
  10194. // - DOM node innerText
  10195. // | title: { node: "titleNode", type: "innerText" }
  10196. // Maps this.title to this.titleNode.innerText
  10197. //
  10198. // - DOM node CSS class
  10199. // | myClass: { node: "domNode", type: "class" }
  10200. // Maps this.myClass to this.domNode.className
  10201. //
  10202. // If the value is an array, then each element in the array matches one of the
  10203. // formats of the above list.
  10204. //
  10205. // There are also some shorthands for backwards compatibility:
  10206. // - string --> { node: string, type: "attribute" }, for example:
  10207. // | "focusNode" ---> { node: "focusNode", type: "attribute" }
  10208. // - "" --> { node: "domNode", type: "attribute" }
  10209. attributeMap: {},
  10210. // _blankGif: [protected] String
  10211. // Path to a blank 1x1 image.
  10212. // Used by <img> nodes in templates that really get their image via CSS background-image.
  10213. _blankGif: config.blankGif || require.toUrl("dojo/resources/blank.gif"),
  10214. //////////// INITIALIZATION METHODS ///////////////////////////////////////
  10215. postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){
  10216. // summary:
  10217. // Kicks off widget instantiation. See create() for details.
  10218. // tags:
  10219. // private
  10220. this.create(params, srcNodeRef);
  10221. },
  10222. create: function(/*Object?*/params, /*DomNode|String?*/srcNodeRef){
  10223. // summary:
  10224. // Kick off the life-cycle of a widget
  10225. // params:
  10226. // Hash of initialization parameters for widget, including
  10227. // scalar values (like title, duration etc.) and functions,
  10228. // typically callbacks like onClick.
  10229. // srcNodeRef:
  10230. // If a srcNodeRef (DOM node) is specified:
  10231. // - use srcNodeRef.innerHTML as my contents
  10232. // - if this is a behavioral widget then apply behavior
  10233. // to that srcNodeRef
  10234. // - otherwise, replace srcNodeRef with my generated DOM
  10235. // tree
  10236. // description:
  10237. // Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate,
  10238. // etc.), some of which of you'll want to override. See http://dojotoolkit.org/reference-guide/dijit/_WidgetBase.html
  10239. // for a discussion of the widget creation lifecycle.
  10240. //
  10241. // Of course, adventurous developers could override create entirely, but this should
  10242. // only be done as a last resort.
  10243. // tags:
  10244. // private
  10245. // store pointer to original DOM tree
  10246. this.srcNodeRef = dom.byId(srcNodeRef);
  10247. // For garbage collection. An array of listener handles returned by this.connect() / this.subscribe()
  10248. this._connects = [];
  10249. // For widgets internal to this widget, invisible to calling code
  10250. this._supportingWidgets = [];
  10251. // this is here for back-compat, remove in 2.0 (but check NodeList-instantiate.html test)
  10252. if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; }
  10253. // mix in our passed parameters
  10254. if(params){
  10255. this.params = params;
  10256. lang.mixin(this, params);
  10257. }
  10258. this.postMixInProperties();
  10259. // generate an id for the widget if one wasn't specified
  10260. // (be sure to do this before buildRendering() because that function might
  10261. // expect the id to be there.)
  10262. if(!this.id){
  10263. this.id = registry.getUniqueId(this.declaredClass.replace(/\./g,"_"));
  10264. }
  10265. registry.add(this);
  10266. this.buildRendering();
  10267. if(this.domNode){
  10268. // Copy attributes listed in attributeMap into the [newly created] DOM for the widget.
  10269. // Also calls custom setters for all attributes with custom setters.
  10270. this._applyAttributes();
  10271. // If srcNodeRef was specified, then swap out original srcNode for this widget's DOM tree.
  10272. // For 2.0, move this after postCreate(). postCreate() shouldn't depend on the
  10273. // widget being attached to the DOM since it isn't when a widget is created programmatically like
  10274. // new MyWidget({}). See #11635.
  10275. var source = this.srcNodeRef;
  10276. if(source && source.parentNode && this.domNode !== source){
  10277. source.parentNode.replaceChild(this.domNode, source);
  10278. }
  10279. }
  10280. if(this.domNode){
  10281. // Note: for 2.0 may want to rename widgetId to dojo._scopeName + "_widgetId",
  10282. // assuming that dojo._scopeName even exists in 2.0
  10283. this.domNode.setAttribute("widgetId", this.id);
  10284. }
  10285. this.postCreate();
  10286. // If srcNodeRef has been processed and removed from the DOM (e.g. TemplatedWidget) then delete it to allow GC.
  10287. if(this.srcNodeRef && !this.srcNodeRef.parentNode){
  10288. delete this.srcNodeRef;
  10289. }
  10290. this._created = true;
  10291. },
  10292. _applyAttributes: function(){
  10293. // summary:
  10294. // Step during widget creation to copy widget attributes to the
  10295. // DOM according to attributeMap and _setXXXAttr objects, and also to call
  10296. // custom _setXXXAttr() methods.
  10297. //
  10298. // Skips over blank/false attribute values, unless they were explicitly specified
  10299. // as parameters to the widget, since those are the default anyway,
  10300. // and setting tabIndex="" is different than not setting tabIndex at all.
  10301. //
  10302. // For backwards-compatibility reasons attributeMap overrides _setXXXAttr when
  10303. // _setXXXAttr is a hash/string/array, but _setXXXAttr as a functions override attributeMap.
  10304. // tags:
  10305. // private
  10306. // Get list of attributes where this.set(name, value) will do something beyond
  10307. // setting this[name] = value. Specifically, attributes that have:
  10308. // - associated _setXXXAttr() method/hash/string/array
  10309. // - entries in attributeMap.
  10310. var ctor = this.constructor,
  10311. list = ctor._setterAttrs;
  10312. if(!list){
  10313. list = (ctor._setterAttrs = []);
  10314. for(var attr in this.attributeMap){
  10315. list.push(attr);
  10316. }
  10317. var proto = ctor.prototype;
  10318. for(var fxName in proto){
  10319. if(fxName in this.attributeMap){ continue; }
  10320. var setterName = "_set" + fxName.replace(/^[a-z]|-[a-zA-Z]/g, function(c){ return c.charAt(c.length-1).toUpperCase(); }) + "Attr";
  10321. if(setterName in proto){
  10322. list.push(fxName);
  10323. }
  10324. }
  10325. }
  10326. // Call this.set() for each attribute that was either specified as parameter to constructor,
  10327. // or was found above and has a default non-null value. For correlated attributes like value and displayedValue, the one
  10328. // specified as a parameter should take precedence, so apply attributes in this.params last.
  10329. // Particularly important for new DateTextBox({displayedValue: ...}) since DateTextBox's default value is
  10330. // NaN and thus is not ignored like a default value of "".
  10331. array.forEach(list, function(attr){
  10332. if(this.params && attr in this.params){
  10333. // skip this one, do it below
  10334. }else if(this[attr]){
  10335. this.set(attr, this[attr]);
  10336. }
  10337. }, this);
  10338. for(var param in this.params){
  10339. this.set(param, this[param]);
  10340. }
  10341. },
  10342. postMixInProperties: function(){
  10343. // summary:
  10344. // Called after the parameters to the widget have been read-in,
  10345. // but before the widget template is instantiated. Especially
  10346. // useful to set properties that are referenced in the widget
  10347. // template.
  10348. // tags:
  10349. // protected
  10350. },
  10351. buildRendering: function(){
  10352. // summary:
  10353. // Construct the UI for this widget, setting this.domNode.
  10354. // Most widgets will mixin `dijit._TemplatedMixin`, which implements this method.
  10355. // tags:
  10356. // protected
  10357. if(!this.domNode){
  10358. // Create root node if it wasn't created by _Templated
  10359. this.domNode = this.srcNodeRef || domConstruct.create('div');
  10360. }
  10361. // baseClass is a single class name or occasionally a space-separated list of names.
  10362. // Add those classes to the DOMNode. If RTL mode then also add with Rtl suffix.
  10363. // TODO: make baseClass custom setter
  10364. if(this.baseClass){
  10365. var classes = this.baseClass.split(" ");
  10366. if(!this.isLeftToRight()){
  10367. classes = classes.concat( array.map(classes, function(name){ return name+"Rtl"; }));
  10368. }
  10369. domClass.add(this.domNode, classes);
  10370. }
  10371. },
  10372. postCreate: function(){
  10373. // summary:
  10374. // Processing after the DOM fragment is created
  10375. // description:
  10376. // Called after the DOM fragment has been created, but not necessarily
  10377. // added to the document. Do not include any operations which rely on
  10378. // node dimensions or placement.
  10379. // tags:
  10380. // protected
  10381. },
  10382. startup: function(){
  10383. // summary:
  10384. // Processing after the DOM fragment is added to the document
  10385. // description:
  10386. // Called after a widget and its children have been created and added to the page,
  10387. // and all related widgets have finished their create() cycle, up through postCreate().
  10388. // This is useful for composite widgets that need to control or layout sub-widgets.
  10389. // Many layout widgets can use this as a wiring phase.
  10390. if(this._started){ return; }
  10391. this._started = true;
  10392. array.forEach(this.getChildren(), function(obj){
  10393. if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){
  10394. obj.startup();
  10395. obj._started = true;
  10396. }
  10397. });
  10398. },
  10399. //////////// DESTROY FUNCTIONS ////////////////////////////////
  10400. destroyRecursive: function(/*Boolean?*/ preserveDom){
  10401. // summary:
  10402. // Destroy this widget and its descendants
  10403. // description:
  10404. // This is the generic "destructor" function that all widget users
  10405. // should call to cleanly discard with a widget. Once a widget is
  10406. // destroyed, it is removed from the manager object.
  10407. // preserveDom:
  10408. // If true, this method will leave the original DOM structure
  10409. // alone of descendant Widgets. Note: This will NOT work with
  10410. // dijit._Templated widgets.
  10411. this._beingDestroyed = true;
  10412. this.destroyDescendants(preserveDom);
  10413. this.destroy(preserveDom);
  10414. },
  10415. destroy: function(/*Boolean*/ preserveDom){
  10416. // summary:
  10417. // Destroy this widget, but not its descendants.
  10418. // This method will, however, destroy internal widgets such as those used within a template.
  10419. // preserveDom: Boolean
  10420. // If true, this method will leave the original DOM structure alone.
  10421. // Note: This will not yet work with _Templated widgets
  10422. this._beingDestroyed = true;
  10423. this.uninitialize();
  10424. // remove this.connect() and this.subscribe() listeners
  10425. var c;
  10426. while((c = this._connects.pop())){
  10427. c.remove();
  10428. }
  10429. // destroy widgets created as part of template, etc.
  10430. var w;
  10431. while((w = this._supportingWidgets.pop())){
  10432. if(w.destroyRecursive){
  10433. w.destroyRecursive();
  10434. }else if(w.destroy){
  10435. w.destroy();
  10436. }
  10437. }
  10438. this.destroyRendering(preserveDom);
  10439. registry.remove(this.id);
  10440. this._destroyed = true;
  10441. },
  10442. destroyRendering: function(/*Boolean?*/ preserveDom){
  10443. // summary:
  10444. // Destroys the DOM nodes associated with this widget
  10445. // preserveDom:
  10446. // If true, this method will leave the original DOM structure alone
  10447. // during tear-down. Note: this will not work with _Templated
  10448. // widgets yet.
  10449. // tags:
  10450. // protected
  10451. if(this.bgIframe){
  10452. this.bgIframe.destroy(preserveDom);
  10453. delete this.bgIframe;
  10454. }
  10455. if(this.domNode){
  10456. if(preserveDom){
  10457. domAttr.remove(this.domNode, "widgetId");
  10458. }else{
  10459. domConstruct.destroy(this.domNode);
  10460. }
  10461. delete this.domNode;
  10462. }
  10463. if(this.srcNodeRef){
  10464. if(!preserveDom){
  10465. domConstruct.destroy(this.srcNodeRef);
  10466. }
  10467. delete this.srcNodeRef;
  10468. }
  10469. },
  10470. destroyDescendants: function(/*Boolean?*/ preserveDom){
  10471. // summary:
  10472. // Recursively destroy the children of this widget and their
  10473. // descendants.
  10474. // preserveDom:
  10475. // If true, the preserveDom attribute is passed to all descendant
  10476. // widget's .destroy() method. Not for use with _Templated
  10477. // widgets.
  10478. // get all direct descendants and destroy them recursively
  10479. array.forEach(this.getChildren(), function(widget){
  10480. if(widget.destroyRecursive){
  10481. widget.destroyRecursive(preserveDom);
  10482. }
  10483. });
  10484. },
  10485. uninitialize: function(){
  10486. // summary:
  10487. // Stub function. Override to implement custom widget tear-down
  10488. // behavior.
  10489. // tags:
  10490. // protected
  10491. return false;
  10492. },
  10493. ////////////////// GET/SET, CUSTOM SETTERS, ETC. ///////////////////
  10494. _setStyleAttr: function(/*String||Object*/ value){
  10495. // summary:
  10496. // Sets the style attribute of the widget according to value,
  10497. // which is either a hash like {height: "5px", width: "3px"}
  10498. // or a plain string
  10499. // description:
  10500. // Determines which node to set the style on based on style setting
  10501. // in attributeMap.
  10502. // tags:
  10503. // protected
  10504. var mapNode = this.domNode;
  10505. // Note: technically we should revert any style setting made in a previous call
  10506. // to his method, but that's difficult to keep track of.
  10507. if(lang.isObject(value)){
  10508. domStyle.set(mapNode, value);
  10509. }else{
  10510. if(mapNode.style.cssText){
  10511. mapNode.style.cssText += "; " + value;
  10512. }else{
  10513. mapNode.style.cssText = value;
  10514. }
  10515. }
  10516. this._set("style", value);
  10517. },
  10518. _attrToDom: function(/*String*/ attr, /*String*/ value, /*Object?*/ commands){
  10519. // summary:
  10520. // Reflect a widget attribute (title, tabIndex, duration etc.) to
  10521. // the widget DOM, as specified by commands parameter.
  10522. // If commands isn't specified then it's looked up from attributeMap.
  10523. // Note some attributes like "type"
  10524. // cannot be processed this way as they are not mutable.
  10525. //
  10526. // tags:
  10527. // private
  10528. commands = arguments.length >= 3 ? commands : this.attributeMap[attr];
  10529. array.forEach(lang.isArray(commands) ? commands : [commands], function(command){
  10530. // Get target node and what we are doing to that node
  10531. var mapNode = this[command.node || command || "domNode"]; // DOM node
  10532. var type = command.type || "attribute"; // class, innerHTML, innerText, or attribute
  10533. switch(type){
  10534. case "attribute":
  10535. if(lang.isFunction(value)){ // functions execute in the context of the widget
  10536. value = lang.hitch(this, value);
  10537. }
  10538. // Get the name of the DOM node attribute; usually it's the same
  10539. // as the name of the attribute in the widget (attr), but can be overridden.
  10540. // Also maps handler names to lowercase, like onSubmit --> onsubmit
  10541. var attrName = command.attribute ? command.attribute :
  10542. (/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr);
  10543. domAttr.set(mapNode, attrName, value);
  10544. break;
  10545. case "innerText":
  10546. mapNode.innerHTML = "";
  10547. mapNode.appendChild(win.doc.createTextNode(value));
  10548. break;
  10549. case "innerHTML":
  10550. mapNode.innerHTML = value;
  10551. break;
  10552. case "class":
  10553. domClass.replace(mapNode, value, this[attr]);
  10554. break;
  10555. }
  10556. }, this);
  10557. },
  10558. get: function(name){
  10559. // summary:
  10560. // Get a property from a widget.
  10561. // name:
  10562. // The property to get.
  10563. // description:
  10564. // Get a named property from a widget. The property may
  10565. // potentially be retrieved via a getter method. If no getter is defined, this
  10566. // just retrieves the object's property.
  10567. //
  10568. // For example, if the widget has properties `foo` and `bar`
  10569. // and a method named `_getFooAttr()`, calling:
  10570. // `myWidget.get("foo")` would be equivalent to calling
  10571. // `widget._getFooAttr()` and `myWidget.get("bar")`
  10572. // would be equivalent to the expression
  10573. // `widget.bar2`
  10574. var names = this._getAttrNames(name);
  10575. return this[names.g] ? this[names.g]() : this[name];
  10576. },
  10577. set: function(name, value){
  10578. // summary:
  10579. // Set a property on a widget
  10580. // name:
  10581. // The property to set.
  10582. // value:
  10583. // The value to set in the property.
  10584. // description:
  10585. // Sets named properties on a widget which may potentially be handled by a
  10586. // setter in the widget.
  10587. //
  10588. // For example, if the widget has properties `foo` and `bar`
  10589. // and a method named `_setFooAttr()`, calling
  10590. // `myWidget.set("foo", "Howdy!")` would be equivalent to calling
  10591. // `widget._setFooAttr("Howdy!")` and `myWidget.set("bar", 3)`
  10592. // would be equivalent to the statement `widget.bar = 3;`
  10593. //
  10594. // set() may also be called with a hash of name/value pairs, ex:
  10595. //
  10596. // | myWidget.set({
  10597. // | foo: "Howdy",
  10598. // | bar: 3
  10599. // | });
  10600. //
  10601. // This is equivalent to calling `set(foo, "Howdy")` and `set(bar, 3)`
  10602. if(typeof name === "object"){
  10603. for(var x in name){
  10604. this.set(x, name[x]);
  10605. }
  10606. return this;
  10607. }
  10608. var names = this._getAttrNames(name),
  10609. setter = this[names.s];
  10610. if(lang.isFunction(setter)){
  10611. // use the explicit setter
  10612. var result = setter.apply(this, Array.prototype.slice.call(arguments, 1));
  10613. }else{
  10614. // Mapping from widget attribute to DOMNode attribute/value/etc.
  10615. // Map according to:
  10616. // 1. attributeMap setting, if one exists (TODO: attributeMap deprecated, remove in 2.0)
  10617. // 2. _setFooAttr: {...} type attribute in the widget (if one exists)
  10618. // 3. apply to focusNode or domNode if standard attribute name, excluding funcs like onClick.
  10619. // Checks if an attribute is a "standard attribute" by whether the DOMNode JS object has a similar
  10620. // attribute name (ex: accept-charset attribute matches jsObject.acceptCharset).
  10621. // Note also that Tree.focusNode() is a function not a DOMNode, so test for that.
  10622. var defaultNode = this.focusNode && !lang.isFunction(this.focusNode) ? "focusNode" : "domNode",
  10623. tag = this[defaultNode].tagName,
  10624. attrsForTag = tagAttrs[tag] || (tagAttrs[tag] = getAttrs(this[defaultNode])),
  10625. map = name in this.attributeMap ? this.attributeMap[name] :
  10626. names.s in this ? this[names.s] :
  10627. ((names.l in attrsForTag && typeof value != "function") ||
  10628. /^aria-|^data-|^role$/.test(name)) ? defaultNode : null;
  10629. if(map != null){
  10630. this._attrToDom(name, value, map);
  10631. }
  10632. this._set(name, value);
  10633. }
  10634. return result || this;
  10635. },
  10636. _attrPairNames: {}, // shared between all widgets
  10637. _getAttrNames: function(name){
  10638. // summary:
  10639. // Helper function for get() and set().
  10640. // Caches attribute name values so we don't do the string ops every time.
  10641. // tags:
  10642. // private
  10643. var apn = this._attrPairNames;
  10644. if(apn[name]){ return apn[name]; }
  10645. var uc = name.replace(/^[a-z]|-[a-zA-Z]/g, function(c){ return c.charAt(c.length-1).toUpperCase(); });
  10646. return (apn[name] = {
  10647. n: name+"Node",
  10648. s: "_set"+uc+"Attr", // converts dashes to camel case, ex: accept-charset --> _setAcceptCharsetAttr
  10649. g: "_get"+uc+"Attr",
  10650. l: uc.toLowerCase() // lowercase name w/out dashes, ex: acceptcharset
  10651. });
  10652. },
  10653. _set: function(/*String*/ name, /*anything*/ value){
  10654. // summary:
  10655. // Helper function to set new value for specified attribute, and call handlers
  10656. // registered with watch() if the value has changed.
  10657. var oldValue = this[name];
  10658. this[name] = value;
  10659. if(this._watchCallbacks && this._created && !isEqual(value, oldValue)){
  10660. this._watchCallbacks(name, oldValue, value);
  10661. }
  10662. },
  10663. on: function(/*String*/ type, /*Function*/ func){
  10664. // summary:
  10665. // Call specified function when event occurs, ex: myWidget.on("click", function(){ ... }).
  10666. // description:
  10667. // Call specified function when event `type` occurs, ex: `myWidget.on("click", function(){ ... })`.
  10668. // Note that the function is not run in any particular scope, so if (for example) you want it to run in the
  10669. // widget's scope you must do `myWidget.on("click", lang.hitch(myWidget, func))`.
  10670. return aspect.after(this, this._onMap(type), func, true);
  10671. },
  10672. _onMap: function(/*String*/ type){
  10673. // summary:
  10674. // Maps on() type parameter (ex: "mousemove") to method name (ex: "onMouseMove")
  10675. var ctor = this.constructor, map = ctor._onMap;
  10676. if(!map){
  10677. map = (ctor._onMap = {});
  10678. for(var attr in ctor.prototype){
  10679. if(/^on/.test(attr)){
  10680. map[attr.replace(/^on/, "").toLowerCase()] = attr;
  10681. }
  10682. }
  10683. }
  10684. return map[type.toLowerCase()]; // String
  10685. },
  10686. toString: function(){
  10687. // summary:
  10688. // Returns a string that represents the widget
  10689. // description:
  10690. // When a widget is cast to a string, this method will be used to generate the
  10691. // output. Currently, it does not implement any sort of reversible
  10692. // serialization.
  10693. return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
  10694. },
  10695. getChildren: function(){
  10696. // summary:
  10697. // Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode.
  10698. // Does not return nested widgets, nor widgets that are part of this widget's template.
  10699. return this.containerNode ? registry.findWidgets(this.containerNode) : []; // dijit._Widget[]
  10700. },
  10701. getParent: function(){
  10702. // summary:
  10703. // Returns the parent widget of this widget
  10704. return registry.getEnclosingWidget(this.domNode.parentNode);
  10705. },
  10706. connect: function(
  10707. /*Object|null*/ obj,
  10708. /*String|Function*/ event,
  10709. /*String|Function*/ method){
  10710. // summary:
  10711. // Connects specified obj/event to specified method of this object
  10712. // and registers for disconnect() on widget destroy.
  10713. // description:
  10714. // Provide widget-specific analog to dojo.connect, except with the
  10715. // implicit use of this widget as the target object.
  10716. // Events connected with `this.connect` are disconnected upon
  10717. // destruction.
  10718. // returns:
  10719. // A handle that can be passed to `disconnect` in order to disconnect before
  10720. // the widget is destroyed.
  10721. // example:
  10722. // | var btn = new dijit.form.Button();
  10723. // | // when foo.bar() is called, call the listener we're going to
  10724. // | // provide in the scope of btn
  10725. // | btn.connect(foo, "bar", function(){
  10726. // | console.debug(this.toString());
  10727. // | });
  10728. // tags:
  10729. // protected
  10730. var handle = connect.connect(obj, event, this, method);
  10731. this._connects.push(handle);
  10732. return handle; // _Widget.Handle
  10733. },
  10734. disconnect: function(handle){
  10735. // summary:
  10736. // Disconnects handle created by `connect`.
  10737. // Also removes handle from this widget's list of connects.
  10738. // tags:
  10739. // protected
  10740. var i = array.indexOf(this._connects, handle);
  10741. if(i != -1){
  10742. handle.remove();
  10743. this._connects.splice(i, 1);
  10744. }
  10745. },
  10746. subscribe: function(t, method){
  10747. // summary:
  10748. // Subscribes to the specified topic and calls the specified method
  10749. // of this object and registers for unsubscribe() on widget destroy.
  10750. // description:
  10751. // Provide widget-specific analog to dojo.subscribe, except with the
  10752. // implicit use of this widget as the target object.
  10753. // t: String
  10754. // The topic
  10755. // method: Function
  10756. // The callback
  10757. // example:
  10758. // | var btn = new dijit.form.Button();
  10759. // | // when /my/topic is published, this button changes its label to
  10760. // | // be the parameter of the topic.
  10761. // | btn.subscribe("/my/topic", function(v){
  10762. // | this.set("label", v);
  10763. // | });
  10764. // tags:
  10765. // protected
  10766. var handle = topic.subscribe(t, lang.hitch(this, method));
  10767. this._connects.push(handle);
  10768. return handle; // _Widget.Handle
  10769. },
  10770. unsubscribe: function(/*Object*/ handle){
  10771. // summary:
  10772. // Unsubscribes handle created by this.subscribe.
  10773. // Also removes handle from this widget's list of subscriptions
  10774. // tags:
  10775. // protected
  10776. this.disconnect(handle);
  10777. },
  10778. isLeftToRight: function(){
  10779. // summary:
  10780. // Return this widget's explicit or implicit orientation (true for LTR, false for RTL)
  10781. // tags:
  10782. // protected
  10783. return this.dir ? (this.dir == "ltr") : domGeometry.isBodyLtr(); //Boolean
  10784. },
  10785. isFocusable: function(){
  10786. // summary:
  10787. // Return true if this widget can currently be focused
  10788. // and false if not
  10789. return this.focus && (domStyle.get(this.domNode, "display") != "none");
  10790. },
  10791. placeAt: function(/* String|DomNode|_Widget */reference, /* String?|Int? */position){
  10792. // summary:
  10793. // Place this widget's domNode reference somewhere in the DOM based
  10794. // on standard domConstruct.place conventions, or passing a Widget reference that
  10795. // contains and addChild member.
  10796. //
  10797. // description:
  10798. // A convenience function provided in all _Widgets, providing a simple
  10799. // shorthand mechanism to put an existing (or newly created) Widget
  10800. // somewhere in the dom, and allow chaining.
  10801. //
  10802. // reference:
  10803. // The String id of a domNode, a domNode reference, or a reference to a Widget possessing
  10804. // an addChild method.
  10805. //
  10806. // position:
  10807. // If passed a string or domNode reference, the position argument
  10808. // accepts a string just as domConstruct.place does, one of: "first", "last",
  10809. // "before", or "after".
  10810. //
  10811. // If passed a _Widget reference, and that widget reference has an ".addChild" method,
  10812. // it will be called passing this widget instance into that method, supplying the optional
  10813. // position index passed.
  10814. //
  10815. // returns:
  10816. // dijit._Widget
  10817. // Provides a useful return of the newly created dijit._Widget instance so you
  10818. // can "chain" this function by instantiating, placing, then saving the return value
  10819. // to a variable.
  10820. //
  10821. // example:
  10822. // | // create a Button with no srcNodeRef, and place it in the body:
  10823. // | var button = new dijit.form.Button({ label:"click" }).placeAt(win.body());
  10824. // | // now, 'button' is still the widget reference to the newly created button
  10825. // | button.on("click", function(e){ console.log('click'); }));
  10826. //
  10827. // example:
  10828. // | // create a button out of a node with id="src" and append it to id="wrapper":
  10829. // | var button = new dijit.form.Button({},"src").placeAt("wrapper");
  10830. //
  10831. // example:
  10832. // | // place a new button as the first element of some div
  10833. // | var button = new dijit.form.Button({ label:"click" }).placeAt("wrapper","first");
  10834. //
  10835. // example:
  10836. // | // create a contentpane and add it to a TabContainer
  10837. // | var tc = dijit.byId("myTabs");
  10838. // | new dijit.layout.ContentPane({ href:"foo.html", title:"Wow!" }).placeAt(tc)
  10839. if(reference.declaredClass && reference.addChild){
  10840. reference.addChild(this, position);
  10841. }else{
  10842. domConstruct.place(this.domNode, reference, position);
  10843. }
  10844. return this;
  10845. },
  10846. getTextDir: function(/*String*/ text,/*String*/ originalDir){
  10847. // summary:
  10848. // Return direction of the text.
  10849. // The function overridden in the _BidiSupport module,
  10850. // its main purpose is to calculate the direction of the
  10851. // text, if was defined by the programmer through textDir.
  10852. // tags:
  10853. // protected.
  10854. return originalDir;
  10855. },
  10856. applyTextDir: function(/*===== element, text =====*/){
  10857. // summary:
  10858. // The function overridden in the _BidiSupport module,
  10859. // originally used for setting element.dir according to this.textDir.
  10860. // In this case does nothing.
  10861. // element: DOMNode
  10862. // text: String
  10863. // tags:
  10864. // protected.
  10865. },
  10866. defer: function(fcn, delay){
  10867. // summary:
  10868. // Wrapper to setTimeout to avoid deferred functions executing
  10869. // after the originating widget has been destroyed.
  10870. // Returns an object handle with a remove method (that returns null) (replaces clearTimeout).
  10871. // fcn: function reference
  10872. // delay: Optional number (defaults to 0)
  10873. // tags:
  10874. // protected.
  10875. var timer = setTimeout(lang.hitch(this,
  10876. function(){
  10877. if(!timer){ return; }
  10878. timer = null;
  10879. if(!this._destroyed){
  10880. lang.hitch(this, fcn)();
  10881. }
  10882. }),
  10883. delay || 0
  10884. );
  10885. return {
  10886. remove: function(){
  10887. if(timer){
  10888. clearTimeout(timer);
  10889. timer = null;
  10890. }
  10891. return null; // so this works well: handle = handle.remove();
  10892. }
  10893. };
  10894. }
  10895. });
  10896. });
  10897. },
  10898. 'dojox/mobile/app/AlertDialog':function(){
  10899. // wrapped by build app
  10900. define(["dijit","dojo","dojox","dojo/require!dijit/_WidgetBase"], function(dijit,dojo,dojox){
  10901. dojo.provide("dojox.mobile.app.AlertDialog");
  10902. dojo.experimental("dojox.mobile.app.AlertDialog");
  10903. dojo.require("dijit._WidgetBase");
  10904. dojo.declare("dojox.mobile.app.AlertDialog", dijit._WidgetBase, {
  10905. // title: String
  10906. // The title of the AlertDialog
  10907. title: "",
  10908. // text: String
  10909. // The text message displayed in the AlertDialog
  10910. text: "",
  10911. // controller: Object
  10912. // The SceneController for the currently active scene
  10913. controller: null,
  10914. // buttons: Array
  10915. buttons: null,
  10916. defaultButtonLabel: "OK",
  10917. // onChoose: Function
  10918. // The callback function that is invoked when a button is tapped.
  10919. // If the dialog is cancelled, no parameter is passed to this function.
  10920. onChoose: null,
  10921. constructor: function(){
  10922. this.onClick = dojo.hitch(this, this.onClick);
  10923. this._handleSelect = dojo.hitch(this, this._handleSelect);
  10924. },
  10925. buildRendering: function(){
  10926. this.domNode = dojo.create("div",{
  10927. "class": "alertDialog"
  10928. });
  10929. // Create the outer dialog body
  10930. var dlgBody = dojo.create("div", {"class": "alertDialogBody"}, this.domNode);
  10931. // Create the title
  10932. dojo.create("div", {"class": "alertTitle", innerHTML: this.title || ""}, dlgBody);
  10933. // Create the text
  10934. dojo.create("div", {"class": "alertText", innerHTML: this.text || ""}, dlgBody);
  10935. // Create the node that encapsulates all the buttons
  10936. var btnContainer = dojo.create("div", {"class": "alertBtns"}, dlgBody);
  10937. // If no buttons have been defined, default to a single button saying OK
  10938. if(!this.buttons || this.buttons.length == 0){
  10939. this.buttons = [{
  10940. label: this.defaultButtonLabel,
  10941. value: "ok",
  10942. "class": "affirmative"
  10943. }];
  10944. }
  10945. var _this = this;
  10946. // Create each of the buttons
  10947. dojo.forEach(this.buttons, function(btnInfo){
  10948. var btn = new dojox.mobile.Button({
  10949. btnClass: btnInfo["class"] || "",
  10950. label: btnInfo.label
  10951. });
  10952. btn._dialogValue = btnInfo.value;
  10953. dojo.place(btn.domNode, btnContainer);
  10954. _this.connect(btn, "onClick", _this._handleSelect);
  10955. });
  10956. var viewportSize = this.controller.getWindowSize();
  10957. // Create the mask that blocks out the rest of the screen
  10958. this.mask = dojo.create("div", {"class": "dialogUnderlayWrapper",
  10959. innerHTML: "<div class=\"dialogUnderlay\"></div>",
  10960. style: {
  10961. width: viewportSize.w + "px",
  10962. height: viewportSize.h + "px"
  10963. }
  10964. }, this.controller.assistant.domNode);
  10965. this.connect(this.mask, "onclick", function(){
  10966. _this.onChoose && _this.onChoose();
  10967. _this.hide();
  10968. });
  10969. },
  10970. postCreate: function(){
  10971. this.subscribe("/dojox/mobile/app/goback", this._handleSelect);
  10972. },
  10973. _handleSelect: function(event){
  10974. // summary:
  10975. // Handle the selection of a value
  10976. var node;
  10977. console.log("handleSelect");
  10978. if(event && event.target){
  10979. node = event.target;
  10980. // Find the widget that was tapped.
  10981. while(!dijit.byNode(node)){
  10982. node - node.parentNode;
  10983. }
  10984. }
  10985. // If an onChoose function was provided, tell it what button
  10986. // value was chosen
  10987. if(this.onChoose){
  10988. this.onChoose(node ? dijit.byNode(node)._dialogValue: undefined);
  10989. }
  10990. // Hide the dialog
  10991. this.hide();
  10992. },
  10993. show: function(){
  10994. // summary:
  10995. // Show the dialog
  10996. this._doTransition(1);
  10997. },
  10998. hide: function(){
  10999. // summary:
  11000. // Hide the dialog
  11001. this._doTransition(-1);
  11002. },
  11003. _doTransition: function(dir){
  11004. // summary:
  11005. // Either shows or hides the dialog.
  11006. // dir:
  11007. // An integer. If positive, the dialog is shown. If negative,
  11008. // the dialog is hidden.
  11009. // TODO: replace this with CSS transitions
  11010. var anim;
  11011. var h = dojo.marginBox(this.domNode.firstChild).h;
  11012. var bodyHeight = this.controller.getWindowSize().h;
  11013. console.log("dialog height = " + h, " body height = " + bodyHeight);
  11014. var high = bodyHeight - h;
  11015. var low = bodyHeight;
  11016. var anim1 = dojo.fx.slideTo({
  11017. node: this.domNode,
  11018. duration: 400,
  11019. top: {start: dir < 0 ? high : low, end: dir < 0 ? low: high}
  11020. });
  11021. var anim2 = dojo[dir < 0 ? "fadeOut" : "fadeIn"]({
  11022. node: this.mask,
  11023. duration: 400
  11024. });
  11025. var anim = dojo.fx.combine([anim1, anim2]);
  11026. var _this = this;
  11027. dojo.connect(anim, "onEnd", this, function(){
  11028. if(dir < 0){
  11029. _this.domNode.style.display = "none";
  11030. dojo.destroy(_this.domNode);
  11031. dojo.destroy(_this.mask);
  11032. }
  11033. });
  11034. anim.play();
  11035. },
  11036. destroy: function(){
  11037. this.inherited(arguments);
  11038. dojo.destroy(this.mask);
  11039. },
  11040. onClick: function(){
  11041. }
  11042. });
  11043. });
  11044. }}});
  11045. define("dojox/mobile/app", [
  11046. "./app/_base"
  11047. ], function(appBase){
  11048. return appBase;
  11049. });