dijit.js.uncompressed.js 215 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510
  1. /*
  2. Copyright (c) 2004-2022, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. /*
  7. This is an optimized version of Dojo, built for deployment and not for
  8. development. To get sources and documentation, please visit:
  9. http://dojotoolkit.org
  10. */
  11. if(!dojo._hasResource["dojo.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  12. dojo._hasResource["dojo.window"] = true;
  13. dojo.provide("dojo.window");
  14. dojo.getObject("window", true, dojo);
  15. dojo.window.getBox = function(){
  16. // summary:
  17. // Returns the dimensions and scroll position of the viewable area of a browser window
  18. var scrollRoot = (dojo.doc.compatMode == 'BackCompat') ? dojo.body() : dojo.doc.documentElement;
  19. // get scroll position
  20. var scroll = dojo._docScroll(); // scrollRoot.scrollTop/Left should work
  21. return { w: scrollRoot.clientWidth, h: scrollRoot.clientHeight, l: scroll.x, t: scroll.y };
  22. };
  23. dojo.window.get = function(doc){
  24. // summary:
  25. // Get window object associated with document doc
  26. // In some IE versions (at least 6.0), document.parentWindow does not return a
  27. // reference to the real window object (maybe a copy), so we must fix it as well
  28. // We use IE specific execScript to attach the real window reference to
  29. // document._parentWindow for later use
  30. if(dojo.isIE && window !== document.parentWindow){
  31. /*
  32. In IE 6, only the variable "window" can be used to connect events (others
  33. may be only copies).
  34. */
  35. doc.parentWindow.execScript("document._parentWindow = window;", "Javascript");
  36. //to prevent memory leak, unset it after use
  37. //another possibility is to add an onUnload handler which seems overkill to me (liucougar)
  38. var win = doc._parentWindow;
  39. doc._parentWindow = null;
  40. return win; // Window
  41. }
  42. return doc.parentWindow || doc.defaultView; // Window
  43. };
  44. dojo.window.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
  45. // summary:
  46. // Scroll the passed node into view using minimal movement, if it is not already.
  47. // Don't rely on node.scrollIntoView working just because the function is there since
  48. // it forces the node to the page's bottom or top (and left or right in IE) without consideration for the minimal movement.
  49. // WebKit's node.scrollIntoViewIfNeeded doesn't work either for inner scrollbars in right-to-left mode
  50. // and when there's a fixed position scrollable element
  51. node = dojo.byId(node);
  52. var body, doc = node.ownerDocument || dojo.doc;
  53. // has() functions but without has() support
  54. if(!("rtl_adjust_position_for_verticalScrollBar" in dojo.window)){
  55. body = dojo.body();
  56. var scrollable = dojo.create('div', {
  57. style: {overflow:'scroll', overflowX:'visible', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', top:'0', width:'64px', height:'64px'}
  58. }, body, "last"),
  59. div = dojo.create('div', {
  60. style: {overflow:'hidden', direction:'ltr'}
  61. }, scrollable, "last");
  62. dojo.window.rtl_adjust_position_for_verticalScrollBar = dojo.position(div).x != 0;
  63. scrollable.removeChild(div);
  64. body.removeChild(scrollable);
  65. }
  66. if(!("position_fixed_support" in dojo.window)){
  67. // IE6, IE7+quirks, and some older mobile browsers don't support position:fixed
  68. body = dojo.body();
  69. var outer = dojo.create('span', {
  70. style: {visibility:'hidden', position:'fixed', left:'1px', top:'1px'}
  71. }, body, "last"),
  72. inner = dojo.create('span', {
  73. style: {position:'fixed', left:'0', top:'0'}
  74. }, outer, "last");
  75. dojo.window.position_fixed_support = dojo.position(inner).x != dojo.position(outer).x;
  76. outer.removeChild(inner);
  77. body.removeChild(outer);
  78. }
  79. try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method
  80. body = doc.body || doc.getElementsByTagName("body")[0];
  81. var html = doc.documentElement || body.parentNode,
  82. isIE = dojo.isIE,
  83. isWK = dojo.isWebKit;
  84. // if an untested browser, then use the native method
  85. if(node == body || node == html){ return; }
  86. if(!(dojo.isMozilla || isIE || isWK || dojo.isOpera) && ("scrollIntoView" in node)){
  87. node.scrollIntoView(false); // short-circuit to native if possible
  88. return;
  89. }
  90. var backCompat = doc.compatMode == 'BackCompat',
  91. rootWidth = Math.min(body.clientWidth || html.clientWidth, html.clientWidth || body.clientWidth),
  92. rootHeight = Math.min(body.clientHeight || html.clientHeight, html.clientHeight || body.clientHeight),
  93. scrollRoot = (isWK || backCompat) ? body : html,
  94. nodePos = pos || dojo.position(node),
  95. el = node.parentNode,
  96. isFixed = function(el){
  97. return (isIE <= 6 || (isIE == 7 && backCompat))
  98. ? false
  99. : (dojo.window.position_fixed_support && (dojo.style(el, 'position').toLowerCase() == "fixed"));
  100. };
  101. if(isFixed(node)){ return; } // nothing to do
  102. while(el){
  103. if(el == body){ el = scrollRoot; }
  104. var elPos = dojo.position(el),
  105. fixedPos = isFixed(el),
  106. rtl = dojo.getComputedStyle(el).direction.toLowerCase() == "rtl";
  107. if(el == scrollRoot){
  108. elPos.w = rootWidth; elPos.h = rootHeight;
  109. if(scrollRoot == html && isIE && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x
  110. if(elPos.x < 0 || !isIE || isIE >= 9){ elPos.x = 0; } // older IE can have values > 0
  111. if(elPos.y < 0 || !isIE || isIE >= 9){ elPos.y = 0; }
  112. }else{
  113. var pb = dojo._getPadBorderExtents(el);
  114. elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t;
  115. var clientSize = el.clientWidth,
  116. scrollBarSize = elPos.w - clientSize;
  117. if(clientSize > 0 && scrollBarSize > 0){
  118. if(rtl && dojo.window.rtl_adjust_position_for_verticalScrollBar){
  119. elPos.x += scrollBarSize;
  120. }
  121. elPos.w = clientSize;
  122. }
  123. clientSize = el.clientHeight;
  124. scrollBarSize = elPos.h - clientSize;
  125. if(clientSize > 0 && scrollBarSize > 0){
  126. elPos.h = clientSize;
  127. }
  128. }
  129. if(fixedPos){ // bounded by viewport, not parents
  130. if(elPos.y < 0){
  131. elPos.h += elPos.y; elPos.y = 0;
  132. }
  133. if(elPos.x < 0){
  134. elPos.w += elPos.x; elPos.x = 0;
  135. }
  136. if(elPos.y + elPos.h > rootHeight){
  137. elPos.h = rootHeight - elPos.y;
  138. }
  139. if(elPos.x + elPos.w > rootWidth){
  140. elPos.w = rootWidth - elPos.x;
  141. }
  142. }
  143. // calculate overflow in all 4 directions
  144. var l = nodePos.x - elPos.x, // beyond left: < 0
  145. // t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0
  146. t = nodePos.y - elPos.y, // beyond top: < 0
  147. r = l + nodePos.w - elPos.w, // beyond right: > 0
  148. bot = t + nodePos.h - elPos.h; // beyond bottom: > 0
  149. var s, old;
  150. if(r * l > 0 && (!!el.scrollLeft || el == scrollRoot || el.scrollWidth > el.offsetHeight)){
  151. s = Math[l < 0? "max" : "min"](l, r);
  152. if(rtl && ((isIE == 8 && !backCompat) || isIE >= 9)){ s = -s; }
  153. old = el.scrollLeft;
  154. el.scrollLeft += s;
  155. s = el.scrollLeft - old;
  156. nodePos.x -= s;
  157. }
  158. if(bot * t > 0 && (!!el.scrollTop || el == scrollRoot || el.scrollHeight > el.offsetHeight)){
  159. s = Math.ceil(Math[t < 0? "max" : "min"](t, bot));
  160. old = el.scrollTop;
  161. el.scrollTop += s;
  162. s = el.scrollTop - old;
  163. nodePos.y -= s;
  164. }
  165. el = (el != scrollRoot) && !fixedPos && el.parentNode;
  166. }
  167. }catch(error){
  168. console.error('scrollIntoView: ' + error);
  169. node.scrollIntoView(false);
  170. }
  171. };
  172. }
  173. if(!dojo._hasResource["dijit._base.manager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  174. dojo._hasResource["dijit._base.manager"] = true;
  175. dojo.provide("dijit._base.manager");
  176. dojo.declare("dijit.WidgetSet", null, {
  177. // summary:
  178. // A set of widgets indexed by id. A default instance of this class is
  179. // available as `dijit.registry`
  180. //
  181. // example:
  182. // Create a small list of widgets:
  183. // | var ws = new dijit.WidgetSet();
  184. // | ws.add(dijit.byId("one"));
  185. // | ws.add(dijit.byId("two"));
  186. // | // destroy both:
  187. // | ws.forEach(function(w){ w.destroy(); });
  188. //
  189. // example:
  190. // Using dijit.registry:
  191. // | dijit.registry.forEach(function(w){ /* do something */ });
  192. constructor: function(){
  193. this._hash = {};
  194. this.length = 0;
  195. },
  196. add: function(/*dijit._Widget*/ widget){
  197. // summary:
  198. // Add a widget to this list. If a duplicate ID is detected, a error is thrown.
  199. //
  200. // widget: dijit._Widget
  201. // Any dijit._Widget subclass.
  202. if(this._hash[widget.id]){
  203. throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
  204. }
  205. this._hash[widget.id] = widget;
  206. this.length++;
  207. },
  208. remove: function(/*String*/ id){
  209. // summary:
  210. // Remove a widget from this WidgetSet. Does not destroy the widget; simply
  211. // removes the reference.
  212. if(this._hash[id]){
  213. delete this._hash[id];
  214. this.length--;
  215. }
  216. },
  217. forEach: function(/*Function*/ func, /* Object? */thisObj){
  218. // summary:
  219. // Call specified function for each widget in this set.
  220. //
  221. // func:
  222. // A callback function to run for each item. Is passed the widget, the index
  223. // in the iteration, and the full hash, similar to `dojo.forEach`.
  224. //
  225. // thisObj:
  226. // An optional scope parameter
  227. //
  228. // example:
  229. // Using the default `dijit.registry` instance:
  230. // | dijit.registry.forEach(function(widget){
  231. // | console.log(widget.declaredClass);
  232. // | });
  233. //
  234. // returns:
  235. // Returns self, in order to allow for further chaining.
  236. thisObj = thisObj || dojo.global;
  237. var i = 0, id;
  238. for(id in this._hash){
  239. func.call(thisObj, this._hash[id], i++, this._hash);
  240. }
  241. return this; // dijit.WidgetSet
  242. },
  243. filter: function(/*Function*/ filter, /* Object? */thisObj){
  244. // summary:
  245. // Filter down this WidgetSet to a smaller new WidgetSet
  246. // Works the same as `dojo.filter` and `dojo.NodeList.filter`
  247. //
  248. // filter:
  249. // Callback function to test truthiness. Is passed the widget
  250. // reference and the pseudo-index in the object.
  251. //
  252. // thisObj: Object?
  253. // Option scope to use for the filter function.
  254. //
  255. // example:
  256. // Arbitrary: select the odd widgets in this list
  257. // | dijit.registry.filter(function(w, i){
  258. // | return i % 2 == 0;
  259. // | }).forEach(function(w){ /* odd ones */ });
  260. thisObj = thisObj || dojo.global;
  261. var res = new dijit.WidgetSet(), i = 0, id;
  262. for(id in this._hash){
  263. var w = this._hash[id];
  264. if(filter.call(thisObj, w, i++, this._hash)){
  265. res.add(w);
  266. }
  267. }
  268. return res; // dijit.WidgetSet
  269. },
  270. byId: function(/*String*/ id){
  271. // summary:
  272. // Find a widget in this list by it's id.
  273. // example:
  274. // Test if an id is in a particular WidgetSet
  275. // | var ws = new dijit.WidgetSet();
  276. // | ws.add(dijit.byId("bar"));
  277. // | var t = ws.byId("bar") // returns a widget
  278. // | var x = ws.byId("foo"); // returns undefined
  279. return this._hash[id]; // dijit._Widget
  280. },
  281. byClass: function(/*String*/ cls){
  282. // summary:
  283. // Reduce this widgetset to a new WidgetSet of a particular `declaredClass`
  284. //
  285. // cls: String
  286. // The Class to scan for. Full dot-notated string.
  287. //
  288. // example:
  289. // Find all `dijit.TitlePane`s in a page:
  290. // | dijit.registry.byClass("dijit.TitlePane").forEach(function(tp){ tp.close(); });
  291. var res = new dijit.WidgetSet(), id, widget;
  292. for(id in this._hash){
  293. widget = this._hash[id];
  294. if(widget.declaredClass == cls){
  295. res.add(widget);
  296. }
  297. }
  298. return res; // dijit.WidgetSet
  299. },
  300. toArray: function(){
  301. // summary:
  302. // Convert this WidgetSet into a true Array
  303. //
  304. // example:
  305. // Work with the widget .domNodes in a real Array
  306. // | dojo.map(dijit.registry.toArray(), function(w){ return w.domNode; });
  307. var ar = [];
  308. for(var id in this._hash){
  309. ar.push(this._hash[id]);
  310. }
  311. return ar; // dijit._Widget[]
  312. },
  313. map: function(/* Function */func, /* Object? */thisObj){
  314. // summary:
  315. // Create a new Array from this WidgetSet, following the same rules as `dojo.map`
  316. // example:
  317. // | var nodes = dijit.registry.map(function(w){ return w.domNode; });
  318. //
  319. // returns:
  320. // A new array of the returned values.
  321. return dojo.map(this.toArray(), func, thisObj); // Array
  322. },
  323. every: function(func, thisObj){
  324. // summary:
  325. // A synthetic clone of `dojo.every` acting explicitly on this WidgetSet
  326. //
  327. // func: Function
  328. // A callback function run for every widget in this list. Exits loop
  329. // when the first false return is encountered.
  330. //
  331. // thisObj: Object?
  332. // Optional scope parameter to use for the callback
  333. thisObj = thisObj || dojo.global;
  334. var x = 0, i;
  335. for(i in this._hash){
  336. if(!func.call(thisObj, this._hash[i], x++, this._hash)){
  337. return false; // Boolean
  338. }
  339. }
  340. return true; // Boolean
  341. },
  342. some: function(func, thisObj){
  343. // summary:
  344. // A synthetic clone of `dojo.some` acting explictly on this WidgetSet
  345. //
  346. // func: Function
  347. // A callback function run for every widget in this list. Exits loop
  348. // when the first true return is encountered.
  349. //
  350. // thisObj: Object?
  351. // Optional scope parameter to use for the callback
  352. thisObj = thisObj || dojo.global;
  353. var x = 0, i;
  354. for(i in this._hash){
  355. if(func.call(thisObj, this._hash[i], x++, this._hash)){
  356. return true; // Boolean
  357. }
  358. }
  359. return false; // Boolean
  360. }
  361. });
  362. (function(){
  363. /*=====
  364. dijit.registry = {
  365. // summary:
  366. // A list of widgets on a page.
  367. // description:
  368. // Is an instance of `dijit.WidgetSet`
  369. };
  370. =====*/
  371. dijit.registry = new dijit.WidgetSet();
  372. var hash = dijit.registry._hash,
  373. attr = dojo.attr,
  374. hasAttr = dojo.hasAttr,
  375. style = dojo.style;
  376. dijit.byId = function(/*String|dijit._Widget*/ id){
  377. // summary:
  378. // Returns a widget by it's id, or if passed a widget, no-op (like dojo.byId())
  379. return typeof id == "string" ? hash[id] : id; // dijit._Widget
  380. };
  381. var _widgetTypeCtr = {};
  382. dijit.getUniqueId = function(/*String*/widgetType){
  383. // summary:
  384. // Generates a unique id for a given widgetType
  385. var id;
  386. do{
  387. id = widgetType + "_" +
  388. (widgetType in _widgetTypeCtr ?
  389. ++_widgetTypeCtr[widgetType] : _widgetTypeCtr[widgetType] = 0);
  390. }while(hash[id]);
  391. return dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String
  392. };
  393. dijit.findWidgets = function(/*DomNode*/ root){
  394. // summary:
  395. // Search subtree under root returning widgets found.
  396. // Doesn't search for nested widgets (ie, widgets inside other widgets).
  397. var outAry = [];
  398. function getChildrenHelper(root){
  399. for(var node = root.firstChild; node; node = node.nextSibling){
  400. if(node.nodeType == 1){
  401. var widgetId = node.getAttribute("widgetId");
  402. if(widgetId){
  403. var widget = hash[widgetId];
  404. if(widget){ // may be null on page w/multiple dojo's loaded
  405. outAry.push(widget);
  406. }
  407. }else{
  408. getChildrenHelper(node);
  409. }
  410. }
  411. }
  412. }
  413. getChildrenHelper(root);
  414. return outAry;
  415. };
  416. dijit._destroyAll = function(){
  417. // summary:
  418. // Code to destroy all widgets and do other cleanup on page unload
  419. // Clean up focus manager lingering references to widgets and nodes
  420. dijit._curFocus = null;
  421. dijit._prevFocus = null;
  422. dijit._activeStack = [];
  423. // Destroy all the widgets, top down
  424. dojo.forEach(dijit.findWidgets(dojo.body()), function(widget){
  425. // Avoid double destroy of widgets like Menu that are attached to <body>
  426. // even though they are logically children of other widgets.
  427. if(!widget._destroyed){
  428. if(widget.destroyRecursive){
  429. widget.destroyRecursive();
  430. }else if(widget.destroy){
  431. widget.destroy();
  432. }
  433. }
  434. });
  435. };
  436. if(dojo.isIE){
  437. // Only run _destroyAll() for IE because we think it's only necessary in that case,
  438. // and because it causes problems on FF. See bug #3531 for details.
  439. dojo.addOnWindowUnload(function(){
  440. dijit._destroyAll();
  441. });
  442. }
  443. dijit.byNode = function(/*DOMNode*/ node){
  444. // summary:
  445. // Returns the widget corresponding to the given DOMNode
  446. return hash[node.getAttribute("widgetId")]; // dijit._Widget
  447. };
  448. dijit.getEnclosingWidget = function(/*DOMNode*/ node){
  449. // summary:
  450. // Returns the widget whose DOM tree contains the specified DOMNode, or null if
  451. // the node is not contained within the DOM tree of any widget
  452. while(node){
  453. var id = node.getAttribute && node.getAttribute("widgetId");
  454. if(id){
  455. return hash[id];
  456. }
  457. node = node.parentNode;
  458. }
  459. return null;
  460. };
  461. var shown = (dijit._isElementShown = function(/*Element*/ elem){
  462. var s = style(elem);
  463. return (s.visibility != "hidden")
  464. && (s.visibility != "collapsed")
  465. && (s.display != "none")
  466. && (attr(elem, "type") != "hidden");
  467. });
  468. dijit.hasDefaultTabStop = function(/*Element*/ elem){
  469. // summary:
  470. // Tests if element is tab-navigable even without an explicit tabIndex setting
  471. // No explicit tabIndex setting, need to investigate node type
  472. switch(elem.nodeName.toLowerCase()){
  473. case "a":
  474. // An <a> w/out a tabindex is only navigable if it has an href
  475. return hasAttr(elem, "href");
  476. case "area":
  477. case "button":
  478. case "input":
  479. case "object":
  480. case "select":
  481. case "textarea":
  482. // These are navigable by default
  483. return true;
  484. case "iframe":
  485. // If it's an editor <iframe> then it's tab navigable.
  486. var body;
  487. try{
  488. // non-IE
  489. var contentDocument = elem.contentDocument;
  490. if("designMode" in contentDocument && contentDocument.designMode == "on"){
  491. return true;
  492. }
  493. body = contentDocument.body;
  494. }catch(e1){
  495. // contentWindow.document isn't accessible within IE7/8
  496. // if the iframe.src points to a foreign url and this
  497. // page contains an element, that could get focus
  498. try{
  499. body = elem.contentWindow.document.body;
  500. }catch(e2){
  501. return false;
  502. }
  503. }
  504. return body.contentEditable == 'true' || (body.firstChild && body.firstChild.contentEditable == 'true');
  505. default:
  506. return elem.contentEditable == 'true';
  507. }
  508. };
  509. var isTabNavigable = (dijit.isTabNavigable = function(/*Element*/ elem){
  510. // summary:
  511. // Tests if an element is tab-navigable
  512. // TODO: convert (and rename method) to return effective tabIndex; will save time in _getTabNavigable()
  513. if(attr(elem, "disabled")){
  514. return false;
  515. }else if(hasAttr(elem, "tabIndex")){
  516. // Explicit tab index setting
  517. return attr(elem, "tabIndex") >= 0; // boolean
  518. }else{
  519. // No explicit tabIndex setting, so depends on node type
  520. return dijit.hasDefaultTabStop(elem);
  521. }
  522. });
  523. dijit._getTabNavigable = function(/*DOMNode*/ root){
  524. // summary:
  525. // Finds descendants of the specified root node.
  526. //
  527. // description:
  528. // Finds the following descendants of the specified root node:
  529. // * the first tab-navigable element in document order
  530. // without a tabIndex or with tabIndex="0"
  531. // * the last tab-navigable element in document order
  532. // without a tabIndex or with tabIndex="0"
  533. // * the first element in document order with the lowest
  534. // positive tabIndex value
  535. // * the last element in document order with the highest
  536. // positive tabIndex value
  537. var first, last, lowest, lowestTabindex, highest, highestTabindex, radioSelected = {};
  538. function radioName(node) {
  539. // If this element is part of a radio button group, return the name for that group.
  540. return node && node.tagName.toLowerCase() == "input" &&
  541. node.type && node.type.toLowerCase() == "radio" &&
  542. node.name && node.name.toLowerCase();
  543. }
  544. var walkTree = function(/*DOMNode*/parent){
  545. dojo.query("> *", parent).forEach(function(child){
  546. // Skip hidden elements, and also non-HTML elements (those in custom namespaces) in IE,
  547. // since show() invokes getAttribute("type"), which crash on VML nodes in IE.
  548. if((dojo.isIE <= 9 && child.scopeName !== "HTML") || !shown(child)){
  549. return;
  550. }
  551. if(isTabNavigable(child)){
  552. var tabindex = attr(child, "tabIndex");
  553. if(!hasAttr(child, "tabIndex") || tabindex == 0){
  554. if(!first){ first = child; }
  555. last = child;
  556. }else if(tabindex > 0){
  557. if(!lowest || tabindex < lowestTabindex){
  558. lowestTabindex = tabindex;
  559. lowest = child;
  560. }
  561. if(!highest || tabindex >= highestTabindex){
  562. highestTabindex = tabindex;
  563. highest = child;
  564. }
  565. }
  566. var rn = radioName(child);
  567. if(dojo.attr(child, "checked") && rn) {
  568. radioSelected[rn] = child;
  569. }
  570. }
  571. if(child.nodeName.toUpperCase() != 'SELECT'){
  572. walkTree(child);
  573. }
  574. });
  575. };
  576. if(shown(root)){ walkTree(root) }
  577. function rs(node) {
  578. // substitute checked radio button for unchecked one, if there is a checked one with the same name.
  579. return radioSelected[radioName(node)] || node;
  580. }
  581. return { first: rs(first), last: rs(last), lowest: rs(lowest), highest: rs(highest) };
  582. }
  583. dijit.getFirstInTabbingOrder = function(/*String|DOMNode*/ root){
  584. // summary:
  585. // Finds the descendant of the specified root node
  586. // that is first in the tabbing order
  587. var elems = dijit._getTabNavigable(dojo.byId(root));
  588. return elems.lowest ? elems.lowest : elems.first; // DomNode
  589. };
  590. dijit.getLastInTabbingOrder = function(/*String|DOMNode*/ root){
  591. // summary:
  592. // Finds the descendant of the specified root node
  593. // that is last in the tabbing order
  594. var elems = dijit._getTabNavigable(dojo.byId(root));
  595. return elems.last ? elems.last : elems.highest; // DomNode
  596. };
  597. /*=====
  598. dojo.mixin(dijit, {
  599. // defaultDuration: Integer
  600. // The default animation speed (in ms) to use for all Dijit
  601. // transitional animations, unless otherwise specified
  602. // on a per-instance basis. Defaults to 200, overrided by
  603. // `djConfig.defaultDuration`
  604. defaultDuration: 200
  605. });
  606. =====*/
  607. dijit.defaultDuration = dojo.config["defaultDuration"] || 200;
  608. })();
  609. }
  610. if(!dojo._hasResource["dijit._base.focus"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  611. dojo._hasResource["dijit._base.focus"] = true;
  612. dojo.provide("dijit._base.focus");
  613. // summary:
  614. // These functions are used to query or set the focus and selection.
  615. //
  616. // Also, they trace when widgets become activated/deactivated,
  617. // so that the widget can fire _onFocus/_onBlur events.
  618. // "Active" here means something similar to "focused", but
  619. // "focus" isn't quite the right word because we keep track of
  620. // a whole stack of "active" widgets. Example: ComboButton --> Menu -->
  621. // MenuItem. The onBlur event for ComboButton doesn't fire due to focusing
  622. // on the Menu or a MenuItem, since they are considered part of the
  623. // ComboButton widget. It only happens when focus is shifted
  624. // somewhere completely different.
  625. dojo.mixin(dijit, {
  626. // _curFocus: DomNode
  627. // Currently focused item on screen
  628. _curFocus: null,
  629. // _prevFocus: DomNode
  630. // Previously focused item on screen
  631. _prevFocus: null,
  632. isCollapsed: function(){
  633. // summary:
  634. // Returns true if there is no text selected
  635. return dijit.getBookmark().isCollapsed;
  636. },
  637. getBookmark: function(){
  638. // summary:
  639. // Retrieves a bookmark that can be used with moveToBookmark to return to the same range
  640. var bm, rg, tg, sel = dojo.doc.selection, cf = dijit._curFocus;
  641. if(dojo.global.getSelection){
  642. //W3C Range API for selections.
  643. sel = dojo.global.getSelection();
  644. if(sel){
  645. if(sel.isCollapsed){
  646. tg = cf? cf.tagName : "";
  647. if(tg){
  648. //Create a fake rangelike item to restore selections.
  649. tg = tg.toLowerCase();
  650. if(tg == "textarea" ||
  651. (tg == "input" && (!cf.type || cf.type.toLowerCase() == "text"))){
  652. sel = {
  653. start: cf.selectionStart,
  654. end: cf.selectionEnd,
  655. node: cf,
  656. pRange: true
  657. };
  658. return {isCollapsed: (sel.end <= sel.start), mark: sel}; //Object.
  659. }
  660. }
  661. bm = {isCollapsed:true};
  662. if(sel.rangeCount){
  663. bm.mark = sel.getRangeAt(0).cloneRange();
  664. }
  665. }else{
  666. rg = sel.getRangeAt(0);
  667. bm = {isCollapsed: false, mark: rg.cloneRange()};
  668. }
  669. }
  670. }else if(sel){
  671. // If the current focus was a input of some sort and no selection, don't bother saving
  672. // a native bookmark. This is because it causes issues with dialog/page selection restore.
  673. // So, we need to create psuedo bookmarks to work with.
  674. tg = cf ? cf.tagName : "";
  675. tg = tg.toLowerCase();
  676. if(cf && tg && (tg == "button" || tg == "textarea" || tg == "input")){
  677. if(sel.type && sel.type.toLowerCase() == "none"){
  678. return {
  679. isCollapsed: true,
  680. mark: null
  681. }
  682. }else{
  683. rg = sel.createRange();
  684. return {
  685. isCollapsed: rg.text && rg.text.length?false:true,
  686. mark: {
  687. range: rg,
  688. pRange: true
  689. }
  690. };
  691. }
  692. }
  693. bm = {};
  694. //'IE' way for selections.
  695. try{
  696. // createRange() throws exception when dojo in iframe
  697. //and nothing selected, see #9632
  698. rg = sel.createRange();
  699. bm.isCollapsed = !(sel.type == 'Text' ? rg.htmlText.length : rg.length);
  700. }catch(e){
  701. bm.isCollapsed = true;
  702. return bm;
  703. }
  704. if(sel.type.toUpperCase() == 'CONTROL'){
  705. if(rg.length){
  706. bm.mark=[];
  707. var i=0,len=rg.length;
  708. while(i<len){
  709. bm.mark.push(rg.item(i++));
  710. }
  711. }else{
  712. bm.isCollapsed = true;
  713. bm.mark = null;
  714. }
  715. }else{
  716. bm.mark = rg.getBookmark();
  717. }
  718. }else{
  719. console.warn("No idea how to store the current selection for this browser!");
  720. }
  721. return bm; // Object
  722. },
  723. moveToBookmark: function(/*Object*/bookmark){
  724. // summary:
  725. // Moves current selection to a bookmark
  726. // bookmark:
  727. // This should be a returned object from dijit.getBookmark()
  728. var _doc = dojo.doc,
  729. mark = bookmark.mark;
  730. if(mark){
  731. if(dojo.global.getSelection){
  732. //W3C Rangi API (FF, WebKit, Opera, etc)
  733. var sel = dojo.global.getSelection();
  734. if(sel && sel.removeAllRanges){
  735. if(mark.pRange){
  736. var r = mark;
  737. var n = r.node;
  738. n.selectionStart = r.start;
  739. n.selectionEnd = r.end;
  740. }else{
  741. sel.removeAllRanges();
  742. sel.addRange(mark);
  743. }
  744. }else{
  745. console.warn("No idea how to restore selection for this browser!");
  746. }
  747. }else if(_doc.selection && mark){
  748. //'IE' way.
  749. var rg;
  750. if(mark.pRange){
  751. rg = mark.range;
  752. }else if(dojo.isArray(mark)){
  753. rg = _doc.body.createControlRange();
  754. //rg.addElement does not have call/apply method, so can not call it directly
  755. //rg is not available in "range.addElement(item)", so can't use that either
  756. dojo.forEach(mark, function(n){
  757. rg.addElement(n);
  758. });
  759. }else{
  760. rg = _doc.body.createTextRange();
  761. rg.moveToBookmark(mark);
  762. }
  763. rg.select();
  764. }
  765. }
  766. },
  767. getFocus: function(/*Widget?*/ menu, /*Window?*/ openedForWindow){
  768. // summary:
  769. // Called as getFocus(), this returns an Object showing the current focus
  770. // and selected text.
  771. //
  772. // Called as getFocus(widget), where widget is a (widget representing) a button
  773. // that was just pressed, it returns where focus was before that button
  774. // was pressed. (Pressing the button may have either shifted focus to the button,
  775. // or removed focus altogether.) In this case the selected text is not returned,
  776. // since it can't be accurately determined.
  777. //
  778. // menu: dijit._Widget or {domNode: DomNode} structure
  779. // The button that was just pressed. If focus has disappeared or moved
  780. // to this button, returns the previous focus. In this case the bookmark
  781. // information is already lost, and null is returned.
  782. //
  783. // openedForWindow:
  784. // iframe in which menu was opened
  785. //
  786. // returns:
  787. // A handle to restore focus/selection, to be passed to `dijit.focus`
  788. var node = !dijit._curFocus || (menu && dojo.isDescendant(dijit._curFocus, menu.domNode)) ? dijit._prevFocus : dijit._curFocus;
  789. return {
  790. node: node,
  791. bookmark: (node == dijit._curFocus) && dojo.withGlobal(openedForWindow || dojo.global, dijit.getBookmark),
  792. openedForWindow: openedForWindow
  793. }; // Object
  794. },
  795. focus: function(/*Object || DomNode */ handle){
  796. // summary:
  797. // Sets the focused node and the selection according to argument.
  798. // To set focus to an iframe's content, pass in the iframe itself.
  799. // handle:
  800. // object returned by get(), or a DomNode
  801. if(!handle){ return; }
  802. var node = "node" in handle ? handle.node : handle, // because handle is either DomNode or a composite object
  803. bookmark = handle.bookmark,
  804. openedForWindow = handle.openedForWindow,
  805. collapsed = bookmark ? bookmark.isCollapsed : false;
  806. // Set the focus
  807. // Note that for iframe's we need to use the <iframe> to follow the parentNode chain,
  808. // but we need to set focus to iframe.contentWindow
  809. if(node){
  810. var focusNode = (node.tagName.toLowerCase() == "iframe") ? node.contentWindow : node;
  811. if(focusNode && focusNode.focus){
  812. try{
  813. // Gecko throws sometimes if setting focus is impossible,
  814. // node not displayed or something like that
  815. focusNode.focus();
  816. }catch(e){/*quiet*/}
  817. }
  818. dijit._onFocusNode(node);
  819. }
  820. // set the selection
  821. // do not need to restore if current selection is not empty
  822. // (use keyboard to select a menu item) or if previous selection was collapsed
  823. // as it may cause focus shift (Esp in IE).
  824. if(bookmark && dojo.withGlobal(openedForWindow || dojo.global, dijit.isCollapsed) && !collapsed){
  825. if(openedForWindow){
  826. openedForWindow.focus();
  827. }
  828. try{
  829. dojo.withGlobal(openedForWindow || dojo.global, dijit.moveToBookmark, null, [bookmark]);
  830. }catch(e2){
  831. /*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
  832. }
  833. }
  834. },
  835. // _activeStack: dijit._Widget[]
  836. // List of currently active widgets (focused widget and it's ancestors)
  837. _activeStack: [],
  838. registerIframe: function(/*DomNode*/ iframe){
  839. // summary:
  840. // Registers listeners on the specified iframe so that any click
  841. // or focus event on that iframe (or anything in it) is reported
  842. // as a focus/click event on the <iframe> itself.
  843. // description:
  844. // Currently only used by editor.
  845. // returns:
  846. // Handle to pass to unregisterIframe()
  847. return dijit.registerWin(iframe.contentWindow, iframe);
  848. },
  849. unregisterIframe: function(/*Object*/ handle){
  850. // summary:
  851. // Unregisters listeners on the specified iframe created by registerIframe.
  852. // After calling be sure to delete or null out the handle itself.
  853. // handle:
  854. // Handle returned by registerIframe()
  855. dijit.unregisterWin(handle);
  856. },
  857. registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){
  858. // summary:
  859. // Registers listeners on the specified window (either the main
  860. // window or an iframe's window) to detect when the user has clicked somewhere
  861. // or focused somewhere.
  862. // description:
  863. // Users should call registerIframe() instead of this method.
  864. // targetWindow:
  865. // If specified this is the window associated with the iframe,
  866. // i.e. iframe.contentWindow.
  867. // effectiveNode:
  868. // If specified, report any focus events inside targetWindow as
  869. // an event on effectiveNode, rather than on evt.target.
  870. // returns:
  871. // Handle to pass to unregisterWin()
  872. // TODO: make this function private in 2.0; Editor/users should call registerIframe(),
  873. var mousedownListener = function(evt){
  874. dijit._justMouseDowned = true;
  875. setTimeout(function(){ dijit._justMouseDowned = false; }, 0);
  876. // workaround weird IE bug where the click is on an orphaned node
  877. // (first time clicking a Select/DropDownButton inside a TooltipDialog)
  878. if(dojo.isIE && evt && evt.srcElement && evt.srcElement.parentNode == null){
  879. return;
  880. }
  881. dijit._onTouchNode(effectiveNode || evt.target || evt.srcElement, "mouse");
  882. };
  883. //dojo.connect(targetWindow, "onscroll", ???);
  884. // Listen for blur and focus events on targetWindow's document.
  885. // IIRC, I'm using attachEvent() rather than dojo.connect() because focus/blur events don't bubble
  886. // through dojo.connect(), and also maybe to catch the focus events early, before onfocus handlers
  887. // fire.
  888. // Connect to <html> (rather than document) on IE to avoid memory leaks, but document on other browsers because
  889. // (at least for FF) the focus event doesn't fire on <html> or <body>.
  890. var doc = dojo.isIE ? targetWindow.document.documentElement : targetWindow.document;
  891. if(doc){
  892. if(dojo.isIE){
  893. targetWindow.document.body.attachEvent('onmousedown', mousedownListener);
  894. var activateListener = function(evt){
  895. // IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1,
  896. // Should consider those more like a mouse-click than a focus....
  897. if(evt.srcElement.tagName.toLowerCase() != "#document" &&
  898. dijit.isTabNavigable(evt.srcElement)){
  899. dijit._onFocusNode(effectiveNode || evt.srcElement);
  900. }else{
  901. dijit._onTouchNode(effectiveNode || evt.srcElement);
  902. }
  903. };
  904. doc.attachEvent('onactivate', activateListener);
  905. var deactivateListener = function(evt){
  906. dijit._onBlurNode(effectiveNode || evt.srcElement);
  907. };
  908. doc.attachEvent('ondeactivate', deactivateListener);
  909. return function(){
  910. targetWindow.document.detachEvent('onmousedown', mousedownListener);
  911. doc.detachEvent('onactivate', activateListener);
  912. doc.detachEvent('ondeactivate', deactivateListener);
  913. doc = null; // prevent memory leak (apparent circular reference via closure)
  914. };
  915. }else if(doc.body){
  916. doc.body.addEventListener('mousedown', mousedownListener, true);
  917. var focusListener = function(evt){
  918. dijit._onFocusNode(effectiveNode || evt.target);
  919. };
  920. doc.addEventListener('focus', focusListener, true);
  921. var blurListener = function(evt){
  922. dijit._onBlurNode(effectiveNode || evt.target);
  923. };
  924. doc.addEventListener('blur', blurListener, true);
  925. return function(){
  926. doc.body.removeEventListener('mousedown', mousedownListener, true);
  927. doc.removeEventListener('focus', focusListener, true);
  928. doc.removeEventListener('blur', blurListener, true);
  929. doc = null; // prevent memory leak (apparent circular reference via closure)
  930. };
  931. }
  932. }
  933. },
  934. unregisterWin: function(/*Handle*/ handle){
  935. // summary:
  936. // Unregisters listeners on the specified window (either the main
  937. // window or an iframe's window) according to handle returned from registerWin().
  938. // After calling be sure to delete or null out the handle itself.
  939. // Currently our handle is actually a function
  940. handle && handle();
  941. },
  942. _onBlurNode: function(/*DomNode*/ node){
  943. // summary:
  944. // Called when focus leaves a node.
  945. // Usually ignored, _unless_ it *isn't* follwed by touching another node,
  946. // which indicates that we tabbed off the last field on the page,
  947. // in which case every widget is marked inactive
  948. dijit._prevFocus = dijit._curFocus;
  949. dijit._curFocus = null;
  950. if(dijit._justMouseDowned){
  951. // the mouse down caused a new widget to be marked as active; this blur event
  952. // is coming late, so ignore it.
  953. return;
  954. }
  955. // if the blur event isn't followed by a focus event then mark all widgets as inactive.
  956. if(dijit._clearActiveWidgetsTimer){
  957. clearTimeout(dijit._clearActiveWidgetsTimer);
  958. }
  959. dijit._clearActiveWidgetsTimer = setTimeout(function(){
  960. delete dijit._clearActiveWidgetsTimer;
  961. dijit._setStack([]);
  962. dijit._prevFocus = null;
  963. }, 100);
  964. },
  965. _onTouchNode: function(/*DomNode*/ node, /*String*/ by){
  966. // summary:
  967. // Callback when node is focused or mouse-downed
  968. // node:
  969. // The node that was touched.
  970. // by:
  971. // "mouse" if the focus/touch was caused by a mouse down event
  972. // ignore the recent blurNode event
  973. if(dijit._clearActiveWidgetsTimer){
  974. clearTimeout(dijit._clearActiveWidgetsTimer);
  975. delete dijit._clearActiveWidgetsTimer;
  976. }
  977. // compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem)
  978. var newStack=[];
  979. try{
  980. while(node){
  981. var popupParent = dojo.attr(node, "dijitPopupParent");
  982. if(popupParent){
  983. node=dijit.byId(popupParent).domNode;
  984. }else if(node.tagName && node.tagName.toLowerCase() == "body"){
  985. // is this the root of the document or just the root of an iframe?
  986. if(node === dojo.body()){
  987. // node is the root of the main document
  988. break;
  989. }
  990. // otherwise, find the iframe this node refers to (can't access it via parentNode,
  991. // need to do this trick instead). window.frameElement is supported in IE/FF/Webkit
  992. node=dojo.window.get(node.ownerDocument).frameElement;
  993. }else{
  994. // if this node is the root node of a widget, then add widget id to stack,
  995. // except ignore clicks on disabled widgets (actually focusing a disabled widget still works,
  996. // to support MenuItem)
  997. var id = node.getAttribute && node.getAttribute("widgetId"),
  998. widget = id && dijit.byId(id);
  999. if(widget && !(by == "mouse" && widget.get("disabled"))){
  1000. newStack.unshift(id);
  1001. }
  1002. node=node.parentNode;
  1003. }
  1004. }
  1005. }catch(e){ /* squelch */ }
  1006. dijit._setStack(newStack, by);
  1007. },
  1008. _onFocusNode: function(/*DomNode*/ node){
  1009. // summary:
  1010. // Callback when node is focused
  1011. if(!node){
  1012. return;
  1013. }
  1014. if(node.nodeType == 9){
  1015. // Ignore focus events on the document itself. This is here so that
  1016. // (for example) clicking the up/down arrows of a spinner
  1017. // (which don't get focus) won't cause that widget to blur. (FF issue)
  1018. return;
  1019. }
  1020. dijit._onTouchNode(node);
  1021. if(node == dijit._curFocus){ return; }
  1022. if(dijit._curFocus){
  1023. dijit._prevFocus = dijit._curFocus;
  1024. }
  1025. dijit._curFocus = node;
  1026. dojo.publish("focusNode", [node]);
  1027. },
  1028. _setStack: function(/*String[]*/ newStack, /*String*/ by){
  1029. // summary:
  1030. // The stack of active widgets has changed. Send out appropriate events and records new stack.
  1031. // newStack:
  1032. // array of widget id's, starting from the top (outermost) widget
  1033. // by:
  1034. // "mouse" if the focus/touch was caused by a mouse down event
  1035. var oldStack = dijit._activeStack;
  1036. dijit._activeStack = newStack;
  1037. // compare old stack to new stack to see how many elements they have in common
  1038. for(var nCommon=0; nCommon<Math.min(oldStack.length, newStack.length); nCommon++){
  1039. if(oldStack[nCommon] != newStack[nCommon]){
  1040. break;
  1041. }
  1042. }
  1043. var widget;
  1044. // for all elements that have gone out of focus, send blur event
  1045. for(var i=oldStack.length-1; i>=nCommon; i--){
  1046. widget = dijit.byId(oldStack[i]);
  1047. if(widget){
  1048. widget._focused = false;
  1049. widget.set("focused", false);
  1050. widget._hasBeenBlurred = true;
  1051. if(widget._onBlur){
  1052. widget._onBlur(by);
  1053. }
  1054. dojo.publish("widgetBlur", [widget, by]);
  1055. }
  1056. }
  1057. // for all element that have come into focus, send focus event
  1058. for(i=nCommon; i<newStack.length; i++){
  1059. widget = dijit.byId(newStack[i]);
  1060. if(widget){
  1061. widget._focused = true;
  1062. widget.set("focused", true);
  1063. if(widget._onFocus){
  1064. widget._onFocus(by);
  1065. }
  1066. dojo.publish("widgetFocus", [widget, by]);
  1067. }
  1068. }
  1069. }
  1070. });
  1071. // register top window and all the iframes it contains
  1072. dojo.addOnLoad(function(){
  1073. var handle = dijit.registerWin(window);
  1074. if(dojo.isIE){
  1075. dojo.addOnWindowUnload(function(){
  1076. dijit.unregisterWin(handle);
  1077. handle = null;
  1078. })
  1079. }
  1080. });
  1081. }
  1082. if(!dojo._hasResource["dojo.AdapterRegistry"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  1083. dojo._hasResource["dojo.AdapterRegistry"] = true;
  1084. dojo.provide("dojo.AdapterRegistry");
  1085. dojo.AdapterRegistry = function(/*Boolean?*/ returnWrappers){
  1086. // summary:
  1087. // A registry to make contextual calling/searching easier.
  1088. // description:
  1089. // Objects of this class keep list of arrays in the form [name, check,
  1090. // wrap, directReturn] that are used to determine what the contextual
  1091. // result of a set of checked arguments is. All check/wrap functions
  1092. // in this registry should be of the same arity.
  1093. // example:
  1094. // | // create a new registry
  1095. // | var reg = new dojo.AdapterRegistry();
  1096. // | reg.register("handleString",
  1097. // | dojo.isString,
  1098. // | function(str){
  1099. // | // do something with the string here
  1100. // | }
  1101. // | );
  1102. // | reg.register("handleArr",
  1103. // | dojo.isArray,
  1104. // | function(arr){
  1105. // | // do something with the array here
  1106. // | }
  1107. // | );
  1108. // |
  1109. // | // now we can pass reg.match() *either* an array or a string and
  1110. // | // the value we pass will get handled by the right function
  1111. // | reg.match("someValue"); // will call the first function
  1112. // | reg.match(["someValue"]); // will call the second
  1113. this.pairs = [];
  1114. this.returnWrappers = returnWrappers || false; // Boolean
  1115. };
  1116. dojo.extend(dojo.AdapterRegistry, {
  1117. register: function(/*String*/ name, /*Function*/ check, /*Function*/ wrap, /*Boolean?*/ directReturn, /*Boolean?*/ override){
  1118. // summary:
  1119. // register a check function to determine if the wrap function or
  1120. // object gets selected
  1121. // name:
  1122. // a way to identify this matcher.
  1123. // check:
  1124. // a function that arguments are passed to from the adapter's
  1125. // match() function. The check function should return true if the
  1126. // given arguments are appropriate for the wrap function.
  1127. // directReturn:
  1128. // If directReturn is true, the value passed in for wrap will be
  1129. // returned instead of being called. Alternately, the
  1130. // AdapterRegistry can be set globally to "return not call" using
  1131. // the returnWrappers property. Either way, this behavior allows
  1132. // the registry to act as a "search" function instead of a
  1133. // function interception library.
  1134. // override:
  1135. // If override is given and true, the check function will be given
  1136. // highest priority. Otherwise, it will be the lowest priority
  1137. // adapter.
  1138. this.pairs[((override) ? "unshift" : "push")]([name, check, wrap, directReturn]);
  1139. },
  1140. match: function(/* ... */){
  1141. // summary:
  1142. // Find an adapter for the given arguments. If no suitable adapter
  1143. // is found, throws an exception. match() accepts any number of
  1144. // arguments, all of which are passed to all matching functions
  1145. // from the registered pairs.
  1146. for(var i = 0; i < this.pairs.length; i++){
  1147. var pair = this.pairs[i];
  1148. if(pair[1].apply(this, arguments)){
  1149. if((pair[3])||(this.returnWrappers)){
  1150. return pair[2];
  1151. }else{
  1152. return pair[2].apply(this, arguments);
  1153. }
  1154. }
  1155. }
  1156. throw new Error("No match found");
  1157. },
  1158. unregister: function(name){
  1159. // summary: Remove a named adapter from the registry
  1160. // FIXME: this is kind of a dumb way to handle this. On a large
  1161. // registry this will be slow-ish and we can use the name as a lookup
  1162. // should we choose to trade memory for speed.
  1163. for(var i = 0; i < this.pairs.length; i++){
  1164. var pair = this.pairs[i];
  1165. if(pair[0] == name){
  1166. this.pairs.splice(i, 1);
  1167. return true;
  1168. }
  1169. }
  1170. return false;
  1171. }
  1172. });
  1173. }
  1174. if(!dojo._hasResource["dijit._base.place"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  1175. dojo._hasResource["dijit._base.place"] = true;
  1176. dojo.provide("dijit._base.place");
  1177. dijit.getViewport = function(){
  1178. // summary:
  1179. // Returns the dimensions and scroll position of the viewable area of a browser window
  1180. return dojo.window.getBox();
  1181. };
  1182. /*=====
  1183. dijit.__Position = function(){
  1184. // x: Integer
  1185. // horizontal coordinate in pixels, relative to document body
  1186. // y: Integer
  1187. // vertical coordinate in pixels, relative to document body
  1188. thix.x = x;
  1189. this.y = y;
  1190. }
  1191. =====*/
  1192. dijit.placeOnScreen = function(
  1193. /* DomNode */ node,
  1194. /* dijit.__Position */ pos,
  1195. /* String[] */ corners,
  1196. /* dijit.__Position? */ padding){
  1197. // summary:
  1198. // Positions one of the node's corners at specified position
  1199. // such that node is fully visible in viewport.
  1200. // description:
  1201. // NOTE: node is assumed to be absolutely or relatively positioned.
  1202. // pos:
  1203. // Object like {x: 10, y: 20}
  1204. // corners:
  1205. // Array of Strings representing order to try corners in, like ["TR", "BL"].
  1206. // Possible values are:
  1207. // * "BL" - bottom left
  1208. // * "BR" - bottom right
  1209. // * "TL" - top left
  1210. // * "TR" - top right
  1211. // padding:
  1212. // set padding to put some buffer around the element you want to position.
  1213. // example:
  1214. // Try to place node's top right corner at (10,20).
  1215. // If that makes node go (partially) off screen, then try placing
  1216. // bottom left corner at (10,20).
  1217. // | placeOnScreen(node, {x: 10, y: 20}, ["TR", "BL"])
  1218. var choices = dojo.map(corners, function(corner){
  1219. var c = { corner: corner, pos: {x:pos.x,y:pos.y} };
  1220. if(padding){
  1221. c.pos.x += corner.charAt(1) == 'L' ? padding.x : -padding.x;
  1222. c.pos.y += corner.charAt(0) == 'T' ? padding.y : -padding.y;
  1223. }
  1224. return c;
  1225. });
  1226. return dijit._place(node, choices);
  1227. }
  1228. dijit._place = function(/*DomNode*/ node, choices, layoutNode, /*Object*/ aroundNodeCoords){
  1229. // summary:
  1230. // Given a list of spots to put node, put it at the first spot where it fits,
  1231. // of if it doesn't fit anywhere then the place with the least overflow
  1232. // choices: Array
  1233. // Array of elements like: {corner: 'TL', pos: {x: 10, y: 20} }
  1234. // Above example says to put the top-left corner of the node at (10,20)
  1235. // layoutNode: Function(node, aroundNodeCorner, nodeCorner, size)
  1236. // for things like tooltip, they are displayed differently (and have different dimensions)
  1237. // based on their orientation relative to the parent. This adjusts the popup based on orientation.
  1238. // It also passes in the available size for the popup, which is useful for tooltips to
  1239. // tell them that their width is limited to a certain amount. layoutNode() may return a value expressing
  1240. // how much the popup had to be modified to fit into the available space. This is used to determine
  1241. // what the best placement is.
  1242. // aroundNodeCoords: Object
  1243. // Size of aroundNode, ex: {w: 200, h: 50}
  1244. // get {x: 10, y: 10, w: 100, h:100} type obj representing position of
  1245. // viewport over document
  1246. var view = dojo.window.getBox();
  1247. // This won't work if the node is inside a <div style="position: relative">,
  1248. // so reattach it to dojo.doc.body. (Otherwise, the positioning will be wrong
  1249. // and also it might get cutoff)
  1250. if(!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body"){
  1251. dojo.body().appendChild(node);
  1252. }
  1253. var best = null;
  1254. dojo.some(choices, function(choice){
  1255. var corner = choice.corner;
  1256. var pos = choice.pos;
  1257. var overflow = 0;
  1258. // calculate amount of space available given specified position of node
  1259. var spaceAvailable = {
  1260. w: corner.charAt(1) == 'L' ? (view.l + view.w) - pos.x : pos.x - view.l,
  1261. h: corner.charAt(1) == 'T' ? (view.t + view.h) - pos.y : pos.y - view.t
  1262. };
  1263. // configure node to be displayed in given position relative to button
  1264. // (need to do this in order to get an accurate size for the node, because
  1265. // a tooltip's size changes based on position, due to triangle)
  1266. if(layoutNode){
  1267. var res = layoutNode(node, choice.aroundCorner, corner, spaceAvailable, aroundNodeCoords);
  1268. overflow = typeof res == "undefined" ? 0 : res;
  1269. }
  1270. // get node's size
  1271. var style = node.style;
  1272. var oldDisplay = style.display;
  1273. var oldVis = style.visibility;
  1274. style.visibility = "hidden";
  1275. style.display = "";
  1276. var mb = dojo.marginBox(node);
  1277. style.display = oldDisplay;
  1278. style.visibility = oldVis;
  1279. // coordinates and size of node with specified corner placed at pos,
  1280. // and clipped by viewport
  1281. var startX = Math.max(view.l, corner.charAt(1) == 'L' ? pos.x : (pos.x - mb.w)),
  1282. startY = Math.max(view.t, corner.charAt(0) == 'T' ? pos.y : (pos.y - mb.h)),
  1283. endX = Math.min(view.l + view.w, corner.charAt(1) == 'L' ? (startX + mb.w) : pos.x),
  1284. endY = Math.min(view.t + view.h, corner.charAt(0) == 'T' ? (startY + mb.h) : pos.y),
  1285. width = endX - startX,
  1286. height = endY - startY;
  1287. overflow += (mb.w - width) + (mb.h - height);
  1288. if(best == null || overflow < best.overflow){
  1289. best = {
  1290. corner: corner,
  1291. aroundCorner: choice.aroundCorner,
  1292. x: startX,
  1293. y: startY,
  1294. w: width,
  1295. h: height,
  1296. overflow: overflow,
  1297. spaceAvailable: spaceAvailable
  1298. };
  1299. }
  1300. return !overflow;
  1301. });
  1302. // In case the best position is not the last one we checked, need to call
  1303. // layoutNode() again.
  1304. if(best.overflow && layoutNode){
  1305. layoutNode(node, best.aroundCorner, best.corner, best.spaceAvailable, aroundNodeCoords);
  1306. }
  1307. // And then position the node. Do this last, after the layoutNode() above
  1308. // has sized the node, due to browser quirks when the viewport is scrolled
  1309. // (specifically that a Tooltip will shrink to fit as though the window was
  1310. // scrolled to the left).
  1311. //
  1312. // In RTL mode, set style.right rather than style.left so in the common case,
  1313. // window resizes move the popup along with the aroundNode.
  1314. var l = dojo._isBodyLtr(),
  1315. s = node.style;
  1316. s.top = best.y + "px";
  1317. s[l ? "left" : "right"] = (l ? best.x : view.w - best.x - best.w) + "px";
  1318. s[l ? "right" : "left"] = "auto"; // needed for FF or else tooltip goes to far left
  1319. return best;
  1320. }
  1321. dijit.placeOnScreenAroundNode = function(
  1322. /* DomNode */ node,
  1323. /* DomNode */ aroundNode,
  1324. /* Object */ aroundCorners,
  1325. /* Function? */ layoutNode){
  1326. // summary:
  1327. // Position node adjacent or kitty-corner to aroundNode
  1328. // such that it's fully visible in viewport.
  1329. //
  1330. // description:
  1331. // Place node such that corner of node touches a corner of
  1332. // aroundNode, and that node is fully visible.
  1333. //
  1334. // aroundCorners:
  1335. // Ordered list of pairs of corners to try matching up.
  1336. // Each pair of corners is represented as a key/value in the hash,
  1337. // where the key corresponds to the aroundNode's corner, and
  1338. // the value corresponds to the node's corner:
  1339. //
  1340. // | { aroundNodeCorner1: nodeCorner1, aroundNodeCorner2: nodeCorner2, ...}
  1341. //
  1342. // The following strings are used to represent the four corners:
  1343. // * "BL" - bottom left
  1344. // * "BR" - bottom right
  1345. // * "TL" - top left
  1346. // * "TR" - top right
  1347. //
  1348. // layoutNode: Function(node, aroundNodeCorner, nodeCorner)
  1349. // For things like tooltip, they are displayed differently (and have different dimensions)
  1350. // based on their orientation relative to the parent. This adjusts the popup based on orientation.
  1351. //
  1352. // example:
  1353. // | dijit.placeOnScreenAroundNode(node, aroundNode, {'BL':'TL', 'TR':'BR'});
  1354. // This will try to position node such that node's top-left corner is at the same position
  1355. // as the bottom left corner of the aroundNode (ie, put node below
  1356. // aroundNode, with left edges aligned). If that fails it will try to put
  1357. // the bottom-right corner of node where the top right corner of aroundNode is
  1358. // (ie, put node above aroundNode, with right edges aligned)
  1359. //
  1360. // get coordinates of aroundNode
  1361. aroundNode = dojo.byId(aroundNode);
  1362. var aroundNodePos = dojo.position(aroundNode, true);
  1363. // place the node around the calculated rectangle
  1364. return dijit._placeOnScreenAroundRect(node,
  1365. aroundNodePos.x, aroundNodePos.y, aroundNodePos.w, aroundNodePos.h, // rectangle
  1366. aroundCorners, layoutNode);
  1367. };
  1368. /*=====
  1369. dijit.__Rectangle = function(){
  1370. // x: Integer
  1371. // horizontal offset in pixels, relative to document body
  1372. // y: Integer
  1373. // vertical offset in pixels, relative to document body
  1374. // width: Integer
  1375. // width in pixels
  1376. // height: Integer
  1377. // height in pixels
  1378. this.x = x;
  1379. this.y = y;
  1380. this.width = width;
  1381. this.height = height;
  1382. }
  1383. =====*/
  1384. dijit.placeOnScreenAroundRectangle = function(
  1385. /* DomNode */ node,
  1386. /* dijit.__Rectangle */ aroundRect,
  1387. /* Object */ aroundCorners,
  1388. /* Function */ layoutNode){
  1389. // summary:
  1390. // Like dijit.placeOnScreenAroundNode(), except that the "around"
  1391. // parameter is an arbitrary rectangle on the screen (x, y, width, height)
  1392. // instead of a dom node.
  1393. return dijit._placeOnScreenAroundRect(node,
  1394. aroundRect.x, aroundRect.y, aroundRect.width, aroundRect.height, // rectangle
  1395. aroundCorners, layoutNode);
  1396. };
  1397. dijit._placeOnScreenAroundRect = function(
  1398. /* DomNode */ node,
  1399. /* Number */ x,
  1400. /* Number */ y,
  1401. /* Number */ width,
  1402. /* Number */ height,
  1403. /* Object */ aroundCorners,
  1404. /* Function */ layoutNode){
  1405. // summary:
  1406. // Like dijit.placeOnScreenAroundNode(), except it accepts coordinates
  1407. // of a rectangle to place node adjacent to.
  1408. // TODO: combine with placeOnScreenAroundRectangle()
  1409. // Generate list of possible positions for node
  1410. var choices = [];
  1411. for(var nodeCorner in aroundCorners){
  1412. choices.push( {
  1413. aroundCorner: nodeCorner,
  1414. corner: aroundCorners[nodeCorner],
  1415. pos: {
  1416. x: x + (nodeCorner.charAt(1) == 'L' ? 0 : width),
  1417. y: y + (nodeCorner.charAt(0) == 'T' ? 0 : height)
  1418. }
  1419. });
  1420. }
  1421. return dijit._place(node, choices, layoutNode, {w: width, h: height});
  1422. };
  1423. dijit.placementRegistry= new dojo.AdapterRegistry();
  1424. dijit.placementRegistry.register("node",
  1425. function(n, x){
  1426. return typeof x == "object" &&
  1427. typeof x.offsetWidth != "undefined" && typeof x.offsetHeight != "undefined";
  1428. },
  1429. dijit.placeOnScreenAroundNode);
  1430. dijit.placementRegistry.register("rect",
  1431. function(n, x){
  1432. return typeof x == "object" &&
  1433. "x" in x && "y" in x && "width" in x && "height" in x;
  1434. },
  1435. dijit.placeOnScreenAroundRectangle);
  1436. dijit.placeOnScreenAroundElement = function(
  1437. /* DomNode */ node,
  1438. /* Object */ aroundElement,
  1439. /* Object */ aroundCorners,
  1440. /* Function */ layoutNode){
  1441. // summary:
  1442. // Like dijit.placeOnScreenAroundNode(), except it accepts an arbitrary object
  1443. // for the "around" argument and finds a proper processor to place a node.
  1444. return dijit.placementRegistry.match.apply(dijit.placementRegistry, arguments);
  1445. };
  1446. dijit.getPopupAroundAlignment = function(/*Array*/ position, /*Boolean*/ leftToRight){
  1447. // summary:
  1448. // Transforms the passed array of preferred positions into a format suitable for passing as the aroundCorners argument to dijit.placeOnScreenAroundElement.
  1449. //
  1450. // position: String[]
  1451. // This variable controls the position of the drop down.
  1452. // It's an array of strings with the following values:
  1453. //
  1454. // * before: places drop down to the left of the target node/widget, or to the right in
  1455. // the case of RTL scripts like Hebrew and Arabic
  1456. // * after: places drop down to the right of the target node/widget, or to the left in
  1457. // the case of RTL scripts like Hebrew and Arabic
  1458. // * above: drop down goes above target node
  1459. // * below: drop down goes below target node
  1460. //
  1461. // The list is positions is tried, in order, until a position is found where the drop down fits
  1462. // within the viewport.
  1463. //
  1464. // leftToRight: Boolean
  1465. // Whether the popup will be displaying in leftToRight mode.
  1466. //
  1467. var align = {};
  1468. dojo.forEach(position, function(pos){
  1469. switch(pos){
  1470. case "after":
  1471. align[leftToRight ? "BR" : "BL"] = leftToRight ? "BL" : "BR";
  1472. break;
  1473. case "before":
  1474. align[leftToRight ? "BL" : "BR"] = leftToRight ? "BR" : "BL";
  1475. break;
  1476. case "below-alt":
  1477. leftToRight = !leftToRight;
  1478. // fall through
  1479. case "below":
  1480. // first try to align left borders, next try to align right borders (or reverse for RTL mode)
  1481. align[leftToRight ? "BL" : "BR"] = leftToRight ? "TL" : "TR";
  1482. align[leftToRight ? "BR" : "BL"] = leftToRight ? "TR" : "TL";
  1483. break;
  1484. case "above-alt":
  1485. leftToRight = !leftToRight;
  1486. // fall through
  1487. case "above":
  1488. default:
  1489. // first try to align left borders, next try to align right borders (or reverse for RTL mode)
  1490. align[leftToRight ? "TL" : "TR"] = leftToRight ? "BL" : "BR";
  1491. align[leftToRight ? "TR" : "TL"] = leftToRight ? "BR" : "BL";
  1492. break;
  1493. }
  1494. });
  1495. return align;
  1496. };
  1497. }
  1498. if(!dojo._hasResource["dijit._base.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  1499. dojo._hasResource["dijit._base.window"] = true;
  1500. dojo.provide("dijit._base.window");
  1501. dijit.getDocumentWindow = function(doc){
  1502. return dojo.window.get(doc);
  1503. };
  1504. }
  1505. if(!dojo._hasResource["dijit._base.popup"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  1506. dojo._hasResource["dijit._base.popup"] = true;
  1507. dojo.provide("dijit._base.popup");
  1508. /*=====
  1509. dijit.popup.__OpenArgs = function(){
  1510. // popup: Widget
  1511. // widget to display
  1512. // parent: Widget
  1513. // the button etc. that is displaying this popup
  1514. // around: DomNode
  1515. // DOM node (typically a button); place popup relative to this node. (Specify this *or* "x" and "y" parameters.)
  1516. // x: Integer
  1517. // Absolute horizontal position (in pixels) to place node at. (Specify this *or* "around" parameter.)
  1518. // y: Integer
  1519. // Absolute vertical position (in pixels) to place node at. (Specify this *or* "around" parameter.)
  1520. // orient: Object|String
  1521. // When the around parameter is specified, orient should be an
  1522. // ordered list of tuples of the form (around-node-corner, popup-node-corner).
  1523. // dijit.popup.open() tries to position the popup according to each tuple in the list, in order,
  1524. // until the popup appears fully within the viewport.
  1525. //
  1526. // The default value is {BL:'TL', TL:'BL'}, which represents a list of two tuples:
  1527. // 1. (BL, TL)
  1528. // 2. (TL, BL)
  1529. // where BL means "bottom left" and "TL" means "top left".
  1530. // So by default, it first tries putting the popup below the around node, left-aligning them,
  1531. // and then tries to put it above the around node, still left-aligning them. Note that the
  1532. // default is horizontally reversed when in RTL mode.
  1533. //
  1534. // When an (x,y) position is specified rather than an around node, orient is either
  1535. // "R" or "L". R (for right) means that it tries to put the popup to the right of the mouse,
  1536. // specifically positioning the popup's top-right corner at the mouse position, and if that doesn't
  1537. // fit in the viewport, then it tries, in order, the bottom-right corner, the top left corner,
  1538. // and the top-right corner.
  1539. // onCancel: Function
  1540. // callback when user has canceled the popup by
  1541. // 1. hitting ESC or
  1542. // 2. by using the popup widget's proprietary cancel mechanism (like a cancel button in a dialog);
  1543. // i.e. whenever popupWidget.onCancel() is called, args.onCancel is called
  1544. // onClose: Function
  1545. // callback whenever this popup is closed
  1546. // onExecute: Function
  1547. // callback when user "executed" on the popup/sub-popup by selecting a menu choice, etc. (top menu only)
  1548. // padding: dijit.__Position
  1549. // adding a buffer around the opening position. This is only useful when around is not set.
  1550. this.popup = popup;
  1551. this.parent = parent;
  1552. this.around = around;
  1553. this.x = x;
  1554. this.y = y;
  1555. this.orient = orient;
  1556. this.onCancel = onCancel;
  1557. this.onClose = onClose;
  1558. this.onExecute = onExecute;
  1559. this.padding = padding;
  1560. }
  1561. =====*/
  1562. dijit.popup = {
  1563. // summary:
  1564. // This singleton is used to show/hide widgets as popups.
  1565. // _stack: dijit._Widget[]
  1566. // Stack of currently popped up widgets.
  1567. // (someone opened _stack[0], and then it opened _stack[1], etc.)
  1568. _stack: [],
  1569. // _beginZIndex: Number
  1570. // Z-index of the first popup. (If first popup opens other
  1571. // popups they get a higher z-index.)
  1572. _beginZIndex: 1000,
  1573. _idGen: 1,
  1574. _createWrapper: function(/*Widget || DomNode*/ widget){
  1575. // summary:
  1576. // Initialization for widgets that will be used as popups.
  1577. // Puts widget inside a wrapper DIV (if not already in one),
  1578. // and returns pointer to that wrapper DIV.
  1579. var node = widget.domNode || widget,
  1580. wrapper = widget.declaredClass ? widget._popupWrapper :
  1581. node.parentNode && dojo.hasClass(node.parentNode, "dijitPopup") ? node.parentNode : null;
  1582. if(!wrapper){
  1583. // Create wrapper <div> for when this widget [in the future] will be used as a popup.
  1584. // This is done early because of IE bugs where creating/moving DOM nodes causes focus
  1585. // to go wonky, see tests/robot/Toolbar.html to reproduce
  1586. wrapper = dojo.create("div",{
  1587. "class":"dijitPopup",
  1588. style:{ display: "none"},
  1589. role: "presentation"
  1590. }, dojo.body());
  1591. wrapper.appendChild(node);
  1592. var s = node.style;
  1593. s.display = "";
  1594. s.visibility = "";
  1595. s.position = "";
  1596. s.top = "0px";
  1597. if(widget.declaredClass){ // TODO: in 2.0 change signature to always take widget, then remove if()
  1598. widget._popupWrapper = wrapper;
  1599. dojo.connect(widget, "destroy", function(){
  1600. dojo.destroy(wrapper);
  1601. delete widget._popupWrapper;
  1602. });
  1603. }
  1604. }
  1605. return wrapper; // DOMNode
  1606. },
  1607. moveOffScreen: function(/*Widget || DomNode*/ widget){
  1608. // summary:
  1609. // Moves the popup widget off-screen.
  1610. // Do not use this method to hide popups when not in use, because
  1611. // that will create an accessibility issue: the offscreen popup is
  1612. // still in the tabbing order.
  1613. // Create wrapper if not already there
  1614. var wrapper = this._createWrapper(widget);
  1615. dojo.style(wrapper, {
  1616. visibility: "hidden",
  1617. top: "-9999px", // prevent transient scrollbar causing misalign (#5776), and initial flash in upper left (#10111)
  1618. display: ""
  1619. });
  1620. },
  1621. hide: function(/*dijit._Widget*/ widget){
  1622. // summary:
  1623. // Hide this popup widget (until it is ready to be shown).
  1624. // Initialization for widgets that will be used as popups
  1625. //
  1626. // Also puts widget inside a wrapper DIV (if not already in one)
  1627. //
  1628. // If popup widget needs to layout it should
  1629. // do so when it is made visible, and popup._onShow() is called.
  1630. // Create wrapper if not already there
  1631. var wrapper = this._createWrapper(widget);
  1632. dojo.style(wrapper, "display", "none");
  1633. },
  1634. getTopPopup: function(){
  1635. // summary:
  1636. // Compute the closest ancestor popup that's *not* a child of another popup.
  1637. // Ex: For a TooltipDialog with a button that spawns a tree of menus, find the popup of the button.
  1638. var stack = this._stack;
  1639. for(var pi=stack.length-1; pi > 0 && stack[pi].parent === stack[pi-1].widget; pi--){
  1640. /* do nothing, just trying to get right value for pi */
  1641. }
  1642. return stack[pi];
  1643. },
  1644. open: function(/*dijit.popup.__OpenArgs*/ args){
  1645. // summary:
  1646. // Popup the widget at the specified position
  1647. //
  1648. // example:
  1649. // opening at the mouse position
  1650. // | dijit.popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
  1651. //
  1652. // example:
  1653. // opening the widget as a dropdown
  1654. // | dijit.popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...}});
  1655. //
  1656. // Note that whatever widget called dijit.popup.open() should also listen to its own _onBlur callback
  1657. // (fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
  1658. var stack = this._stack,
  1659. widget = args.popup,
  1660. orient = args.orient || (
  1661. (args.parent ? args.parent.isLeftToRight() : dojo._isBodyLtr()) ?
  1662. {'BL':'TL', 'BR':'TR', 'TL':'BL', 'TR':'BR'} :
  1663. {'BR':'TR', 'BL':'TL', 'TR':'BR', 'TL':'BL'}
  1664. ),
  1665. around = args.around,
  1666. id = (args.around && args.around.id) ? (args.around.id+"_dropdown") : ("popup_"+this._idGen++);
  1667. // If we are opening a new popup that isn't a child of a currently opened popup, then
  1668. // close currently opened popup(s). This should happen automatically when the old popups
  1669. // gets the _onBlur() event, except that the _onBlur() event isn't reliable on IE, see [22198].
  1670. while(stack.length && (!args.parent || !dojo.isDescendant(args.parent.domNode, stack[stack.length-1].widget.domNode))){
  1671. dijit.popup.close(stack[stack.length-1].widget);
  1672. }
  1673. // Get pointer to popup wrapper, and create wrapper if it doesn't exist
  1674. var wrapper = this._createWrapper(widget);
  1675. dojo.attr(wrapper, {
  1676. id: id,
  1677. style: {
  1678. zIndex: this._beginZIndex + stack.length
  1679. },
  1680. "class": "dijitPopup " + (widget.baseClass || widget["class"] || "").split(" ")[0] +"Popup",
  1681. dijitPopupParent: args.parent ? args.parent.id : ""
  1682. });
  1683. if(dojo.isIE || dojo.isMoz){
  1684. if(!widget.bgIframe){
  1685. // setting widget.bgIframe triggers cleanup in _Widget.destroy()
  1686. widget.bgIframe = new dijit.BackgroundIframe(wrapper);
  1687. }
  1688. }
  1689. // position the wrapper node and make it visible
  1690. var best = around ?
  1691. dijit.placeOnScreenAroundElement(wrapper, around, orient, widget.orient ? dojo.hitch(widget, "orient") : null) :
  1692. dijit.placeOnScreen(wrapper, args, orient == 'R' ? ['TR','BR','TL','BL'] : ['TL','BL','TR','BR'], args.padding);
  1693. wrapper.style.display = "";
  1694. wrapper.style.visibility = "visible";
  1695. widget.domNode.style.visibility = "visible"; // counteract effects from _HasDropDown
  1696. var handlers = [];
  1697. // provide default escape and tab key handling
  1698. // (this will work for any widget, not just menu)
  1699. handlers.push(dojo.connect(wrapper, "onkeypress", this, function(evt){
  1700. if(evt.charOrCode == dojo.keys.ESCAPE && args.onCancel){
  1701. dojo.stopEvent(evt);
  1702. args.onCancel();
  1703. }else if(evt.charOrCode === dojo.keys.TAB){
  1704. dojo.stopEvent(evt);
  1705. var topPopup = this.getTopPopup();
  1706. if(topPopup && topPopup.onCancel){
  1707. topPopup.onCancel();
  1708. }
  1709. }
  1710. }));
  1711. // watch for cancel/execute events on the popup and notify the caller
  1712. // (for a menu, "execute" means clicking an item)
  1713. if(widget.onCancel){
  1714. handlers.push(dojo.connect(widget, "onCancel", args.onCancel));
  1715. }
  1716. handlers.push(dojo.connect(widget, widget.onExecute ? "onExecute" : "onChange", this, function(){
  1717. var topPopup = this.getTopPopup();
  1718. if(topPopup && topPopup.onExecute){
  1719. topPopup.onExecute();
  1720. }
  1721. }));
  1722. stack.push({
  1723. widget: widget,
  1724. parent: args.parent,
  1725. onExecute: args.onExecute,
  1726. onCancel: args.onCancel,
  1727. onClose: args.onClose,
  1728. handlers: handlers
  1729. });
  1730. if(widget.onOpen){
  1731. // TODO: in 2.0 standardize onShow() (used by StackContainer) and onOpen() (used here)
  1732. widget.onOpen(best);
  1733. }
  1734. return best;
  1735. },
  1736. close: function(/*dijit._Widget?*/ popup){
  1737. // summary:
  1738. // Close specified popup and any popups that it parented.
  1739. // If no popup is specified, closes all popups.
  1740. var stack = this._stack;
  1741. // Basically work backwards from the top of the stack closing popups
  1742. // until we hit the specified popup, but IIRC there was some issue where closing
  1743. // a popup would cause others to close too. Thus if we are trying to close B in [A,B,C]
  1744. // closing C might close B indirectly and then the while() condition will run where stack==[A]...
  1745. // so the while condition is constructed defensively.
  1746. while((popup && dojo.some(stack, function(elem){return elem.widget == popup;})) ||
  1747. (!popup && stack.length)){
  1748. var top = stack.pop(),
  1749. widget = top.widget,
  1750. onClose = top.onClose;
  1751. if(widget.onClose){
  1752. // TODO: in 2.0 standardize onHide() (used by StackContainer) and onClose() (used here)
  1753. widget.onClose();
  1754. }
  1755. dojo.forEach(top.handlers, dojo.disconnect);
  1756. // Hide the widget and it's wrapper unless it has already been destroyed in above onClose() etc.
  1757. if(widget && widget.domNode){
  1758. this.hide(widget);
  1759. }
  1760. if(onClose){
  1761. onClose();
  1762. }
  1763. }
  1764. }
  1765. };
  1766. // TODO: remove dijit._frames, it isn't being used much, since popups never release their
  1767. // iframes (see [22236])
  1768. dijit._frames = new function(){
  1769. // summary:
  1770. // cache of iframes
  1771. var queue = [];
  1772. this.pop = function(){
  1773. var iframe;
  1774. if(queue.length){
  1775. iframe = queue.pop();
  1776. iframe.style.display="";
  1777. }else{
  1778. if(dojo.isIE < 9){
  1779. var burl = dojo.config["dojoBlankHtmlUrl"] || (dojo.moduleUrl("dojo", "resources/blank.html")+"") || "javascript:\"\"";
  1780. var html="<iframe src='" + burl + "'"
  1781. + " style='position: absolute; left: 0px; top: 0px;"
  1782. + "z-index: -1; filter:Alpha(Opacity=\"0\");'>";
  1783. iframe = dojo.doc.createElement(html);
  1784. }else{
  1785. iframe = dojo.create("iframe");
  1786. iframe.src = 'javascript:""';
  1787. iframe.className = "dijitBackgroundIframe";
  1788. dojo.style(iframe, "opacity", 0.1);
  1789. }
  1790. iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didn't work.
  1791. dijit.setWaiRole(iframe,"presentation");
  1792. }
  1793. return iframe;
  1794. };
  1795. this.push = function(iframe){
  1796. iframe.style.display="none";
  1797. queue.push(iframe);
  1798. }
  1799. }();
  1800. dijit.BackgroundIframe = function(/*DomNode*/ node){
  1801. // summary:
  1802. // For IE/FF z-index schenanigans. id attribute is required.
  1803. //
  1804. // description:
  1805. // new dijit.BackgroundIframe(node)
  1806. // Makes a background iframe as a child of node, that fills
  1807. // area (and position) of node
  1808. if(!node.id){ throw new Error("no id"); }
  1809. if(dojo.isIE || dojo.isMoz){
  1810. var iframe = (this.iframe = dijit._frames.pop());
  1811. node.appendChild(iframe);
  1812. if(dojo.isIE<7 || dojo.isQuirks){
  1813. this.resize(node);
  1814. this._conn = dojo.connect(node, 'onresize', this, function(){
  1815. this.resize(node);
  1816. });
  1817. }else{
  1818. dojo.style(iframe, {
  1819. width: '100%',
  1820. height: '100%'
  1821. });
  1822. }
  1823. }
  1824. };
  1825. dojo.extend(dijit.BackgroundIframe, {
  1826. resize: function(node){
  1827. // summary:
  1828. // Resize the iframe so it's the same size as node.
  1829. // Needed on IE6 and IE/quirks because height:100% doesn't work right.
  1830. if(this.iframe){
  1831. dojo.style(this.iframe, {
  1832. width: node.offsetWidth + 'px',
  1833. height: node.offsetHeight + 'px'
  1834. });
  1835. }
  1836. },
  1837. destroy: function(){
  1838. // summary:
  1839. // destroy the iframe
  1840. if(this._conn){
  1841. dojo.disconnect(this._conn);
  1842. this._conn = null;
  1843. }
  1844. if(this.iframe){
  1845. dijit._frames.push(this.iframe);
  1846. delete this.iframe;
  1847. }
  1848. }
  1849. });
  1850. }
  1851. if(!dojo._hasResource["dijit._base.scroll"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  1852. dojo._hasResource["dijit._base.scroll"] = true;
  1853. dojo.provide("dijit._base.scroll");
  1854. dijit.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
  1855. // summary:
  1856. // Scroll the passed node into view, if it is not already.
  1857. // Deprecated, use `dojo.window.scrollIntoView` instead.
  1858. dojo.window.scrollIntoView(node, pos);
  1859. };
  1860. }
  1861. if(!dojo._hasResource["dojo.uacss"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  1862. dojo._hasResource["dojo.uacss"] = true;
  1863. dojo.provide("dojo.uacss");
  1864. (function(){
  1865. // summary:
  1866. // Applies pre-set CSS classes to the top-level HTML node, based on:
  1867. // - browser (ex: dj_ie)
  1868. // - browser version (ex: dj_ie6)
  1869. // - box model (ex: dj_contentBox)
  1870. // - text direction (ex: dijitRtl)
  1871. //
  1872. // In addition, browser, browser version, and box model are
  1873. // combined with an RTL flag when browser text is RTL. ex: dj_ie-rtl.
  1874. var d = dojo,
  1875. html = d.doc.documentElement,
  1876. ie = d.isIE,
  1877. opera = d.isOpera,
  1878. maj = Math.floor,
  1879. ff = d.isFF,
  1880. boxModel = d.boxModel.replace(/-/,''),
  1881. classes = {
  1882. dj_quirks: d.isQuirks,
  1883. // NOTE: Opera not supported by dijit
  1884. dj_opera: opera,
  1885. dj_khtml: d.isKhtml,
  1886. dj_webkit: d.isWebKit,
  1887. dj_safari: d.isSafari,
  1888. dj_chrome: d.isChrome,
  1889. dj_gecko: d.isMozilla
  1890. }; // no dojo unsupported browsers
  1891. if(ie){
  1892. classes["dj_ie"] = true;
  1893. classes["dj_ie" + maj(ie)] = true;
  1894. classes["dj_iequirks"] = d.isQuirks;
  1895. }
  1896. if(ff){
  1897. classes["dj_ff" + maj(ff)] = true;
  1898. }
  1899. classes["dj_" + boxModel] = true;
  1900. // apply browser, browser version, and box model class names
  1901. var classStr = "";
  1902. for(var clz in classes){
  1903. if(classes[clz]){
  1904. classStr += clz + " ";
  1905. }
  1906. }
  1907. html.className = d.trim(html.className + " " + classStr);
  1908. // If RTL mode, then add dj_rtl flag plus repeat existing classes with -rtl extension.
  1909. // We can't run the code below until the <body> tag has loaded (so we can check for dir=rtl).
  1910. // Unshift() is to run sniff code before the parser.
  1911. dojo._loaders.unshift(function(){
  1912. if(!dojo._isBodyLtr()){
  1913. var rtlClassStr = "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl ")
  1914. html.className = d.trim(html.className + " " + rtlClassStr);
  1915. }
  1916. });
  1917. })();
  1918. }
  1919. if(!dojo._hasResource["dijit._base.sniff"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  1920. dojo._hasResource["dijit._base.sniff"] = true;
  1921. dojo.provide("dijit._base.sniff");
  1922. // summary:
  1923. // Applies pre-set CSS classes to the top-level HTML node, see
  1924. // `dojo.uacss` for details.
  1925. //
  1926. // Simply doing a require on this module will
  1927. // establish this CSS. Modified version of Morris' CSS hack.
  1928. }
  1929. if(!dojo._hasResource["dijit._base.typematic"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  1930. dojo._hasResource["dijit._base.typematic"] = true;
  1931. dojo.provide("dijit._base.typematic");
  1932. dijit.typematic = {
  1933. // summary:
  1934. // These functions are used to repetitively call a user specified callback
  1935. // method when a specific key or mouse click over a specific DOM node is
  1936. // held down for a specific amount of time.
  1937. // Only 1 such event is allowed to occur on the browser page at 1 time.
  1938. _fireEventAndReload: function(){
  1939. this._timer = null;
  1940. this._callback(++this._count, this._node, this._evt);
  1941. // Schedule next event, timer is at most minDelay (default 10ms) to avoid
  1942. // browser overload (particularly avoiding starving DOH robot so it never gets to send a mouseup)
  1943. this._currentTimeout = Math.max(
  1944. this._currentTimeout < 0 ? this._initialDelay :
  1945. (this._subsequentDelay > 1 ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay)),
  1946. this._minDelay);
  1947. this._timer = setTimeout(dojo.hitch(this, "_fireEventAndReload"), this._currentTimeout);
  1948. },
  1949. trigger: function(/*Event*/ evt, /*Object*/ _this, /*DOMNode*/ node, /*Function*/ callback, /*Object*/ obj, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
  1950. // summary:
  1951. // Start a timed, repeating callback sequence.
  1952. // If already started, the function call is ignored.
  1953. // This method is not normally called by the user but can be
  1954. // when the normal listener code is insufficient.
  1955. // evt:
  1956. // key or mouse event object to pass to the user callback
  1957. // _this:
  1958. // pointer to the user's widget space.
  1959. // node:
  1960. // the DOM node object to pass the the callback function
  1961. // callback:
  1962. // function to call until the sequence is stopped called with 3 parameters:
  1963. // count:
  1964. // integer representing number of repeated calls (0..n) with -1 indicating the iteration has stopped
  1965. // node:
  1966. // the DOM node object passed in
  1967. // evt:
  1968. // key or mouse event object
  1969. // obj:
  1970. // user space object used to uniquely identify each typematic sequence
  1971. // subsequentDelay (optional):
  1972. // if > 1, the number of milliseconds until the 3->n events occur
  1973. // or else the fractional time multiplier for the next event's delay, default=0.9
  1974. // initialDelay (optional):
  1975. // the number of milliseconds until the 2nd event occurs, default=500ms
  1976. // minDelay (optional):
  1977. // the maximum delay in milliseconds for event to fire, default=10ms
  1978. if(obj != this._obj){
  1979. this.stop();
  1980. this._initialDelay = initialDelay || 500;
  1981. this._subsequentDelay = subsequentDelay || 0.90;
  1982. this._minDelay = minDelay || 10;
  1983. this._obj = obj;
  1984. this._evt = evt;
  1985. this._node = node;
  1986. this._currentTimeout = -1;
  1987. this._count = -1;
  1988. this._callback = dojo.hitch(_this, callback);
  1989. this._fireEventAndReload();
  1990. this._evt = dojo.mixin({faux: true}, evt);
  1991. }
  1992. },
  1993. stop: function(){
  1994. // summary:
  1995. // Stop an ongoing timed, repeating callback sequence.
  1996. if(this._timer){
  1997. clearTimeout(this._timer);
  1998. this._timer = null;
  1999. }
  2000. if(this._obj){
  2001. this._callback(-1, this._node, this._evt);
  2002. this._obj = null;
  2003. }
  2004. },
  2005. addKeyListener: function(/*DOMNode*/ node, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
  2006. // summary:
  2007. // Start listening for a specific typematic key.
  2008. // See also the trigger method for other parameters.
  2009. // keyObject:
  2010. // an object defining the key to listen for:
  2011. // charOrCode:
  2012. // the printable character (string) or keyCode (number) to listen for.
  2013. // keyCode:
  2014. // (deprecated - use charOrCode) the keyCode (number) to listen for (implies charCode = 0).
  2015. // charCode:
  2016. // (deprecated - use charOrCode) the charCode (number) to listen for.
  2017. // ctrlKey:
  2018. // desired ctrl key state to initiate the callback sequence:
  2019. // - pressed (true)
  2020. // - released (false)
  2021. // - either (unspecified)
  2022. // altKey:
  2023. // same as ctrlKey but for the alt key
  2024. // shiftKey:
  2025. // same as ctrlKey but for the shift key
  2026. // returns:
  2027. // an array of dojo.connect handles
  2028. if(keyObject.keyCode){
  2029. keyObject.charOrCode = keyObject.keyCode;
  2030. dojo.deprecated("keyCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0");
  2031. }else if(keyObject.charCode){
  2032. keyObject.charOrCode = String.fromCharCode(keyObject.charCode);
  2033. dojo.deprecated("charCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0");
  2034. }
  2035. return [
  2036. dojo.connect(node, "onkeypress", this, function(evt){
  2037. if(evt.charOrCode == keyObject.charOrCode &&
  2038. (keyObject.ctrlKey === undefined || keyObject.ctrlKey == evt.ctrlKey) &&
  2039. (keyObject.altKey === undefined || keyObject.altKey == evt.altKey) &&
  2040. (keyObject.metaKey === undefined || keyObject.metaKey == (evt.metaKey || false)) && // IE doesn't even set metaKey
  2041. (keyObject.shiftKey === undefined || keyObject.shiftKey == evt.shiftKey)){
  2042. dojo.stopEvent(evt);
  2043. dijit.typematic.trigger(evt, _this, node, callback, keyObject, subsequentDelay, initialDelay, minDelay);
  2044. }else if(dijit.typematic._obj == keyObject){
  2045. dijit.typematic.stop();
  2046. }
  2047. }),
  2048. dojo.connect(node, "onkeyup", this, function(evt){
  2049. if(dijit.typematic._obj == keyObject){
  2050. dijit.typematic.stop();
  2051. }
  2052. })
  2053. ];
  2054. },
  2055. addMouseListener: function(/*DOMNode*/ node, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
  2056. // summary:
  2057. // Start listening for a typematic mouse click.
  2058. // See the trigger method for other parameters.
  2059. // returns:
  2060. // an array of dojo.connect handles
  2061. var dc = dojo.connect;
  2062. return [
  2063. dc(node, "mousedown", this, function(evt){
  2064. dojo.stopEvent(evt);
  2065. dijit.typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay);
  2066. }),
  2067. dc(node, "mouseup", this, function(evt){
  2068. dojo.stopEvent(evt);
  2069. dijit.typematic.stop();
  2070. }),
  2071. dc(node, "mouseout", this, function(evt){
  2072. dojo.stopEvent(evt);
  2073. dijit.typematic.stop();
  2074. }),
  2075. dc(node, "mousemove", this, function(evt){
  2076. evt.preventDefault();
  2077. }),
  2078. dc(node, "dblclick", this, function(evt){
  2079. dojo.stopEvent(evt);
  2080. if(dojo.isIE < 9){
  2081. dijit.typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay);
  2082. setTimeout(dojo.hitch(this, dijit.typematic.stop), 50);
  2083. }
  2084. })
  2085. ];
  2086. },
  2087. addListener: function(/*Node*/ mouseNode, /*Node*/ keyNode, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
  2088. // summary:
  2089. // Start listening for a specific typematic key and mouseclick.
  2090. // This is a thin wrapper to addKeyListener and addMouseListener.
  2091. // See the addMouseListener and addKeyListener methods for other parameters.
  2092. // mouseNode:
  2093. // the DOM node object to listen on for mouse events.
  2094. // keyNode:
  2095. // the DOM node object to listen on for key events.
  2096. // returns:
  2097. // an array of dojo.connect handles
  2098. return this.addKeyListener(keyNode, keyObject, _this, callback, subsequentDelay, initialDelay, minDelay).concat(
  2099. this.addMouseListener(mouseNode, _this, callback, subsequentDelay, initialDelay, minDelay));
  2100. }
  2101. };
  2102. }
  2103. if(!dojo._hasResource["dijit._base.wai"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  2104. dojo._hasResource["dijit._base.wai"] = true;
  2105. dojo.provide("dijit._base.wai");
  2106. dijit.wai = {
  2107. onload: function(){
  2108. // summary:
  2109. // Detects if we are in high-contrast mode or not
  2110. // This must be a named function and not an anonymous
  2111. // function, so that the widget parsing code can make sure it
  2112. // registers its onload function after this function.
  2113. // DO NOT USE "this" within this function.
  2114. // create div for testing if high contrast mode is on or images are turned off
  2115. var div = dojo.create("div",{
  2116. id: "a11yTestNode",
  2117. style:{
  2118. cssText:'border: 1px solid;'
  2119. + 'border-color:red green;'
  2120. + 'position: absolute;'
  2121. + 'height: 5px;'
  2122. + 'top: -999px;'
  2123. + 'background-image: url("' + (dojo.config.blankGif || dojo.moduleUrl("dojo", "resources/blank.gif")) + '");'
  2124. }
  2125. }, dojo.body());
  2126. // test it
  2127. var cs = dojo.getComputedStyle(div);
  2128. if(cs){
  2129. var bkImg = cs.backgroundImage;
  2130. var needsA11y = (cs.borderTopColor == cs.borderRightColor) || (bkImg != null && (bkImg == "none" || bkImg == "url(invalid-url:)" ));
  2131. dojo[needsA11y ? "addClass" : "removeClass"](dojo.body(), "dijit_a11y");
  2132. if(dojo.isIE){
  2133. div.outerHTML = ""; // prevent mixed-content warning, see http://support.microsoft.com/kb/925014
  2134. }else{
  2135. dojo.body().removeChild(div);
  2136. }
  2137. }
  2138. }
  2139. };
  2140. // Test if computer is in high contrast mode.
  2141. // Make sure the a11y test runs first, before widgets are instantiated.
  2142. if(dojo.isIE || dojo.isMoz){ // NOTE: checking in Safari messes things up
  2143. dojo._loaders.unshift(dijit.wai.onload);
  2144. }
  2145. dojo.mixin(dijit, {
  2146. hasWaiRole: function(/*Element*/ elem, /*String?*/ role){
  2147. // summary:
  2148. // Determines if an element has a particular role.
  2149. // returns:
  2150. // True if elem has the specific role attribute and false if not.
  2151. // For backwards compatibility if role parameter not provided,
  2152. // returns true if has a role
  2153. var waiRole = this.getWaiRole(elem);
  2154. return role ? (waiRole.indexOf(role) > -1) : (waiRole.length > 0);
  2155. },
  2156. getWaiRole: function(/*Element*/ elem){
  2157. // summary:
  2158. // Gets the role for an element (which should be a wai role).
  2159. // returns:
  2160. // The role of elem or an empty string if elem
  2161. // does not have a role.
  2162. return dojo.trim((dojo.attr(elem, "role") || "").replace("wairole:",""));
  2163. },
  2164. setWaiRole: function(/*Element*/ elem, /*String*/ role){
  2165. // summary:
  2166. // Sets the role on an element.
  2167. // description:
  2168. // Replace existing role attribute with new role.
  2169. dojo.attr(elem, "role", role);
  2170. },
  2171. removeWaiRole: function(/*Element*/ elem, /*String*/ role){
  2172. // summary:
  2173. // Removes the specified role from an element.
  2174. // Removes role attribute if no specific role provided (for backwards compat.)
  2175. var roleValue = dojo.attr(elem, "role");
  2176. if(!roleValue){ return; }
  2177. if(role){
  2178. var t = dojo.trim((" " + roleValue + " ").replace(" " + role + " ", " "));
  2179. dojo.attr(elem, "role", t);
  2180. }else{
  2181. elem.removeAttribute("role");
  2182. }
  2183. },
  2184. hasWaiState: function(/*Element*/ elem, /*String*/ state){
  2185. // summary:
  2186. // Determines if an element has a given state.
  2187. // description:
  2188. // Checks for an attribute called "aria-"+state.
  2189. // returns:
  2190. // true if elem has a value for the given state and
  2191. // false if it does not.
  2192. return elem.hasAttribute ? elem.hasAttribute("aria-"+state) : !!elem.getAttribute("aria-"+state);
  2193. },
  2194. getWaiState: function(/*Element*/ elem, /*String*/ state){
  2195. // summary:
  2196. // Gets the value of a state on an element.
  2197. // description:
  2198. // Checks for an attribute called "aria-"+state.
  2199. // returns:
  2200. // The value of the requested state on elem
  2201. // or an empty string if elem has no value for state.
  2202. return elem.getAttribute("aria-"+state) || "";
  2203. },
  2204. setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){
  2205. // summary:
  2206. // Sets a state on an element.
  2207. // description:
  2208. // Sets an attribute called "aria-"+state.
  2209. elem.setAttribute("aria-"+state, value);
  2210. },
  2211. removeWaiState: function(/*Element*/ elem, /*String*/ state){
  2212. // summary:
  2213. // Removes a state from an element.
  2214. // description:
  2215. // Sets an attribute called "aria-"+state.
  2216. elem.removeAttribute("aria-"+state);
  2217. }
  2218. });
  2219. }
  2220. if(!dojo._hasResource["dijit._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  2221. dojo._hasResource["dijit._base"] = true;
  2222. dojo.provide("dijit._base");
  2223. }
  2224. if(!dojo._hasResource["dojo.date.stamp"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  2225. dojo._hasResource["dojo.date.stamp"] = true;
  2226. dojo.provide("dojo.date.stamp");
  2227. dojo.getObject("date.stamp", true, dojo);
  2228. // Methods to convert dates to or from a wire (string) format using well-known conventions
  2229. dojo.date.stamp.fromISOString = function(/*String*/formattedString, /*Number?*/defaultTime){
  2230. // summary:
  2231. // Returns a Date object given a string formatted according to a subset of the ISO-8601 standard.
  2232. //
  2233. // description:
  2234. // Accepts a string formatted according to a profile of ISO8601 as defined by
  2235. // [RFC3339](http://www.ietf.org/rfc/rfc3339.txt), except that partial input is allowed.
  2236. // Can also process dates as specified [by the W3C](http://www.w3.org/TR/NOTE-datetime)
  2237. // The following combinations are valid:
  2238. //
  2239. // * dates only
  2240. // | * yyyy
  2241. // | * yyyy-MM
  2242. // | * yyyy-MM-dd
  2243. // * times only, with an optional time zone appended
  2244. // | * THH:mm
  2245. // | * THH:mm:ss
  2246. // | * THH:mm:ss.SSS
  2247. // * and "datetimes" which could be any combination of the above
  2248. //
  2249. // timezones may be specified as Z (for UTC) or +/- followed by a time expression HH:mm
  2250. // Assumes the local time zone if not specified. Does not validate. Improperly formatted
  2251. // input may return null. Arguments which are out of bounds will be handled
  2252. // by the Date constructor (e.g. January 32nd typically gets resolved to February 1st)
  2253. // Only years between 100 and 9999 are supported.
  2254. //
  2255. // formattedString:
  2256. // A string such as 2005-06-30T08:05:00-07:00 or 2005-06-30 or T08:05:00
  2257. //
  2258. // defaultTime:
  2259. // Used for defaults for fields omitted in the formattedString.
  2260. // Uses 1970-01-01T00:00:00.0Z by default.
  2261. if(!dojo.date.stamp._isoRegExp){
  2262. dojo.date.stamp._isoRegExp =
  2263. //TODO: could be more restrictive and check for 00-59, etc.
  2264. /^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(.\d+)?)?((?:[+-](\d{2}):(\d{2}))|Z)?)?$/;
  2265. }
  2266. var match = dojo.date.stamp._isoRegExp.exec(formattedString),
  2267. result = null;
  2268. if(match){
  2269. match.shift();
  2270. if(match[1]){match[1]--;} // Javascript Date months are 0-based
  2271. if(match[6]){match[6] *= 1000;} // Javascript Date expects fractional seconds as milliseconds
  2272. if(defaultTime){
  2273. // mix in defaultTime. Relatively expensive, so use || operators for the fast path of defaultTime === 0
  2274. defaultTime = new Date(defaultTime);
  2275. dojo.forEach(dojo.map(["FullYear", "Month", "Date", "Hours", "Minutes", "Seconds", "Milliseconds"], function(prop){
  2276. return defaultTime["get" + prop]();
  2277. }), function(value, index){
  2278. match[index] = match[index] || value;
  2279. });
  2280. }
  2281. result = new Date(match[0]||1970, match[1]||0, match[2]||1, match[3]||0, match[4]||0, match[5]||0, match[6]||0); //TODO: UTC defaults
  2282. if(match[0] < 100){
  2283. result.setFullYear(match[0] || 1970);
  2284. }
  2285. var offset = 0,
  2286. zoneSign = match[7] && match[7].charAt(0);
  2287. if(zoneSign != 'Z'){
  2288. offset = ((match[8] || 0) * 60) + (Number(match[9]) || 0);
  2289. if(zoneSign != '-'){ offset *= -1; }
  2290. }
  2291. if(zoneSign){
  2292. offset -= result.getTimezoneOffset();
  2293. }
  2294. if(offset){
  2295. result.setTime(result.getTime() + offset * 60000);
  2296. }
  2297. }
  2298. return result; // Date or null
  2299. };
  2300. /*=====
  2301. dojo.date.stamp.__Options = function(){
  2302. // selector: String
  2303. // "date" or "time" for partial formatting of the Date object.
  2304. // Both date and time will be formatted by default.
  2305. // zulu: Boolean
  2306. // if true, UTC/GMT is used for a timezone
  2307. // milliseconds: Boolean
  2308. // if true, output milliseconds
  2309. this.selector = selector;
  2310. this.zulu = zulu;
  2311. this.milliseconds = milliseconds;
  2312. }
  2313. =====*/
  2314. dojo.date.stamp.toISOString = function(/*Date*/dateObject, /*dojo.date.stamp.__Options?*/options){
  2315. // summary:
  2316. // Format a Date object as a string according a subset of the ISO-8601 standard
  2317. //
  2318. // description:
  2319. // When options.selector is omitted, output follows [RFC3339](http://www.ietf.org/rfc/rfc3339.txt)
  2320. // The local time zone is included as an offset from GMT, except when selector=='time' (time without a date)
  2321. // Does not check bounds. Only years between 100 and 9999 are supported.
  2322. //
  2323. // dateObject:
  2324. // A Date object
  2325. var _ = function(n){ return (n < 10) ? "0" + n : n; };
  2326. options = options || {};
  2327. var formattedDate = [],
  2328. getter = options.zulu ? "getUTC" : "get",
  2329. date = "";
  2330. if(options.selector != "time"){
  2331. var year = dateObject[getter+"FullYear"]();
  2332. date = ["0000".substr((year+"").length)+year, _(dateObject[getter+"Month"]()+1), _(dateObject[getter+"Date"]())].join('-');
  2333. }
  2334. formattedDate.push(date);
  2335. if(options.selector != "date"){
  2336. var time = [_(dateObject[getter+"Hours"]()), _(dateObject[getter+"Minutes"]()), _(dateObject[getter+"Seconds"]())].join(':');
  2337. var millis = dateObject[getter+"Milliseconds"]();
  2338. if(options.milliseconds){
  2339. time += "."+ (millis < 100 ? "0" : "") + _(millis);
  2340. }
  2341. if(options.zulu){
  2342. time += "Z";
  2343. }else if(options.selector != "time"){
  2344. var timezoneOffset = dateObject.getTimezoneOffset();
  2345. var absOffset = Math.abs(timezoneOffset);
  2346. time += (timezoneOffset > 0 ? "-" : "+") +
  2347. _(Math.floor(absOffset/60)) + ":" + _(absOffset%60);
  2348. }
  2349. formattedDate.push(time);
  2350. }
  2351. return formattedDate.join('T'); // String
  2352. };
  2353. }
  2354. if(!dojo._hasResource["dojo.parser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  2355. dojo._hasResource["dojo.parser"] = true;
  2356. dojo.provide("dojo.parser");
  2357. new Date("X"); // workaround for #11279, new Date("") == NaN
  2358. dojo.parser = new function(){
  2359. // summary:
  2360. // The Dom/Widget parsing package
  2361. var d = dojo;
  2362. function val2type(/*Object*/ value){
  2363. // summary:
  2364. // Returns name of type of given value.
  2365. if(d.isString(value)){ return "string"; }
  2366. if(typeof value == "number"){ return "number"; }
  2367. if(typeof value == "boolean"){ return "boolean"; }
  2368. if(d.isFunction(value)){ return "function"; }
  2369. if(d.isArray(value)){ return "array"; } // typeof [] == "object"
  2370. if(value instanceof Date) { return "date"; } // assume timestamp
  2371. if(value instanceof d._Url){ return "url"; }
  2372. return "object";
  2373. }
  2374. function str2obj(/*String*/ value, /*String*/ type){
  2375. // summary:
  2376. // Convert given string value to given type
  2377. switch(type){
  2378. case "string":
  2379. return value;
  2380. case "number":
  2381. return value.length ? Number(value) : NaN;
  2382. case "boolean":
  2383. // for checked/disabled value might be "" or "checked". interpret as true.
  2384. return typeof value == "boolean" ? value : !(value.toLowerCase()=="false");
  2385. case "function":
  2386. if(d.isFunction(value)){
  2387. // IE gives us a function, even when we say something like onClick="foo"
  2388. // (in which case it gives us an invalid function "function(){ foo }").
  2389. // Therefore, convert to string
  2390. value=value.toString();
  2391. value=d.trim(value.substring(value.indexOf('{')+1, value.length-1));
  2392. }
  2393. try{
  2394. if(value === "" || value.search(/[^\w\.]+/i) != -1){
  2395. // The user has specified some text for a function like "return x+5"
  2396. return new Function(value);
  2397. }else{
  2398. // The user has specified the name of a function like "myOnClick"
  2399. // or a single word function "return"
  2400. return d.getObject(value, false) || new Function(value);
  2401. }
  2402. }catch(e){ return new Function(); }
  2403. case "array":
  2404. return value ? value.split(/\s*,\s*/) : [];
  2405. case "date":
  2406. switch(value){
  2407. case "": return new Date(""); // the NaN of dates
  2408. case "now": return new Date(); // current date
  2409. default: return d.date.stamp.fromISOString(value);
  2410. }
  2411. case "url":
  2412. return d.baseUrl + value;
  2413. default:
  2414. return d.fromJson(value);
  2415. }
  2416. }
  2417. var dummyClass = {}, instanceClasses = {
  2418. // map from fully qualified name (like "dijit.Button") to structure like
  2419. // { cls: dijit.Button, params: {label: "string", disabled: "boolean"} }
  2420. };
  2421. // Widgets like BorderContainer add properties to _Widget via dojo.extend().
  2422. // If BorderContainer is loaded after _Widget's parameter list has been cached,
  2423. // we need to refresh that parameter list (for _Widget and all widgets that extend _Widget).
  2424. // TODO: remove this in 2.0, when we stop caching parameters.
  2425. d.connect(d, "extend", function(){
  2426. instanceClasses = {};
  2427. });
  2428. function getProtoInfo(cls, params){
  2429. // cls: A prototype
  2430. // The prototype of the class to check props on
  2431. // params: Object
  2432. // The parameters object to mix found parameters onto.
  2433. for(var name in cls){
  2434. if(name.charAt(0)=="_"){ continue; } // skip internal properties
  2435. if(name in dummyClass){ continue; } // skip "constructor" and "toString"
  2436. params[name] = val2type(cls[name]);
  2437. }
  2438. return params;
  2439. }
  2440. function getClassInfo(/*String*/ className, /*Boolean*/ skipParamsLookup){
  2441. // summary:
  2442. // Maps a widget name string like "dijit.form.Button" to the widget constructor itself,
  2443. // and a list of that widget's parameters and their types
  2444. // className:
  2445. // fully qualified name (like "dijit.form.Button")
  2446. // returns:
  2447. // structure like
  2448. // {
  2449. // cls: dijit.Button,
  2450. // params: { label: "string", disabled: "boolean"}
  2451. // }
  2452. var c = instanceClasses[className];
  2453. if(!c){
  2454. // get pointer to widget class
  2455. var cls = d.getObject(className), params = null;
  2456. if(!cls){ return null; } // class not defined [yet]
  2457. if(!skipParamsLookup){ // from fastpath, we don't need to lookup the attrs on the proto because they are explicit
  2458. params = getProtoInfo(cls.prototype, {})
  2459. }
  2460. c = { cls: cls, params: params };
  2461. }else if(!skipParamsLookup && !c.params){
  2462. // if we're calling getClassInfo and have a cls proto, but no params info, scan that cls for params now
  2463. // and update the pointer in instanceClasses[className]. This happens when a widget appears in another
  2464. // widget's template which still uses dojoType, but an instance of the widget appears prior with a data-dojo-type,
  2465. // skipping this lookup the first time.
  2466. c.params = getProtoInfo(c.cls.prototype, {});
  2467. }
  2468. return c;
  2469. }
  2470. this._functionFromScript = function(script, attrData){
  2471. // summary:
  2472. // Convert a <script type="dojo/method" args="a, b, c"> ... </script>
  2473. // into a function
  2474. // script: DOMNode
  2475. // The <script> DOMNode
  2476. // attrData: String
  2477. // For HTML5 compliance, searches for attrData + "args" (typically
  2478. // "data-dojo-args") instead of "args"
  2479. var preamble = "";
  2480. var suffix = "";
  2481. var argsStr = (script.getAttribute(attrData + "args") || script.getAttribute("args"));
  2482. if(argsStr){
  2483. d.forEach(argsStr.split(/\s*,\s*/), function(part, idx){
  2484. preamble += "var "+part+" = arguments["+idx+"]; ";
  2485. });
  2486. }
  2487. var withStr = script.getAttribute("with");
  2488. if(withStr && withStr.length){
  2489. d.forEach(withStr.split(/\s*,\s*/), function(part){
  2490. preamble += "with("+part+"){";
  2491. suffix += "}";
  2492. });
  2493. }
  2494. return new Function(preamble+script.innerHTML+suffix);
  2495. };
  2496. this.instantiate = function(/* Array */nodes, /* Object? */mixin, /* Object? */args){
  2497. // summary:
  2498. // Takes array of nodes, and turns them into class instances and
  2499. // potentially calls a startup method to allow them to connect with
  2500. // any children.
  2501. // nodes: Array
  2502. // Array of nodes or objects like
  2503. // | {
  2504. // | type: "dijit.form.Button",
  2505. // | node: DOMNode,
  2506. // | scripts: [ ... ], // array of <script type="dojo/..."> children of node
  2507. // | inherited: { ... } // settings inherited from ancestors like dir, theme, etc.
  2508. // | }
  2509. // mixin: Object?
  2510. // An object that will be mixed in with each node in the array.
  2511. // Values in the mixin will override values in the node, if they
  2512. // exist.
  2513. // args: Object?
  2514. // An object used to hold kwArgs for instantiation.
  2515. // See parse.args argument for details.
  2516. var thelist = [],
  2517. mixin = mixin||{};
  2518. args = args||{};
  2519. // TODO: for 2.0 default to data-dojo- regardless of scopeName (or maybe scopeName won't exist in 2.0)
  2520. var attrName = (args.scope || d._scopeName) + "Type", // typically "dojoType"
  2521. attrData = "data-" + (args.scope || d._scopeName) + "-"; // typically "data-dojo-"
  2522. d.forEach(nodes, function(obj){
  2523. if(!obj){ return; }
  2524. // Get pointers to DOMNode, dojoType string, and clsInfo (metadata about the dojoType), etc.
  2525. var node, type, clsInfo, clazz, scripts, fastpath;
  2526. if(obj.node){
  2527. // new format of nodes[] array, object w/lots of properties pre-computed for me
  2528. node = obj.node;
  2529. type = obj.type;
  2530. fastpath = obj.fastpath;
  2531. clsInfo = obj.clsInfo || (type && getClassInfo(type, fastpath));
  2532. clazz = clsInfo && clsInfo.cls;
  2533. scripts = obj.scripts;
  2534. }else{
  2535. // old (backwards compatible) format of nodes[] array, simple array of DOMNodes. no fastpath/data-dojo-type support here.
  2536. node = obj;
  2537. type = attrName in mixin ? mixin[attrName] : node.getAttribute(attrName);
  2538. clsInfo = type && getClassInfo(type);
  2539. clazz = clsInfo && clsInfo.cls;
  2540. scripts = (clazz && (clazz._noScript || clazz.prototype._noScript) ? [] :
  2541. d.query("> script[type^='dojo/']", node));
  2542. }
  2543. if(!clsInfo){
  2544. throw new Error("Could not load class '" + type);
  2545. }
  2546. // Setup hash to hold parameter settings for this widget. Start with the parameter
  2547. // settings inherited from ancestors ("dir" and "lang").
  2548. // Inherited setting may later be overridden by explicit settings on node itself.
  2549. var params = {};
  2550. if(args.defaults){
  2551. // settings for the document itself (or whatever subtree is being parsed)
  2552. d._mixin(params, args.defaults);
  2553. }
  2554. if(obj.inherited){
  2555. // settings from dir=rtl or lang=... on a node above this node
  2556. d._mixin(params, obj.inherited);
  2557. }
  2558. // mix things found in data-dojo-props into the params
  2559. if(fastpath){
  2560. var extra = node.getAttribute(attrData + "props");
  2561. if(extra && extra.length){
  2562. try{
  2563. extra = d.fromJson.call(args.propsThis, "{" + extra + "}");
  2564. d._mixin(params, extra);
  2565. }catch(e){
  2566. // give the user a pointer to their invalid parameters. FIXME: can we kill this in production?
  2567. throw new Error(e.toString() + " in data-dojo-props='" + extra + "'");
  2568. }
  2569. }
  2570. // For the benefit of _Templated, check if node has data-dojo-attach-point/data-dojo-attach-event
  2571. // and mix those in as though they were parameters
  2572. var attachPoint = node.getAttribute(attrData + "attach-point");
  2573. if(attachPoint){
  2574. params.dojoAttachPoint = attachPoint;
  2575. }
  2576. var attachEvent = node.getAttribute(attrData + "attach-event");
  2577. if(attachEvent){
  2578. params.dojoAttachEvent = attachEvent;
  2579. }
  2580. dojo.mixin(params, mixin);
  2581. }else{
  2582. // FIXME: we need something like "deprecateOnce()" to throw dojo.deprecation for something.
  2583. // remove this logic in 2.0
  2584. // read parameters (ie, attributes) specified on DOMNode
  2585. var attributes = node.attributes;
  2586. // clsInfo.params lists expected params like {"checked": "boolean", "n": "number"}
  2587. for(var name in clsInfo.params){
  2588. var item = name in mixin ? { value:mixin[name], specified:true } : attributes.getNamedItem(name);
  2589. if(!item || (!item.specified && (!dojo.isIE || name.toLowerCase()!="value"))){ continue; }
  2590. var value = item.value;
  2591. // Deal with IE quirks for 'class' and 'style'
  2592. switch(name){
  2593. case "class":
  2594. value = "className" in mixin ? mixin.className : node.className;
  2595. break;
  2596. case "style":
  2597. value = "style" in mixin ? mixin.style : (node.style && node.style.cssText); // FIXME: Opera?
  2598. }
  2599. var _type = clsInfo.params[name];
  2600. if(typeof value == "string"){
  2601. params[name] = str2obj(value, _type);
  2602. }else{
  2603. params[name] = value;
  2604. }
  2605. }
  2606. }
  2607. // Process <script type="dojo/*"> script tags
  2608. // <script type="dojo/method" event="foo"> tags are added to params, and passed to
  2609. // the widget on instantiation.
  2610. // <script type="dojo/method"> tags (with no event) are executed after instantiation
  2611. // <script type="dojo/connect" event="foo"> tags are dojo.connected after instantiation
  2612. // note: dojo/* script tags cannot exist in self closing widgets, like <input />
  2613. var connects = [], // functions to connect after instantiation
  2614. calls = []; // functions to call after instantiation
  2615. d.forEach(scripts, function(script){
  2616. node.removeChild(script);
  2617. // FIXME: drop event="" support in 2.0. use data-dojo-event="" instead
  2618. var event = (script.getAttribute(attrData + "event") || script.getAttribute("event")),
  2619. type = script.getAttribute("type"),
  2620. nf = d.parser._functionFromScript(script, attrData);
  2621. if(event){
  2622. if(type == "dojo/connect"){
  2623. connects.push({event: event, func: nf});
  2624. }else{
  2625. params[event] = nf;
  2626. }
  2627. }else{
  2628. calls.push(nf);
  2629. }
  2630. });
  2631. var markupFactory = clazz.markupFactory || clazz.prototype && clazz.prototype.markupFactory;
  2632. // create the instance
  2633. var instance = markupFactory ? markupFactory(params, node, clazz) : new clazz(params, node);
  2634. thelist.push(instance);
  2635. // map it to the JS namespace if that makes sense
  2636. // FIXME: in 2.0, drop jsId support. use data-dojo-id instead
  2637. var jsname = (node.getAttribute(attrData + "id") || node.getAttribute("jsId"));
  2638. if(jsname){
  2639. d.setObject(jsname, instance);
  2640. }
  2641. // process connections and startup functions
  2642. d.forEach(connects, function(connect){
  2643. d.connect(instance, connect.event, null, connect.func);
  2644. });
  2645. d.forEach(calls, function(func){
  2646. func.call(instance);
  2647. });
  2648. });
  2649. // Call startup on each top level instance if it makes sense (as for
  2650. // widgets). Parent widgets will recursively call startup on their
  2651. // (non-top level) children
  2652. if(!mixin._started){
  2653. // TODO: for 2.0, when old instantiate() API is desupported, store parent-child
  2654. // relationships in the nodes[] array so that no getParent() call is needed.
  2655. // Note that will require a parse() call from ContentPane setting a param that the
  2656. // ContentPane is the parent widget (so that the parse doesn't call startup() on the
  2657. // ContentPane's children)
  2658. d.forEach(thelist, function(instance){
  2659. if( !args.noStart && instance &&
  2660. dojo.isFunction(instance.startup) &&
  2661. !instance._started &&
  2662. (!instance.getParent || !instance.getParent())
  2663. ){
  2664. instance.startup();
  2665. }
  2666. });
  2667. }
  2668. return thelist;
  2669. };
  2670. this.parse = function(rootNode, args){
  2671. // summary:
  2672. // Scan the DOM for class instances, and instantiate them.
  2673. //
  2674. // description:
  2675. // Search specified node (or root node) recursively for class instances,
  2676. // and instantiate them. Searches for either data-dojo-type="Class" or
  2677. // dojoType="Class" where "Class" is a a fully qualified class name,
  2678. // like `dijit.form.Button`
  2679. //
  2680. // Using `data-dojo-type`:
  2681. // Attributes using can be mixed into the parameters used to instantitate the
  2682. // Class by using a `data-dojo-props` attribute on the node being converted.
  2683. // `data-dojo-props` should be a string attribute to be converted from JSON.
  2684. //
  2685. // Using `dojoType`:
  2686. // Attributes are read from the original domNode and converted to appropriate
  2687. // types by looking up the Class prototype values. This is the default behavior
  2688. // from Dojo 1.0 to Dojo 1.5. `dojoType` support is deprecated, and will
  2689. // go away in Dojo 2.0.
  2690. //
  2691. // rootNode: DomNode?
  2692. // A default starting root node from which to start the parsing. Can be
  2693. // omitted, defaulting to the entire document. If omitted, the `args`
  2694. // object can be passed in this place. If the `args` object has a
  2695. // `rootNode` member, that is used.
  2696. //
  2697. // args: Object
  2698. // a kwArgs object passed along to instantiate()
  2699. //
  2700. // * noStart: Boolean?
  2701. // when set will prevent the parser from calling .startup()
  2702. // when locating the nodes.
  2703. // * rootNode: DomNode?
  2704. // identical to the function's `rootNode` argument, though
  2705. // allowed to be passed in via this `args object.
  2706. // * template: Boolean
  2707. // If true, ignores ContentPane's stopParser flag and parses contents inside of
  2708. // a ContentPane inside of a template. This allows dojoAttachPoint on widgets/nodes
  2709. // nested inside the ContentPane to work.
  2710. // * inherited: Object
  2711. // Hash possibly containing dir and lang settings to be applied to
  2712. // parsed widgets, unless there's another setting on a sub-node that overrides
  2713. // * scope: String
  2714. // Root for attribute names to search for. If scopeName is dojo,
  2715. // will search for data-dojo-type (or dojoType). For backwards compatibility
  2716. // reasons defaults to dojo._scopeName (which is "dojo" except when
  2717. // multi-version support is used, when it will be something like dojo16, dojo20, etc.)
  2718. // * propsThis: Object
  2719. // If specified, "this" referenced from data-dojo-props will refer to propsThis.
  2720. // Intended for use from the widgets-in-template feature of `dijit._Templated`
  2721. //
  2722. // example:
  2723. // Parse all widgets on a page:
  2724. // | dojo.parser.parse();
  2725. //
  2726. // example:
  2727. // Parse all classes within the node with id="foo"
  2728. // | dojo.parser.parse(dojo.byId('foo'));
  2729. //
  2730. // example:
  2731. // Parse all classes in a page, but do not call .startup() on any
  2732. // child
  2733. // | dojo.parser.parse({ noStart: true })
  2734. //
  2735. // example:
  2736. // Parse all classes in a node, but do not call .startup()
  2737. // | dojo.parser.parse(someNode, { noStart:true });
  2738. // | // or
  2739. // | dojo.parser.parse({ noStart:true, rootNode: someNode });
  2740. // determine the root node based on the passed arguments.
  2741. var root;
  2742. if(!args && rootNode && rootNode.rootNode){
  2743. args = rootNode;
  2744. root = args.rootNode;
  2745. }else{
  2746. root = rootNode;
  2747. }
  2748. root = root ? dojo.byId(root) : dojo.body();
  2749. args = args || {};
  2750. var attrName = (args.scope || d._scopeName) + "Type", // typically "dojoType"
  2751. attrData = "data-" + (args.scope || d._scopeName) + "-"; // typically "data-dojo-"
  2752. function scan(parent, list){
  2753. // summary:
  2754. // Parent is an Object representing a DOMNode, with or without a dojoType specified.
  2755. // Scan parent's children looking for nodes with dojoType specified, storing in list[].
  2756. // If parent has a dojoType, also collects <script type=dojo/*> children and stores in parent.scripts[].
  2757. // parent: Object
  2758. // Object representing the parent node, like
  2759. // | {
  2760. // | node: DomNode, // scan children of this node
  2761. // | inherited: {dir: "rtl"}, // dir/lang setting inherited from above node
  2762. // |
  2763. // | // attributes only set if node has dojoType specified
  2764. // | scripts: [], // empty array, put <script type=dojo/*> in here
  2765. // | clsInfo: { cls: dijit.form.Button, ...}
  2766. // | }
  2767. // list: DomNode[]
  2768. // Output array of objects (same format as parent) representing nodes to be turned into widgets
  2769. // Effective dir and lang settings on parent node, either set directly or inherited from grandparent
  2770. var inherited = dojo.clone(parent.inherited);
  2771. dojo.forEach(["dir", "lang"], function(name){
  2772. // TODO: what if this is a widget and dir/lang are declared in data-dojo-props?
  2773. var val = parent.node.getAttribute(name);
  2774. if(val){
  2775. inherited[name] = val;
  2776. }
  2777. });
  2778. // if parent is a widget, then search for <script type=dojo/*> tags and put them in scripts[].
  2779. var scripts = parent.clsInfo && !parent.clsInfo.cls.prototype._noScript ? parent.scripts : null;
  2780. // unless parent is a widget with the stopParser flag set, continue search for dojoType, recursively
  2781. var recurse = (!parent.clsInfo || !parent.clsInfo.cls.prototype.stopParser) || (args && args.template);
  2782. // scan parent's children looking for dojoType and <script type=dojo/*>
  2783. for(var child = parent.node.firstChild; child; child = child.nextSibling){
  2784. if(child.nodeType == 1){
  2785. // FIXME: desupport dojoType in 2.0. use data-dojo-type instead
  2786. var type, html5 = recurse && child.getAttribute(attrData + "type");
  2787. if(html5){
  2788. type = html5;
  2789. }else{
  2790. // fallback to backward compatible mode, using dojoType. remove in 2.0
  2791. type = recurse && child.getAttribute(attrName);
  2792. }
  2793. var fastpath = html5 == type;
  2794. if(type){
  2795. // if dojoType/data-dojo-type specified, add to output array of nodes to instantiate
  2796. var params = {
  2797. "type": type,
  2798. fastpath: fastpath,
  2799. clsInfo: getClassInfo(type, fastpath), // note: won't find classes declared via dojo.Declaration
  2800. node: child,
  2801. scripts: [], // <script> nodes that are parent's children
  2802. inherited: inherited // dir & lang attributes inherited from parent
  2803. };
  2804. list.push(params);
  2805. // Recurse, collecting <script type="dojo/..."> children, and also looking for
  2806. // descendant nodes with dojoType specified (unless the widget has the stopParser flag),
  2807. scan(params, list);
  2808. }else if(scripts && child.nodeName.toLowerCase() == "script"){
  2809. // if <script type="dojo/...">, save in scripts[]
  2810. type = child.getAttribute("type");
  2811. if (type && /^dojo\/\w/i.test(type)) {
  2812. scripts.push(child);
  2813. }
  2814. }else if(recurse){
  2815. // Recurse, looking for grandchild nodes with dojoType specified
  2816. scan({
  2817. node: child,
  2818. inherited: inherited
  2819. }, list);
  2820. }
  2821. }
  2822. }
  2823. }
  2824. // Ignore bogus entries in inherited hash like {dir: ""}
  2825. var inherited = {};
  2826. if(args && args.inherited){
  2827. for(var key in args.inherited){
  2828. if(args.inherited[key]){ inherited[key] = args.inherited[key]; }
  2829. }
  2830. }
  2831. // Make list of all nodes on page w/dojoType specified
  2832. var list = [];
  2833. scan({
  2834. node: root,
  2835. inherited: inherited
  2836. }, list);
  2837. // go build the object instances
  2838. var mixin = args && args.template ? {template: true} : null;
  2839. return this.instantiate(list, mixin, args); // Array
  2840. };
  2841. }();
  2842. //Register the parser callback. It should be the first callback
  2843. //after the a11y test.
  2844. (function(){
  2845. var parseRunner = function(){
  2846. if(dojo.config.parseOnLoad){
  2847. dojo.parser.parse();
  2848. }
  2849. };
  2850. // FIXME: need to clobber cross-dependency!!
  2851. if(dojo.getObject("dijit.wai.onload") === dojo._loaders[0]){
  2852. dojo._loaders.splice(1, 0, parseRunner);
  2853. }else{
  2854. dojo._loaders.unshift(parseRunner);
  2855. }
  2856. })();
  2857. }
  2858. if(!dojo._hasResource["dojo.Stateful"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  2859. dojo._hasResource["dojo.Stateful"] = true;
  2860. dojo.provide("dojo.Stateful");
  2861. dojo.declare("dojo.Stateful", null, {
  2862. // summary:
  2863. // Base class for objects that provide named properties with optional getter/setter
  2864. // control and the ability to watch for property changes
  2865. // example:
  2866. // | var obj = new dojo.Stateful();
  2867. // | obj.watch("foo", function(){
  2868. // | console.log("foo changed to " + this.get("foo"));
  2869. // | });
  2870. // | obj.set("foo","bar");
  2871. postscript: function(mixin){
  2872. if(mixin){
  2873. dojo.mixin(this, mixin);
  2874. }
  2875. },
  2876. get: function(/*String*/name){
  2877. // summary:
  2878. // Get a property on a Stateful instance.
  2879. // name:
  2880. // The property to get.
  2881. // description:
  2882. // Get a named property on a Stateful object. The property may
  2883. // potentially be retrieved via a getter method in subclasses. In the base class
  2884. // this just retrieves the object's property.
  2885. // For example:
  2886. // | stateful = new dojo.Stateful({foo: 3});
  2887. // | stateful.get("foo") // returns 3
  2888. // | stateful.foo // returns 3
  2889. return this[name];
  2890. },
  2891. set: function(/*String*/name, /*Object*/value){
  2892. // summary:
  2893. // Set a property on a Stateful instance
  2894. // name:
  2895. // The property to set.
  2896. // value:
  2897. // The value to set in the property.
  2898. // description:
  2899. // Sets named properties on a stateful object and notifies any watchers of
  2900. // the property. A programmatic setter may be defined in subclasses.
  2901. // For example:
  2902. // | stateful = new dojo.Stateful();
  2903. // | stateful.watch(function(name, oldValue, value){
  2904. // | // this will be called on the set below
  2905. // | }
  2906. // | stateful.set(foo, 5);
  2907. //
  2908. // set() may also be called with a hash of name/value pairs, ex:
  2909. // | myObj.set({
  2910. // | foo: "Howdy",
  2911. // | bar: 3
  2912. // | })
  2913. // This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
  2914. if(typeof name === "object"){
  2915. for(var x in name){
  2916. this.set(x, name[x]);
  2917. }
  2918. return this;
  2919. }
  2920. var oldValue = this[name];
  2921. this[name] = value;
  2922. if(this._watchCallbacks){
  2923. this._watchCallbacks(name, oldValue, value);
  2924. }
  2925. return this;
  2926. },
  2927. watch: function(/*String?*/name, /*Function*/callback){
  2928. // summary:
  2929. // Watches a property for changes
  2930. // name:
  2931. // Indicates the property to watch. This is optional (the callback may be the
  2932. // only parameter), and if omitted, all the properties will be watched
  2933. // returns:
  2934. // An object handle for the watch. The unwatch method of this object
  2935. // can be used to discontinue watching this property:
  2936. // | var watchHandle = obj.watch("foo", callback);
  2937. // | watchHandle.unwatch(); // callback won't be called now
  2938. // callback:
  2939. // The function to execute when the property changes. This will be called after
  2940. // the property has been changed. The callback will be called with the |this|
  2941. // set to the instance, the first argument as the name of the property, the
  2942. // second argument as the old value and the third argument as the new value.
  2943. var callbacks = this._watchCallbacks;
  2944. if(!callbacks){
  2945. var self = this;
  2946. callbacks = this._watchCallbacks = function(name, oldValue, value, ignoreCatchall){
  2947. var notify = function(propertyCallbacks){
  2948. if(propertyCallbacks){
  2949. propertyCallbacks = propertyCallbacks.slice();
  2950. for(var i = 0, l = propertyCallbacks.length; i < l; i++){
  2951. try{
  2952. propertyCallbacks[i].call(self, name, oldValue, value);
  2953. }catch(e){
  2954. console.error(e);
  2955. }
  2956. }
  2957. }
  2958. };
  2959. notify(callbacks['_' + name]);
  2960. if(!ignoreCatchall){
  2961. notify(callbacks["*"]); // the catch-all
  2962. }
  2963. }; // we use a function instead of an object so it will be ignored by JSON conversion
  2964. }
  2965. if(!callback && typeof name === "function"){
  2966. callback = name;
  2967. name = "*";
  2968. }else{
  2969. // prepend with dash to prevent name conflicts with function (like "name" property)
  2970. name = '_' + name;
  2971. }
  2972. var propertyCallbacks = callbacks[name];
  2973. if(typeof propertyCallbacks !== "object"){
  2974. propertyCallbacks = callbacks[name] = [];
  2975. }
  2976. propertyCallbacks.push(callback);
  2977. return {
  2978. unwatch: function(){
  2979. propertyCallbacks.splice(dojo.indexOf(propertyCallbacks, callback), 1);
  2980. }
  2981. };
  2982. }
  2983. });
  2984. }
  2985. if(!dojo._hasResource["dijit._WidgetBase"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  2986. dojo._hasResource["dijit._WidgetBase"] = true;
  2987. dojo.provide("dijit._WidgetBase");
  2988. (function(){
  2989. function isEqual(a, b){
  2990. // summary:
  2991. // Function that determines whether two values are identical,
  2992. // taking into account that NaN is not normally equal to itself
  2993. // in JS.
  2994. return a === b || (/* a is NaN */ a !== a && /* b is NaN */ b !== b);
  2995. }
  2996. dojo.declare("dijit._WidgetBase", dojo.Stateful, {
  2997. // summary:
  2998. // Future base class for all Dijit widgets.
  2999. // _Widget extends this class adding support for various features needed by desktop.
  3000. // id: [const] String
  3001. // A unique, opaque ID string that can be assigned by users or by the
  3002. // system. If the developer passes an ID which is known not to be
  3003. // unique, the specified ID is ignored and the system-generated ID is
  3004. // used instead.
  3005. id: "",
  3006. // lang: [const] String
  3007. // Rarely used. Overrides the default Dojo locale used to render this widget,
  3008. // as defined by the [HTML LANG](http://www.w3.org/TR/html401/struct/dirlang.html#adef-lang) attribute.
  3009. // Value must be among the list of locales specified during by the Dojo bootstrap,
  3010. // formatted according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt) (like en-us).
  3011. lang: "",
  3012. // dir: [const] String
  3013. // Bi-directional support, as defined by the [HTML DIR](http://www.w3.org/TR/html401/struct/dirlang.html#adef-dir)
  3014. // attribute. Either left-to-right "ltr" or right-to-left "rtl". If undefined, widgets renders in page's
  3015. // default direction.
  3016. dir: "",
  3017. // class: String
  3018. // HTML class attribute
  3019. "class": "",
  3020. // style: String||Object
  3021. // HTML style attributes as cssText string or name/value hash
  3022. style: "",
  3023. // title: String
  3024. // HTML title attribute.
  3025. //
  3026. // For form widgets this specifies a tooltip to display when hovering over
  3027. // the widget (just like the native HTML title attribute).
  3028. //
  3029. // For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer,
  3030. // etc., it's used to specify the tab label, accordion pane title, etc.
  3031. title: "",
  3032. // tooltip: String
  3033. // When this widget's title attribute is used to for a tab label, accordion pane title, etc.,
  3034. // this specifies the tooltip to appear when the mouse is hovered over that text.
  3035. tooltip: "",
  3036. // baseClass: [protected] String
  3037. // Root CSS class of the widget (ex: dijitTextBox), used to construct CSS classes to indicate
  3038. // widget state.
  3039. baseClass: "",
  3040. // srcNodeRef: [readonly] DomNode
  3041. // pointer to original DOM node
  3042. srcNodeRef: null,
  3043. // domNode: [readonly] DomNode
  3044. // This is our visible representation of the widget! Other DOM
  3045. // Nodes may by assigned to other properties, usually through the
  3046. // template system's dojoAttachPoint syntax, but the domNode
  3047. // property is the canonical "top level" node in widget UI.
  3048. domNode: null,
  3049. // containerNode: [readonly] DomNode
  3050. // Designates where children of the source DOM node will be placed.
  3051. // "Children" in this case refers to both DOM nodes and widgets.
  3052. // For example, for myWidget:
  3053. //
  3054. // | <div dojoType=myWidget>
  3055. // | <b> here's a plain DOM node
  3056. // | <span dojoType=subWidget>and a widget</span>
  3057. // | <i> and another plain DOM node </i>
  3058. // | </div>
  3059. //
  3060. // containerNode would point to:
  3061. //
  3062. // | <b> here's a plain DOM node
  3063. // | <span dojoType=subWidget>and a widget</span>
  3064. // | <i> and another plain DOM node </i>
  3065. //
  3066. // In templated widgets, "containerNode" is set via a
  3067. // dojoAttachPoint assignment.
  3068. //
  3069. // containerNode must be defined for any widget that accepts innerHTML
  3070. // (like ContentPane or BorderContainer or even Button), and conversely
  3071. // is null for widgets that don't, like TextBox.
  3072. containerNode: null,
  3073. /*=====
  3074. // _started: Boolean
  3075. // startup() has completed.
  3076. _started: false,
  3077. =====*/
  3078. // attributeMap: [protected] Object
  3079. // attributeMap sets up a "binding" between attributes (aka properties)
  3080. // of the widget and the widget's DOM.
  3081. // Changes to widget attributes listed in attributeMap will be
  3082. // reflected into the DOM.
  3083. //
  3084. // For example, calling set('title', 'hello')
  3085. // on a TitlePane will automatically cause the TitlePane's DOM to update
  3086. // with the new title.
  3087. //
  3088. // attributeMap is a hash where the key is an attribute of the widget,
  3089. // and the value reflects a binding to a:
  3090. //
  3091. // - DOM node attribute
  3092. // | focus: {node: "focusNode", type: "attribute"}
  3093. // Maps this.focus to this.focusNode.focus
  3094. //
  3095. // - DOM node innerHTML
  3096. // | title: { node: "titleNode", type: "innerHTML" }
  3097. // Maps this.title to this.titleNode.innerHTML
  3098. //
  3099. // - DOM node innerText
  3100. // | title: { node: "titleNode", type: "innerText" }
  3101. // Maps this.title to this.titleNode.innerText
  3102. //
  3103. // - DOM node CSS class
  3104. // | myClass: { node: "domNode", type: "class" }
  3105. // Maps this.myClass to this.domNode.className
  3106. //
  3107. // If the value is an array, then each element in the array matches one of the
  3108. // formats of the above list.
  3109. //
  3110. // There are also some shorthands for backwards compatibility:
  3111. // - string --> { node: string, type: "attribute" }, for example:
  3112. // | "focusNode" ---> { node: "focusNode", type: "attribute" }
  3113. // - "" --> { node: "domNode", type: "attribute" }
  3114. attributeMap: {id:"", dir:"", lang:"", "class":"", style:"", title:""},
  3115. // _blankGif: [protected] String
  3116. // Path to a blank 1x1 image.
  3117. // Used by <img> nodes in templates that really get their image via CSS background-image.
  3118. _blankGif: (dojo.config.blankGif || dojo.moduleUrl("dojo", "resources/blank.gif")).toString(),
  3119. //////////// INITIALIZATION METHODS ///////////////////////////////////////
  3120. postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){
  3121. // summary:
  3122. // Kicks off widget instantiation. See create() for details.
  3123. // tags:
  3124. // private
  3125. this.create(params, srcNodeRef);
  3126. },
  3127. create: function(/*Object?*/params, /*DomNode|String?*/srcNodeRef){
  3128. // summary:
  3129. // Kick off the life-cycle of a widget
  3130. // params:
  3131. // Hash of initialization parameters for widget, including
  3132. // scalar values (like title, duration etc.) and functions,
  3133. // typically callbacks like onClick.
  3134. // srcNodeRef:
  3135. // If a srcNodeRef (DOM node) is specified:
  3136. // - use srcNodeRef.innerHTML as my contents
  3137. // - if this is a behavioral widget then apply behavior
  3138. // to that srcNodeRef
  3139. // - otherwise, replace srcNodeRef with my generated DOM
  3140. // tree
  3141. // description:
  3142. // Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate,
  3143. // etc.), some of which of you'll want to override. See http://docs.dojocampus.org/dijit/_Widget
  3144. // for a discussion of the widget creation lifecycle.
  3145. //
  3146. // Of course, adventurous developers could override create entirely, but this should
  3147. // only be done as a last resort.
  3148. // tags:
  3149. // private
  3150. // store pointer to original DOM tree
  3151. this.srcNodeRef = dojo.byId(srcNodeRef);
  3152. // For garbage collection. An array of handles returned by Widget.connect()
  3153. // Each handle returned from Widget.connect() is an array of handles from dojo.connect()
  3154. this._connects = [];
  3155. // For garbage collection. An array of handles returned by Widget.subscribe()
  3156. // The handle returned from Widget.subscribe() is the handle returned from dojo.subscribe()
  3157. this._subscribes = [];
  3158. // mix in our passed parameters
  3159. if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; }
  3160. if(params){
  3161. this.params = params;
  3162. dojo._mixin(this, params);
  3163. }
  3164. this.postMixInProperties();
  3165. // generate an id for the widget if one wasn't specified
  3166. // (be sure to do this before buildRendering() because that function might
  3167. // expect the id to be there.)
  3168. if(!this.id){
  3169. this.id = dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
  3170. }
  3171. dijit.registry.add(this);
  3172. this.buildRendering();
  3173. if(this.domNode){
  3174. // Copy attributes listed in attributeMap into the [newly created] DOM for the widget.
  3175. // Also calls custom setters for all attributes with custom setters.
  3176. this._applyAttributes();
  3177. // If srcNodeRef was specified, then swap out original srcNode for this widget's DOM tree.
  3178. // For 2.0, move this after postCreate(). postCreate() shouldn't depend on the
  3179. // widget being attached to the DOM since it isn't when a widget is created programmatically like
  3180. // new MyWidget({}). See #11635.
  3181. var source = this.srcNodeRef;
  3182. if(source && source.parentNode && this.domNode !== source){
  3183. source.parentNode.replaceChild(this.domNode, source);
  3184. }
  3185. }
  3186. if(this.domNode){
  3187. // Note: for 2.0 may want to rename widgetId to dojo._scopeName + "_widgetId",
  3188. // assuming that dojo._scopeName even exists in 2.0
  3189. this.domNode.setAttribute("widgetId", this.id);
  3190. }
  3191. this.postCreate();
  3192. // If srcNodeRef has been processed and removed from the DOM (e.g. TemplatedWidget) then delete it to allow GC.
  3193. if(this.srcNodeRef && !this.srcNodeRef.parentNode){
  3194. delete this.srcNodeRef;
  3195. }
  3196. this._created = true;
  3197. },
  3198. _applyAttributes: function(){
  3199. // summary:
  3200. // Step during widget creation to copy all widget attributes to the
  3201. // DOM as per attributeMap and _setXXXAttr functions.
  3202. // description:
  3203. // Skips over blank/false attribute values, unless they were explicitly specified
  3204. // as parameters to the widget, since those are the default anyway,
  3205. // and setting tabIndex="" is different than not setting tabIndex at all.
  3206. //
  3207. // It processes the attributes in the attribute map first, and then
  3208. // it goes through and processes the attributes for the _setXXXAttr
  3209. // functions that have been specified
  3210. // tags:
  3211. // private
  3212. var condAttrApply = function(attr, scope){
  3213. if((scope.params && attr in scope.params) || scope[attr]){
  3214. scope.set(attr, scope[attr]);
  3215. }
  3216. };
  3217. // Do the attributes in attributeMap
  3218. for(var attr in this.attributeMap){
  3219. condAttrApply(attr, this);
  3220. }
  3221. // And also any attributes with custom setters
  3222. dojo.forEach(this._getSetterAttributes(), function(a){
  3223. if(!(a in this.attributeMap)){
  3224. condAttrApply(a, this);
  3225. }
  3226. }, this);
  3227. },
  3228. _getSetterAttributes: function(){
  3229. // summary:
  3230. // Returns list of attributes with custom setters for this widget
  3231. var ctor = this.constructor;
  3232. if(!ctor._setterAttrs){
  3233. var r = (ctor._setterAttrs = []),
  3234. attrs,
  3235. proto = ctor.prototype;
  3236. for(var fxName in proto){
  3237. if(dojo.isFunction(proto[fxName]) && (attrs = fxName.match(/^_set([a-zA-Z]*)Attr$/)) && attrs[1]){
  3238. r.push(attrs[1].charAt(0).toLowerCase() + attrs[1].substr(1));
  3239. }
  3240. }
  3241. }
  3242. return ctor._setterAttrs; // String[]
  3243. },
  3244. postMixInProperties: function(){
  3245. // summary:
  3246. // Called after the parameters to the widget have been read-in,
  3247. // but before the widget template is instantiated. Especially
  3248. // useful to set properties that are referenced in the widget
  3249. // template.
  3250. // tags:
  3251. // protected
  3252. },
  3253. buildRendering: function(){
  3254. // summary:
  3255. // Construct the UI for this widget, setting this.domNode
  3256. // description:
  3257. // Most widgets will mixin `dijit._Templated`, which implements this
  3258. // method.
  3259. // tags:
  3260. // protected
  3261. if(!this.domNode){
  3262. // Create root node if it wasn't created by _Templated
  3263. this.domNode = this.srcNodeRef || dojo.create('div');
  3264. }
  3265. // baseClass is a single class name or occasionally a space-separated list of names.
  3266. // Add those classes to the DOMNode. If RTL mode then also add with Rtl suffix.
  3267. // TODO: make baseClass custom setter
  3268. if(this.baseClass){
  3269. var classes = this.baseClass.split(" ");
  3270. if(!this.isLeftToRight()){
  3271. classes = classes.concat( dojo.map(classes, function(name){ return name+"Rtl"; }));
  3272. }
  3273. dojo.addClass(this.domNode, classes);
  3274. }
  3275. },
  3276. postCreate: function(){
  3277. // summary:
  3278. // Processing after the DOM fragment is created
  3279. // description:
  3280. // Called after the DOM fragment has been created, but not necessarily
  3281. // added to the document. Do not include any operations which rely on
  3282. // node dimensions or placement.
  3283. // tags:
  3284. // protected
  3285. },
  3286. startup: function(){
  3287. // summary:
  3288. // Processing after the DOM fragment is added to the document
  3289. // description:
  3290. // Called after a widget and its children have been created and added to the page,
  3291. // and all related widgets have finished their create() cycle, up through postCreate().
  3292. // This is useful for composite widgets that need to control or layout sub-widgets.
  3293. // Many layout widgets can use this as a wiring phase.
  3294. this._started = true;
  3295. },
  3296. //////////// DESTROY FUNCTIONS ////////////////////////////////
  3297. destroyRecursive: function(/*Boolean?*/ preserveDom){
  3298. // summary:
  3299. // Destroy this widget and its descendants
  3300. // description:
  3301. // This is the generic "destructor" function that all widget users
  3302. // should call to cleanly discard with a widget. Once a widget is
  3303. // destroyed, it is removed from the manager object.
  3304. // preserveDom:
  3305. // If true, this method will leave the original DOM structure
  3306. // alone of descendant Widgets. Note: This will NOT work with
  3307. // dijit._Templated widgets.
  3308. this._beingDestroyed = true;
  3309. this.destroyDescendants(preserveDom);
  3310. this.destroy(preserveDom);
  3311. },
  3312. destroy: function(/*Boolean*/ preserveDom){
  3313. // summary:
  3314. // Destroy this widget, but not its descendants.
  3315. // This method will, however, destroy internal widgets such as those used within a template.
  3316. // preserveDom: Boolean
  3317. // If true, this method will leave the original DOM structure alone.
  3318. // Note: This will not yet work with _Templated widgets
  3319. this._beingDestroyed = true;
  3320. this.uninitialize();
  3321. var d = dojo,
  3322. dfe = d.forEach,
  3323. dun = d.unsubscribe;
  3324. dfe(this._connects, function(array){
  3325. dfe(array, d.disconnect);
  3326. });
  3327. dfe(this._subscribes, function(handle){
  3328. dun(handle);
  3329. });
  3330. // destroy widgets created as part of template, etc.
  3331. dfe(this._supportingWidgets || [], function(w){
  3332. if(w.destroyRecursive){
  3333. w.destroyRecursive();
  3334. }else if(w.destroy){
  3335. w.destroy();
  3336. }
  3337. });
  3338. this.destroyRendering(preserveDom);
  3339. dijit.registry.remove(this.id);
  3340. this._destroyed = true;
  3341. },
  3342. destroyRendering: function(/*Boolean?*/ preserveDom){
  3343. // summary:
  3344. // Destroys the DOM nodes associated with this widget
  3345. // preserveDom:
  3346. // If true, this method will leave the original DOM structure alone
  3347. // during tear-down. Note: this will not work with _Templated
  3348. // widgets yet.
  3349. // tags:
  3350. // protected
  3351. if(this.bgIframe){
  3352. this.bgIframe.destroy(preserveDom);
  3353. delete this.bgIframe;
  3354. }
  3355. if(this.domNode){
  3356. if(preserveDom){
  3357. dojo.removeAttr(this.domNode, "widgetId");
  3358. }else{
  3359. dojo.destroy(this.domNode);
  3360. }
  3361. delete this.domNode;
  3362. }
  3363. if(this.srcNodeRef){
  3364. if(!preserveDom){
  3365. dojo.destroy(this.srcNodeRef);
  3366. }
  3367. delete this.srcNodeRef;
  3368. }
  3369. },
  3370. destroyDescendants: function(/*Boolean?*/ preserveDom){
  3371. // summary:
  3372. // Recursively destroy the children of this widget and their
  3373. // descendants.
  3374. // preserveDom:
  3375. // If true, the preserveDom attribute is passed to all descendant
  3376. // widget's .destroy() method. Not for use with _Templated
  3377. // widgets.
  3378. // get all direct descendants and destroy them recursively
  3379. dojo.forEach(this.getChildren(), function(widget){
  3380. if(widget.destroyRecursive){
  3381. widget.destroyRecursive(preserveDom);
  3382. }
  3383. });
  3384. },
  3385. uninitialize: function(){
  3386. // summary:
  3387. // Stub function. Override to implement custom widget tear-down
  3388. // behavior.
  3389. // tags:
  3390. // protected
  3391. return false;
  3392. },
  3393. ////////////////// GET/SET, CUSTOM SETTERS, ETC. ///////////////////
  3394. _setClassAttr: function(/*String*/ value){
  3395. // summary:
  3396. // Custom setter for the CSS "class" attribute
  3397. // tags:
  3398. // protected
  3399. var mapNode = this[this.attributeMap["class"] || 'domNode'];
  3400. dojo.replaceClass(mapNode, value, this["class"]);
  3401. this._set("class", value);
  3402. },
  3403. _setStyleAttr: function(/*String||Object*/ value){
  3404. // summary:
  3405. // Sets the style attribute of the widget according to value,
  3406. // which is either a hash like {height: "5px", width: "3px"}
  3407. // or a plain string
  3408. // description:
  3409. // Determines which node to set the style on based on style setting
  3410. // in attributeMap.
  3411. // tags:
  3412. // protected
  3413. var mapNode = this[this.attributeMap.style || 'domNode'];
  3414. // Note: technically we should revert any style setting made in a previous call
  3415. // to his method, but that's difficult to keep track of.
  3416. if(dojo.isObject(value)){
  3417. dojo.style(mapNode, value);
  3418. }else{
  3419. if(mapNode.style.cssText){
  3420. mapNode.style.cssText += "; " + value;
  3421. }else{
  3422. mapNode.style.cssText = value;
  3423. }
  3424. }
  3425. this._set("style", value);
  3426. },
  3427. _attrToDom: function(/*String*/ attr, /*String*/ value){
  3428. // summary:
  3429. // Reflect a widget attribute (title, tabIndex, duration etc.) to
  3430. // the widget DOM, as specified in attributeMap.
  3431. // Note some attributes like "type"
  3432. // cannot be processed this way as they are not mutable.
  3433. //
  3434. // tags:
  3435. // private
  3436. var commands = this.attributeMap[attr];
  3437. dojo.forEach(dojo.isArray(commands) ? commands : [commands], function(command){
  3438. // Get target node and what we are doing to that node
  3439. var mapNode = this[command.node || command || "domNode"]; // DOM node
  3440. var type = command.type || "attribute"; // class, innerHTML, innerText, or attribute
  3441. switch(type){
  3442. case "attribute":
  3443. if(dojo.isFunction(value)){ // functions execute in the context of the widget
  3444. value = dojo.hitch(this, value);
  3445. }
  3446. // Get the name of the DOM node attribute; usually it's the same
  3447. // as the name of the attribute in the widget (attr), but can be overridden.
  3448. // Also maps handler names to lowercase, like onSubmit --> onsubmit
  3449. var attrName = command.attribute ? command.attribute :
  3450. (/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr);
  3451. dojo.attr(mapNode, attrName, value);
  3452. break;
  3453. case "innerText":
  3454. mapNode.innerHTML = "";
  3455. mapNode.appendChild(dojo.doc.createTextNode(value));
  3456. break;
  3457. case "innerHTML":
  3458. mapNode.innerHTML = value;
  3459. break;
  3460. case "class":
  3461. dojo.replaceClass(mapNode, value, this[attr]);
  3462. break;
  3463. }
  3464. }, this);
  3465. },
  3466. get: function(name){
  3467. // summary:
  3468. // Get a property from a widget.
  3469. // name:
  3470. // The property to get.
  3471. // description:
  3472. // Get a named property from a widget. The property may
  3473. // potentially be retrieved via a getter method. If no getter is defined, this
  3474. // just retrieves the object's property.
  3475. // For example, if the widget has a properties "foo"
  3476. // and "bar" and a method named "_getFooAttr", calling:
  3477. // | myWidget.get("foo");
  3478. // would be equivalent to writing:
  3479. // | widget._getFooAttr();
  3480. // and:
  3481. // | myWidget.get("bar");
  3482. // would be equivalent to writing:
  3483. // | widget.bar;
  3484. var names = this._getAttrNames(name);
  3485. return this[names.g] ? this[names.g]() : this[name];
  3486. },
  3487. set: function(name, value){
  3488. // summary:
  3489. // Set a property on a widget
  3490. // name:
  3491. // The property to set.
  3492. // value:
  3493. // The value to set in the property.
  3494. // description:
  3495. // Sets named properties on a widget which may potentially be handled by a
  3496. // setter in the widget.
  3497. // For example, if the widget has a properties "foo"
  3498. // and "bar" and a method named "_setFooAttr", calling:
  3499. // | myWidget.set("foo", "Howdy!");
  3500. // would be equivalent to writing:
  3501. // | widget._setFooAttr("Howdy!");
  3502. // and:
  3503. // | myWidget.set("bar", 3);
  3504. // would be equivalent to writing:
  3505. // | widget.bar = 3;
  3506. //
  3507. // set() may also be called with a hash of name/value pairs, ex:
  3508. // | myWidget.set({
  3509. // | foo: "Howdy",
  3510. // | bar: 3
  3511. // | })
  3512. // This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
  3513. if(typeof name === "object"){
  3514. for(var x in name){
  3515. this.set(x, name[x]);
  3516. }
  3517. return this;
  3518. }
  3519. var names = this._getAttrNames(name);
  3520. if(this[names.s]){
  3521. // use the explicit setter
  3522. var result = this[names.s].apply(this, Array.prototype.slice.call(arguments, 1));
  3523. }else{
  3524. // if param is specified as DOM node attribute, copy it
  3525. if(name in this.attributeMap){
  3526. this._attrToDom(name, value);
  3527. }
  3528. this._set(name, value);
  3529. }
  3530. return result || this;
  3531. },
  3532. _attrPairNames: {}, // shared between all widgets
  3533. _getAttrNames: function(name){
  3534. // summary:
  3535. // Helper function for get() and set().
  3536. // Caches attribute name values so we don't do the string ops every time.
  3537. // tags:
  3538. // private
  3539. var apn = this._attrPairNames;
  3540. if(apn[name]){ return apn[name]; }
  3541. var uc = name.charAt(0).toUpperCase() + name.substr(1);
  3542. return (apn[name] = {
  3543. n: name+"Node",
  3544. s: "_set"+uc+"Attr",
  3545. g: "_get"+uc+"Attr"
  3546. });
  3547. },
  3548. _set: function(/*String*/ name, /*anything*/ value){
  3549. // summary:
  3550. // Helper function to set new value for specified attribute, and call handlers
  3551. // registered with watch() if the value has changed.
  3552. var oldValue = this[name];
  3553. this[name] = value;
  3554. if(this._watchCallbacks && this._created && !isEqual(value, oldValue)){
  3555. this._watchCallbacks(name, oldValue, value);
  3556. }
  3557. },
  3558. toString: function(){
  3559. // summary:
  3560. // Returns a string that represents the widget
  3561. // description:
  3562. // When a widget is cast to a string, this method will be used to generate the
  3563. // output. Currently, it does not implement any sort of reversible
  3564. // serialization.
  3565. return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
  3566. },
  3567. getDescendants: function(){
  3568. // summary:
  3569. // Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode.
  3570. // This method should generally be avoided as it returns widgets declared in templates, which are
  3571. // supposed to be internal/hidden, but it's left here for back-compat reasons.
  3572. return this.containerNode ? dojo.query('[widgetId]', this.containerNode).map(dijit.byNode) : []; // dijit._Widget[]
  3573. },
  3574. getChildren: function(){
  3575. // summary:
  3576. // Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode.
  3577. // Does not return nested widgets, nor widgets that are part of this widget's template.
  3578. return this.containerNode ? dijit.findWidgets(this.containerNode) : []; // dijit._Widget[]
  3579. },
  3580. connect: function(
  3581. /*Object|null*/ obj,
  3582. /*String|Function*/ event,
  3583. /*String|Function*/ method){
  3584. // summary:
  3585. // Connects specified obj/event to specified method of this object
  3586. // and registers for disconnect() on widget destroy.
  3587. // description:
  3588. // Provide widget-specific analog to dojo.connect, except with the
  3589. // implicit use of this widget as the target object.
  3590. // Events connected with `this.connect` are disconnected upon
  3591. // destruction.
  3592. // returns:
  3593. // A handle that can be passed to `disconnect` in order to disconnect before
  3594. // the widget is destroyed.
  3595. // example:
  3596. // | var btn = new dijit.form.Button();
  3597. // | // when foo.bar() is called, call the listener we're going to
  3598. // | // provide in the scope of btn
  3599. // | btn.connect(foo, "bar", function(){
  3600. // | console.debug(this.toString());
  3601. // | });
  3602. // tags:
  3603. // protected
  3604. var handles = [dojo._connect(obj, event, this, method)];
  3605. this._connects.push(handles);
  3606. return handles; // _Widget.Handle
  3607. },
  3608. disconnect: function(/* _Widget.Handle */ handles){
  3609. // summary:
  3610. // Disconnects handle created by `connect`.
  3611. // Also removes handle from this widget's list of connects.
  3612. // tags:
  3613. // protected
  3614. for(var i=0; i<this._connects.length; i++){
  3615. if(this._connects[i] == handles){
  3616. dojo.forEach(handles, dojo.disconnect);
  3617. this._connects.splice(i, 1);
  3618. return;
  3619. }
  3620. }
  3621. },
  3622. subscribe: function(
  3623. /*String*/ topic,
  3624. /*String|Function*/ method){
  3625. // summary:
  3626. // Subscribes to the specified topic and calls the specified method
  3627. // of this object and registers for unsubscribe() on widget destroy.
  3628. // description:
  3629. // Provide widget-specific analog to dojo.subscribe, except with the
  3630. // implicit use of this widget as the target object.
  3631. // example:
  3632. // | var btn = new dijit.form.Button();
  3633. // | // when /my/topic is published, this button changes its label to
  3634. // | // be the parameter of the topic.
  3635. // | btn.subscribe("/my/topic", function(v){
  3636. // | this.set("label", v);
  3637. // | });
  3638. var handle = dojo.subscribe(topic, this, method);
  3639. // return handles for Any widget that may need them
  3640. this._subscribes.push(handle);
  3641. return handle;
  3642. },
  3643. unsubscribe: function(/*Object*/ handle){
  3644. // summary:
  3645. // Unsubscribes handle created by this.subscribe.
  3646. // Also removes handle from this widget's list of subscriptions
  3647. for(var i=0; i<this._subscribes.length; i++){
  3648. if(this._subscribes[i] == handle){
  3649. dojo.unsubscribe(handle);
  3650. this._subscribes.splice(i, 1);
  3651. return;
  3652. }
  3653. }
  3654. },
  3655. isLeftToRight: function(){
  3656. // summary:
  3657. // Return this widget's explicit or implicit orientation (true for LTR, false for RTL)
  3658. // tags:
  3659. // protected
  3660. return this.dir ? (this.dir == "ltr") : dojo._isBodyLtr(); //Boolean
  3661. },
  3662. placeAt: function(/* String|DomNode|_Widget */reference, /* String?|Int? */position){
  3663. // summary:
  3664. // Place this widget's domNode reference somewhere in the DOM based
  3665. // on standard dojo.place conventions, or passing a Widget reference that
  3666. // contains and addChild member.
  3667. //
  3668. // description:
  3669. // A convenience function provided in all _Widgets, providing a simple
  3670. // shorthand mechanism to put an existing (or newly created) Widget
  3671. // somewhere in the dom, and allow chaining.
  3672. //
  3673. // reference:
  3674. // The String id of a domNode, a domNode reference, or a reference to a Widget posessing
  3675. // an addChild method.
  3676. //
  3677. // position:
  3678. // If passed a string or domNode reference, the position argument
  3679. // accepts a string just as dojo.place does, one of: "first", "last",
  3680. // "before", or "after".
  3681. //
  3682. // If passed a _Widget reference, and that widget reference has an ".addChild" method,
  3683. // it will be called passing this widget instance into that method, supplying the optional
  3684. // position index passed.
  3685. //
  3686. // returns:
  3687. // dijit._Widget
  3688. // Provides a useful return of the newly created dijit._Widget instance so you
  3689. // can "chain" this function by instantiating, placing, then saving the return value
  3690. // to a variable.
  3691. //
  3692. // example:
  3693. // | // create a Button with no srcNodeRef, and place it in the body:
  3694. // | var button = new dijit.form.Button({ label:"click" }).placeAt(dojo.body());
  3695. // | // now, 'button' is still the widget reference to the newly created button
  3696. // | dojo.connect(button, "onClick", function(e){ console.log('click'); });
  3697. //
  3698. // example:
  3699. // | // create a button out of a node with id="src" and append it to id="wrapper":
  3700. // | var button = new dijit.form.Button({},"src").placeAt("wrapper");
  3701. //
  3702. // example:
  3703. // | // place a new button as the first element of some div
  3704. // | var button = new dijit.form.Button({ label:"click" }).placeAt("wrapper","first");
  3705. //
  3706. // example:
  3707. // | // create a contentpane and add it to a TabContainer
  3708. // | var tc = dijit.byId("myTabs");
  3709. // | new dijit.layout.ContentPane({ href:"foo.html", title:"Wow!" }).placeAt(tc)
  3710. if(reference.declaredClass && reference.addChild){
  3711. reference.addChild(this, position);
  3712. }else{
  3713. dojo.place(this.domNode, reference, position);
  3714. }
  3715. return this;
  3716. },
  3717. defer: function(fcn, delay){
  3718. // summary:
  3719. // Wrapper to setTimeout to avoid deferred functions executing
  3720. // after the originating widget has been destroyed.
  3721. // Returns an object handle with a remove method (that returns null) (replaces clearTimeout).
  3722. // fcn: function reference
  3723. // delay: Optional number (defaults to 0)
  3724. // tags:
  3725. // protected.
  3726. var timer = setTimeout(dojo.hitch(this,
  3727. function(){
  3728. timer = null;
  3729. if(!this._destroyed){
  3730. dojo.hitch(this, fcn)();
  3731. }
  3732. }),
  3733. delay || 0
  3734. );
  3735. return {
  3736. remove: function(){
  3737. if(timer){
  3738. clearTimeout(timer);
  3739. timer = null;
  3740. }
  3741. return null; // so this works well: handle = handle.remove();
  3742. }
  3743. };
  3744. }
  3745. });
  3746. })();
  3747. }
  3748. if(!dojo._hasResource["dijit._Widget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  3749. dojo._hasResource["dijit._Widget"] = true;
  3750. dojo.provide("dijit._Widget");
  3751. ////////////////// DEFERRED CONNECTS ///////////////////
  3752. // This code is to assist deferring dojo.connect() calls in widgets (connecting to events on the widgets'
  3753. // DOM nodes) until someone actually needs to monitor that event.
  3754. dojo.connect(dojo, "_connect",
  3755. function(/*dijit._Widget*/ widget, /*String*/ event){
  3756. if(widget && dojo.isFunction(widget._onConnect)){
  3757. widget._onConnect(event);
  3758. }
  3759. });
  3760. dijit._connectOnUseEventHandler = function(/*Event*/ event){};
  3761. ////////////////// ONDIJITCLICK SUPPORT ///////////////////
  3762. // Keep track of where the last keydown event was, to help avoid generating
  3763. // spurious ondijitclick events when:
  3764. // 1. focus is on a <button> or <a>
  3765. // 2. user presses then releases the ENTER key
  3766. // 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler
  3767. // 4. onkeyup event fires, causing the ondijitclick handler to fire
  3768. dijit._lastKeyDownNode = null;
  3769. if(dojo.isIE){
  3770. (function(){
  3771. var keydownCallback = function(evt){
  3772. dijit._lastKeyDownNode = evt.srcElement;
  3773. };
  3774. dojo.doc.attachEvent('onkeydown', keydownCallback);
  3775. dojo.addOnWindowUnload(function(){
  3776. dojo.doc.detachEvent('onkeydown', keydownCallback);
  3777. });
  3778. })();
  3779. }else{
  3780. dojo.doc.addEventListener('keydown', function(evt){
  3781. dijit._lastKeyDownNode = evt.target;
  3782. }, true);
  3783. }
  3784. (function(){
  3785. dojo.declare("dijit._Widget", dijit._WidgetBase, {
  3786. // summary:
  3787. // Base class for all Dijit widgets.
  3788. //
  3789. // Extends _WidgetBase, adding support for:
  3790. // - deferred connections
  3791. // A call like dojo.connect(myWidget, "onMouseMove", func)
  3792. // will essentially do a dojo.connect(myWidget.domNode, "onMouseMove", func)
  3793. // - ondijitclick
  3794. // Support new dojoAttachEvent="ondijitclick: ..." that is triggered by a mouse click or a SPACE/ENTER keypress
  3795. // - focus related functions
  3796. // In particular, the onFocus()/onBlur() callbacks. Driven internally by
  3797. // dijit/_base/focus.js.
  3798. // - deprecated methods
  3799. // - onShow(), onHide(), onClose()
  3800. //
  3801. // Also, by loading code in dijit/_base, turns on:
  3802. // - browser sniffing (putting browser id like .dj_ie on <html> node)
  3803. // - high contrast mode sniffing (add .dijit_a11y class to <body> if machine is in high contrast mode)
  3804. ////////////////// DEFERRED CONNECTS ///////////////////
  3805. // _deferredConnects: [protected] Object
  3806. // attributeMap addendum for event handlers that should be connected only on first use
  3807. _deferredConnects: {
  3808. onClick: "",
  3809. onDblClick: "",
  3810. onKeyDown: "",
  3811. onKeyPress: "",
  3812. onKeyUp: "",
  3813. onMouseMove: "",
  3814. onMouseDown: "",
  3815. onMouseOut: "",
  3816. onMouseOver: "",
  3817. onMouseLeave: "",
  3818. onMouseEnter: "",
  3819. onMouseUp: ""
  3820. },
  3821. onClick: dijit._connectOnUseEventHandler,
  3822. /*=====
  3823. onClick: function(event){
  3824. // summary:
  3825. // Connect to this function to receive notifications of mouse click events.
  3826. // event:
  3827. // mouse Event
  3828. // tags:
  3829. // callback
  3830. },
  3831. =====*/
  3832. onDblClick: dijit._connectOnUseEventHandler,
  3833. /*=====
  3834. onDblClick: function(event){
  3835. // summary:
  3836. // Connect to this function to receive notifications of mouse double click events.
  3837. // event:
  3838. // mouse Event
  3839. // tags:
  3840. // callback
  3841. },
  3842. =====*/
  3843. onKeyDown: dijit._connectOnUseEventHandler,
  3844. /*=====
  3845. onKeyDown: function(event){
  3846. // summary:
  3847. // Connect to this function to receive notifications of keys being pressed down.
  3848. // event:
  3849. // key Event
  3850. // tags:
  3851. // callback
  3852. },
  3853. =====*/
  3854. onKeyPress: dijit._connectOnUseEventHandler,
  3855. /*=====
  3856. onKeyPress: function(event){
  3857. // summary:
  3858. // Connect to this function to receive notifications of printable keys being typed.
  3859. // event:
  3860. // key Event
  3861. // tags:
  3862. // callback
  3863. },
  3864. =====*/
  3865. onKeyUp: dijit._connectOnUseEventHandler,
  3866. /*=====
  3867. onKeyUp: function(event){
  3868. // summary:
  3869. // Connect to this function to receive notifications of keys being released.
  3870. // event:
  3871. // key Event
  3872. // tags:
  3873. // callback
  3874. },
  3875. =====*/
  3876. onMouseDown: dijit._connectOnUseEventHandler,
  3877. /*=====
  3878. onMouseDown: function(event){
  3879. // summary:
  3880. // Connect to this function to receive notifications of when the mouse button is pressed down.
  3881. // event:
  3882. // mouse Event
  3883. // tags:
  3884. // callback
  3885. },
  3886. =====*/
  3887. onMouseMove: dijit._connectOnUseEventHandler,
  3888. /*=====
  3889. onMouseMove: function(event){
  3890. // summary:
  3891. // Connect to this function to receive notifications of when the mouse moves over nodes contained within this widget.
  3892. // event:
  3893. // mouse Event
  3894. // tags:
  3895. // callback
  3896. },
  3897. =====*/
  3898. onMouseOut: dijit._connectOnUseEventHandler,
  3899. /*=====
  3900. onMouseOut: function(event){
  3901. // summary:
  3902. // Connect to this function to receive notifications of when the mouse moves off of nodes contained within this widget.
  3903. // event:
  3904. // mouse Event
  3905. // tags:
  3906. // callback
  3907. },
  3908. =====*/
  3909. onMouseOver: dijit._connectOnUseEventHandler,
  3910. /*=====
  3911. onMouseOver: function(event){
  3912. // summary:
  3913. // Connect to this function to receive notifications of when the mouse moves onto nodes contained within this widget.
  3914. // event:
  3915. // mouse Event
  3916. // tags:
  3917. // callback
  3918. },
  3919. =====*/
  3920. onMouseLeave: dijit._connectOnUseEventHandler,
  3921. /*=====
  3922. onMouseLeave: function(event){
  3923. // summary:
  3924. // Connect to this function to receive notifications of when the mouse moves off of this widget.
  3925. // event:
  3926. // mouse Event
  3927. // tags:
  3928. // callback
  3929. },
  3930. =====*/
  3931. onMouseEnter: dijit._connectOnUseEventHandler,
  3932. /*=====
  3933. onMouseEnter: function(event){
  3934. // summary:
  3935. // Connect to this function to receive notifications of when the mouse moves onto this widget.
  3936. // event:
  3937. // mouse Event
  3938. // tags:
  3939. // callback
  3940. },
  3941. =====*/
  3942. onMouseUp: dijit._connectOnUseEventHandler,
  3943. /*=====
  3944. onMouseUp: function(event){
  3945. // summary:
  3946. // Connect to this function to receive notifications of when the mouse button is released.
  3947. // event:
  3948. // mouse Event
  3949. // tags:
  3950. // callback
  3951. },
  3952. =====*/
  3953. create: function(/*Object?*/params, /*DomNode|String?*/srcNodeRef){
  3954. // To avoid double-connects, remove entries from _deferredConnects
  3955. // that have been setup manually by a subclass (ex, by dojoAttachEvent).
  3956. // If a subclass has redefined a callback (ex: onClick) then assume it's being
  3957. // connected to manually.
  3958. this._deferredConnects = dojo.clone(this._deferredConnects);
  3959. for(var attr in this.attributeMap){
  3960. delete this._deferredConnects[attr]; // can't be in both attributeMap and _deferredConnects
  3961. }
  3962. for(attr in this._deferredConnects){
  3963. if(this[attr] !== dijit._connectOnUseEventHandler){
  3964. delete this._deferredConnects[attr]; // redefined, probably dojoAttachEvent exists
  3965. }
  3966. }
  3967. this.inherited(arguments);
  3968. if(this.domNode){
  3969. // If the developer has specified a handler as a widget parameter
  3970. // (ex: new Button({onClick: ...})
  3971. // then naturally need to connect from DOM node to that handler immediately,
  3972. for(attr in this.params){
  3973. this._onConnect(attr);
  3974. }
  3975. }
  3976. },
  3977. _onConnect: function(/*String*/ event){
  3978. // summary:
  3979. // Called when someone connects to one of my handlers.
  3980. // "Turn on" that handler if it isn't active yet.
  3981. //
  3982. // This is also called for every single initialization parameter
  3983. // so need to do nothing for parameters like "id".
  3984. // tags:
  3985. // private
  3986. if(event in this._deferredConnects){
  3987. var mapNode = this[this._deferredConnects[event] || 'domNode'];
  3988. this.connect(mapNode, event.toLowerCase(), event);
  3989. delete this._deferredConnects[event];
  3990. }
  3991. },
  3992. ////////////////// FOCUS RELATED ///////////////////
  3993. // _onFocus() and _onBlur() are called by the focus manager
  3994. // focused: [readonly] Boolean
  3995. // This widget or a widget it contains has focus, or is "active" because
  3996. // it was recently clicked.
  3997. focused: false,
  3998. isFocusable: function(){
  3999. // summary:
  4000. // Return true if this widget can currently be focused
  4001. // and false if not
  4002. return this.focus && (dojo.style(this.domNode, "display") != "none");
  4003. },
  4004. onFocus: function(){
  4005. // summary:
  4006. // Called when the widget becomes "active" because
  4007. // it or a widget inside of it either has focus, or has recently
  4008. // been clicked.
  4009. // tags:
  4010. // callback
  4011. },
  4012. onBlur: function(){
  4013. // summary:
  4014. // Called when the widget stops being "active" because
  4015. // focus moved to something outside of it, or the user
  4016. // clicked somewhere outside of it, or the widget was
  4017. // hidden.
  4018. // tags:
  4019. // callback
  4020. },
  4021. _onFocus: function(e){
  4022. // summary:
  4023. // This is where widgets do processing for when they are active,
  4024. // such as changing CSS classes. See onFocus() for more details.
  4025. // tags:
  4026. // protected
  4027. this.onFocus();
  4028. },
  4029. _onBlur: function(){
  4030. // summary:
  4031. // This is where widgets do processing for when they stop being active,
  4032. // such as changing CSS classes. See onBlur() for more details.
  4033. // tags:
  4034. // protected
  4035. this.onBlur();
  4036. },
  4037. ////////////////// DEPRECATED METHODS ///////////////////
  4038. setAttribute: function(/*String*/ attr, /*anything*/ value){
  4039. // summary:
  4040. // Deprecated. Use set() instead.
  4041. // tags:
  4042. // deprecated
  4043. dojo.deprecated(this.declaredClass+"::setAttribute(attr, value) is deprecated. Use set() instead.", "", "2.0");
  4044. this.set(attr, value);
  4045. },
  4046. attr: function(/*String|Object*/name, /*Object?*/value){
  4047. // summary:
  4048. // Set or get properties on a widget instance.
  4049. // name:
  4050. // The property to get or set. If an object is passed here and not
  4051. // a string, its keys are used as names of attributes to be set
  4052. // and the value of the object as values to set in the widget.
  4053. // value:
  4054. // Optional. If provided, attr() operates as a setter. If omitted,
  4055. // the current value of the named property is returned.
  4056. // description:
  4057. // This method is deprecated, use get() or set() directly.
  4058. // Print deprecation warning but only once per calling function
  4059. if(dojo.config.isDebug){
  4060. var alreadyCalledHash = arguments.callee._ach || (arguments.callee._ach = {}),
  4061. caller = (arguments.callee.caller || "unknown caller").toString();
  4062. if(!alreadyCalledHash[caller]){
  4063. dojo.deprecated(this.declaredClass + "::attr() is deprecated. Use get() or set() instead, called from " +
  4064. caller, "", "2.0");
  4065. alreadyCalledHash[caller] = true;
  4066. }
  4067. }
  4068. var args = arguments.length;
  4069. if(args >= 2 || typeof name === "object"){ // setter
  4070. return this.set.apply(this, arguments);
  4071. }else{ // getter
  4072. return this.get(name);
  4073. }
  4074. },
  4075. ////////////////// ONDIJITCLICK SUPPORT ///////////////////
  4076. // nodesWithKeyClick: [private] String[]
  4077. // List of nodes that correctly handle click events via native browser support,
  4078. // and don't need dijit's help
  4079. nodesWithKeyClick: ["input", "button"],
  4080. connect: function(
  4081. /*Object|null*/ obj,
  4082. /*String|Function*/ event,
  4083. /*String|Function*/ method){
  4084. // summary:
  4085. // Connects specified obj/event to specified method of this object
  4086. // and registers for disconnect() on widget destroy.
  4087. // description:
  4088. // Provide widget-specific analog to dojo.connect, except with the
  4089. // implicit use of this widget as the target object.
  4090. // This version of connect also provides a special "ondijitclick"
  4091. // event which triggers on a click or space or enter keyup.
  4092. // Events connected with `this.connect` are disconnected upon
  4093. // destruction.
  4094. // returns:
  4095. // A handle that can be passed to `disconnect` in order to disconnect before
  4096. // the widget is destroyed.
  4097. // example:
  4098. // | var btn = new dijit.form.Button();
  4099. // | // when foo.bar() is called, call the listener we're going to
  4100. // | // provide in the scope of btn
  4101. // | btn.connect(foo, "bar", function(){
  4102. // | console.debug(this.toString());
  4103. // | });
  4104. // tags:
  4105. // protected
  4106. var d = dojo,
  4107. dc = d._connect,
  4108. handles = this.inherited(arguments, [obj, event == "ondijitclick" ? "onclick" : event, method]);
  4109. if(event == "ondijitclick"){
  4110. // add key based click activation for unsupported nodes.
  4111. // do all processing onkey up to prevent spurious clicks
  4112. // for details see comments at top of this file where _lastKeyDownNode is defined
  4113. if(d.indexOf(this.nodesWithKeyClick, obj.nodeName.toLowerCase()) == -1){ // is NOT input or button
  4114. var m = d.hitch(this, method);
  4115. handles.push(
  4116. dc(obj, "onkeydown", this, function(e){
  4117. //console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode));
  4118. if((e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) &&
  4119. !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
  4120. // needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work
  4121. dijit._lastKeyDownNode = e.target;
  4122. // Stop event to prevent scrolling on space key in IE.
  4123. // But don't do this for _HasDropDown because it surpresses the onkeypress
  4124. // event needed to open the drop down when the user presses the SPACE key.
  4125. if(!("openDropDown" in this && obj == this._buttonNode)){
  4126. e.preventDefault();
  4127. }
  4128. }
  4129. }),
  4130. dc(obj, "onkeyup", this, function(e){
  4131. //console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode));
  4132. if( (e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) &&
  4133. e.target == dijit._lastKeyDownNode && // === breaks greasemonkey
  4134. !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
  4135. //need reset here or have problems in FF when focus returns to trigger element after closing popup/alert
  4136. dijit._lastKeyDownNode = null;
  4137. return m(e);
  4138. }
  4139. })
  4140. );
  4141. }
  4142. }
  4143. return handles; // _Widget.Handle
  4144. },
  4145. ////////////////// MISCELLANEOUS METHODS ///////////////////
  4146. _onShow: function(){
  4147. // summary:
  4148. // Internal method called when this widget is made visible.
  4149. // See `onShow` for details.
  4150. this.onShow();
  4151. },
  4152. onShow: function(){
  4153. // summary:
  4154. // Called when this widget becomes the selected pane in a
  4155. // `dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
  4156. // `dijit.layout.AccordionContainer`, etc.
  4157. //
  4158. // Also called to indicate display of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
  4159. // tags:
  4160. // callback
  4161. },
  4162. onHide: function(){
  4163. // summary:
  4164. // Called when another widget becomes the selected pane in a
  4165. // `dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
  4166. // `dijit.layout.AccordionContainer`, etc.
  4167. //
  4168. // Also called to indicate hide of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
  4169. // tags:
  4170. // callback
  4171. },
  4172. onClose: function(){
  4173. // summary:
  4174. // Called when this widget is being displayed as a popup (ex: a Calendar popped
  4175. // up from a DateTextBox), and it is hidden.
  4176. // This is called from the dijit.popup code, and should not be called directly.
  4177. //
  4178. // Also used as a parameter for children of `dijit.layout.StackContainer` or subclasses.
  4179. // Callback if a user tries to close the child. Child will be closed if this function returns true.
  4180. // tags:
  4181. // extension
  4182. return true; // Boolean
  4183. }
  4184. });
  4185. })();
  4186. }
  4187. if(!dojo._hasResource["dojo.string"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  4188. dojo._hasResource["dojo.string"] = true;
  4189. dojo.provide("dojo.string");
  4190. dojo.getObject("string", true, dojo);
  4191. /*=====
  4192. dojo.string = {
  4193. // summary: String utilities for Dojo
  4194. };
  4195. =====*/
  4196. dojo.string.rep = function(/*String*/str, /*Integer*/num){
  4197. // summary:
  4198. // Efficiently replicate a string `n` times.
  4199. // str:
  4200. // the string to replicate
  4201. // num:
  4202. // number of times to replicate the string
  4203. if(num <= 0 || !str){ return ""; }
  4204. var buf = [];
  4205. for(;;){
  4206. if(num & 1){
  4207. buf.push(str);
  4208. }
  4209. if(!(num >>= 1)){ break; }
  4210. str += str;
  4211. }
  4212. return buf.join(""); // String
  4213. };
  4214. dojo.string.pad = function(/*String*/text, /*Integer*/size, /*String?*/ch, /*Boolean?*/end){
  4215. // summary:
  4216. // Pad a string to guarantee that it is at least `size` length by
  4217. // filling with the character `ch` at either the start or end of the
  4218. // string. Pads at the start, by default.
  4219. // text:
  4220. // the string to pad
  4221. // size:
  4222. // length to provide padding
  4223. // ch:
  4224. // character to pad, defaults to '0'
  4225. // end:
  4226. // adds padding at the end if true, otherwise pads at start
  4227. // example:
  4228. // | // Fill the string to length 10 with "+" characters on the right. Yields "Dojo++++++".
  4229. // | dojo.string.pad("Dojo", 10, "+", true);
  4230. if(!ch){
  4231. ch = '0';
  4232. }
  4233. var out = String(text),
  4234. pad = dojo.string.rep(ch, Math.ceil((size - out.length) / ch.length));
  4235. return end ? out + pad : pad + out; // String
  4236. };
  4237. dojo.string.substitute = function( /*String*/ template,
  4238. /*Object|Array*/map,
  4239. /*Function?*/ transform,
  4240. /*Object?*/ thisObject){
  4241. // summary:
  4242. // Performs parameterized substitutions on a string. Throws an
  4243. // exception if any parameter is unmatched.
  4244. // template:
  4245. // a string with expressions in the form `${key}` to be replaced or
  4246. // `${key:format}` which specifies a format function. keys are case-sensitive.
  4247. // map:
  4248. // hash to search for substitutions
  4249. // transform:
  4250. // a function to process all parameters before substitution takes
  4251. // place, e.g. mylib.encodeXML
  4252. // thisObject:
  4253. // where to look for optional format function; default to the global
  4254. // namespace
  4255. // example:
  4256. // Substitutes two expressions in a string from an Array or Object
  4257. // | // returns "File 'foo.html' is not found in directory '/temp'."
  4258. // | // by providing substitution data in an Array
  4259. // | dojo.string.substitute(
  4260. // | "File '${0}' is not found in directory '${1}'.",
  4261. // | ["foo.html","/temp"]
  4262. // | );
  4263. // |
  4264. // | // also returns "File 'foo.html' is not found in directory '/temp'."
  4265. // | // but provides substitution data in an Object structure. Dotted
  4266. // | // notation may be used to traverse the structure.
  4267. // | dojo.string.substitute(
  4268. // | "File '${name}' is not found in directory '${info.dir}'.",
  4269. // | { name: "foo.html", info: { dir: "/temp" } }
  4270. // | );
  4271. // example:
  4272. // Use a transform function to modify the values:
  4273. // | // returns "file 'foo.html' is not found in directory '/temp'."
  4274. // | dojo.string.substitute(
  4275. // | "${0} is not found in ${1}.",
  4276. // | ["foo.html","/temp"],
  4277. // | function(str){
  4278. // | // try to figure out the type
  4279. // | var prefix = (str.charAt(0) == "/") ? "directory": "file";
  4280. // | return prefix + " '" + str + "'";
  4281. // | }
  4282. // | );
  4283. // example:
  4284. // Use a formatter
  4285. // | // returns "thinger -- howdy"
  4286. // | dojo.string.substitute(
  4287. // | "${0:postfix}", ["thinger"], null, {
  4288. // | postfix: function(value, key){
  4289. // | return value + " -- howdy";
  4290. // | }
  4291. // | }
  4292. // | );
  4293. thisObject = thisObject || dojo.global;
  4294. transform = transform ?
  4295. dojo.hitch(thisObject, transform) : function(v){ return v; };
  4296. return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g,
  4297. function(match, key, format){
  4298. var value = dojo.getObject(key, false, map);
  4299. if(format){
  4300. value = dojo.getObject(format, false, thisObject).call(thisObject, value, key);
  4301. }
  4302. return transform(value, key).toString();
  4303. }); // String
  4304. };
  4305. /*=====
  4306. dojo.string.trim = function(str){
  4307. // summary:
  4308. // Trims whitespace from both sides of the string
  4309. // str: String
  4310. // String to be trimmed
  4311. // returns: String
  4312. // Returns the trimmed string
  4313. // description:
  4314. // This version of trim() was taken from [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript).
  4315. // The short yet performant version of this function is dojo.trim(),
  4316. // which is part of Dojo base. Uses String.prototype.trim instead, if available.
  4317. return ""; // String
  4318. }
  4319. =====*/
  4320. dojo.string.trim = String.prototype.trim ?
  4321. dojo.trim : // aliasing to the native function
  4322. function(str){
  4323. str = str.replace(/^\s+/, '');
  4324. for(var i = str.length - 1; i >= 0; i--){
  4325. if(/\S/.test(str.charAt(i))){
  4326. str = str.substring(0, i + 1);
  4327. break;
  4328. }
  4329. }
  4330. return str;
  4331. };
  4332. }
  4333. if(!dojo._hasResource["dojo.cache"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  4334. dojo._hasResource["dojo.cache"] = true;
  4335. dojo.provide("dojo.cache");
  4336. /*=====
  4337. dojo.cache = {
  4338. // summary:
  4339. // A way to cache string content that is fetchable via `dojo.moduleUrl`.
  4340. };
  4341. =====*/
  4342. var cache = {};
  4343. dojo.cache = function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){
  4344. // summary:
  4345. // A getter and setter for storing the string content associated with the
  4346. // module and url arguments.
  4347. // description:
  4348. // module and url are used to call `dojo.moduleUrl()` to generate a module URL.
  4349. // If value is specified, the cache value for the moduleUrl will be set to
  4350. // that value. Otherwise, dojo.cache will fetch the moduleUrl and store it
  4351. // in its internal cache and return that cached value for the URL. To clear
  4352. // a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the
  4353. // the URL contents, only modules on the same domain of the page can use this capability.
  4354. // The build system can inline the cache values though, to allow for xdomain hosting.
  4355. // module: String||Object
  4356. // If a String, the module name to use for the base part of the URL, similar to module argument
  4357. // to `dojo.moduleUrl`. If an Object, something that has a .toString() method that
  4358. // generates a valid path for the cache item. For example, a dojo._Url object.
  4359. // url: String
  4360. // The rest of the path to append to the path derived from the module argument. If
  4361. // module is an object, then this second argument should be the "value" argument instead.
  4362. // value: String||Object?
  4363. // If a String, the value to use in the cache for the module/url combination.
  4364. // If an Object, it can have two properties: value and sanitize. The value property
  4365. // should be the value to use in the cache, and sanitize can be set to true or false,
  4366. // to indicate if XML declarations should be removed from the value and if the HTML
  4367. // inside a body tag in the value should be extracted as the real value. The value argument
  4368. // or the value property on the value argument are usually only used by the build system
  4369. // as it inlines cache content.
  4370. // example:
  4371. // To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style
  4372. // of call is used to avoid an issue with the build system erroneously trying to intern
  4373. // this example. To get the build system to intern your dojo.cache calls, use the
  4374. // "dojo.cache" style of call):
  4375. // | //If template.html contains "<h1>Hello</h1>" that will be
  4376. // | //the value for the text variable.
  4377. // | var text = dojo["cache"]("my.module", "template.html");
  4378. // example:
  4379. // To ask dojo.cache to fetch content and store it in the cache, and sanitize the input
  4380. // (the dojo["cache"] style of call is used to avoid an issue with the build system
  4381. // erroneously trying to intern this example. To get the build system to intern your
  4382. // dojo.cache calls, use the "dojo.cache" style of call):
  4383. // | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the
  4384. // | //text variable will contain just "<h1>Hello</h1>".
  4385. // | var text = dojo["cache"]("my.module", "template.html", {sanitize: true});
  4386. // example:
  4387. // Same example as previous, but demostrates how an object can be passed in as
  4388. // the first argument, then the value argument can then be the second argument.
  4389. // | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the
  4390. // | //text variable will contain just "<h1>Hello</h1>".
  4391. // | var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true});
  4392. //Module could be a string, or an object that has a toString() method
  4393. //that will return a useful path. If it is an object, then the "url" argument
  4394. //will actually be the value argument.
  4395. if(typeof module == "string"){
  4396. var pathObj = dojo.moduleUrl(module, url);
  4397. }else{
  4398. pathObj = module;
  4399. value = url;
  4400. }
  4401. var key = pathObj.toString();
  4402. var val = value;
  4403. if(value != undefined && !dojo.isString(value)){
  4404. val = ("value" in value ? value.value : undefined);
  4405. }
  4406. var sanitize = value && value.sanitize ? true : false;
  4407. if(typeof val == "string"){
  4408. //We have a string, set cache value
  4409. val = cache[key] = sanitize ? dojo.cache._sanitize(val) : val;
  4410. }else if(val === null){
  4411. //Remove cached value
  4412. delete cache[key];
  4413. }else{
  4414. //Allow cache values to be empty strings. If key property does
  4415. //not exist, fetch it.
  4416. if(!(key in cache)){
  4417. val = dojo._getText(key);
  4418. cache[key] = sanitize ? dojo.cache._sanitize(val) : val;
  4419. }
  4420. val = cache[key];
  4421. }
  4422. return val; //String
  4423. };
  4424. dojo.cache._sanitize = function(/*String*/val){
  4425. // summary:
  4426. // Strips <?xml ...?> declarations so that external SVG and XML
  4427. // documents can be added to a document without worry. Also, if the string
  4428. // is an HTML document, only the part inside the body tag is returned.
  4429. // description:
  4430. // Copied from dijit._Templated._sanitizeTemplateString.
  4431. if(val){
  4432. val = val.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
  4433. var matches = val.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
  4434. if(matches){
  4435. val = matches[1];
  4436. }
  4437. }else{
  4438. val = "";
  4439. }
  4440. return val; //String
  4441. };
  4442. }
  4443. if(!dojo._hasResource["dijit._Templated"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  4444. dojo._hasResource["dijit._Templated"] = true;
  4445. dojo.provide("dijit._Templated");
  4446. dojo.declare("dijit._Templated",
  4447. null,
  4448. {
  4449. // summary:
  4450. // Mixin for widgets that are instantiated from a template
  4451. // templateString: [protected] String
  4452. // A string that represents the widget template. Pre-empts the
  4453. // templatePath. In builds that have their strings "interned", the
  4454. // templatePath is converted to an inline templateString, thereby
  4455. // preventing a synchronous network call.
  4456. //
  4457. // Use in conjunction with dojo.cache() to load from a file.
  4458. templateString: null,
  4459. // templatePath: [protected deprecated] String
  4460. // Path to template (HTML file) for this widget relative to dojo.baseUrl.
  4461. // Deprecated: use templateString with dojo.cache() instead.
  4462. templatePath: null,
  4463. // widgetsInTemplate: [protected] Boolean
  4464. // Should we parse the template to find widgets that might be
  4465. // declared in markup inside it? False by default.
  4466. widgetsInTemplate: false,
  4467. // skipNodeCache: [protected] Boolean
  4468. // If using a cached widget template node poses issues for a
  4469. // particular widget class, it can set this property to ensure
  4470. // that its template is always re-built from a string
  4471. _skipNodeCache: false,
  4472. // _earlyTemplatedStartup: Boolean
  4473. // A fallback to preserve the 1.0 - 1.3 behavior of children in
  4474. // templates having their startup called before the parent widget
  4475. // fires postCreate. Defaults to 'false', causing child widgets to
  4476. // have their .startup() called immediately before a parent widget
  4477. // .startup(), but always after the parent .postCreate(). Set to
  4478. // 'true' to re-enable to previous, arguably broken, behavior.
  4479. _earlyTemplatedStartup: false,
  4480. /*=====
  4481. // _attachPoints: [private] String[]
  4482. // List of widget attribute names associated with dojoAttachPoint=... in the
  4483. // template, ex: ["containerNode", "labelNode"]
  4484. _attachPoints: [],
  4485. =====*/
  4486. /*=====
  4487. // _attachEvents: [private] Handle[]
  4488. // List of connections associated with dojoAttachEvent=... in the
  4489. // template
  4490. _attachEvents: [],
  4491. =====*/
  4492. constructor: function(){
  4493. this._attachPoints = [];
  4494. this._attachEvents = [];
  4495. },
  4496. _stringRepl: function(tmpl){
  4497. // summary:
  4498. // Does substitution of ${foo} type properties in template string
  4499. // tags:
  4500. // private
  4501. var className = this.declaredClass, _this = this;
  4502. // Cache contains a string because we need to do property replacement
  4503. // do the property replacement
  4504. return dojo.string.substitute(tmpl, this, function(value, key){
  4505. if(key.charAt(0) == '!'){ value = dojo.getObject(key.substr(1), false, _this); }
  4506. if(typeof value == "undefined"){ throw new Error(className+" template:"+key); } // a debugging aide
  4507. if(value == null){ return ""; }
  4508. // Substitution keys beginning with ! will skip the transform step,
  4509. // in case a user wishes to insert unescaped markup, e.g. ${!foo}
  4510. return key.charAt(0) == "!" ? value :
  4511. // Safer substitution, see heading "Attribute values" in
  4512. // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
  4513. value.toString().replace(/"/g,"&quot;"); //TODO: add &amp? use encodeXML method?
  4514. }, this);
  4515. },
  4516. buildRendering: function(){
  4517. // summary:
  4518. // Construct the UI for this widget from a template, setting this.domNode.
  4519. // tags:
  4520. // protected
  4521. // Lookup cached version of template, and download to cache if it
  4522. // isn't there already. Returns either a DomNode or a string, depending on
  4523. // whether or not the template contains ${foo} replacement parameters.
  4524. var cached = dijit._Templated.getCachedTemplate(this.templatePath, this.templateString, this._skipNodeCache);
  4525. var node;
  4526. if(dojo.isString(cached)){
  4527. node = dojo._toDom(this._stringRepl(cached));
  4528. if(node.nodeType != 1){
  4529. // Flag common problems such as templates with multiple top level nodes (nodeType == 11)
  4530. throw new Error("Invalid template: " + cached);
  4531. }
  4532. }else{
  4533. // if it's a node, all we have to do is clone it
  4534. node = cached.cloneNode(true);
  4535. }
  4536. this.domNode = node;
  4537. // Call down to _Widget.buildRendering() to get base classes assigned
  4538. // TODO: change the baseClass assignment to attributeMap
  4539. this.inherited(arguments);
  4540. // recurse through the node, looking for, and attaching to, our
  4541. // attachment points and events, which should be defined on the template node.
  4542. this._attachTemplateNodes(node);
  4543. if(this.widgetsInTemplate){
  4544. // Store widgets that we need to start at a later point in time
  4545. var cw = (this._startupWidgets = dojo.parser.parse(node, {
  4546. noStart: !this._earlyTemplatedStartup,
  4547. template: true,
  4548. inherited: {dir: this.dir, lang: this.lang},
  4549. propsThis: this, // so data-dojo-props of widgets in the template can reference "this" to refer to me
  4550. scope: "dojo" // even in multi-version mode templates use dojoType/data-dojo-type
  4551. }));
  4552. this._supportingWidgets = dijit.findWidgets(node);
  4553. this._attachTemplateNodes(cw, function(n,p){
  4554. return n[p];
  4555. });
  4556. }
  4557. this._fillContent(this.srcNodeRef);
  4558. },
  4559. _fillContent: function(/*DomNode*/ source){
  4560. // summary:
  4561. // Relocate source contents to templated container node.
  4562. // this.containerNode must be able to receive children, or exceptions will be thrown.
  4563. // tags:
  4564. // protected
  4565. var dest = this.containerNode;
  4566. if(source && dest){
  4567. while(source.hasChildNodes()){
  4568. dest.appendChild(source.firstChild);
  4569. }
  4570. }
  4571. },
  4572. _attachTemplateNodes: function(rootNode, getAttrFunc){
  4573. // summary:
  4574. // Iterate through the template and attach functions and nodes accordingly.
  4575. // Alternately, if rootNode is an array of widgets, then will process dojoAttachPoint
  4576. // etc. for those widgets.
  4577. // description:
  4578. // Map widget properties and functions to the handlers specified in
  4579. // the dom node and it's descendants. This function iterates over all
  4580. // nodes and looks for these properties:
  4581. // * dojoAttachPoint
  4582. // * dojoAttachEvent
  4583. // * waiRole
  4584. // * waiState
  4585. // rootNode: DomNode|Array[Widgets]
  4586. // the node to search for properties. All children will be searched.
  4587. // getAttrFunc: Function?
  4588. // a function which will be used to obtain property for a given
  4589. // DomNode/Widget
  4590. // tags:
  4591. // private
  4592. getAttrFunc = getAttrFunc || function(n,p){ return n.getAttribute(p); };
  4593. var nodes = dojo.isArray(rootNode) ? rootNode : (rootNode.all || rootNode.getElementsByTagName("*"));
  4594. var x = dojo.isArray(rootNode) ? 0 : -1;
  4595. for(; x<nodes.length; x++){
  4596. var baseNode = (x == -1) ? rootNode : nodes[x];
  4597. if(this.widgetsInTemplate && (getAttrFunc(baseNode, "dojoType") || getAttrFunc(baseNode, "data-dojo-type"))){
  4598. continue;
  4599. }
  4600. // Process dojoAttachPoint
  4601. var attachPoint = getAttrFunc(baseNode, "dojoAttachPoint") || getAttrFunc(baseNode, "data-dojo-attach-point");
  4602. if(attachPoint){
  4603. var point, points = attachPoint.split(/\s*,\s*/);
  4604. while((point = points.shift())){
  4605. if(dojo.isArray(this[point])){
  4606. this[point].push(baseNode);
  4607. }else{
  4608. this[point]=baseNode;
  4609. }
  4610. this._attachPoints.push(point);
  4611. }
  4612. }
  4613. // Process dojoAttachEvent
  4614. var attachEvent = getAttrFunc(baseNode, "dojoAttachEvent") || getAttrFunc(baseNode, "data-dojo-attach-event");;
  4615. if(attachEvent){
  4616. // NOTE: we want to support attributes that have the form
  4617. // "domEvent: nativeEvent; ..."
  4618. var event, events = attachEvent.split(/\s*,\s*/);
  4619. var trim = dojo.trim;
  4620. while((event = events.shift())){
  4621. if(event){
  4622. var thisFunc = null;
  4623. if(event.indexOf(":") != -1){
  4624. // oh, if only JS had tuple assignment
  4625. var funcNameArr = event.split(":");
  4626. event = trim(funcNameArr[0]);
  4627. thisFunc = trim(funcNameArr[1]);
  4628. }else{
  4629. event = trim(event);
  4630. }
  4631. if(!thisFunc){
  4632. thisFunc = event;
  4633. }
  4634. this._attachEvents.push(this.connect(baseNode, event, thisFunc));
  4635. }
  4636. }
  4637. }
  4638. // waiRole, waiState
  4639. // TODO: remove this in 2.0, templates are now using role=... and aria-XXX=... attributes directicly
  4640. var role = getAttrFunc(baseNode, "waiRole");
  4641. if(role){
  4642. dijit.setWaiRole(baseNode, role);
  4643. }
  4644. var values = getAttrFunc(baseNode, "waiState");
  4645. if(values){
  4646. dojo.forEach(values.split(/\s*,\s*/), function(stateValue){
  4647. if(stateValue.indexOf('-') != -1){
  4648. var pair = stateValue.split('-');
  4649. dijit.setWaiState(baseNode, pair[0], pair[1]);
  4650. }
  4651. });
  4652. }
  4653. }
  4654. },
  4655. startup: function(){
  4656. dojo.forEach(this._startupWidgets, function(w){
  4657. if(w && !w._started && w.startup){
  4658. w.startup();
  4659. }
  4660. });
  4661. this.inherited(arguments);
  4662. },
  4663. destroyRendering: function(){
  4664. // Delete all attach points to prevent IE6 memory leaks.
  4665. dojo.forEach(this._attachPoints, function(point){
  4666. delete this[point];
  4667. }, this);
  4668. this._attachPoints = [];
  4669. // And same for event handlers
  4670. dojo.forEach(this._attachEvents, this.disconnect, this);
  4671. this._attachEvents = [];
  4672. this.inherited(arguments);
  4673. }
  4674. }
  4675. );
  4676. // key is either templatePath or templateString; object is either string or DOM tree
  4677. dijit._Templated._templateCache = {};
  4678. dijit._Templated.getCachedTemplate = function(templatePath, templateString, alwaysUseString){
  4679. // summary:
  4680. // Static method to get a template based on the templatePath or
  4681. // templateString key
  4682. // templatePath: String||dojo.uri.Uri
  4683. // The URL to get the template from.
  4684. // templateString: String?
  4685. // a string to use in lieu of fetching the template from a URL. Takes precedence
  4686. // over templatePath
  4687. // returns: Mixed
  4688. // Either string (if there are ${} variables that need to be replaced) or just
  4689. // a DOM tree (if the node can be cloned directly)
  4690. // is it already cached?
  4691. var tmplts = dijit._Templated._templateCache;
  4692. var key = templateString || templatePath;
  4693. var cached = tmplts[key];
  4694. if(cached){
  4695. try{
  4696. // if the cached value is an innerHTML string (no ownerDocument) or a DOM tree created within the current document, then use the current cached value
  4697. if(!cached.ownerDocument || cached.ownerDocument == dojo.doc){
  4698. // string or node of the same document
  4699. return cached;
  4700. }
  4701. }catch(e){ /* squelch */ } // IE can throw an exception if cached.ownerDocument was reloaded
  4702. dojo.destroy(cached);
  4703. }
  4704. // If necessary, load template string from template path
  4705. if(!templateString){
  4706. templateString = dojo.cache(templatePath, {sanitize: true});
  4707. }
  4708. templateString = dojo.string.trim(templateString);
  4709. if(alwaysUseString || templateString.match(/\$\{([^\}]+)\}/g)){
  4710. // there are variables in the template so all we can do is cache the string
  4711. return (tmplts[key] = templateString); //String
  4712. }else{
  4713. // there are no variables in the template so we can cache the DOM tree
  4714. var node = dojo._toDom(templateString);
  4715. if(node.nodeType != 1){
  4716. throw new Error("Invalid template: " + templateString);
  4717. }
  4718. return (tmplts[key] = node); //Node
  4719. }
  4720. };
  4721. if(dojo.isIE){
  4722. dojo.addOnWindowUnload(function(){
  4723. var cache = dijit._Templated._templateCache;
  4724. for(var key in cache){
  4725. var value = cache[key];
  4726. if(typeof value == "object"){ // value is either a string or a DOM node template
  4727. dojo.destroy(value);
  4728. }
  4729. delete cache[key];
  4730. }
  4731. });
  4732. }
  4733. // These arguments can be specified for widgets which are used in templates.
  4734. // Since any widget can be specified as sub widgets in template, mix it
  4735. // into the base widget class. (This is a hack, but it's effective.)
  4736. dojo.extend(dijit._Widget,{
  4737. dojoAttachEvent: "",
  4738. dojoAttachPoint: "",
  4739. waiRole: "",
  4740. waiState:""
  4741. });
  4742. }
  4743. if(!dojo._hasResource["dijit._Container"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  4744. dojo._hasResource["dijit._Container"] = true;
  4745. dojo.provide("dijit._Container");
  4746. dojo.declare("dijit._Container",
  4747. null,
  4748. {
  4749. // summary:
  4750. // Mixin for widgets that contain a set of widget children.
  4751. // description:
  4752. // Use this mixin for widgets that needs to know about and
  4753. // keep track of their widget children. Suitable for widgets like BorderContainer
  4754. // and TabContainer which contain (only) a set of child widgets.
  4755. //
  4756. // It's not suitable for widgets like ContentPane
  4757. // which contains mixed HTML (plain DOM nodes in addition to widgets),
  4758. // and where contained widgets are not necessarily directly below
  4759. // this.containerNode. In that case calls like addChild(node, position)
  4760. // wouldn't make sense.
  4761. // isContainer: [protected] Boolean
  4762. // Indicates that this widget acts as a "parent" to the descendant widgets.
  4763. // When the parent is started it will call startup() on the child widgets.
  4764. // See also `isLayoutContainer`.
  4765. isContainer: true,
  4766. buildRendering: function(){
  4767. this.inherited(arguments);
  4768. if(!this.containerNode){
  4769. // all widgets with descendants must set containerNode
  4770. this.containerNode = this.domNode;
  4771. }
  4772. },
  4773. addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
  4774. // summary:
  4775. // Makes the given widget a child of this widget.
  4776. // description:
  4777. // Inserts specified child widget's dom node as a child of this widget's
  4778. // container node, and possibly does other processing (such as layout).
  4779. var refNode = this.containerNode;
  4780. if(insertIndex && typeof insertIndex == "number"){
  4781. var children = this.getChildren();
  4782. if(children && children.length >= insertIndex){
  4783. refNode = children[insertIndex-1].domNode;
  4784. insertIndex = "after";
  4785. }
  4786. }
  4787. dojo.place(widget.domNode, refNode, insertIndex);
  4788. // If I've been started but the child widget hasn't been started,
  4789. // start it now. Make sure to do this after widget has been
  4790. // inserted into the DOM tree, so it can see that it's being controlled by me,
  4791. // so it doesn't try to size itself.
  4792. if(this._started && !widget._started){
  4793. widget.startup();
  4794. }
  4795. },
  4796. removeChild: function(/*Widget or int*/ widget){
  4797. // summary:
  4798. // Removes the passed widget instance from this widget but does
  4799. // not destroy it. You can also pass in an integer indicating
  4800. // the index within the container to remove
  4801. if(typeof widget == "number"){
  4802. widget = this.getChildren()[widget];
  4803. }
  4804. if(widget){
  4805. var node = widget.domNode;
  4806. if(node && node.parentNode){
  4807. node.parentNode.removeChild(node); // detach but don't destroy
  4808. }
  4809. }
  4810. },
  4811. hasChildren: function(){
  4812. // summary:
  4813. // Returns true if widget has children, i.e. if this.containerNode contains something.
  4814. return this.getChildren().length > 0; // Boolean
  4815. },
  4816. destroyDescendants: function(/*Boolean*/ preserveDom){
  4817. // summary:
  4818. // Destroys all the widgets inside this.containerNode,
  4819. // but not this widget itself
  4820. dojo.forEach(this.getChildren(), function(child){ child.destroyRecursive(preserveDom); });
  4821. },
  4822. _getSiblingOfChild: function(/*dijit._Widget*/ child, /*int*/ dir){
  4823. // summary:
  4824. // Get the next or previous widget sibling of child
  4825. // dir:
  4826. // if 1, get the next sibling
  4827. // if -1, get the previous sibling
  4828. // tags:
  4829. // private
  4830. var node = child.domNode,
  4831. which = (dir>0 ? "nextSibling" : "previousSibling");
  4832. do{
  4833. node = node[which];
  4834. }while(node && (node.nodeType != 1 || !dijit.byNode(node)));
  4835. return node && dijit.byNode(node); // dijit._Widget
  4836. },
  4837. getIndexOfChild: function(/*dijit._Widget*/ child){
  4838. // summary:
  4839. // Gets the index of the child in this container or -1 if not found
  4840. return dojo.indexOf(this.getChildren(), child); // int
  4841. },
  4842. startup: function(){
  4843. // summary:
  4844. // Called after all the widgets have been instantiated and their
  4845. // dom nodes have been inserted somewhere under dojo.doc.body.
  4846. //
  4847. // Widgets should override this method to do any initialization
  4848. // dependent on other widgets existing, and then call
  4849. // this superclass method to finish things off.
  4850. //
  4851. // startup() in subclasses shouldn't do anything
  4852. // size related because the size of the widget hasn't been set yet.
  4853. if(this._started){ return; }
  4854. // Startup all children of this widget
  4855. dojo.forEach(this.getChildren(), function(child){ child.startup(); });
  4856. this.inherited(arguments);
  4857. }
  4858. }
  4859. );
  4860. }
  4861. if(!dojo._hasResource["dijit._Contained"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  4862. dojo._hasResource["dijit._Contained"] = true;
  4863. dojo.provide("dijit._Contained");
  4864. dojo.declare("dijit._Contained",
  4865. null,
  4866. {
  4867. // summary:
  4868. // Mixin for widgets that are children of a container widget
  4869. //
  4870. // example:
  4871. // | // make a basic custom widget that knows about it's parents
  4872. // | dojo.declare("my.customClass",[dijit._Widget,dijit._Contained],{});
  4873. getParent: function(){
  4874. // summary:
  4875. // Returns the parent widget of this widget, assuming the parent
  4876. // specifies isContainer
  4877. var parent = dijit.getEnclosingWidget(this.domNode.parentNode);
  4878. return parent && parent.isContainer ? parent : null;
  4879. },
  4880. _getSibling: function(/*String*/ which){
  4881. // summary:
  4882. // Returns next or previous sibling
  4883. // which:
  4884. // Either "next" or "previous"
  4885. // tags:
  4886. // private
  4887. var node = this.domNode;
  4888. do{
  4889. node = node[which+"Sibling"];
  4890. }while(node && node.nodeType != 1);
  4891. return node && dijit.byNode(node); // dijit._Widget
  4892. },
  4893. getPreviousSibling: function(){
  4894. // summary:
  4895. // Returns null if this is the first child of the parent,
  4896. // otherwise returns the next element sibling to the "left".
  4897. return this._getSibling("previous"); // dijit._Widget
  4898. },
  4899. getNextSibling: function(){
  4900. // summary:
  4901. // Returns null if this is the last child of the parent,
  4902. // otherwise returns the next element sibling to the "right".
  4903. return this._getSibling("next"); // dijit._Widget
  4904. },
  4905. getIndexInParent: function(){
  4906. // summary:
  4907. // Returns the index of this widget within its container parent.
  4908. // It returns -1 if the parent does not exist, or if the parent
  4909. // is not a dijit._Container
  4910. var p = this.getParent();
  4911. if(!p || !p.getIndexOfChild){
  4912. return -1; // int
  4913. }
  4914. return p.getIndexOfChild(this); // int
  4915. }
  4916. }
  4917. );
  4918. }
  4919. if(!dojo._hasResource["dijit.layout._LayoutWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  4920. dojo._hasResource["dijit.layout._LayoutWidget"] = true;
  4921. dojo.provide("dijit.layout._LayoutWidget");
  4922. dojo.declare("dijit.layout._LayoutWidget",
  4923. [dijit._Widget, dijit._Container, dijit._Contained],
  4924. {
  4925. // summary:
  4926. // Base class for a _Container widget which is responsible for laying out its children.
  4927. // Widgets which mixin this code must define layout() to manage placement and sizing of the children.
  4928. // baseClass: [protected extension] String
  4929. // This class name is applied to the widget's domNode
  4930. // and also may be used to generate names for sub nodes,
  4931. // for example dijitTabContainer-content.
  4932. baseClass: "dijitLayoutContainer",
  4933. // isLayoutContainer: [protected] Boolean
  4934. // Indicates that this widget is going to call resize() on its
  4935. // children widgets, setting their size, when they become visible.
  4936. isLayoutContainer: true,
  4937. buildRendering: function(){
  4938. this.inherited(arguments);
  4939. dojo.addClass(this.domNode, "dijitContainer");
  4940. },
  4941. startup: function(){
  4942. // summary:
  4943. // Called after all the widgets have been instantiated and their
  4944. // dom nodes have been inserted somewhere under dojo.doc.body.
  4945. //
  4946. // Widgets should override this method to do any initialization
  4947. // dependent on other widgets existing, and then call
  4948. // this superclass method to finish things off.
  4949. //
  4950. // startup() in subclasses shouldn't do anything
  4951. // size related because the size of the widget hasn't been set yet.
  4952. if(this._started){ return; }
  4953. // Need to call inherited first - so that child widgets get started
  4954. // up correctly
  4955. this.inherited(arguments);
  4956. // If I am a not being controlled by a parent layout widget...
  4957. var parent = this.getParent && this.getParent()
  4958. if(!(parent && parent.isLayoutContainer)){
  4959. // Do recursive sizing and layout of all my descendants
  4960. // (passing in no argument to resize means that it has to glean the size itself)
  4961. this.resize();
  4962. // Since my parent isn't a layout container, and my style *may be* width=height=100%
  4963. // or something similar (either set directly or via a CSS class),
  4964. // monitor when my size changes so that I can re-layout.
  4965. // For browsers where I can't directly monitor when my size changes,
  4966. // monitor when the viewport changes size, which *may* indicate a size change for me.
  4967. this.connect(dojo.isIE ? this.domNode : dojo.global, 'onresize', function(){
  4968. // Using function(){} closure to ensure no arguments to resize.
  4969. this.resize();
  4970. });
  4971. }
  4972. },
  4973. resize: function(changeSize, resultSize){
  4974. // summary:
  4975. // Call this to resize a widget, or after its size has changed.
  4976. // description:
  4977. // Change size mode:
  4978. // When changeSize is specified, changes the marginBox of this widget
  4979. // and forces it to relayout its contents accordingly.
  4980. // changeSize may specify height, width, or both.
  4981. //
  4982. // If resultSize is specified it indicates the size the widget will
  4983. // become after changeSize has been applied.
  4984. //
  4985. // Notification mode:
  4986. // When changeSize is null, indicates that the caller has already changed
  4987. // the size of the widget, or perhaps it changed because the browser
  4988. // window was resized. Tells widget to relayout its contents accordingly.
  4989. //
  4990. // If resultSize is also specified it indicates the size the widget has
  4991. // become.
  4992. //
  4993. // In either mode, this method also:
  4994. // 1. Sets this._borderBox and this._contentBox to the new size of
  4995. // the widget. Queries the current domNode size if necessary.
  4996. // 2. Calls layout() to resize contents (and maybe adjust child widgets).
  4997. //
  4998. // changeSize: Object?
  4999. // Sets the widget to this margin-box size and position.
  5000. // May include any/all of the following properties:
  5001. // | {w: int, h: int, l: int, t: int}
  5002. //
  5003. // resultSize: Object?
  5004. // The margin-box size of this widget after applying changeSize (if
  5005. // changeSize is specified). If caller knows this size and
  5006. // passes it in, we don't need to query the browser to get the size.
  5007. // | {w: int, h: int}
  5008. var node = this.domNode;
  5009. // set margin box size, unless it wasn't specified, in which case use current size
  5010. if(changeSize){
  5011. dojo.marginBox(node, changeSize);
  5012. // set offset of the node
  5013. if(changeSize.t){ node.style.top = changeSize.t + "px"; }
  5014. if(changeSize.l){ node.style.left = changeSize.l + "px"; }
  5015. }
  5016. // If either height or width wasn't specified by the user, then query node for it.
  5017. // But note that setting the margin box and then immediately querying dimensions may return
  5018. // inaccurate results, so try not to depend on it.
  5019. var mb = resultSize || {};
  5020. dojo.mixin(mb, changeSize || {}); // changeSize overrides resultSize
  5021. if( !("h" in mb) || !("w" in mb) ){
  5022. mb = dojo.mixin(dojo.marginBox(node), mb); // just use dojo.marginBox() to fill in missing values
  5023. }
  5024. // Compute and save the size of my border box and content box
  5025. // (w/out calling dojo.contentBox() since that may fail if size was recently set)
  5026. var cs = dojo.getComputedStyle(node);
  5027. var me = dojo._getMarginExtents(node, cs);
  5028. var be = dojo._getBorderExtents(node, cs);
  5029. var bb = (this._borderBox = {
  5030. w: mb.w - (me.w + be.w),
  5031. h: mb.h - (me.h + be.h)
  5032. });
  5033. var pe = dojo._getPadExtents(node, cs);
  5034. this._contentBox = {
  5035. l: dojo._toPixelValue(node, cs.paddingLeft),
  5036. t: dojo._toPixelValue(node, cs.paddingTop),
  5037. w: bb.w - pe.w,
  5038. h: bb.h - pe.h
  5039. };
  5040. // Callback for widget to adjust size of its children
  5041. this.layout();
  5042. },
  5043. layout: function(){
  5044. // summary:
  5045. // Widgets override this method to size and position their contents/children.
  5046. // When this is called this._contentBox is guaranteed to be set (see resize()).
  5047. //
  5048. // This is called after startup(), and also when the widget's size has been
  5049. // changed.
  5050. // tags:
  5051. // protected extension
  5052. },
  5053. _setupChild: function(/*dijit._Widget*/child){
  5054. // summary:
  5055. // Common setup for initial children and children which are added after startup
  5056. // tags:
  5057. // protected extension
  5058. var cls = this.baseClass + "-child "
  5059. + (child.baseClass ? this.baseClass + "-" + child.baseClass : "");
  5060. dojo.addClass(child.domNode, cls);
  5061. },
  5062. addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
  5063. // Overrides _Container.addChild() to call _setupChild()
  5064. this.inherited(arguments);
  5065. if(this._started){
  5066. this._setupChild(child);
  5067. }
  5068. },
  5069. removeChild: function(/*dijit._Widget*/ child){
  5070. // Overrides _Container.removeChild() to remove class added by _setupChild()
  5071. var cls = this.baseClass + "-child"
  5072. + (child.baseClass ?
  5073. " " + this.baseClass + "-" + child.baseClass : "");
  5074. dojo.removeClass(child.domNode, cls);
  5075. this.inherited(arguments);
  5076. }
  5077. }
  5078. );
  5079. dijit.layout.marginBox2contentBox = function(/*DomNode*/ node, /*Object*/ mb){
  5080. // summary:
  5081. // Given the margin-box size of a node, return its content box size.
  5082. // Functions like dojo.contentBox() but is more reliable since it doesn't have
  5083. // to wait for the browser to compute sizes.
  5084. var cs = dojo.getComputedStyle(node);
  5085. var me = dojo._getMarginExtents(node, cs);
  5086. var pb = dojo._getPadBorderExtents(node, cs);
  5087. return {
  5088. l: dojo._toPixelValue(node, cs.paddingLeft),
  5089. t: dojo._toPixelValue(node, cs.paddingTop),
  5090. w: mb.w - (me.w + pb.w),
  5091. h: mb.h - (me.h + pb.h)
  5092. };
  5093. };
  5094. (function(){
  5095. var capitalize = function(word){
  5096. return word.substring(0,1).toUpperCase() + word.substring(1);
  5097. };
  5098. var size = function(widget, dim){
  5099. // size the child
  5100. var newSize = widget.resize ? widget.resize(dim) : dojo.marginBox(widget.domNode, dim);
  5101. // record child's size
  5102. if(newSize){
  5103. // if the child returned it's new size then use that
  5104. dojo.mixin(widget, newSize);
  5105. }else{
  5106. // otherwise, call marginBox(), but favor our own numbers when we have them.
  5107. // the browser lies sometimes
  5108. dojo.mixin(widget, dojo.marginBox(widget.domNode));
  5109. dojo.mixin(widget, dim);
  5110. }
  5111. };
  5112. dijit.layout.layoutChildren = function(/*DomNode*/ container, /*Object*/ dim, /*Widget[]*/ children,
  5113. /*String?*/ changedRegionId, /*Number?*/ changedRegionSize){
  5114. // summary
  5115. // Layout a bunch of child dom nodes within a parent dom node
  5116. // container:
  5117. // parent node
  5118. // dim:
  5119. // {l, t, w, h} object specifying dimensions of container into which to place children
  5120. // children:
  5121. // an array of Widgets or at least objects containing:
  5122. // * domNode: pointer to DOM node to position
  5123. // * region or layoutAlign: position to place DOM node
  5124. // * resize(): (optional) method to set size of node
  5125. // * id: (optional) Id of widgets, referenced from resize object, below.
  5126. // changedRegionId:
  5127. // If specified, the slider for the region with the specified id has been dragged, and thus
  5128. // the region's height or width should be adjusted according to changedRegionSize
  5129. // changedRegionSize:
  5130. // See changedRegionId.
  5131. // copy dim because we are going to modify it
  5132. dim = dojo.mixin({}, dim);
  5133. dojo.addClass(container, "dijitLayoutContainer");
  5134. // Move "client" elements to the end of the array for layout. a11y dictates that the author
  5135. // needs to be able to put them in the document in tab-order, but this algorithm requires that
  5136. // client be last. TODO: move these lines to LayoutContainer? Unneeded other places I think.
  5137. children = dojo.filter(children, function(item){ return item.region != "center" && item.layoutAlign != "client"; })
  5138. .concat(dojo.filter(children, function(item){ return item.region == "center" || item.layoutAlign == "client"; }));
  5139. // set positions/sizes
  5140. dojo.forEach(children, function(child){
  5141. var elm = child.domNode,
  5142. pos = (child.region || child.layoutAlign);
  5143. // set elem to upper left corner of unused space; may move it later
  5144. var elmStyle = elm.style;
  5145. elmStyle.left = dim.l+"px";
  5146. elmStyle.top = dim.t+"px";
  5147. elmStyle.position = "absolute";
  5148. dojo.addClass(elm, "dijitAlign" + capitalize(pos));
  5149. // Size adjustments to make to this child widget
  5150. var sizeSetting = {};
  5151. // Check for optional size adjustment due to splitter drag (height adjustment for top/bottom align
  5152. // panes and width adjustment for left/right align panes.
  5153. if(changedRegionId && changedRegionId == child.id){
  5154. sizeSetting[child.region == "top" || child.region == "bottom" ? "h" : "w"] = changedRegionSize;
  5155. }
  5156. // set size && adjust record of remaining space.
  5157. // note that setting the width of a <div> may affect its height.
  5158. if(pos == "top" || pos == "bottom"){
  5159. sizeSetting.w = dim.w;
  5160. size(child, sizeSetting);
  5161. dim.h -= child.h;
  5162. if(pos == "top"){
  5163. dim.t += child.h;
  5164. }else{
  5165. elmStyle.top = dim.t + dim.h + "px";
  5166. }
  5167. }else if(pos == "left" || pos == "right"){
  5168. sizeSetting.h = dim.h;
  5169. size(child, sizeSetting);
  5170. dim.w -= child.w;
  5171. if(pos == "left"){
  5172. dim.l += child.w;
  5173. }else{
  5174. elmStyle.left = dim.l + dim.w + "px";
  5175. }
  5176. }else if(pos == "client" || pos == "center"){
  5177. size(child, dim);
  5178. }
  5179. });
  5180. };
  5181. })();
  5182. }
  5183. if(!dojo._hasResource["dijit._CssStateMixin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  5184. dojo._hasResource["dijit._CssStateMixin"] = true;
  5185. dojo.provide("dijit._CssStateMixin");
  5186. dojo.declare("dijit._CssStateMixin", [], {
  5187. // summary:
  5188. // Mixin for widgets to set CSS classes on the widget DOM nodes depending on hover/mouse press/focus
  5189. // state changes, and also higher-level state changes such becoming disabled or selected.
  5190. //
  5191. // description:
  5192. // By mixing this class into your widget, and setting the this.baseClass attribute, it will automatically
  5193. // maintain CSS classes on the widget root node (this.domNode) depending on hover,
  5194. // active, focus, etc. state. Ex: with a baseClass of dijitButton, it will apply the classes
  5195. // dijitButtonHovered and dijitButtonActive, as the user moves the mouse over the widget and clicks it.
  5196. //
  5197. // It also sets CSS like dijitButtonDisabled based on widget semantic state.
  5198. //
  5199. // By setting the cssStateNodes attribute, a widget can also track events on subnodes (like buttons
  5200. // within the widget).
  5201. // cssStateNodes: [protected] Object
  5202. // List of sub-nodes within the widget that need CSS classes applied on mouse hover/press and focus
  5203. //.
  5204. // Each entry in the hash is a an attachpoint names (like "upArrowButton") mapped to a CSS class names
  5205. // (like "dijitUpArrowButton"). Example:
  5206. // | {
  5207. // | "upArrowButton": "dijitUpArrowButton",
  5208. // | "downArrowButton": "dijitDownArrowButton"
  5209. // | }
  5210. // The above will set the CSS class dijitUpArrowButton to the this.upArrowButton DOMNode when it
  5211. // is hovered, etc.
  5212. cssStateNodes: {},
  5213. // hovering: [readonly] Boolean
  5214. // True if cursor is over this widget
  5215. hovering: false,
  5216. // active: [readonly] Boolean
  5217. // True if mouse was pressed while over this widget, and hasn't been released yet
  5218. active: false,
  5219. _applyAttributes: function(){
  5220. // This code would typically be in postCreate(), but putting in _applyAttributes() for
  5221. // performance: so the class changes happen before DOM is inserted into the document.
  5222. // Change back to postCreate() in 2.0. See #11635.
  5223. this.inherited(arguments);
  5224. // Automatically monitor mouse events (essentially :hover and :active) on this.domNode
  5225. dojo.forEach(["onmouseenter", "onmouseleave", "onmousedown"], function(e){
  5226. this.connect(this.domNode, e, "_cssMouseEvent");
  5227. }, this);
  5228. // Monitoring changes to disabled, readonly, etc. state, and update CSS class of root node
  5229. dojo.forEach(["disabled", "readOnly", "checked", "selected", "focused", "state", "hovering", "active"], function(attr){
  5230. this.watch(attr, dojo.hitch(this, "_setStateClass"));
  5231. }, this);
  5232. // Events on sub nodes within the widget
  5233. for(var ap in this.cssStateNodes){
  5234. this._trackMouseState(this[ap], this.cssStateNodes[ap]);
  5235. }
  5236. // Set state initially; there's probably no hover/active/focus state but widget might be
  5237. // disabled/readonly/checked/selected so we want to set CSS classes for those conditions.
  5238. this._setStateClass();
  5239. },
  5240. _cssMouseEvent: function(/*Event*/ event){
  5241. // summary:
  5242. // Sets hovering and active properties depending on mouse state,
  5243. // which triggers _setStateClass() to set appropriate CSS classes for this.domNode.
  5244. if(!this.disabled){
  5245. switch(event.type){
  5246. case "mouseenter":
  5247. case "mouseover": // generated on non-IE browsers even though we connected to mouseenter
  5248. this._set("hovering", true);
  5249. this._set("active", this._mouseDown);
  5250. break;
  5251. case "mouseleave":
  5252. case "mouseout": // generated on non-IE browsers even though we connected to mouseleave
  5253. this._set("hovering", false);
  5254. this._set("active", false);
  5255. break;
  5256. case "mousedown" :
  5257. this._set("active", true);
  5258. this._mouseDown = true;
  5259. // Set a global event to handle mouseup, so it fires properly
  5260. // even if the cursor leaves this.domNode before the mouse up event.
  5261. // Alternately could set active=false on mouseout.
  5262. var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){
  5263. this._mouseDown = false;
  5264. this._set("active", false);
  5265. this.disconnect(mouseUpConnector);
  5266. });
  5267. break;
  5268. }
  5269. }
  5270. },
  5271. _setStateClass: function(){
  5272. // summary:
  5273. // Update the visual state of the widget by setting the css classes on this.domNode
  5274. // (or this.stateNode if defined) by combining this.baseClass with
  5275. // various suffixes that represent the current widget state(s).
  5276. //
  5277. // description:
  5278. // In the case where a widget has multiple
  5279. // states, it sets the class based on all possible
  5280. // combinations. For example, an invalid form widget that is being hovered
  5281. // will be "dijitInput dijitInputInvalid dijitInputHover dijitInputInvalidHover".
  5282. //
  5283. // The widget may have one or more of the following states, determined
  5284. // by this.state, this.checked, this.valid, and this.selected:
  5285. // - Error - ValidationTextBox sets this.state to "Error" if the current input value is invalid
  5286. // - Incomplete - ValidationTextBox sets this.state to "Incomplete" if the current input value is not finished yet
  5287. // - Checked - ex: a checkmark or a ToggleButton in a checked state, will have this.checked==true
  5288. // - Selected - ex: currently selected tab will have this.selected==true
  5289. //
  5290. // In addition, it may have one or more of the following states,
  5291. // based on this.disabled and flags set in _onMouse (this.active, this.hovering) and from focus manager (this.focused):
  5292. // - Disabled - if the widget is disabled
  5293. // - Active - if the mouse (or space/enter key?) is being pressed down
  5294. // - Focused - if the widget has focus
  5295. // - Hover - if the mouse is over the widget
  5296. // Compute new set of classes
  5297. var newStateClasses = this.baseClass.split(" ");
  5298. function multiply(modifier){
  5299. newStateClasses = newStateClasses.concat(dojo.map(newStateClasses, function(c){ return c+modifier; }), "dijit"+modifier);
  5300. }
  5301. if(!this.isLeftToRight()){
  5302. // For RTL mode we need to set an addition class like dijitTextBoxRtl.
  5303. multiply("Rtl");
  5304. }
  5305. if(this.checked){
  5306. multiply("Checked");
  5307. }
  5308. if(this.state){
  5309. multiply(this.state);
  5310. }
  5311. if(this.selected){
  5312. multiply("Selected");
  5313. }
  5314. if(this.disabled){
  5315. multiply("Disabled");
  5316. }else if(this.readOnly){
  5317. multiply("ReadOnly");
  5318. }else{
  5319. if(this.active){
  5320. multiply("Active");
  5321. }else if(this.hovering){
  5322. multiply("Hover");
  5323. }
  5324. }
  5325. if(this._focused){
  5326. multiply("Focused");
  5327. }
  5328. // Remove old state classes and add new ones.
  5329. // For performance concerns we only write into domNode.className once.
  5330. var tn = this.stateNode || this.domNode,
  5331. classHash = {}; // set of all classes (state and otherwise) for node
  5332. dojo.forEach(tn.className.split(" "), function(c){ classHash[c] = true; });
  5333. if("_stateClasses" in this){
  5334. dojo.forEach(this._stateClasses, function(c){ delete classHash[c]; });
  5335. }
  5336. dojo.forEach(newStateClasses, function(c){ classHash[c] = true; });
  5337. var newClasses = [];
  5338. for(var c in classHash){
  5339. newClasses.push(c);
  5340. }
  5341. tn.className = newClasses.join(" ");
  5342. this._stateClasses = newStateClasses;
  5343. },
  5344. _trackMouseState: function(/*DomNode*/ node, /*String*/ clazz){
  5345. // summary:
  5346. // Track mouse/focus events on specified node and set CSS class on that node to indicate
  5347. // current state. Usually not called directly, but via cssStateNodes attribute.
  5348. // description:
  5349. // Given class=foo, will set the following CSS class on the node
  5350. // - fooActive: if the user is currently pressing down the mouse button while over the node
  5351. // - fooHover: if the user is hovering the mouse over the node, but not pressing down a button
  5352. // - fooFocus: if the node is focused
  5353. //
  5354. // Note that it won't set any classes if the widget is disabled.
  5355. // node: DomNode
  5356. // Should be a sub-node of the widget, not the top node (this.domNode), since the top node
  5357. // is handled specially and automatically just by mixing in this class.
  5358. // clazz: String
  5359. // CSS class name (ex: dijitSliderUpArrow).
  5360. // Current state of node (initially false)
  5361. // NB: setting specifically to false because dojo.toggleClass() needs true boolean as third arg
  5362. var hovering=false, active=false, focused=false;
  5363. var self = this,
  5364. cn = dojo.hitch(this, "connect", node);
  5365. function setClass(){
  5366. var disabled = ("disabled" in self && self.disabled) || ("readonly" in self && self.readonly);
  5367. dojo.toggleClass(node, clazz+"Hover", hovering && !active && !disabled);
  5368. dojo.toggleClass(node, clazz+"Active", active && !disabled);
  5369. dojo.toggleClass(node, clazz+"Focused", focused && !disabled);
  5370. }
  5371. // Mouse
  5372. cn("onmouseenter", function(){
  5373. hovering = true;
  5374. setClass();
  5375. });
  5376. cn("onmouseleave", function(){
  5377. hovering = false;
  5378. active = false;
  5379. setClass();
  5380. });
  5381. cn("onmousedown", function(){
  5382. active = true;
  5383. setClass();
  5384. });
  5385. cn("onmouseup", function(){
  5386. active = false;
  5387. setClass();
  5388. });
  5389. // Focus
  5390. cn("onfocus", function(){
  5391. focused = true;
  5392. setClass();
  5393. });
  5394. cn("onblur", function(){
  5395. focused = false;
  5396. setClass();
  5397. });
  5398. // Just in case widget is enabled/disabled while it has focus/hover/active state.
  5399. // Maybe this is overkill.
  5400. this.watch("disabled", setClass);
  5401. this.watch("readOnly", setClass);
  5402. }
  5403. });
  5404. }
  5405. if(!dojo._hasResource["dijit.form._FormWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  5406. dojo._hasResource["dijit.form._FormWidget"] = true;
  5407. dojo.provide("dijit.form._FormWidget");
  5408. dojo.declare("dijit.form._FormWidget", [dijit._Widget, dijit._Templated, dijit._CssStateMixin],
  5409. {
  5410. // summary:
  5411. // Base class for widgets corresponding to native HTML elements such as <checkbox> or <button>,
  5412. // which can be children of a <form> node or a `dijit.form.Form` widget.
  5413. //
  5414. // description:
  5415. // Represents a single HTML element.
  5416. // All these widgets should have these attributes just like native HTML input elements.
  5417. // You can set them during widget construction or afterwards, via `dijit._Widget.attr`.
  5418. //
  5419. // They also share some common methods.
  5420. // name: [const] String
  5421. // Name used when submitting form; same as "name" attribute or plain HTML elements
  5422. name: "",
  5423. // alt: String
  5424. // Corresponds to the native HTML <input> element's attribute.
  5425. alt: "",
  5426. // value: String
  5427. // Corresponds to the native HTML <input> element's attribute.
  5428. value: "",
  5429. // type: String
  5430. // Corresponds to the native HTML <input> element's attribute.
  5431. type: "text",
  5432. // tabIndex: Integer
  5433. // Order fields are traversed when user hits the tab key
  5434. tabIndex: "0",
  5435. // disabled: Boolean
  5436. // Should this widget respond to user input?
  5437. // In markup, this is specified as "disabled='disabled'", or just "disabled".
  5438. disabled: false,
  5439. // intermediateChanges: Boolean
  5440. // Fires onChange for each value change or only on demand
  5441. intermediateChanges: false,
  5442. // scrollOnFocus: Boolean
  5443. // On focus, should this widget scroll into view?
  5444. scrollOnFocus: true,
  5445. // These mixins assume that the focus node is an INPUT, as many but not all _FormWidgets are.
  5446. attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
  5447. value: "focusNode",
  5448. id: "focusNode",
  5449. tabIndex: "focusNode",
  5450. alt: "focusNode",
  5451. title: "focusNode"
  5452. }),
  5453. postMixInProperties: function(){
  5454. // Setup name=foo string to be referenced from the template (but only if a name has been specified)
  5455. // Unfortunately we can't use attributeMap to set the name due to IE limitations, see #8660
  5456. // Regarding escaping, see heading "Attribute values" in
  5457. // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
  5458. this.nameAttrSetting = this.name ? ('name="' + this.name.replace(/'/g, "&quot;") + '"') : '';
  5459. this.inherited(arguments);
  5460. },
  5461. postCreate: function(){
  5462. this.inherited(arguments);
  5463. this.connect(this.domNode, "onmousedown", "_onMouseDown");
  5464. },
  5465. _setDisabledAttr: function(/*Boolean*/ value){
  5466. this._set("disabled", value);
  5467. dojo.attr(this.focusNode, 'disabled', value);
  5468. if(this.valueNode){
  5469. dojo.attr(this.valueNode, 'disabled', value);
  5470. }
  5471. dijit.setWaiState(this.focusNode, "disabled", value);
  5472. if(value){
  5473. // reset these, because after the domNode is disabled, we can no longer receive
  5474. // mouse related events, see #4200
  5475. this._set("hovering", false);
  5476. this._set("active", false);
  5477. // clear tab stop(s) on this widget's focusable node(s) (ComboBox has two focusable nodes)
  5478. var attachPointNames = "tabIndex" in this.attributeMap ? this.attributeMap.tabIndex : "focusNode";
  5479. dojo.forEach(dojo.isArray(attachPointNames) ? attachPointNames : [attachPointNames], function(attachPointName){
  5480. var node = this[attachPointName];
  5481. // complex code because tabIndex=-1 on a <div> doesn't work on FF
  5482. if(dojo.isWebKit || dijit.hasDefaultTabStop(node)){ // see #11064 about webkit bug
  5483. node.setAttribute('tabIndex', "-1");
  5484. }else{
  5485. node.removeAttribute('tabIndex');
  5486. }
  5487. }, this);
  5488. }else{
  5489. if(this.tabIndex != ""){
  5490. this.focusNode.setAttribute('tabIndex', this.tabIndex);
  5491. }
  5492. }
  5493. },
  5494. setDisabled: function(/*Boolean*/ disabled){
  5495. // summary:
  5496. // Deprecated. Use set('disabled', ...) instead.
  5497. dojo.deprecated("setDisabled("+disabled+") is deprecated. Use set('disabled',"+disabled+") instead.", "", "2.0");
  5498. this.set('disabled', disabled);
  5499. },
  5500. _onFocus: function(e){
  5501. if(this.scrollOnFocus){
  5502. dojo.window.scrollIntoView(this.domNode);
  5503. }
  5504. this.inherited(arguments);
  5505. },
  5506. isFocusable: function(){
  5507. // summary:
  5508. // Tells if this widget is focusable or not. Used internally by dijit.
  5509. // tags:
  5510. // protected
  5511. return !this.disabled && this.focusNode && (dojo.style(this.domNode, "display") != "none");
  5512. },
  5513. focus: function(){
  5514. // summary:
  5515. // Put focus on this widget
  5516. if(!this.disabled){
  5517. dijit.focus(this.focusNode);
  5518. }
  5519. },
  5520. compare: function(/*anything*/ val1, /*anything*/ val2){
  5521. // summary:
  5522. // Compare 2 values (as returned by get('value') for this widget).
  5523. // tags:
  5524. // protected
  5525. if(typeof val1 == "number" && typeof val2 == "number"){
  5526. return (isNaN(val1) && isNaN(val2)) ? 0 : val1 - val2;
  5527. }else if(val1 > val2){
  5528. return 1;
  5529. }else if(val1 < val2){
  5530. return -1;
  5531. }else{
  5532. return 0;
  5533. }
  5534. },
  5535. onChange: function(newValue){
  5536. // summary:
  5537. // Callback when this widget's value is changed.
  5538. // tags:
  5539. // callback
  5540. },
  5541. // _onChangeActive: [private] Boolean
  5542. // Indicates that changes to the value should call onChange() callback.
  5543. // This is false during widget initialization, to avoid calling onChange()
  5544. // when the initial value is set.
  5545. _onChangeActive: false,
  5546. _handleOnChange: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
  5547. // summary:
  5548. // Called when the value of the widget is set. Calls onChange() if appropriate
  5549. // newValue:
  5550. // the new value
  5551. // priorityChange:
  5552. // For a slider, for example, dragging the slider is priorityChange==false,
  5553. // but on mouse up, it's priorityChange==true. If intermediateChanges==false,
  5554. // onChange is only called form priorityChange=true events.
  5555. // tags:
  5556. // private
  5557. if(this._lastValueReported == undefined && (priorityChange === null || !this._onChangeActive)){
  5558. // this block executes not for a change, but during initialization,
  5559. // and is used to store away the original value (or for ToggleButton, the original checked state)
  5560. this._resetValue = this._lastValueReported = newValue;
  5561. }
  5562. this._pendingOnChange = this._pendingOnChange
  5563. || (typeof newValue != typeof this._lastValueReported)
  5564. || (this.compare(newValue, this._lastValueReported) != 0);
  5565. if((this.intermediateChanges || priorityChange || priorityChange === undefined) && this._pendingOnChange){
  5566. this._lastValueReported = newValue;
  5567. this._pendingOnChange = false;
  5568. if(this._onChangeActive){
  5569. if(this._onChangeHandle){
  5570. clearTimeout(this._onChangeHandle);
  5571. }
  5572. // setTimout allows hidden value processing to run and
  5573. // also the onChange handler can safely adjust focus, etc
  5574. this._onChangeHandle = setTimeout(dojo.hitch(this,
  5575. function(){
  5576. this._onChangeHandle = null;
  5577. this.onChange(newValue);
  5578. }), 0); // try to collapse multiple onChange's fired faster than can be processed
  5579. }
  5580. }
  5581. },
  5582. create: function(){
  5583. // Overrides _Widget.create()
  5584. this.inherited(arguments);
  5585. this._onChangeActive = true;
  5586. },
  5587. destroy: function(){
  5588. if(this._onChangeHandle){ // destroy called before last onChange has fired
  5589. clearTimeout(this._onChangeHandle);
  5590. this.onChange(this._lastValueReported);
  5591. }
  5592. this.inherited(arguments);
  5593. },
  5594. setValue: function(/*String*/ value){
  5595. // summary:
  5596. // Deprecated. Use set('value', ...) instead.
  5597. dojo.deprecated("dijit.form._FormWidget:setValue("+value+") is deprecated. Use set('value',"+value+") instead.", "", "2.0");
  5598. this.set('value', value);
  5599. },
  5600. getValue: function(){
  5601. // summary:
  5602. // Deprecated. Use get('value') instead.
  5603. dojo.deprecated(this.declaredClass+"::getValue() is deprecated. Use get('value') instead.", "", "2.0");
  5604. return this.get('value');
  5605. },
  5606. _onMouseDown: function(e){
  5607. // If user clicks on the button, even if the mouse is released outside of it,
  5608. // this button should get focus (to mimics native browser buttons).
  5609. // This is also needed on chrome because otherwise buttons won't get focus at all,
  5610. // which leads to bizarre focus restore on Dialog close etc.
  5611. if(!e.ctrlKey && dojo.mouseButtons.isLeft(e) && this.isFocusable()){ // !e.ctrlKey to ignore right-click on mac
  5612. // Set a global event to handle mouseup, so it fires properly
  5613. // even if the cursor leaves this.domNode before the mouse up event.
  5614. var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){
  5615. if (this.isFocusable()) {
  5616. this.focus();
  5617. }
  5618. this.disconnect(mouseUpConnector);
  5619. });
  5620. }
  5621. }
  5622. });
  5623. dojo.declare("dijit.form._FormValueWidget", dijit.form._FormWidget,
  5624. {
  5625. // summary:
  5626. // Base class for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values.
  5627. // description:
  5628. // Each _FormValueWidget represents a single input value, and has a (possibly hidden) <input> element,
  5629. // to which it serializes it's input value, so that form submission (either normal submission or via FormBind?)
  5630. // works as expected.
  5631. // Don't attempt to mixin the 'type', 'name' attributes here programatically -- they must be declared
  5632. // directly in the template as read by the parser in order to function. IE is known to specifically
  5633. // require the 'name' attribute at element creation time. See #8484, #8660.
  5634. // TODO: unclear what that {value: ""} is for; FormWidget.attributeMap copies value to focusNode,
  5635. // so maybe {value: ""} is so the value *doesn't* get copied to focusNode?
  5636. // Seems like we really want value removed from attributeMap altogether
  5637. // (although there's no easy way to do that now)
  5638. // readOnly: Boolean
  5639. // Should this widget respond to user input?
  5640. // In markup, this is specified as "readOnly".
  5641. // Similar to disabled except readOnly form values are submitted.
  5642. readOnly: false,
  5643. attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, {
  5644. value: "",
  5645. readOnly: "focusNode"
  5646. }),
  5647. _setReadOnlyAttr: function(/*Boolean*/ value){
  5648. dojo.attr(this.focusNode, 'readOnly', value);
  5649. dijit.setWaiState(this.focusNode, "readonly", value);
  5650. this._set("readOnly", value);
  5651. },
  5652. postCreate: function(){
  5653. this.inherited(arguments);
  5654. if(dojo.isIE < 9 || (dojo.isIE && dojo.isQuirks)){ // IE won't stop the event with keypress
  5655. this.connect(this.focusNode || this.domNode, "onkeydown", this._onKeyDown);
  5656. }
  5657. // Update our reset value if it hasn't yet been set (because this.set()
  5658. // is only called when there *is* a value)
  5659. if(this._resetValue === undefined){
  5660. this._lastValueReported = this._resetValue = this.value;
  5661. }
  5662. },
  5663. _setValueAttr: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
  5664. // summary:
  5665. // Hook so set('value', value) works.
  5666. // description:
  5667. // Sets the value of the widget.
  5668. // If the value has changed, then fire onChange event, unless priorityChange
  5669. // is specified as null (or false?)
  5670. this._handleOnChange(newValue, priorityChange);
  5671. },
  5672. _handleOnChange: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
  5673. // summary:
  5674. // Called when the value of the widget has changed. Saves the new value in this.value,
  5675. // and calls onChange() if appropriate. See _FormWidget._handleOnChange() for details.
  5676. this._set("value", newValue);
  5677. this.inherited(arguments);
  5678. },
  5679. undo: function(){
  5680. // summary:
  5681. // Restore the value to the last value passed to onChange
  5682. this._setValueAttr(this._lastValueReported, false);
  5683. },
  5684. reset: function(){
  5685. // summary:
  5686. // Reset the widget's value to what it was at initialization time
  5687. this._hasBeenBlurred = false;
  5688. this._setValueAttr(this._resetValue, true);
  5689. },
  5690. _onKeyDown: function(e){
  5691. if(e.keyCode == dojo.keys.ESCAPE && !(e.ctrlKey || e.altKey || e.metaKey)){
  5692. var te;
  5693. if(dojo.isIE){
  5694. e.preventDefault(); // default behavior needs to be stopped here since keypress is too late
  5695. te = document.createEventObject();
  5696. te.keyCode = dojo.keys.ESCAPE;
  5697. te.shiftKey = e.shiftKey;
  5698. e.srcElement.fireEvent('onkeypress', te);
  5699. }
  5700. }
  5701. },
  5702. _layoutHackIE7: function(){
  5703. // summary:
  5704. // Work around table sizing bugs on IE7 by forcing redraw
  5705. if(dojo.isIE == 7){ // fix IE7 layout bug when the widget is scrolled out of sight
  5706. var domNode = this.domNode;
  5707. var parent = domNode.parentNode;
  5708. var pingNode = domNode.firstChild || domNode; // target node most unlikely to have a custom filter
  5709. var origFilter = pingNode.style.filter; // save custom filter, most likely nothing
  5710. var _this = this;
  5711. while(parent && parent.clientHeight == 0){ // search for parents that haven't rendered yet
  5712. (function ping(){
  5713. var disconnectHandle = _this.connect(parent, "onscroll",
  5714. function(e){
  5715. _this.disconnect(disconnectHandle); // only call once
  5716. pingNode.style.filter = (new Date()).getMilliseconds(); // set to anything that's unique
  5717. setTimeout(function(){ pingNode.style.filter = origFilter }, 0); // restore custom filter, if any
  5718. }
  5719. );
  5720. })();
  5721. parent = parent.parentNode;
  5722. }
  5723. }
  5724. }
  5725. });
  5726. }
  5727. if(!dojo._hasResource["dijit.dijit"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  5728. dojo._hasResource["dijit.dijit"] = true;
  5729. dojo.provide("dijit.dijit");
  5730. /*=====
  5731. dijit.dijit = {
  5732. // summary:
  5733. // A roll-up for common dijit methods
  5734. // description:
  5735. // A rollup file for the build system including the core and common
  5736. // dijit files.
  5737. //
  5738. // example:
  5739. // | <script type="text/javascript" src="js/dojo/dijit/dijit.js"></script>
  5740. //
  5741. };
  5742. =====*/
  5743. // All the stuff in _base (these are the function that are guaranteed available without an explicit dojo.require)
  5744. // And some other stuff that we tend to pull in all the time anyway
  5745. }